From de3d15f4c99a2595a50f56e2ef636ce7eb4fd064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Tue, 8 Dec 2020 03:30:02 +0000 Subject: [PATCH] v1.4.0 * (Add) Tool - Raft relief: Relief raft by adding holes in between to reduce FEP suction, save resin and easier to remove the prints. --- CHANGELOG.md | 4 + UVtools.Core/Layer/LayerManager.cs | 102 ++++++++++++++- .../Operations/OperationRaftRelief.cs | 116 ++++++++++++++++++ UVtools.Core/UVtools.Core.csproj | 2 +- UVtools.WPF/Assets/Icons/dot-circle-16x16.png | Bin 0 -> 195 bytes .../Tools/ToolRaftReliefControl.axaml | 95 ++++++++++++++ .../Tools/ToolRaftReliefControl.axaml.cs | 21 ++++ UVtools.WPF/MainWindow.axaml.cs | 11 ++ UVtools.WPF/Structures/OperationProfiles.cs | 1 + UVtools.WPF/UVtools.WPF.csproj | 2 +- 10 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 UVtools.Core/Operations/OperationRaftRelief.cs create mode 100644 UVtools.WPF/Assets/Icons/dot-circle-16x16.png create mode 100644 UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml create mode 100644 UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index c2d3ba6..c655792 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 04/11/2020 - v1.4.0 + +* (Add) Tool - Raft relief: Relief raft by adding holes in between to reduce FEP suction, save resin and easier to remove the prints. + ## 04/11/2020 - v1.3.5 * (Add) Pixel Dimming: Chamfer - Allow the number of walls pixels to be gradually varied as the operation progresses from the starting layer to the ending layer (#106) diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index 95f41a4..38dd145 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -540,8 +540,6 @@ namespace UVtools.Core out var maxIteration ); - Debug.WriteLine($"Steps: {iterationSteps}, Max iteration: {maxIteration}"); - Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, //new ParallelOptions {MaxDegreeOfParallelism = 1}, layerIndex => @@ -709,6 +707,106 @@ namespace UVtools.Core progress.Token.ThrowIfCancellationRequested(); }*/ + public void RaftRelief(OperationRaftRelief operation, OperationProgress progress) + { + const uint minLength = 5; + if (progress is null) progress = new OperationProgress(); + //progress.Reset(operation.ProgressAction); + + Mat supportsMat = null; + + uint firstSupportLayerIndex = 0; + for (; firstSupportLayerIndex < Count; firstSupportLayerIndex++) + { + progress.Reset("Tracing raft", Count, firstSupportLayerIndex); + if (progress.Token.IsCancellationRequested) return; + supportsMat = operation.GetRoiOrDefault(this[firstSupportLayerIndex].LayerMat); + var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.Gradient, 1, 20, 100, 30, 5, 200); + if (circles.Length >= minLength) break; + + supportsMat.Dispose(); + supportsMat = null; + } + + if (supportsMat is null) return; + Mat patternMat = null; + + switch (operation.ReliefType) + { + case OperationRaftRelief.RaftReliefTypes.Relief: + patternMat = EmguExtensions.InitMat(supportsMat.Size); + int shapeSize = operation.HoleDiameter + operation.HoleSpacing; + using (var shape = EmguExtensions.InitMat(new Size(shapeSize, shapeSize))) + { + + int center = operation.HoleDiameter / 2; + int centerTwo = operation.HoleDiameter + operation.HoleSpacing + operation.HoleDiameter / 2; + int radius = center; + CvInvoke.Circle(shape, new Point(shapeSize / 2, shapeSize / 2), radius, EmguExtensions.WhiteByte, -1); + CvInvoke.Circle(shape, new Point(0, 0), radius / 2, EmguExtensions.WhiteByte, -1); + CvInvoke.Circle(shape, new Point(0, shapeSize), radius / 2, EmguExtensions.WhiteByte, -1); + CvInvoke.Circle(shape, new Point(shapeSize, 0), radius / 2, EmguExtensions.WhiteByte, -1); + CvInvoke.Circle(shape, new Point(shapeSize, shapeSize), radius / 2, EmguExtensions.WhiteByte, -1); + + //shape.Save("D:\\shape.png"); + + CvInvoke.Repeat(shape, supportsMat.Height / shape.Height + 1, supportsMat.Width / shape.Width + 1, patternMat); + + + patternMat = new Mat(patternMat, new Rectangle(0, 0, supportsMat.Width, supportsMat.Height)); + } + + break; + case OperationRaftRelief.RaftReliefTypes.Decimate: + if (operation.DilateIterations <= 0) break; + CvInvoke.Dilate(supportsMat, supportsMat, + CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(3, 3), new Point(-1, -1)), + new Point(-1, -1), operation.DilateIterations, BorderType.Reflect101, new MCvScalar()); + break; + } + + progress.Reset(operation.ProgressAction, firstSupportLayerIndex); + Parallel.For(0, firstSupportLayerIndex, layerIndex => + { + using (Mat dst = this[layerIndex].LayerMat) + { + var target = operation.GetRoiOrDefault(dst); + + switch (operation.ReliefType) + { + case OperationRaftRelief.RaftReliefTypes.Relief: + using (Mat mask = new Mat()) + { + CvInvoke.Subtract(target, supportsMat, mask); + //target.CopyTo(mask); + CvInvoke.Erode(mask, mask, + CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), + new Point(-1, -1)), + new Point(-1, -1), operation.WallMargin, BorderType.Reflect101, new MCvScalar()); + CvInvoke.Subtract(target, patternMat, target, mask); + } + + break; + case OperationRaftRelief.RaftReliefTypes.Decimate: + supportsMat.CopyTo(target); + break; + } + + + this[layerIndex].LayerMat = dst; + } + + lock (progress.Mutex) + { + progress++; + } + }); + + + supportsMat.Dispose(); + patternMat?.Dispose(); + } + public void Arithmetic(OperationArithmetic operation, OperationProgress progress = null) { if (!operation.IsValid) return; diff --git a/UVtools.Core/Operations/OperationRaftRelief.cs b/UVtools.Core/Operations/OperationRaftRelief.cs new file mode 100644 index 0000000..55ce521 --- /dev/null +++ b/UVtools.Core/Operations/OperationRaftRelief.cs @@ -0,0 +1,116 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ + +using System; + +namespace UVtools.Core.Operations +{ + [Serializable] + public class OperationRaftRelief : Operation + { + private RaftReliefTypes _reliefType = RaftReliefTypes.Relief; + private byte _dilateIterations = 10; + private byte _wallMargin = 10; + private byte _holeDiameter = 50; + private byte _holeSpacing = 20; + public override string Title => "Raft relief"; + public override string Description => + "Relief raft by adding holes in between to reduce FEP suction, save resin and easier to remove the prints."; + + public override string ConfirmationText => + $"relief the raft"; + + public override string ProgressTitle => + $"Relieving raft"; + + public override string ProgressAction => "Relieved layers"; + + public override Enumerations.LayerRangeSelection StartLayerRangeSelection => + Enumerations.LayerRangeSelection.None; + + + public OperationRaftRelief() + { + } + + public override string ToString() + { + var result = $"[{_reliefType}] [Dilate: {_dilateIterations}] [Wall margin: {_wallMargin}] [Hole diameter: {_holeDiameter}] [Hole spacing: {_holeSpacing}]"; + if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}"; + return result; + } + + public enum RaftReliefTypes : byte + { + Relief, + Decimate + } + + public static Array RaftReliefItems => Enum.GetValues(typeof(RaftReliefTypes)); + + public RaftReliefTypes ReliefType + { + get => _reliefType; + set => RaiseAndSetIfChanged(ref _reliefType, value); + } + + public byte DilateIterations + { + get => _dilateIterations; + set => RaiseAndSetIfChanged(ref _dilateIterations, value); + } + + public byte WallMargin + { + get => _wallMargin; + set => RaiseAndSetIfChanged(ref _wallMargin, value); + } + + public byte HoleDiameter + { + get => _holeDiameter; + set => RaiseAndSetIfChanged(ref _holeDiameter, value); + } + + public byte HoleSpacing + { + get => _holeSpacing; + set => RaiseAndSetIfChanged(ref _holeSpacing, value); + } + + #region Equality + + protected bool Equals(OperationRaftRelief other) + { + return _reliefType == other._reliefType && _dilateIterations == other._dilateIterations && _holeDiameter == other._holeDiameter && _holeSpacing == other._holeSpacing && _wallMargin == other._wallMargin; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((OperationRaftRelief) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (int) _reliefType; + hashCode = (hashCode * 397) ^ _dilateIterations.GetHashCode(); + hashCode = (hashCode * 397) ^ _holeDiameter.GetHashCode(); + hashCode = (hashCode * 397) ^ _holeSpacing.GetHashCode(); + hashCode = (hashCode * 397) ^ _wallMargin.GetHashCode(); + return hashCode; + } + } + + #endregion + } +} diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 566debb..2d8dfab 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, repair, conversion and manipulation - 1.3.5 + 1.4.0 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 diff --git a/UVtools.WPF/Assets/Icons/dot-circle-16x16.png b/UVtools.WPF/Assets/Icons/dot-circle-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..d86c0b5fc55ed9b7350a2028ed86167f7b94fe20 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6x;$MRLn;_sCp5CM7z((`A2>8^ zl9ZSSyJHlmSdh=0FB8lz`Q`~c&yRU`kGa0*r=Z;&7NMg)EZ*Gn&Iwq{Jxr_lnD$6Q zTK1UZZ9Nmdj{b|MugEBR?>Vp|Wzxb^2Ro;PX%y8dnX+Cw-^KFqXI^k|!{l=}Zde-r uDLeT8ch*7OyS&E_IjRJo_1R)l$-J_D#oD=CIz~WOF?hQAxvX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml.cs new file mode 100644 index 0000000..aa333eb --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml.cs @@ -0,0 +1,21 @@ +using Avalonia.Markup.Xaml; +using UVtools.Core.Operations; + +namespace UVtools.WPF.Controls.Tools +{ + public class ToolRaftReliefControl : ToolControl + { + public OperationRaftRelief Operation => BaseOperation as OperationRaftRelief; + + public ToolRaftReliefControl() + { + this.InitializeComponent(); + BaseOperation = new OperationRaftRelief(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 6cde099..9123232 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -119,6 +119,14 @@ namespace UVtools.WPF } }, new MenuItem + { + Tag = new OperationRaftRelief(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/dot-circle-16x16.png")) + } + }, + new MenuItem { Tag = new OperationThreshold(), Icon = new Avalonia.Controls.Image @@ -1268,6 +1276,9 @@ namespace UVtools.WPF case OperationMorph operation: SlicerFile.LayerManager.Morph(operation, BorderType.Default, new MCvScalar(), ProgressWindow.RestartProgress(operation.CanCancel)); break; + case OperationRaftRelief operation: + SlicerFile.LayerManager.RaftRelief(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; case OperationThreshold operation: SlicerFile.LayerManager.ThresholdPixels(operation, ProgressWindow.RestartProgress(operation.CanCancel)); break; diff --git a/UVtools.WPF/Structures/OperationProfiles.cs b/UVtools.WPF/Structures/OperationProfiles.cs index 8dd604e..1ce9503 100644 --- a/UVtools.WPF/Structures/OperationProfiles.cs +++ b/UVtools.WPF/Structures/OperationProfiles.cs @@ -30,6 +30,7 @@ namespace UVtools.WPF.Structures //[XmlElement(typeof(OperationLayerRemove))] //[XmlElement(typeof(OperationMask))] [XmlElement(typeof(OperationMorph))] + [XmlElement(typeof(OperationRaftRelief))] //[XmlElement(typeof(OperationMove))] //[XmlElement(typeof(OperationPattern))] [XmlElement(typeof(OperationPixelDimming))] diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 70be849..22d8777 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ LICENSE https://github.com/sn4k3/UVtools Git - 1.3.5 + 1.4.0