Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2020-10-13 04:04:05 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2020-10-13 04:04:05 +0300
commit1a0229a654c49385d9c757383d30f0d38882d3d7 (patch)
tree66deae60c2715c3c59df2e39a667f772fe9654cf
parent4721a525653789f44615c7fe19433c570077a352 (diff)
v0.8.4.3v0.8.4.3
* (Add) Tool - Layer repair: Allow remove islands recursively (#74) * (Fix) Pixel Editor: Cursor dimentions when using brushes with thickness > 1 (#73)
-rw-r--r--CHANGELOG.md5
-rw-r--r--README.md8
-rw-r--r--UVtools.Core/Layer/LayerIssue.cs38
-rw-r--r--UVtools.Core/Layer/LayerManager.cs81
-rw-r--r--UVtools.Core/Operations/OperationRepairLayers.cs56
-rw-r--r--UVtools.Core/UVtools.Core.csproj6
-rw-r--r--UVtools.GUI/App.config6
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.Designer.cs62
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs2
-rw-r--r--UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.resx14
-rw-r--r--UVtools.GUI/FrmMain.cs9
-rw-r--r--UVtools.GUI/Properties/AssemblyInfo.cs4
-rw-r--r--UVtools.GUI/Properties/Settings.Designer.cs12
-rw-r--r--UVtools.GUI/Properties/Settings.settings3
-rw-r--r--UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml89
-rw-r--r--UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs4
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs1
-rw-r--r--UVtools.WPF/UserSettings.cs43
-rw-r--r--UVtools.WPF/Windows/SettingsWindow.axaml58
19 files changed, 409 insertions, 92 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6121d9f..85ae86c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,11 @@
* (Improvement) GUI is now scalable
* (Fix) Some bug found and fixed during convertion
+## 13/10/2020 - v0.8.4.3
+
+* (Add) Tool - Layer repair: Allow remove islands recursively (#74)
+* (Fix) Pixel Editor: Cursor dimentions when using brushes with thickness > 1 (#73)
+
## 10/10/2020 - v0.8.4.2
* (Fix) pws and pw0: Error when try to save or copy to clipboard the slicer information / properties
diff --git a/README.md b/README.md
index 2042ceb..8a6c734 100644
--- a/README.md
+++ b/README.md
@@ -190,15 +190,21 @@ The current public build will only work in windows.**
<!---
* Donwload and install: https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.402-macos-x64-installer
+brew install libjpeg libpng libgeotiff libdc1394 ffmpeg openexr tbb
-->
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew analytics off
-brew install libjpeg libpng libgeotiff libdc1394 ffmpeg openexr tbb
brew cask install dotnet
```
+To run UVtools open it folder on a terminal and call one of:
+
+* `dotnet UVtools.dll`
+* `sh UVtools.sh`
+* As a pratical alternative you can create a shortcut on Desktop
+
## How to use
There are multiple ways to open your file:
diff --git a/UVtools.Core/Layer/LayerIssue.cs b/UVtools.Core/Layer/LayerIssue.cs
index bba9c2c..ef93c20 100644
--- a/UVtools.Core/Layer/LayerIssue.cs
+++ b/UVtools.Core/Layer/LayerIssue.cs
@@ -14,6 +14,24 @@ namespace UVtools.Core
{
#region LayerIssue Class
+ public class IssuesDetectionConfiguration
+ {
+ public IslandDetectionConfiguration IslandConfig { get; }
+ public OverhangDetectionConfiguration OverhangConfig { get; }
+ public ResinTrapDetectionConfiguration ResinTrapConfig { get; }
+ public TouchingBoundDetectionConfiguration TouchingBoundConfig { get; }
+ public bool EmptyLayerConfig { get; }
+
+ public IssuesDetectionConfiguration(IslandDetectionConfiguration islandConfig, OverhangDetectionConfiguration overhangConfig, ResinTrapDetectionConfiguration resinTrapConfig, TouchingBoundDetectionConfiguration touchingBoundConfig, bool emptyLayerConfig)
+ {
+ IslandConfig = islandConfig;
+ OverhangConfig = overhangConfig;
+ ResinTrapConfig = resinTrapConfig;
+ TouchingBoundConfig = touchingBoundConfig;
+ EmptyLayerConfig = emptyLayerConfig;
+ }
+ }
+
public class IslandDetectionConfiguration
{
/// <summary>
@@ -60,6 +78,11 @@ namespace UVtools.Core
/// will be considered..
/// </summary>
public bool AllowDiagonalBonds { get; set; } = false;
+
+ public IslandDetectionConfiguration(bool enabled = true)
+ {
+ Enabled = enabled;
+ }
}
/// <summary>
@@ -93,6 +116,11 @@ namespace UVtools.Core
/// The survived pixels are potential overhangs.
/// </summary>
public byte ErodeIterations { get; set; } = 40;
+
+ public OverhangDetectionConfiguration(bool enabled = true)
+ {
+ Enabled = enabled;
+ }
}
public class ResinTrapDetectionConfiguration
@@ -122,6 +150,11 @@ namespace UVtools.Core
/// Gets the maximum pixel brightness to be a drain pixel (0-150)
/// </summary>
public byte MaximumPixelBrightnessToDrain { get; set; } = 30;
+
+ public ResinTrapDetectionConfiguration(bool enabled = true)
+ {
+ Enabled = enabled;
+ }
}
@@ -136,6 +169,11 @@ namespace UVtools.Core
/// Gets the maximum pixel brightness to be a touching bound
/// </summary>
public byte MaximumPixelBrightness { get; set; } = 200;
+
+ public TouchingBoundDetectionConfiguration(bool enabled = true)
+ {
+ Enabled = enabled;
+ }
}
diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs
index e4d3faa..5e7d5c7 100644
--- a/UVtools.Core/Layer/LayerManager.cs
+++ b/UVtools.Core/Layer/LayerManager.cs
@@ -1348,10 +1348,85 @@ namespace UVtools.Core
public void RepairLayers(OperationRepairLayers operation, OperationProgress progress = null)
{
if(ReferenceEquals(progress, null)) progress = new OperationProgress();
- progress.Reset(operation.ProgressAction, operation.LayerRangeCount);
+
var issues = operation.Issues;
+ // Remove islands
+ if (!ReferenceEquals(issues, null)
+ && !ReferenceEquals(operation.IslandDetectionConfig, null)
+ && operation.RepairIslands
+ && operation.RemoveIslandsBelowEqualPixelCount > 0
+ && operation.RemoveIslandsRecursiveIterations != 1)
+ {
+ progress.Reset("Removed recursive islands", 0);
+ ushort limit = operation.RemoveIslandsRecursiveIterations == 0
+ ? ushort.MaxValue
+ : operation.RemoveIslandsRecursiveIterations;
+
+ var recursiveIssues = issues;
+ ConcurrentBag<uint> islandsToRecompute = null;
+
+ var islandConfig = operation.IslandDetectionConfig;
+ var overhangConfig = new OverhangDetectionConfiguration(false);
+ var touchingBoundsConfig = new TouchingBoundDetectionConfiguration(false);
+ var resinTrapsConfig = new ResinTrapDetectionConfiguration(false);
+ var emptyLayersConfig = false;
+
+ islandConfig.Enabled = true;
+ islandConfig.RequiredAreaToProcessCheck = (byte) Math.Ceiling(operation.RemoveIslandsBelowEqualPixelCount/2m);
+
+ for (uint i = 0; i < limit; i++)
+ {
+ if (i > 0)
+ {
+ /*var whiteList = islandsToRecompute.GroupBy(u => u)
+ .Select(grp => grp.First())
+ .ToList();*/
+ islandConfig.WhiteListLayers = islandsToRecompute.ToList();
+ recursiveIssues = GetAllIssues(islandConfig, overhangConfig, resinTrapsConfig, touchingBoundsConfig, emptyLayersConfig);
+ //Debug.WriteLine(i);
+ }
+
+ var issuesGroup =
+ recursiveIssues
+ .Where(issue => issue.Type == LayerIssue.IssueType.Island &&
+ issue.Pixels.Length <= operation.RemoveIslandsBelowEqualPixelCount)
+ .GroupBy(issue => issue.LayerIndex);
+
+ if (!issuesGroup.Any()) break; // Nothing to process
+ islandsToRecompute = new ConcurrentBag<uint>();
+ Parallel.ForEach(issuesGroup, group =>
+ {
+ if (progress.Token.IsCancellationRequested) return;
+ Layer layer = this[group.Key];
+ Mat image = layer.LayerMat;
+ Span<byte> bytes = image.GetPixelSpan<byte>();
+ foreach (var issue in group)
+ {
+ foreach (var issuePixel in issue.Pixels)
+ {
+ bytes[image.GetPixelPos(issuePixel)] = 0;
+ }
+
+ lock (progress.Mutex)
+ {
+ progress++;
+ }
+ }
+
+ var nextLayerIndex = group.Key + 1;
+ if(nextLayerIndex < Count)
+ islandsToRecompute.Add(nextLayerIndex);
+
+ layer.LayerMat = image;
+ });
+
+ if (islandsToRecompute.IsEmpty) break; // No more leftovers
+ }
+ }
+
+ progress.Reset(operation.ProgressAction, operation.LayerRangeCount);
if (operation.RepairIslands || operation.RepairResinTraps)
{
Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd, layerIndex =>
@@ -1362,13 +1437,13 @@ namespace UVtools.Core
void initImage()
{
- if(ReferenceEquals(image, null))
+ if(image is null)
image = layer.LayerMat;
}
if (!ReferenceEquals(issues, null))
{
- if (operation.RepairIslands && operation.RemoveIslandsBelowEqualPixelCount > 0)
+ if (operation.RepairIslands && operation.RemoveIslandsBelowEqualPixelCount > 0 && operation.RemoveIslandsRecursiveIterations == 1)
{
Span<byte> bytes = null;
foreach (var issue in issues)
diff --git a/UVtools.Core/Operations/OperationRepairLayers.cs b/UVtools.Core/Operations/OperationRepairLayers.cs
index 4291576..e004682 100644
--- a/UVtools.Core/Operations/OperationRepairLayers.cs
+++ b/UVtools.Core/Operations/OperationRepairLayers.cs
@@ -14,6 +14,13 @@ namespace UVtools.Core.Operations
{
public class OperationRepairLayers : Operation
{
+ private bool _repairIslands = true;
+ private bool _repairResinTraps = true;
+ private bool _removeEmptyLayers = true;
+ private byte _removeIslandsBelowEqualPixelCount = 5;
+ private ushort _removeIslandsRecursiveIterations = 4;
+ private uint _gapClosingIterations = 1;
+ private uint _noiseRemovalIterations = 0;
public override bool CanROI { get; set; } = false;
public override string Title => "Repair layers and issues";
public override string Description => null;
@@ -37,12 +44,49 @@ namespace UVtools.Core.Operations
return new StringTag(sb.ToString());
}
- public bool RepairIslands { get; set; } = true;
- public bool RepairResinTraps { get; set; } = true;
- public bool RemoveEmptyLayers { get; set; } = true;
- public byte RemoveIslandsBelowEqualPixelCount { get; set; } = 5;
- public uint GapClosingIterations { get; set; } = 1;
- public uint NoiseRemovalIterations { get; set; } = 0;
+ public bool RepairIslands
+ {
+ get => _repairIslands;
+ set => RaiseAndSetIfChanged(ref _repairIslands, value);
+ }
+
+ public bool RepairResinTraps
+ {
+ get => _repairResinTraps;
+ set => RaiseAndSetIfChanged(ref _repairResinTraps, value);
+ }
+
+ public bool RemoveEmptyLayers
+ {
+ get => _removeEmptyLayers;
+ set => RaiseAndSetIfChanged(ref _removeEmptyLayers, value);
+ }
+
+ public byte RemoveIslandsBelowEqualPixelCount
+ {
+ get => _removeIslandsBelowEqualPixelCount;
+ set => RaiseAndSetIfChanged(ref _removeIslandsBelowEqualPixelCount, value);
+ }
+
+ public ushort RemoveIslandsRecursiveIterations
+ {
+ get => _removeIslandsRecursiveIterations;
+ set => RaiseAndSetIfChanged(ref _removeIslandsRecursiveIterations, value);
+ }
+
+ public uint GapClosingIterations
+ {
+ get => _gapClosingIterations;
+ set => RaiseAndSetIfChanged(ref _gapClosingIterations, value);
+ }
+
+ public uint NoiseRemovalIterations
+ {
+ get => _noiseRemovalIterations;
+ set => RaiseAndSetIfChanged(ref _noiseRemovalIterations, value);
+ }
+
+ public IslandDetectionConfiguration IslandDetectionConfig { get; set; }
public List<LayerIssue> Issues { get; set; }
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 786f667..3e9ed20 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,12 +10,12 @@
<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>0.8.4.2</Version>
+ <Version>0.8.4.3</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
- <AssemblyVersion>0.8.4.2</AssemblyVersion>
- <FileVersion>0.8.4.2</FileVersion>
+ <AssemblyVersion>0.8.4.3</AssemblyVersion>
+ <FileVersion>0.8.4.3</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
diff --git a/UVtools.GUI/App.config b/UVtools.GUI/App.config
index cea47d0..cc2e5e9 100644
--- a/UVtools.GUI/App.config
+++ b/UVtools.GUI/App.config
@@ -216,7 +216,8 @@
<setting name="LayerRepairRemoveEmptyLayers" serializeAs="String">
<value>True</value>
</setting>
- <setting name="LayerRepairRemoveIslandsBelowEqualPixelsDefault" serializeAs="String">
+ <setting name="LayerRepairRemoveIslandsBelowEqualPixelsDefault"
+ serializeAs="String">
<value>10</value>
</setting>
<setting name="PartialUpdateIslandsOnEditing" serializeAs="String">
@@ -267,6 +268,9 @@
<setting name="OverhangIndependentFromIslands" serializeAs="String">
<value>True</value>
</setting>
+ <setting name="LayerRepairRemoveIslandsRecursiveIterations" serializeAs="String">
+ <value>4</value>
+ </setting>
</UVtools.GUI.Properties.Settings>
</userSettings>
</configuration>
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.Designer.cs
index cd08105..24b0fe2 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.Designer.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.Designer.cs
@@ -40,10 +40,14 @@
this.cbRemoveEmptyLayers = new System.Windows.Forms.CheckBox();
this.cbRepairResinTraps = new System.Windows.Forms.CheckBox();
this.cbRepairIslands = new System.Windows.Forms.CheckBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this.nmRemoveIslandsRecursiveIterations = new System.Windows.Forms.NumericUpDown();
+ this.label5 = new System.Windows.Forms.Label();
this.groupAdvancedSettings.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nmOpeningIterations)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmClosingIterations)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmRemoveIslandsBelowEqualPixels)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmRemoveIslandsRecursiveIterations)).BeginInit();
this.SuspendLayout();
//
// groupAdvancedSettings
@@ -52,7 +56,7 @@
this.groupAdvancedSettings.Controls.Add(this.label1);
this.groupAdvancedSettings.Controls.Add(this.nmClosingIterations);
this.groupAdvancedSettings.Controls.Add(this.lbIterationsStart);
- this.groupAdvancedSettings.Location = new System.Drawing.Point(3, 87);
+ this.groupAdvancedSettings.Location = new System.Drawing.Point(3, 111);
this.groupAdvancedSettings.Name = "groupAdvancedSettings";
this.groupAdvancedSettings.Size = new System.Drawing.Size(601, 110);
this.groupAdvancedSettings.TabIndex = 31;
@@ -106,7 +110,7 @@
// label3
//
this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(319, 46);
+ this.label3.Location = new System.Drawing.Point(341, 46);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(25, 20);
this.label3.TabIndex = 30;
@@ -117,15 +121,16 @@
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 46);
this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(250, 20);
+ this.label2.Size = new System.Drawing.Size(276, 20);
this.label2.TabIndex = 29;
- this.label2.Text = "Do not remove islands larger than:";
+ this.label2.Text = "Remove islands equal or smaller than:";
this.toolTip.SetToolTip(this.label2, "The pixel area theshold above which islands will not be removed by this repair. " +
- " Islands remaining after repair will require supports to be added manually.");
+ " Islands remaining after repair will require supports to be added manually.\r\n0 =" +
+ " Disable: Do not remove any island");
//
// nmRemoveIslandsBelowEqualPixels
//
- this.nmRemoveIslandsBelowEqualPixels.Location = new System.Drawing.Point(259, 43);
+ this.nmRemoveIslandsBelowEqualPixels.Location = new System.Drawing.Point(281, 43);
this.nmRemoveIslandsBelowEqualPixels.Maximum = new decimal(new int[] {
255,
0,
@@ -135,7 +140,8 @@
this.nmRemoveIslandsBelowEqualPixels.Size = new System.Drawing.Size(58, 26);
this.nmRemoveIslandsBelowEqualPixels.TabIndex = 28;
this.toolTip.SetToolTip(this.nmRemoveIslandsBelowEqualPixels, "The pixel area theshold above which islands will not be removed by this repair. " +
- " Islands remaining after repair will require supports to be added manually.");
+ " Islands remaining after repair will require supports to be added manually.\r\n0 =" +
+ " Disable: Do not remove any island\r\n");
//
// cbRemoveEmptyLayers
//
@@ -179,12 +185,46 @@
" area removal threshold, and then runs the “gap closure” technique.\r\n");
this.cbRepairIslands.UseVisualStyleBackColor = true;
//
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(3, 77);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(265, 20);
+ this.label4.TabIndex = 32;
+ this.label4.Text = "Recursively remove islands for up to:";
+ this.toolTip.SetToolTip(this.label4, resources.GetString("label4.ToolTip"));
+ //
+ // nmRemoveIslandsRecursiveIterations
+ //
+ this.nmRemoveIslandsRecursiveIterations.Location = new System.Drawing.Point(281, 74);
+ this.nmRemoveIslandsRecursiveIterations.Maximum = new decimal(new int[] {
+ 65535,
+ 0,
+ 0,
+ 0});
+ this.nmRemoveIslandsRecursiveIterations.Name = "nmRemoveIslandsRecursiveIterations";
+ this.nmRemoveIslandsRecursiveIterations.Size = new System.Drawing.Size(58, 26);
+ this.nmRemoveIslandsRecursiveIterations.TabIndex = 33;
+ this.toolTip.SetToolTip(this.nmRemoveIslandsRecursiveIterations, resources.GetString("nmRemoveIslandsRecursiveIterations.ToolTip"));
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(341, 77);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(50, 20);
+ this.label5.TabIndex = 34;
+ this.label5.Text = "layers";
+ //
// CtrlToolRepairLayers
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
- this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.Controls.Add(this.label5);
+ this.Controls.Add(this.nmRemoveIslandsRecursiveIterations);
+ this.Controls.Add(this.label4);
this.Controls.Add(this.groupAdvancedSettings);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
@@ -197,12 +237,13 @@
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.LayerRangeVisible = false;
this.Name = "CtrlToolRepairLayers";
- this.Size = new System.Drawing.Size(607, 200);
+ this.Size = new System.Drawing.Size(607, 224);
this.groupAdvancedSettings.ResumeLayout(false);
this.groupAdvancedSettings.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nmOpeningIterations)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nmClosingIterations)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nmRemoveIslandsBelowEqualPixels)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nmRemoveIslandsRecursiveIterations)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -221,5 +262,8 @@
private System.Windows.Forms.CheckBox cbRemoveEmptyLayers;
private System.Windows.Forms.CheckBox cbRepairResinTraps;
private System.Windows.Forms.CheckBox cbRepairIslands;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.NumericUpDown nmRemoveIslandsRecursiveIterations;
+ private System.Windows.Forms.Label label5;
}
}
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs
index c8fe8a9..f63bd8d 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs
+++ b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.cs
@@ -25,6 +25,7 @@ namespace UVtools.GUI.Controls.Tools
cbRepairResinTraps.Checked = Properties.Settings.Default.LayerRepairResinTraps;
cbRemoveEmptyLayers.Checked = Properties.Settings.Default.LayerRepairRemoveEmptyLayers;
nmRemoveIslandsBelowEqualPixels.Value = Properties.Settings.Default.LayerRepairRemoveIslandsBelowEqualPixelsDefault;
+ nmRemoveIslandsRecursiveIterations.Value = Properties.Settings.Default.LayerRepairRemoveIslandsRecursiveIterations;
nmClosingIterations.Value = Properties.Settings.Default.LayerRepairDefaultClosingIterations;
nmOpeningIterations.Value = Properties.Settings.Default.LayerRepairDefaultOpeningIterations;
@@ -39,6 +40,7 @@ namespace UVtools.GUI.Controls.Tools
Operation.RepairResinTraps = cbRepairResinTraps.Checked;
Operation.RemoveEmptyLayers = cbRemoveEmptyLayers.Checked;
Operation.RemoveIslandsBelowEqualPixelCount = (byte) nmRemoveIslandsBelowEqualPixels.Value;
+ Operation.RemoveIslandsRecursiveIterations = (ushort) nmRemoveIslandsRecursiveIterations.Value;
Operation.GapClosingIterations = (uint) nmClosingIterations.Value;
Operation.NoiseRemovalIterations = (uint) nmOpeningIterations.Value;
diff --git a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.resx b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.resx
index 866a61d..e083b02 100644
--- a/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.resx
+++ b/UVtools.GUI/Controls/Tools/CtrlToolRepairLayers.resx
@@ -131,4 +131,18 @@ WARNING: Even at low settings this operation has the potential to introduce new
Set iterations to 0 to disable.
WARNING: Using high iteration values can destroy your model. Low values recomended.</value>
</data>
+ <data name="label4.ToolTip" xml:space="preserve">
+ <value>If the removal of an island in the current layer results in a new island being introduce in the layer above, the island in the layer above will also be automatically removed.
+This process will repeat for up to the number of layers specified. Set to 0 to repeat until there are no more valid islands to remove.
+
+NOTE: Use with caution as this can remove large portions of your model if proper supports have not been added beforehand.
+ Using this function with high values can be extremely slow depending on resolution and issue count.</value>
+ </data>
+ <data name="nmRemoveIslandsRecursiveIterations.ToolTip" xml:space="preserve">
+ <value>If the removal of an island in the current layer results in a new island being introduce in the layer above, the island in the layer above will also be automatically removed.
+This process will repeat for up to the number of layers specified. Set to 0 to repeat until there are no more valid islands to remove.
+
+NOTE: Use with caution as this can remove large portions of your model if proper supports have not been added beforehand.
+ Using this function with high values can be extremely slow depending on resolution and issue count.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs
index 0f6cd03..e6240de 100644
--- a/UVtools.GUI/FrmMain.cs
+++ b/UVtools.GUI/FrmMain.cs
@@ -4259,6 +4259,7 @@ namespace UVtools.GUI
{
// Tools
case OperationRepairLayers operation:
+ operation.IslandDetectionConfig = GetIslandDetectionConfiguration();
SlicerFile.LayerManager.RepairLayers(operation, FrmLoading.RestartProgress(operation.CanCancel));
break;
case OperationMove operation:
@@ -4378,7 +4379,9 @@ namespace UVtools.GUI
? 1
: nmPixelEditorDrawingThickness.Value);
- int diameter = (brushSize * pbLayer.Zoom / 100);
+
+ var cursorSize = thickness > 1 ? brushSize + thickness : brushSize;
+ int diameter = (int) (cursorSize * pbLayer.ZoomFactor);
if (brushSize > 1 && diameter >= _pixelEditorCursorMinDiamater)
{
bitmap = new Bitmap(diameter, diameter, PixelFormat.Format32bppArgb);
@@ -4392,7 +4395,7 @@ namespace UVtools.GUI
case PixelDrawing.BrushShapeType.Rectangle:
if (thickness >= 1)
{
- gr.DrawRectangle(new Pen(_pixelEditorCursorBrush, thickness), 0, 0, diameter, diameter);
+ gr.DrawRectangle(new Pen(_pixelEditorCursorBrush, (int)(thickness * 2 * pbLayer.ZoomFactor)), 0, 0, diameter, diameter);
}
else
{
@@ -4402,7 +4405,7 @@ namespace UVtools.GUI
case PixelDrawing.BrushShapeType.Circle:
if (thickness >= 1)
{
- gr.DrawEllipse(new Pen(_pixelEditorCursorBrush, thickness), 0, 0, diameter, diameter);
+ gr.DrawEllipse(new Pen(_pixelEditorCursorBrush, (int)(thickness * 2 * pbLayer.ZoomFactor)), 0, 0, diameter, diameter);
}
else
{
diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs
index 20c38ad..36d551e 100644
--- a/UVtools.GUI/Properties/AssemblyInfo.cs
+++ b/UVtools.GUI/Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.8.4.2")]
-[assembly: AssemblyFileVersion("0.8.4.2")]
+[assembly: AssemblyVersion("0.8.4.3")]
+[assembly: AssemblyFileVersion("0.8.4.3")]
diff --git a/UVtools.GUI/Properties/Settings.Designer.cs b/UVtools.GUI/Properties/Settings.Designer.cs
index 1e56ae5..1f91fc8 100644
--- a/UVtools.GUI/Properties/Settings.Designer.cs
+++ b/UVtools.GUI/Properties/Settings.Designer.cs
@@ -970,5 +970,17 @@ namespace UVtools.GUI.Properties {
this["OverhangIndependentFromIslands"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("4")]
+ public short LayerRepairRemoveIslandsRecursiveIterations {
+ get {
+ return ((short)(this["LayerRepairRemoveIslandsRecursiveIterations"]));
+ }
+ set {
+ this["LayerRepairRemoveIslandsRecursiveIterations"] = value;
+ }
+ }
}
}
diff --git a/UVtools.GUI/Properties/Settings.settings b/UVtools.GUI/Properties/Settings.settings
index 5cf1017..e25f334 100644
--- a/UVtools.GUI/Properties/Settings.settings
+++ b/UVtools.GUI/Properties/Settings.settings
@@ -239,5 +239,8 @@
<Setting Name="OverhangIndependentFromIslands" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
+ <Setting Name="LayerRepairRemoveIslandsRecursiveIterations" Type="System.Int16" Scope="User">
+ <Value Profile="(Default)">4</Value>
+ </Setting>
</Settings>
</SettingsFile> \ No newline at end of file
diff --git a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml
index 489fb41..e176d9d 100644
--- a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml
+++ b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml
@@ -49,40 +49,93 @@
</CheckBox>
</StackPanel>
- <StackPanel Orientation="Horizontal" Spacing="10">
+ <Grid ColumnDefinitions="Auto,10,Auto,5,Auto"
+ RowDefinitions="Auto,10,Auto">
- <!-- Do not remove islands larger than -->
+ <!-- Remove islands equal or smaller than -->
<TextBlock
- VerticalAlignment="Center"
- Text="Do not remove islands larger than:">
+ Grid.Row="0"
+ Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Remove islands equal or smaller than:">
+ <ToolTip.Tip>
+ <StackPanel>
+ <TextBlock FontWeight="Bold" Text="Remove islands equal or smaller than:"/>
+ <TextBlock Text="The pixel area theshold above which islands will not be removed by this repair.
+ &#x0a;Islands remaining after repair will require supports to be added manually."/>
+ </StackPanel>
+ </ToolTip.Tip>
+ </TextBlock>
+
+ <NumericUpDown
+ Grid.Row="0"
+ Grid.Column="2"
+ Increment="1"
+ Minimum="0"
+ Maximum="255"
+ Width="70"
+ Value="{Binding Operation.RemoveIslandsBelowEqualPixelCount}"
+ >
+ <ToolTip.Tip>
+ <StackPanel>
+ <TextBlock FontWeight="Bold" Text="Remove islands equal or smaller than:"/>
+ <TextBlock Text="The pixel area theshold above which islands will not be removed by this repair.
+&#x0a;Islands remaining after repair will require supports to be added manually."/>
+ </StackPanel>
+ </ToolTip.Tip>
+ </NumericUpDown>
+ <TextBlock
+ Grid.Row="0"
+ Grid.Column="4"
+ VerticalAlignment="Center"
+ Text="px"/>
+
+
+ <!-- Recursively remove islands for up to -->
+ <TextBlock
+ Grid.Row="2"
+ Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Recursively remove islands for up to:">
<ToolTip.Tip>
<StackPanel>
- <TextBlock FontWeight="Bold" Text="Do not remove islands larger than:"/>
- <TextBlock Text="The pixel area theshold above which islands will not be removed by this repair.
-&#x0a;Islands remaining after repair will require supports to be added manually."/>
+ <TextBlock FontWeight="Bold" Text="Recursively remove islands for up to:"/>
+ <TextBlock Text="If the removal of an island in the current layer results in a new island being introduce in the layer above, the island in the layer above will also be automatically removed.
+&#x0a;This process will repeat for up to the number of layers specified. Set to 0 to repeat until there are no more valid islands to remove.
+&#x0a;
+&#x0a;NOTE: Use with caution as this can remove large portions of your model if proper supports have not been added beforehand.
+&#x0a; Using this function with high values can be extremely slow depending on resolution and issue count."/>
</StackPanel>
</ToolTip.Tip>
- </TextBlock>
-
+ </TextBlock>
+
<NumericUpDown
+ Grid.Row="2"
+ Grid.Column="2"
Increment="1"
Minimum="0"
- Maximum="255"
+ Maximum="65535"
Width="70"
- Value="{Binding Operation.RemoveIslandsBelowEqualPixelCount}"
- >
+ Value="{Binding Operation.RemoveIslandsRecursiveIterations}"
+ >
<ToolTip.Tip>
<StackPanel>
- <TextBlock FontWeight="Bold" Text="Do not remove islands larger than:"/>
- <TextBlock Text="The pixel area theshold above which islands will not be removed by this repair.
-&#x0a;Islands remaining after repair will require supports to be added manually."/>
+ <TextBlock FontWeight="Bold" Text="Recursively remove islands for up to:"/>
+ <TextBlock Text="If the removal of an island in the current layer results in a new island being introduce in the layer above, the island in the layer above will also be automatically removed.
+&#x0a;This process will repeat for up to the number of layers specified. Set to 0 to repeat until there are no more valid islands to remove.
+&#x0a;
+&#x0a;NOTE: Use with caution as this can remove large portions of your model if proper supports have not been added beforehand.
+&#x0a; Using this function with high values can be extremely slow depending on resolution and issue count."/>
</StackPanel>
</ToolTip.Tip>
</NumericUpDown>
<TextBlock
- VerticalAlignment="Center"
- Text="px"/>
- </StackPanel>
+ Grid.Row="2"
+ Grid.Column="4"
+ VerticalAlignment="Center"
+ Text="layers"/>
+
+ </Grid>
<Grid
diff --git a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs
index 70fcabe..843c096 100644
--- a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs
@@ -1,5 +1,4 @@
-using System.Diagnostics;
-using Avalonia.Markup.Xaml;
+using Avalonia.Markup.Xaml;
using UVtools.Core.Operations;
using UVtools.WPF.Windows;
@@ -18,6 +17,7 @@ namespace UVtools.WPF.Controls.Tools
RepairResinTraps = UserSettings.Instance.LayerRepair.RepairResinTraps,
RemoveEmptyLayers = UserSettings.Instance.LayerRepair.RemoveEmptyLayers,
RemoveIslandsBelowEqualPixelCount = UserSettings.Instance.LayerRepair.RemoveIslandsBelowEqualPixels,
+ RemoveIslandsRecursiveIterations = UserSettings.Instance.LayerRepair.RemoveIslandsRecursiveIterations,
GapClosingIterations = UserSettings.Instance.LayerRepair.ClosingIterations,
NoiseRemovalIterations = UserSettings.Instance.LayerRepair.OpeningIterations,
};
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index fe78532..1863f08 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -1108,6 +1108,7 @@ namespace UVtools.WPF
{
// Tools
case OperationRepairLayers operation:
+ operation.IslandDetectionConfig = GetIslandDetectionConfiguration();
SlicerFile.LayerManager.RepairLayers(operation, ProgressWindow.RestartProgress(operation.CanCancel));
break;
case OperationMove operation:
diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs
index 1607311..a5e5ca3 100644
--- a/UVtools.WPF/UserSettings.cs
+++ b/UVtools.WPF/UserSettings.cs
@@ -841,23 +841,30 @@ namespace UVtools.WPF
[Serializable]
public sealed class LayerRepairUserSettings : ReactiveObject
{
- private byte _closingIterations = 2;
- private byte _openingIterations = 0;
- private byte _removeIslandsBelowEqualPixels = 10;
private bool _repairIslands = true;
private bool _repairResinTraps = true;
private bool _removeEmptyLayers = true;
+ private byte _removeIslandsBelowEqualPixels = 10;
+ private ushort _removeIslandsRecursiveIterations = 4;
+ private byte _closingIterations = 2;
+ private byte _openingIterations = 0;
- public byte ClosingIterations
+ public bool RepairIslands
{
- get => _closingIterations;
- set => this.RaiseAndSetIfChanged(ref _closingIterations, value);
+ get => _repairIslands;
+ set => this.RaiseAndSetIfChanged(ref _repairIslands, value);
}
- public byte OpeningIterations
+ public bool RepairResinTraps
{
- get => _openingIterations;
- set => this.RaiseAndSetIfChanged(ref _openingIterations, value);
+ get => _repairResinTraps;
+ set => this.RaiseAndSetIfChanged(ref _repairResinTraps, value);
+ }
+
+ public bool RemoveEmptyLayers
+ {
+ get => _removeEmptyLayers;
+ set => this.RaiseAndSetIfChanged(ref _removeEmptyLayers, value);
}
public byte RemoveIslandsBelowEqualPixels
@@ -866,22 +873,22 @@ namespace UVtools.WPF
set => this.RaiseAndSetIfChanged(ref _removeIslandsBelowEqualPixels, value);
}
- public bool RepairIslands
+ public ushort RemoveIslandsRecursiveIterations
{
- get => _repairIslands;
- set => this.RaiseAndSetIfChanged(ref _repairIslands, value);
+ get => _removeIslandsRecursiveIterations;
+ set => this.RaiseAndSetIfChanged(ref _removeIslandsRecursiveIterations, value);
}
- public bool RepairResinTraps
+ public byte ClosingIterations
{
- get => _repairResinTraps;
- set => this.RaiseAndSetIfChanged(ref _repairResinTraps, value);
+ get => _closingIterations;
+ set => this.RaiseAndSetIfChanged(ref _closingIterations, value);
}
- public bool RemoveEmptyLayers
+ public byte OpeningIterations
{
- get => _removeEmptyLayers;
- set => this.RaiseAndSetIfChanged(ref _removeEmptyLayers, value);
+ get => _openingIterations;
+ set => this.RaiseAndSetIfChanged(ref _openingIterations, value);
}
public LayerRepairUserSettings Clone()
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml
index b65d4c9..21a4ca9 100644
--- a/UVtools.WPF/Windows/SettingsWindow.axaml
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml
@@ -951,46 +951,52 @@
BorderBrush="LightBlue"
BorderThickness="4">
- <StackPanel Orientation="Vertical">
+ <StackPanel Orientation="Vertical" Spacing="15">
<TextBlock Padding="10" Background="LightBlue" FontWeight="Bold" Text="Default values"/>
- <StackPanel Orientation="Horizontal" Margin="15" Spacing="10">
+ <CheckBox IsChecked="{Binding Settings.LayerRepair.RepairIslands}"
+ Margin="15,0" Content="Attempt to repair islands by default"/>
+ <CheckBox IsChecked="{Binding Settings.LayerRepair.RepairResinTraps}"
+ Margin="15,0" Content="Remove empty layers by default"/>
+ <CheckBox IsChecked="{Binding Settings.LayerRepair.RemoveEmptyLayers}"
+ Margin="15,0" Content="Attempt to repair resin traps by default"/>
+
+ <StackPanel Orientation="Horizontal" Margin="15,0" Spacing="10">
+ <NumericUpDown
+ Value="{Binding Settings.LayerRepair.RemoveIslandsBelowEqualPixels}"
+ Width="70"
+ Minimum="0"
+ Maximum="255"/>
+ <TextBlock VerticalAlignment="Center" Text="Default maximum pixel area for Island removal (0 = disable)"/>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Margin="15,0" Spacing="10">
+ <NumericUpDown
+ Value="{Binding Settings.LayerRepair.RemoveIslandsRecursiveIterations}"
+ Width="70"
+ Minimum="0"
+ Maximum="65535"/>
+ <TextBlock VerticalAlignment="Center" Text="Default maximum layers for recursive island removal (0 = All)"/>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Margin="15,0" Spacing="10">
<NumericUpDown
Value="{Binding Settings.LayerRepair.ClosingIterations}"
- Width="60"
+ Width="70"
Minimum="0"
- Maximum="255"
- />
+ Maximum="255"/>
<TextBlock VerticalAlignment="Center" Text="Default 'Gap Closing' iterations"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="15,0,15,15" Spacing="10">
- <NumericUpDown
+ <NumericUpDown
Value="{Binding Settings.LayerRepair.OpeningIterations}"
- Width="60"
+ Width="70"
Minimum="0"
- Maximum="255"
- />
+ Maximum="255"/>
<TextBlock VerticalAlignment="Center" Text="Default 'Noise Removal' iterations"/>
</StackPanel>
- <StackPanel Orientation="Horizontal" Margin="15,0,15,15" Spacing="10">
- <NumericUpDown
- Value="{Binding Settings.LayerRepair.RemoveIslandsBelowEqualPixels}"
- Width="60"
- Minimum="0"
- Maximum="255"
- />
- <TextBlock VerticalAlignment="Center" Text="Default maximum pixel area for Island removal (0 = disable)"/>
- </StackPanel>
-
- <CheckBox IsChecked="{Binding Settings.LayerRepair.RepairIslands}"
- Margin="15,0" Content="Attempt to repair islands by default"/>
- <CheckBox IsChecked="{Binding Settings.LayerRepair.RepairResinTraps}"
- Margin="15,15,15,0" Content="Remove empty layers by default"/>
- <CheckBox IsChecked="{Binding Settings.LayerRepair.RemoveEmptyLayers}"
- Margin="15" Content="Attempt to repair resin traps by default"/>
-
</StackPanel>
</Border>