diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-12-08 06:30:02 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-12-08 06:30:02 +0300 |
commit | de3d15f4c99a2595a50f56e2ef636ce7eb4fd064 (patch) | |
tree | 929e5ce12a784d1982b3f0e89a0086bf644698e5 | |
parent | 5c5670f0b123c98ec2a343caf84fa0a96fd2eac1 (diff) |
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.
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | UVtools.Core/Layer/LayerManager.cs | 102 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationRaftRelief.cs | 116 | ||||
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 2 | ||||
-rw-r--r-- | UVtools.WPF/Assets/Icons/dot-circle-16x16.png | bin | 0 -> 195 bytes | |||
-rw-r--r-- | UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml | 95 | ||||
-rw-r--r-- | UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml.cs | 21 | ||||
-rw-r--r-- | UVtools.WPF/MainWindow.axaml.cs | 11 | ||||
-rw-r--r-- | UVtools.WPF/Structures/OperationProfiles.cs | 1 | ||||
-rw-r--r-- | UVtools.WPF/UVtools.WPF.csproj | 2 |
10 files changed, 350 insertions, 4 deletions
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. <https://fsf.org/> + * 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 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description> - <Version>1.3.5</Version> + <Version>1.4.0</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> diff --git a/UVtools.WPF/Assets/Icons/dot-circle-16x16.png b/UVtools.WPF/Assets/Icons/dot-circle-16x16.png Binary files differnew file mode 100644 index 0000000..d86c0b5 --- /dev/null +++ b/UVtools.WPF/Assets/Icons/dot-circle-16x16.png diff --git a/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml b/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml new file mode 100644 index 0000000..3acf2cc --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml @@ -0,0 +1,95 @@ +<UserControl xmlns="https://github.com/avaloniaui" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + x:Class="UVtools.WPF.Controls.Tools.ToolRaftReliefControl"> + + + <Grid + ColumnDefinitions="Auto,10,Auto,5,Auto" + RowDefinitions="Auto,10,Auto,Auto,10,Auto,10,Auto" + > + + <TextBlock Text="Relief type:" VerticalAlignment="Center"/> + <ComboBox + Name="ReliefType" + Grid.Column="2" + Width="100" + SelectedItem="{Binding Operation.ReliefType}" + Items="{Binding Operation.RaftReliefItems}"/> + + <TextBlock + Grid.Row="2" + ToolTip.Tip="Raft will be replaced by the present supports and then dilated by this value. +
Use large numbers with tiny supports for best adhesion." + Text="Dilate supports by:" VerticalAlignment="Center" + IsVisible="{Binding #ReliefType.SelectedIndex}" + /> + + <NumericUpDown Grid.Row="2" Grid.Column="2" + Width="100" + Minimum="0" + Maximum="255" + Value="{Binding Operation.DilateIterations}" + IsVisible="{Binding #ReliefType.SelectedIndex}"/> + <TextBlock + Grid.Row="2" Grid.Column="4" + Text="px" VerticalAlignment="Center" + IsVisible="{Binding #ReliefType.SelectedIndex}"/> + + + <TextBlock + Grid.Row="3" + Text="Wall margin:" VerticalAlignment="Center" + IsVisible="{Binding !#ReliefType.SelectedIndex}" + /> + + <NumericUpDown Grid.Row="3" Grid.Column="2" + Width="100" + Minimum="1" + Maximum="255" + Value="{Binding Operation.WallMargin}" + IsVisible="{Binding !#ReliefType.SelectedIndex}"/> + <TextBlock + Grid.Row="3" Grid.Column="4" + Text="px" VerticalAlignment="Center" + IsVisible="{Binding !#ReliefType.SelectedIndex}"/> + + <TextBlock + Grid.Row="5" + Text="Hole diameter:" VerticalAlignment="Center" + IsVisible="{Binding !#ReliefType.SelectedIndex}" + /> + + <NumericUpDown Grid.Row="5" Grid.Column="2" + Width="100" + Minimum="10" + Maximum="255" + Value="{Binding Operation.HoleDiameter}" + IsVisible="{Binding !#ReliefType.SelectedIndex}"/> + <TextBlock + Grid.Row="5" Grid.Column="4" + Text="px" VerticalAlignment="Center" + IsVisible="{Binding !#ReliefType.SelectedIndex}"/> + + <TextBlock + Grid.Row="7" + Text="Hole spacing:" VerticalAlignment="Center" + IsVisible="{Binding !#ReliefType.SelectedIndex}" + /> + + <NumericUpDown Grid.Row="7" Grid.Column="2" + Width="100" + Minimum="10" + Maximum="255" + Value="{Binding Operation.HoleSpacing}" + IsVisible="{Binding !#ReliefType.SelectedIndex}"/> + <TextBlock + Grid.Row="7" Grid.Column="4" + Text="px" VerticalAlignment="Center" + IsVisible="{Binding !#ReliefType.SelectedIndex}"/> + + </Grid> + +</UserControl> 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 @@ -120,6 +120,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 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <RepositoryType>Git</RepositoryType> - <Version>1.3.5</Version> + <Version>1.4.0</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |