diff options
Diffstat (limited to 'UVtools.Core/Operations/OperationInfill.cs')
-rw-r--r-- | UVtools.Core/Operations/OperationInfill.cs | 158 |
1 files changed, 109 insertions, 49 deletions
diff --git a/UVtools.Core/Operations/OperationInfill.cs b/UVtools.Core/Operations/OperationInfill.cs index b07ba06..01b3ae9 100644 --- a/UVtools.Core/Operations/OperationInfill.cs +++ b/UVtools.Core/Operations/OperationInfill.cs @@ -33,7 +33,7 @@ namespace UVtools.Core.Operations public override string Title => "Infill"; public override string Description => - $"Generate infill patterns in the model\n\nNOTES:\n1) You must exclude floor and ceil layers from the range.\n2) You must take care of drain holes after the operation."; + $"Generate infill patterns in the model.\n\nNOTES:\n1) You must exclude floor and ceil layers from the range.\n2) You must take care of drain holes after the operation."; public override string ConfirmationText => $"infill model with {InfillType} from layers {LayerIndexStart} through {LayerIndexEnd}?"; @@ -53,6 +53,7 @@ namespace UVtools.Core.Operations CubicCenterLink, CubicDynamicLink, CubicInterlinked, + Honeycomb } #endregion @@ -128,17 +129,23 @@ namespace UVtools.Core.Operations protected override bool ExecuteInternally(OperationProgress progress) { + Mat mask = null; + if (_infillType == InfillAlgorithm.Honeycomb) + { + mask = GetHoneycombMask(GetRoiSizeOrDefault()); + } + Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex => { if (progress.Token.IsCancellationRequested) return; using var mat = SlicerFile[layerIndex].LayerMat; - Execute(mat, layerIndex); + Execute(mat, layerIndex, mask); SlicerFile[layerIndex].LayerMat = mat; progress.LockAndIncrement(); }); - + mask?.Dispose(); return !progress.Token.IsCancellationRequested; } @@ -149,22 +156,22 @@ namespace UVtools.Core.Operations var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); uint index = Convert.ToUInt32(arguments[0]); uint layerIndex = index - LayerIndexStart; - var infillColor = new MCvScalar(InfillBrightness); + var infillColor = new MCvScalar(_infillBrightness); Mat patternMask = null; using Mat erode = new (); using Mat diff = new (); - Mat target = GetRoiOrDefault(mat); + var target = GetRoiOrDefault(mat); using var mask = GetMask(mat); - + bool disposeTargetMask = true; - if (InfillType == InfillAlgorithm.Cubic || - InfillType == InfillAlgorithm.CubicCenterLink || - InfillType == InfillAlgorithm.CubicDynamicLink || - InfillType == InfillAlgorithm.CubicInterlinked) + if (_infillType is InfillAlgorithm.Cubic + or InfillAlgorithm.CubicCenterLink + or InfillAlgorithm.CubicDynamicLink + or InfillAlgorithm.CubicInterlinked) { - using var infillPattern = EmguExtensions.InitMat(new Size(InfillSpacing, InfillSpacing)); - using Mat matPattern = mat.CloneBlank(); + using var infillPattern = EmguExtensions.InitMat(new Size(_infillSpacing, _infillSpacing)); + using var matPattern = mat.CloneBlank(); bool firstPattern = true; uint accumulator = 0; bool dynamicCenter = false; @@ -172,16 +179,16 @@ namespace UVtools.Core.Operations { dynamicCenter = !dynamicCenter; firstPattern = true; - accumulator += InfillSpacing; + accumulator += _infillSpacing; if (accumulator >= layerIndex) break; firstPattern = false; - accumulator += InfillThickness; + accumulator += _infillThickness; } if (firstPattern) { - int thickness = InfillThickness / 2; + int thickness = _infillThickness / 2; // Top Left CvInvoke.Rectangle(infillPattern, new Rectangle(0, 0, thickness, thickness), @@ -207,106 +214,159 @@ namespace UVtools.Core.Operations int margin = (int) (InfillSpacing - accumulator + layerIndex) - thickness; int marginInv = (int) (accumulator - layerIndex) - thickness; - if (InfillType == InfillAlgorithm.CubicCenterLink || - (InfillType == InfillAlgorithm.CubicDynamicLink && + if (_infillType == InfillAlgorithm.CubicCenterLink || + (_infillType == InfillAlgorithm.CubicDynamicLink && dynamicCenter) || - InfillType == InfillAlgorithm.CubicInterlinked) + _infillType == InfillAlgorithm.CubicInterlinked) { CvInvoke.Rectangle(infillPattern, - new Rectangle(margin, margin, InfillThickness, InfillThickness), + new Rectangle(margin, margin, _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(marginInv, marginInv, InfillThickness, - InfillThickness), + new Rectangle(marginInv, marginInv, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(margin, marginInv, InfillThickness, - InfillThickness), + new Rectangle(margin, marginInv, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(marginInv, margin, InfillThickness, - InfillThickness), + new Rectangle(marginInv, margin, _infillThickness, + _infillThickness), infillColor, -1); } - if (InfillType == InfillAlgorithm.CubicInterlinked || - (InfillType == InfillAlgorithm.CubicDynamicLink && + if (_infillType == InfillAlgorithm.CubicInterlinked || + (_infillType == InfillAlgorithm.CubicDynamicLink && !dynamicCenter)) { CvInvoke.Rectangle(infillPattern, - new Rectangle(margin, -thickness, InfillThickness, - InfillThickness), + new Rectangle(margin, -thickness, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(marginInv, -thickness, InfillThickness, - InfillThickness), + new Rectangle(marginInv, -thickness, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(-thickness, margin, InfillThickness, - InfillThickness), + new Rectangle(-thickness, margin, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(-thickness, marginInv, InfillThickness, - InfillThickness), + new Rectangle(-thickness, marginInv, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(InfillSpacing - thickness, margin, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(InfillSpacing - thickness, marginInv, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(margin, InfillSpacing - thickness, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(marginInv, InfillSpacing - thickness, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); } - - } else { CvInvoke.Rectangle(infillPattern, - new Rectangle(0, 0, InfillSpacing, InfillSpacing), - infillColor, InfillThickness); + new Rectangle(0, 0, _infillSpacing, _infillSpacing), + infillColor, _infillThickness); } + CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1, + target.Cols / infillPattern.Cols + 1, matPattern); + patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height)); + disposeTargetMask = true; + } + else if (_infillType == InfillAlgorithm.Honeycomb) + { + if (arguments.Length >= 2) + { + patternMask = (Mat)arguments[1]; + disposeTargetMask = false; + } + else { - CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1, - target.Cols / infillPattern.Cols + 1, matPattern); - patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height)); + patternMask = GetHoneycombMask(target.Size); + disposeTargetMask = true; } } - + //patternMask.Save("D:\\pattern.png"); CvInvoke.Erode(target, erode, kernel, anchor, WallThickness, BorderType.Reflect101, default); CvInvoke.Subtract(target, erode, diff); - + CvInvoke.BitwiseAnd(erode, patternMask, target, mask); CvInvoke.Add(target, diff, target, mask); - patternMask?.Dispose(); + + if (disposeTargetMask) + { + patternMask.Dispose(); + } return true; } + public Mat GetHoneycombMask(Size targetSize) + { + var patternMask = EmguExtensions.InitMat(targetSize); + + var halfInfillSpacing = _infillSpacing / 2; + var halfThickenss = _infillThickness / 2; + int width = (int)Math.Round(4 * (_infillSpacing / 2.0 / Math.Sqrt(3))); + var infillColor = new MCvScalar(_infillBrightness); + + for (int col = 0; col <= targetSize.Width / _infillSpacing; col++) + { + for (int row = 0; row <= targetSize.Height / _infillSpacing; row++) + { + // Move over for the column number. + int x = (int)Math.Round(col * (width * 0.75f)); + + // Move down the required number of rows. + int y = row * _infillSpacing; + + // If the column is odd, move down half a hex more. + if (col % 2 == 1) y += halfInfillSpacing; + + var points = new Point[] + { + new(x, y), + new((int) Math.Round(x + width * 0.25f), y - _infillSpacing / 2), + new((int) Math.Round(x + width * 0.75f), y - _infillSpacing / 2), + new(x + width, y), + new((int) Math.Round(x + width * 0.75f), y + _infillSpacing / 2), + new((int) Math.Round(x + width * 0.25f), y + _infillSpacing / 2), + }; + + CvInvoke.Polylines(patternMask, points, true, infillColor, _infillThickness); + } + } + + return patternMask; + } + #endregion } } |