mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-09 01:52:32 +02:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 195 B |
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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))]
|
||||
|
||||
@@ -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'">
|
||||
|
||||
Reference in New Issue
Block a user