diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-02-07 10:27:28 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-02-07 10:27:28 +0300 |
commit | 6c6b4251dbe1b8a91836c4cdf683191d9baf9a7f (patch) | |
tree | 28afa29deded9d5c3e94d9cd9e4b729e03a55ec9 | |
parent | 0ba61780b7ba662814b040d43bcf60847955ba18 (diff) |
v2.4.1v2.4.1
* **(Fix) Exposure time finder:**
* Use a spiral square instead of configurable shapes to match the exact precise set pixels
* Set pixels as default values
* Optimized the pixel values to always produce a closed shape
* Rename cylinder to hole
* Crash when diameters are empty
* Profiles was not saving
-rw-r--r-- | CHANGELOG.md | 11 | ||||
-rw-r--r-- | UVtools.Core/Objects/ExposureItem.cs | 87 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationCalibrateExposureFinder.cs | 369 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationDynamicLayerHeight.cs | 50 | ||||
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 2 | ||||
-rw-r--r-- | UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml | 25 | ||||
-rw-r--r-- | UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs | 12 | ||||
-rw-r--r-- | UVtools.WPF/Structures/OperationProfiles.cs | 1 | ||||
-rw-r--r-- | UVtools.WPF/UVtools.WPF.csproj | 2 |
9 files changed, 248 insertions, 311 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d7f3b..599ba09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 07/02/2021 - v2.4.1 + +* **(Fix) Exposure time finder:** + * Use a spiral square instead of configurable shapes to match the exact precise set pixels + * Set pixels as default values + * Optimized the pixel values to always produce a closed shape + * Rename cylinder to hole + * Crash when diameters are empty + * Profiles was not saving + + ## 06/02/2021 - v2.4.0 * (Upgrade) EmguCV/OpenCV to v4.5.1 diff --git a/UVtools.Core/Objects/ExposureItem.cs b/UVtools.Core/Objects/ExposureItem.cs new file mode 100644 index 0000000..374a567 --- /dev/null +++ b/UVtools.Core/Objects/ExposureItem.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UVtools.Core.Objects +{ + [Serializable] + public sealed class ExposureItem : BindableBase, IComparable<ExposureItem> + { + private decimal _layerHeight; + private decimal _bottomExposure; + private decimal _exposure; + + + /// <summary> + /// Gets or sets the layer height in millimeters + /// </summary> + public decimal LayerHeight + { + get => _layerHeight; + set => RaiseAndSetIfChanged(ref _layerHeight, Math.Round(value, 2)); + } + + + /// <summary> + /// Gets or sets the bottom exposure in seconds + /// </summary> + public decimal BottomExposure + { + get => _bottomExposure; + set => RaiseAndSetIfChanged(ref _bottomExposure, Math.Round(value, 2)); + } + + /// <summary> + /// Gets or sets the bottom exposure in seconds + /// </summary> + public decimal Exposure + { + get => _exposure; + set => RaiseAndSetIfChanged(ref _exposure, Math.Round(value, 2)); + } + + public bool IsValid => _layerHeight > 0 && _bottomExposure > 0 && _exposure > 0; + + public ExposureItem() { } + + public ExposureItem(decimal layerHeight, decimal bottomExposure = 0, decimal exposure = 0) + { + _layerHeight = Math.Round(layerHeight, 2); + _bottomExposure = Math.Round(bottomExposure, 2); + _exposure = Math.Round(exposure, 2); + } + + public override string ToString() + { + return $"{nameof(LayerHeight)}: {LayerHeight}mm, {nameof(BottomExposure)}: {BottomExposure}s, {nameof(Exposure)}: {Exposure}s"; + } + + private bool Equals(ExposureItem other) + { + return _layerHeight == other._layerHeight && _bottomExposure == other._bottomExposure && _exposure == other._exposure; + } + + public override bool Equals(object obj) + { + return ReferenceEquals(this, obj) || obj is ExposureItem other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(_layerHeight, _bottomExposure, _exposure); + } + + public int CompareTo(ExposureItem other) + { + if (ReferenceEquals(this, other)) return 0; + if (ReferenceEquals(null, other)) return 1; + var layerHeightComparison = _layerHeight.CompareTo(other._layerHeight); + if (layerHeightComparison != 0) return layerHeightComparison; + var bottomExposureComparison = _bottomExposure.CompareTo(other._bottomExposure); + if (bottomExposureComparison != 0) return bottomExposureComparison; + return _exposure.CompareTo(other._exposure); + } + } +} diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs index 183d20e..7342149 100644 --- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs +++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs @@ -13,7 +13,6 @@ using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; -using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; @@ -26,89 +25,6 @@ namespace UVtools.Core.Operations [Serializable] public sealed class OperationCalibrateExposureFinder : Operation { - #region Sub classes - - [Serializable] - public sealed class ExposureItem : BindableBase, IComparable<ExposureItem> - { - private decimal _layerHeight; - private decimal _bottomExposure; - private decimal _exposure; - - - /// <summary> - /// Gets or sets the layer height in millimeters - /// </summary> - public decimal LayerHeight - { - get => _layerHeight; - set => RaiseAndSetIfChanged(ref _layerHeight, Math.Round(value, 2)); - } - - - /// <summary> - /// Gets or sets the bottom exposure in seconds - /// </summary> - public decimal BottomExposure - { - get => _bottomExposure; - set => RaiseAndSetIfChanged(ref _bottomExposure, Math.Round(value, 2)); - } - - /// <summary> - /// Gets or sets the bottom exposure in seconds - /// </summary> - public decimal Exposure - { - get => _exposure; - set => RaiseAndSetIfChanged(ref _exposure, Math.Round(value, 2)); - } - - public bool IsValid => _layerHeight > 0 && _bottomExposure > 0 && _exposure > 0; - - public ExposureItem() { } - - public ExposureItem(decimal layerHeight, decimal bottomExposure = 0, decimal exposure = 0) - { - _layerHeight = Math.Round(layerHeight, 2); - _bottomExposure = Math.Round(bottomExposure, 2); - _exposure = Math.Round(exposure, 2); - } - - public override string ToString() - { - return $"{nameof(LayerHeight)}: {LayerHeight}mm, {nameof(BottomExposure)}: {BottomExposure}s, {nameof(Exposure)}: {Exposure}s"; - } - - private bool Equals(ExposureItem other) - { - return _layerHeight == other._layerHeight && _bottomExposure == other._bottomExposure && _exposure == other._exposure; - } - - public override bool Equals(object obj) - { - return ReferenceEquals(this, obj) || obj is ExposureItem other && Equals(other); - } - - public override int GetHashCode() - { - return HashCode.Combine(_layerHeight, _bottomExposure, _exposure); - } - - public int CompareTo(ExposureItem other) - { - if (ReferenceEquals(this, other)) return 0; - if (ReferenceEquals(null, other)) return 1; - var layerHeightComparison = _layerHeight.CompareTo(other._layerHeight); - if (layerHeightComparison != 0) return layerHeightComparison; - var bottomExposureComparison = _bottomExposure.CompareTo(other._bottomExposure); - if (bottomExposureComparison != 0) return bottomExposureComparison; - return _exposure.CompareTo(other._exposure); - } - } - - #endregion - #region Constants const byte TextSpacing = 60; @@ -136,16 +52,15 @@ namespace UVtools.Core.Operations private bool _enableAntiAliasing = true; private bool _mirrorOutput; private decimal _baseHeight = 1; - private decimal _cylinderHeight = 1; - private decimal _cylinderMargin = 1.5m; - private Measures _unitOfMeasure = Measures.Millimeters; - private string _cylinderDiametersMm = "0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0"; - private string _cylinderDiametersPx = "1, 2, 3, 4, 5, 7, 10 ,15, 20"; + private decimal _holeHeight = 1; + private decimal _holeMargin = 1.5m; + private Measures _unitOfMeasure = Measures.Pixels; + private string _holeDiametersMm = "0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0"; + private string _holeDiametersPx = "1, 2, 4, 6, 9, 12, 16, 20, 25, 30, 36"; private bool _multipleLayerHeight; private decimal _multipleLayerHeightMaximum = 0.1m; private decimal _multipleLayerHeightStep = 0.01m; private bool _multipleExposures; - private Shapes _shape = Shapes.Circle; private ExposureGenTypes _exposureGenType = ExposureGenTypes.Linear; private bool _exposureGenIgnoreBaseExposure; private decimal _exposureGenBottomStep = 0.5m; @@ -194,7 +109,7 @@ namespace UVtools.Core.Operations sb.AppendLine("Display height must be a positive value."); } - if (Cylinders.Length <= 0) + if (Holes.Length <= 0) { sb.AppendLine("No objects to output."); } @@ -228,10 +143,10 @@ namespace UVtools.Core.Operations var result = $"[Layer Height: {_layerHeight}] " + $"[Bottom layers: {_bottomLayers}] " + $"[Exposure: {_bottomExposure}/{_normalExposure}] " + - $"[TB:{_topBottomMargin} LR:{_leftRightMargin} PM:{_partMargin} CM:{_cylinderMargin}] " + + $"[TB:{_topBottomMargin} LR:{_leftRightMargin} PM:{_partMargin} CM:{_holeMargin}] " + $"[Chamfer: {_chamferLayers}] [Erode: {_erodeBottomIterations}] " + - $"[Obj height: {_cylinderHeight}] " + - $"[Cylinders: {Cylinders.Length}] " + + $"[Obj height: {_holeHeight}] " + + $"[Holes: {Holes.Length}] " + $"[AA: {_enableAntiAliasing}] [Mirror: {_mirrorOutput}]"; if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}"; return result; @@ -350,19 +265,19 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _baseHeight, Math.Round(value, 2)); } - public decimal CylinderHeight + public decimal HoleHeight { - get => _cylinderHeight; - set => RaiseAndSetIfChanged(ref _cylinderHeight, Math.Round(value, 2)); + get => _holeHeight; + set => RaiseAndSetIfChanged(ref _holeHeight, Math.Round(value, 2)); } - public decimal CylinderMargin + public decimal HoleMargin { - get => _cylinderMargin; - set => RaiseAndSetIfChanged(ref _cylinderMargin, Math.Round(value, 2)); + get => _holeMargin; + set => RaiseAndSetIfChanged(ref _holeMargin, Math.Round(value, 2)); } - public decimal TotalHeight => BaseHeight + CylinderHeight; + public decimal TotalHeight => BaseHeight + HoleHeight; public Measures UnitOfMeasure { @@ -376,66 +291,60 @@ namespace UVtools.Core.Operations public bool IsUnitOfMeasureMm => _unitOfMeasure == Measures.Millimeters; - public string CylinderDiametersMm + public string HoleDiametersMm { - get => _cylinderDiametersMm; - set => RaiseAndSetIfChanged(ref _cylinderDiametersMm, value); + get => _holeDiametersMm; + set => RaiseAndSetIfChanged(ref _holeDiametersMm, value); } - public string CylinderDiametersPx + public string HoleDiametersPx { - get => _cylinderDiametersPx; - set => RaiseAndSetIfChanged(ref _cylinderDiametersPx, value); + get => _holeDiametersPx; + set => RaiseAndSetIfChanged(ref _holeDiametersPx, value); } /// <summary> - /// Gets all cylinders in pixels and ordered + /// Gets all holes in pixels and ordered /// </summary> - public int[] Cylinders + public int[] Holes { get { - List<int> cylinders = new(); + List<int> holes = new(); if (_unitOfMeasure == Measures.Millimeters) { - var split = _cylinderDiametersMm.Split(',', StringSplitOptions.TrimEntries); + var split = _holeDiametersMm.Split(',', StringSplitOptions.TrimEntries); foreach (var mmStr in split) { if (string.IsNullOrWhiteSpace(mmStr)) continue; if (!decimal.TryParse(mmStr, out var mm)) continue; if(mm <= 0) continue; var mmPx = (int) Math.Floor(mm * Ppmm); - if(cylinders.Contains(mmPx)) continue; - cylinders.Add((int)Math.Floor(mm * Ppmm)); + if(holes.Contains(mmPx) || mmPx > 500) continue; + holes.Add((int)Math.Floor(mm * Ppmm)); } } else { - var split = _cylinderDiametersPx.Split(',', StringSplitOptions.TrimEntries); + var split = _holeDiametersPx.Split(',', StringSplitOptions.TrimEntries); foreach (var pxStr in split) { if (string.IsNullOrWhiteSpace(pxStr)) continue; if (!int.TryParse(pxStr, out var px)) continue; if (px <= 0) continue; - if (cylinders.Contains(px)) continue; - cylinders.Add(px); + if (holes.Contains(px) || px > 500) continue; + holes.Add(px); } } - return cylinders.OrderBy(pixels => pixels).ToArray(); + return holes.OrderBy(pixels => pixels).ToArray(); } } - public Shapes Shape - { - get => _shape; - set => RaiseAndSetIfChanged(ref _shape, value); - } - - public int GetCylindersLength(int[] cylinders) + public int GetHolesLength(int[] holes) { - return (int) (cylinders.Sum() + (cylinders.Length-1) * _cylinderMargin * Yppmm); + return (int) (holes.Sum(i => Math.Sqrt(i)) + (double) ((holes.Length-1) * _holeMargin * Yppmm)); } public bool MultipleLayerHeight @@ -588,20 +497,12 @@ namespace UVtools.Core.Operations public enum Measures : byte { - Millimeters, Pixels, + Millimeters, } public static Array MeasuresItems => Enum.GetValues(typeof(Measures)); - public enum Shapes : byte - { - Circle, - Square - } - - public static Array ShapesItems => Enum.GetValues(typeof(Shapes)); - public enum ExposureGenTypes : byte { Linear, @@ -615,7 +516,7 @@ namespace UVtools.Core.Operations private bool Equals(OperationCalibrateExposureFinder other) { - return _layerHeight == other._layerHeight && _bottomLayers == other._bottomLayers && _bottomExposure == other._bottomExposure && _normalExposure == other._normalExposure && _topBottomMargin == other._topBottomMargin && _leftRightMargin == other._leftRightMargin && _chamferLayers == other._chamferLayers && _erodeBottomIterations == other._erodeBottomIterations && _partMargin == other._partMargin && _enableAntiAliasing == other._enableAntiAliasing && _mirrorOutput == other._mirrorOutput && _baseHeight == other._baseHeight && _cylinderHeight == other._cylinderHeight && _cylinderMargin == other._cylinderMargin && _unitOfMeasure == other._unitOfMeasure && _cylinderDiametersMm == other._cylinderDiametersMm && _cylinderDiametersPx == other._cylinderDiametersPx && _multipleLayerHeight == other._multipleLayerHeight && _multipleLayerHeightMaximum == other._multipleLayerHeightMaximum && _multipleLayerHeightStep == other._multipleLayerHeightStep && _multipleExposures == other._multipleExposures && _shape == other._shape && _exposureGenType == other._exposureGenType && _exposureGenIgnoreBaseExposure == other._exposureGenIgnoreBaseExposure && _exposureGenBottomStep == other._exposureGenBottomStep && _exposureGenNormalStep == other._exposureGenNormalStep && _exposureGenTests == other._exposureGenTests && Equals(_exposureTable, other._exposureTable); + return _layerHeight == other._layerHeight && _bottomLayers == other._bottomLayers && _bottomExposure == other._bottomExposure && _normalExposure == other._normalExposure && _topBottomMargin == other._topBottomMargin && _leftRightMargin == other._leftRightMargin && _chamferLayers == other._chamferLayers && _erodeBottomIterations == other._erodeBottomIterations && _partMargin == other._partMargin && _enableAntiAliasing == other._enableAntiAliasing && _mirrorOutput == other._mirrorOutput && _baseHeight == other._baseHeight && _holeHeight == other._holeHeight && _holeMargin == other._holeMargin && _unitOfMeasure == other._unitOfMeasure && _holeDiametersMm == other._holeDiametersMm && _holeDiametersPx == other._holeDiametersPx && _multipleLayerHeight == other._multipleLayerHeight && _multipleLayerHeightMaximum == other._multipleLayerHeightMaximum && _multipleLayerHeightStep == other._multipleLayerHeightStep && _multipleExposures == other._multipleExposures && _exposureGenType == other._exposureGenType && _exposureGenIgnoreBaseExposure == other._exposureGenIgnoreBaseExposure && _exposureGenBottomStep == other._exposureGenBottomStep && _exposureGenNormalStep == other._exposureGenNormalStep && _exposureGenTests == other._exposureGenTests && Equals(_exposureTable, other._exposureTable); } public override bool Equals(object obj) @@ -638,16 +539,15 @@ namespace UVtools.Core.Operations hashCode.Add(_enableAntiAliasing); hashCode.Add(_mirrorOutput); hashCode.Add(_baseHeight); - hashCode.Add(_cylinderHeight); - hashCode.Add(_cylinderMargin); + hashCode.Add(_holeHeight); + hashCode.Add(_holeMargin); hashCode.Add((int) _unitOfMeasure); - hashCode.Add(_cylinderDiametersMm); - hashCode.Add(_cylinderDiametersPx); + hashCode.Add(_holeDiametersMm); + hashCode.Add(_holeDiametersPx); hashCode.Add(_multipleLayerHeight); hashCode.Add(_multipleLayerHeightMaximum); hashCode.Add(_multipleLayerHeightStep); hashCode.Add(_multipleExposures); - hashCode.Add((int) _shape); hashCode.Add((int) _exposureGenType); hashCode.Add(_exposureGenIgnoreBaseExposure); hashCode.Add(_exposureGenBottomStep); @@ -711,14 +611,16 @@ namespace UVtools.Core.Operations ExposureTable = new(list); } - public Mat[] GetLayers() + public unsafe Mat[] GetLayers() { - var cylinders = Cylinders; - int cylinderMarginX = (int) (Xppmm * _cylinderMargin); - int cylinderMarginY = (int) (Yppmm * _cylinderMargin); + var holes = Holes; + if (holes.Length <= 0) return null; + int holeMarginX = (int) (Xppmm * _holeMargin); + int holeMarginY = (int) (Yppmm * _holeMargin); + int maxArea = (int) Math.Sqrt(holes[^1]); Rectangle rect = new Rectangle(new Point(1, 1), - new Size(cylinderMarginX * 4 + cylinders[^1] * 2, - cylinderMarginY * 3 + GetCylindersLength(cylinders) + TextSpacing)); + new Size(holeMarginX * 4 + maxArea * 2, + holeMarginY * 4 + GetHolesLength(holes) + TextSpacing)); var layers = new Mat[2]; layers[0] = EmguExtensions.InitMat(rect.Size.Inflate(2)); @@ -726,119 +628,110 @@ namespace UVtools.Core.Operations layers[1] = layers[0].Clone(); CvInvoke.Rectangle(layers[1], new Rectangle(0, 0, rect.Size.Width / 2, layers[0].Height), EmguExtensions.BlackByte, -1, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); - //int holeXPos = (int) Math.Round(Xppmm * (CylinderMargin + maxCylinder / 2)); - // Print holes - int holeXPos = 0; - int holeYPos = 0; - for (var layerIndex = 0; layerIndex < layers.Length; layerIndex++) + var span1 = layers[0].GetBytePointer(); + var span2 = layers[1].GetBytePointer(); + + void DrawSpiralHole(int x, int y, int pixels, byte color) { - var layer = layers[layerIndex]; - holeYPos = cylinderMarginY; - for (int i = 0; i < cylinders.Length; i++) + // 0 = Down, 1 = Left, 2 = Up, 3 = Right + byte stepState = 3; + int xStep = 1; + int yStep = 0; + int xCheck = 0; + int yCheck = 1; + + int pixelPos = layers[0].GetPixelPos(x, y); + + span1[pixelPos] = color; + span2[pixelPos] = color; + + Debug.WriteLine($"START: {x}/{x+xCheck}, {y}/{y+yCheck}"); + + for (int i = 1; i < pixels; i++) { - var diameter = cylinders[i]; - var radius = diameter / 2; + x += xStep; + y += yStep; - switch (_shape) - { - case Shapes.Circle: - holeXPos = rect.X + cylinderMarginX + cylinders[^1] - radius; - holeYPos += radius; - break; - case Shapes.Square: - holeXPos = rect.X + cylinderMarginX + cylinders[^1] - diameter; - break; - } - + if (x < 0 || y < 0 || x >= layers[0].Width || y >= layers[0].Height) break; - // Left side - if (layerIndex == 1) - { - if (diameter == 1) - { - layer.SetByte(holeXPos, holeYPos, 255); - } - else - { - switch (_shape) - { - case Shapes.Circle: - CvInvoke.Circle(layers[layerIndex], - new Point(holeXPos, holeYPos), - radius, EmguExtensions.WhiteByte, -1, - _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); - break; - case Shapes.Square: - CvInvoke.Rectangle(layers[layerIndex], - new Rectangle(new Point(holeXPos, holeYPos), new Size(diameter, diameter)), - EmguExtensions.WhiteByte, -1, - _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); - break; - } - - } - } + Debug.WriteLine($"{x}/{x + xCheck}, {y}/{y + yCheck}"); + pixelPos = layers[1].GetPixelPos(x, y); + span1[pixelPos] = color; + span2[pixelPos] = color; - //holeXPos = layers[0].Width - holeXPos; - switch (_shape) - { - case Shapes.Circle: - holeXPos = layers[0].Width - rect.X - cylinderMarginX - cylinders[^1] + radius; - break; - case Shapes.Square: - holeXPos = layers[0].Width - rect.X - cylinderMarginX - cylinders[^1]; - break; - } + xCheck = x + xCheck; + yCheck = y + yCheck; + if (xCheck < 0 || yCheck < 0 || xCheck >= layers[0].Width || yCheck >= layers[0].Height) break; + pixelPos = layers[1].GetPixelPos(xCheck, yCheck); - // Right side - if (diameter == 1) + if (color > 0 && span2[pixelPos] == 0) { - layer.SetByte(holeXPos, holeYPos, 0); + stepState++; } - else + else if (color == 0 && span2[pixelPos] > 0) { - switch (_shape) - { - case Shapes.Circle: - CvInvoke.Circle(layers[layerIndex], - new Point(holeXPos, holeYPos), - radius, EmguExtensions.BlackByte, -1, - _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); - break; - case Shapes.Square: - CvInvoke.Rectangle(layers[layerIndex], - new Rectangle(new Point(holeXPos, holeYPos), new Size(diameter, diameter)), - EmguExtensions.BlackByte, -1, - _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); - break; - } + stepState++; } + if (stepState > 3) stepState = 0; - holeYPos += cylinderMarginY; - - switch (_shape) + switch (stepState) { - case Shapes.Circle: - holeYPos += radius; + case 0: // Down + xStep = 0; + yStep = 1; + xCheck = -1; + yCheck = 0; + break; + case 1: // Left + xStep = -1; + yStep = 0; + xCheck = 0; + yCheck = -1; break; - case Shapes.Square: - holeYPos += diameter; + case 2: // Up + xStep = 0; + yStep = -1; + xCheck = 1; + yCheck = 0; + break; + case 3: // Right + xStep = 1; + yStep = 0; + xCheck = 0; + yCheck = 1; break; } - - } } + //int holeXPos = (int) Math.Round(Xppmm * (HoleMargin + maxCylinder / 2)); + // Print holes + int holeXPos = 0; + int holeYPos = holeMarginY; + for (int i = 0; i < holes.Length; i++) + { + int diameter = holes[i]; + int radius = (int) Math.Sqrt(diameter); + //holeXPos = rect.X + holeMarginX + maxArea - radius; + holeXPos = rect.X + holeMarginX + maxArea / 2; + holeYPos += radius; + + // Left Side, positive + DrawSpiralHole(holeXPos, holeYPos, diameter, 255); + //holeXPos = layers[0].Width - rect.X - holeMarginX - maxArea + radius; + holeXPos = layers[0].Width - holeXPos; + // Right side, negative + DrawSpiralHole(holeXPos, holeYPos, diameter, 0); + + holeYPos += holeMarginY + radius; + } + /*if (_mirrorOutput) { Parallel.ForEach(layers, mat => CvInvoke.Flip(mat, mat, FlipType.Horizontal)); }*/ - - //layers[^1].Save("E:\\layer.png"); - return layers; } @@ -856,7 +749,7 @@ namespace UVtools.Core.Operations CvInvoke.Line(thumbnail, new Point(thumbnail.Width - xSpacing, 0), new Point(thumbnail.Width - xSpacing, ySpacing + 5), new MCvScalar(255, 27, 245), 3); CvInvoke.PutText(thumbnail, "Exposure Time Cal.", new Point(xSpacing, ySpacing * 2), fontFace, fontScale, new MCvScalar(0, 255, 255), fontThickness); CvInvoke.PutText(thumbnail, $"{Microns}um @ {BottomExposure}s/{NormalExposure}s", new Point(xSpacing, ySpacing * 3), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness); - CvInvoke.PutText(thumbnail, $"Objects: {Cylinders.Length}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness); + CvInvoke.PutText(thumbnail, $"Objects: {Holes.Length}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness); return thumbnail; } @@ -881,7 +774,7 @@ namespace UVtools.Core.Operations uint layerIndex = 0; int currentX = sideMarginPx; int currentY = topBottomMarginPx; - int cylinderMarginY = (int)(Yppmm * _cylinderMargin); + int holeMarginY = (int)(Yppmm * _holeMargin); var anchor = new Point(-1, -1); using var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); @@ -939,7 +832,7 @@ namespace UVtools.Core.Operations CvInvoke.Erode(matRoi, matRoi, kernel, anchor, _chamferLayers - layerCountOnHeight, BorderType.Reflect101, default); } - var textHeightStart = matRoi.Height - cylinderMarginY - TextSpacing; + var textHeightStart = matRoi.Height - holeMarginY - TextSpacing; CvInvoke.PutText(matRoi, $"{microns}u", new Point(TextStartX, textHeightStart), FontFace, TextScale, EmguExtensions.WhiteByte, TextThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); CvInvoke.PutText(matRoi, $"{bottomExposure}s", new Point(TextStartX, textHeightStart + TextLineBreak), FontFace, TextScale, EmguExtensions.WhiteByte, TextThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); CvInvoke.PutText(matRoi, $"{normalExposure}s", new Point(TextStartX, textHeightStart + TextLineBreak * 2), FontFace, TextScale, EmguExtensions.WhiteByte, TextThickness, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); diff --git a/UVtools.Core/Operations/OperationDynamicLayerHeight.cs b/UVtools.Core/Operations/OperationDynamicLayerHeight.cs index 3615714..27d7eaf 100644 --- a/UVtools.Core/Operations/OperationDynamicLayerHeight.cs +++ b/UVtools.Core/Operations/OperationDynamicLayerHeight.cs @@ -53,56 +53,6 @@ namespace UVtools.Core.Operations } } - [Serializable] - public sealed class ExposureItem : BindableBase - { - private decimal _layerHeight; - private decimal _bottomExposure; - private decimal _exposure; - - - /// <summary> - /// Gets or sets the layer height in millimeters - /// </summary> - public decimal LayerHeight - { - get => _layerHeight; - set => RaiseAndSetIfChanged(ref _layerHeight, Math.Round(value, 2)); - } - - - /// <summary> - /// Gets or sets the bottom exposure in seconds - /// </summary> - public decimal BottomExposure - { - get => _bottomExposure; - set => RaiseAndSetIfChanged(ref _bottomExposure, Math.Round(value, 2)); - } - - /// <summary> - /// Gets or sets the bottom exposure in seconds - /// </summary> - public decimal Exposure - { - get => _exposure; - set => RaiseAndSetIfChanged(ref _exposure, Math.Round(value, 2)); - } - - public ExposureItem() { } - - public ExposureItem(decimal layerHeight, decimal bottomExposure = 0, decimal exposure = 0) - { - _layerHeight = Math.Round(layerHeight, 2); - _bottomExposure = Math.Round(bottomExposure, 2); - _exposure = Math.Round(exposure, 2); - } - - public override string ToString() - { - return $"{nameof(LayerHeight)}: {LayerHeight}mm, {nameof(BottomExposure)}: {BottomExposure}s, {nameof(Exposure)}: {Exposure}s"; - } - } #endregion #region Constants diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 2ca19df..bcaf156b 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description> - <Version>2.4.0</Version> + <Version>2.4.1</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml index 13e29fc..e2dec88 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml +++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml @@ -208,7 +208,7 @@ Text="mm"/> <TextBlock Grid.Row="0" Grid.Column="6" - Text="Cylinder height:" + Text="Hole height:" VerticalAlignment="Center"/> <NumericUpDown Grid.Row="0" Grid.Column="8" ClipValueToMinMax="True" @@ -216,13 +216,13 @@ Minimum="1" Maximum="100" FormatString="F02" - Value="{Binding Operation.CylinderHeight}"/> + Value="{Binding Operation.HoleHeight}"/> <TextBlock Grid.Row="0" Grid.Column="10" VerticalAlignment="Center" Text="mm"/> <TextBlock Grid.Row="0" Grid.Column="12" - Text="Cylinder margin:" + Text="Hole margin:" VerticalAlignment="Center"/> <NumericUpDown Grid.Row="0" Grid.Column="14" ClipValueToMinMax="True" @@ -230,25 +230,16 @@ Minimum="1" Maximum="100" FormatString="F02" - Value="{Binding Operation.CylinderMargin}"/> + Value="{Binding Operation.HoleMargin}"/> <TextBlock Grid.Row="0" Grid.Column="16" VerticalAlignment="Center" Text="mm"/> <TextBlock Grid.Row="2" Grid.Column="0" - Text="Shape:" - VerticalAlignment="Center"/> - - <ComboBox Grid.Row="2" Grid.Column="2" - HorizontalAlignment="Stretch" - Items="{Binding Operation.ShapesItems}" - SelectedItem="{Binding Operation.Shape}"/> - - <TextBlock Grid.Row="2" Grid.Column="6" Text="Unit of measure:" VerticalAlignment="Center"/> - <ComboBox Grid.Row="2" Grid.Column="8" + <ComboBox Grid.Row="2" Grid.Column="2" HorizontalAlignment="Stretch" Items="{Binding Operation.MeasuresItems}" SelectedItem="{Binding Operation.UnitOfMeasure}"/> @@ -263,12 +254,12 @@ <TextBox Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="13" IsVisible="{Binding Operation.IsUnitOfMeasureMm}" - Text="{Binding Operation.CylinderDiametersMm}"/> + Text="{Binding Operation.HoleDiametersMm}"/> <TextBox Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="13" IsVisible="{Binding !Operation.IsUnitOfMeasureMm}" - Text="{Binding Operation.CylinderDiametersPx}"/> + Text="{Binding Operation.HoleDiametersPx}"/> <TextBlock Grid.Row="4" Grid.Column="16" IsVisible="{Binding Operation.IsUnitOfMeasureMm}" @@ -585,7 +576,7 @@ Multiplier: Current exposure * layer height * step * test number." <Image Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Top" - MaxHeight="800" + MaxHeight="600" Stretch="Uniform" Source="{Binding PreviewImage}"/> </Grid> diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs index c5be0cf..e92c190 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs @@ -8,6 +8,7 @@ using Avalonia.Threading; using DynamicData; using MessageBox.Avalonia.Enums; using UVtools.Core.FileFormats; +using UVtools.Core.Objects; using UVtools.Core.Operations; using UVtools.WPF.Controls.Tools; using UVtools.WPF.Extensions; @@ -72,10 +73,13 @@ namespace UVtools.WPF.Controls.Calibrators { var layers = Operation.GetLayers(); _previewImage?.Dispose(); - PreviewImage = layers[^1].ToBitmap(); - foreach (var layer in layers) + if (layers is not null) { - layer.Dispose(); + PreviewImage = layers[^1].ToBitmap(); + foreach (var layer in layers) + { + layer.Dispose(); + } } } @@ -130,7 +134,7 @@ namespace UVtools.WPF.Controls.Calibrators $"Are you sure you want to remove the {_exposureTable.SelectedItems.Count} selected entries?" ) != ButtonResult.Yes) return; - Operation.ExposureTable.RemoveMany(_exposureTable.SelectedItems.Cast<OperationCalibrateExposureFinder.ExposureItem>()); + Operation.ExposureTable.RemoveMany(_exposureTable.SelectedItems.Cast<ExposureItem>()); } } } diff --git a/UVtools.WPF/Structures/OperationProfiles.cs b/UVtools.WPF/Structures/OperationProfiles.cs index 5796fe8..6300e69 100644 --- a/UVtools.WPF/Structures/OperationProfiles.cs +++ b/UVtools.WPF/Structures/OperationProfiles.cs @@ -47,6 +47,7 @@ namespace UVtools.WPF.Structures [XmlElement(typeof(OperationResize))] [XmlElement(typeof(OperationRotate))] [XmlElement(typeof(OperationThreshold))] + [XmlElement(typeof(OperationCalibrateExposureFinder))] [XmlElement(typeof(OperationCalibrateElephantFoot))] [XmlElement(typeof(OperationCalibrateXYZAccuracy))] [XmlElement(typeof(OperationCalibrateTolerance))] diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 45fa8f8..06daa35 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <RepositoryType>Git</RepositoryType> - <Version>2.4.0</Version> + <Version>2.4.1</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |