mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
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)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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'">
|
||||
|
||||
@@ -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>
|
||||
|
||||
+53
-9
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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")]
|
||||
|
||||
+12
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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.
|
||||

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.
|
||||

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.
|
||||

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.
|
||||

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."/>
|
||||
</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.
|
||||

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.
|
||||

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."/>
|
||||
</StackPanel>
|
||||
</ToolTip.Tip>
|
||||
</NumericUpDown>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="px"/>
|
||||
</StackPanel>
|
||||
Grid.Row="2"
|
||||
Grid.Column="4"
|
||||
VerticalAlignment="Center"
|
||||
Text="layers"/>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<Grid
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
+28
-21
@@ -841,30 +841,13 @@ 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;
|
||||
|
||||
public byte ClosingIterations
|
||||
{
|
||||
get => _closingIterations;
|
||||
set => this.RaiseAndSetIfChanged(ref _closingIterations, value);
|
||||
}
|
||||
|
||||
public byte OpeningIterations
|
||||
{
|
||||
get => _openingIterations;
|
||||
set => this.RaiseAndSetIfChanged(ref _openingIterations, value);
|
||||
}
|
||||
|
||||
public byte RemoveIslandsBelowEqualPixels
|
||||
{
|
||||
get => _removeIslandsBelowEqualPixels;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeIslandsBelowEqualPixels, value);
|
||||
}
|
||||
private byte _removeIslandsBelowEqualPixels = 10;
|
||||
private ushort _removeIslandsRecursiveIterations = 4;
|
||||
private byte _closingIterations = 2;
|
||||
private byte _openingIterations = 0;
|
||||
|
||||
public bool RepairIslands
|
||||
{
|
||||
@@ -884,6 +867,30 @@ namespace UVtools.WPF
|
||||
set => this.RaiseAndSetIfChanged(ref _removeEmptyLayers, value);
|
||||
}
|
||||
|
||||
public byte RemoveIslandsBelowEqualPixels
|
||||
{
|
||||
get => _removeIslandsBelowEqualPixels;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeIslandsBelowEqualPixels, value);
|
||||
}
|
||||
|
||||
public ushort RemoveIslandsRecursiveIterations
|
||||
{
|
||||
get => _removeIslandsRecursiveIterations;
|
||||
set => this.RaiseAndSetIfChanged(ref _removeIslandsRecursiveIterations, value);
|
||||
}
|
||||
|
||||
public byte ClosingIterations
|
||||
{
|
||||
get => _closingIterations;
|
||||
set => this.RaiseAndSetIfChanged(ref _closingIterations, value);
|
||||
}
|
||||
|
||||
public byte OpeningIterations
|
||||
{
|
||||
get => _openingIterations;
|
||||
set => this.RaiseAndSetIfChanged(ref _openingIterations, value);
|
||||
}
|
||||
|
||||
public LayerRepairUserSettings Clone()
|
||||
{
|
||||
return MemberwiseClone() as LayerRepairUserSettings;
|
||||
|
||||
@@ -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">
|
||||
<NumericUpDown
|
||||
Value="{Binding Settings.LayerRepair.ClosingIterations}"
|
||||
Width="60"
|
||||
Minimum="0"
|
||||
Maximum="255"
|
||||
/>
|
||||
<TextBlock VerticalAlignment="Center" Text="Default 'Gap Closing' iterations"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="15,0,15,15" Spacing="10">
|
||||
<NumericUpDown
|
||||
Value="{Binding Settings.LayerRepair.OpeningIterations}"
|
||||
Width="60"
|
||||
Minimum="0"
|
||||
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"/>
|
||||
Margin="15,0" Content="Remove empty layers by default"/>
|
||||
<CheckBox IsChecked="{Binding Settings.LayerRepair.RemoveEmptyLayers}"
|
||||
Margin="15" Content="Attempt to repair resin traps by default"/>
|
||||
|
||||
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="70"
|
||||
Minimum="0"
|
||||
Maximum="255"/>
|
||||
<TextBlock VerticalAlignment="Center" Text="Default 'Gap Closing' iterations"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="15,0,15,15" Spacing="10">
|
||||
<NumericUpDown
|
||||
Value="{Binding Settings.LayerRepair.OpeningIterations}"
|
||||
Width="70"
|
||||
Minimum="0"
|
||||
Maximum="255"/>
|
||||
<TextBlock VerticalAlignment="Center" Text="Default 'Noise Removal' iterations"/>
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user