* **File formats:**
   * Add a layer height check on file load to prevent load files with more decimal digits than supported to avoid precision errors and bugs
   * Fix a wrong cast causing seconds to miliseconds convertion to be caped to the wrong value
   * Internally if a layer colection was replaced, all new layers will be marked as modified to avoid forgeting and ease the code
* **Tools:**
   * Pixel dimming: Better render quality, it now respects AA better and produce better walls (#172)
   * Elephant foot: It now respects AA better and produce better walls for wall dimming
   * Layer Import: Cancelling the operation while importing layers was permanent supresseing layer properties update when changing a base property
* (Change) PrusaSlicer print profiles: Improved raft height and bottom layer count for better print success, less delamination, shorter time and reduce wear of FEP
* (Scripts): Add operation "Validate" pattern to docs and examples (#172)
This commit is contained in:
Tiago Conceição
2021-03-24 03:25:41 +00:00
parent 3f838001c7
commit 2231fdaca3
50 changed files with 668 additions and 514 deletions
+14 -1
View File
@@ -1,5 +1,18 @@
# Changelog
## 24/03/2021 - v2.7.1
* **File formats:**
* Add a layer height check on file load to prevent load files with more decimal digits than supported to avoid precision errors and bugs
* Fix a wrong cast causing seconds to miliseconds convertion to be caped to the wrong value
* Internally if a layer colection was replaced, all new layers will be marked as modified to avoid forgeting and ease the code
* **Tools:**
* Pixel dimming: Better render quality, it now respects AA better and produce better walls (#172)
* Elephant foot: It now respects AA better and produce better walls for wall dimming
* Layer Import: Cancelling the operation while importing layers was permanent supresseing layer properties update when changing a base property
* (Change) PrusaSlicer print profiles: Improved raft height and bottom layer count for better print success, less delamination, shorter time and reduce wear of FEP
* (Scripts): Add operation "Validate" pattern to docs and examples (#172)
## 19/03/2021 - v2.7.0
* **Core:**
@@ -14,7 +27,7 @@
* **Layer preview:**
* Add selectable rotation directions 90º (CW and CCW)
* Add preview flip (CTRL+F) horizontally and/or vertically
* Add maskable regions to process on a layer (SHIFT + Alt + Click) on a area
* Add maskable regions to process on a layer (SHIFT + Alt + Right-Click) on a area
* ROI: Shortcut "Shift + left click" now also selects hollow black areas inside a white perimeter
* ROI: Shortcut "ESC + Shift" to clear only the ROI and leave masks in
* Fix a crash when using the pixel picker tool outside image bounds
+2 -2
View File
@@ -1,4 +1,4 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:31:37 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-21 at 18:54:48 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
@@ -26,7 +26,7 @@ min_exposure_time = 1
min_initial_exposure_time = 1
print_host =
printer_model = SL1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_PHROZEN\nPRINTER_MODEL_SONIC_MINI\nFILEFORMAT_PHZ\n\nSTART_CUSTOM_VALUES\nLightOffDelay_7\nBottomLightOffDelay_7\nBottomLiftHeight_6\nLiftHeight_5\nBottomLiftSpeed_100\nLiftSpeed_100\nRetractSpeed_200\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_PHROZEN\nPRINTER_MODEL_SONIC_MINI\nFILEFORMAT_PHZ\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_8\nLiftHeight_6\nBottomLiftSpeed_100\nLiftSpeed_100\nRetractSpeed_200\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES
printer_settings_id =
printer_technology = SLA
printer_variant = default
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:05:42 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:57:03 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 10
faded_layers = 7
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.05
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:05:47 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:56:51 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 10
faded_layers = 7
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.05
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:05:57 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:56:44 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 10
faded_layers = 7
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.05
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,4 +1,4 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:01 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:56:10 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.08
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,4 +1,4 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:05 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:56:04 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.08
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,4 +1,4 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:11 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:55:53 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.08
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:16 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:55:17 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 4
faded_layers = 6
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.12
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:20 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:54:46 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 4
faded_layers = 6
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.12
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:32 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:54:37 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 4
faded_layers = 6
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.12
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:36 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:53:35 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 4
faded_layers = 5
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.12
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:38 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:53:24 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 4
faded_layers = 5
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.12
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:41 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:53:17 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 4
faded_layers = 5
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.12
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:44 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:49:10 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 5
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.15
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:47 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:49:01 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 5
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.15
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:51 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:48:55 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 5
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.15
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:55 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 03:00:53 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.2
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:06:58 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 03:00:47 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.2
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:01 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 03:00:40 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.2
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:03 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:51:38 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.3
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:06 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:51:32 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.3
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:09 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:51:25 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -21,7 +21,7 @@ pad_object_connector_width = 0.5
pad_object_gap = 1
pad_wall_height = 0
pad_wall_slope = 90
pad_wall_thickness = 0.4
pad_wall_thickness = 0.3
sla_print_settings_id =
slice_closing_radius = 0.005
support_base_diameter = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:12 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:50:52 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:15 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:50:45 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
@@ -1,8 +1,8 @@
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 23:07:18 UTC
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-24 at 02:50:38 UTC
compatible_printers =
compatible_printers_condition =
default_sla_print_profile =
faded_layers = 3
faded_layers = 4
hollowing_closing_distance = 2
hollowing_enable = 0
hollowing_min_thickness = 3
+3 -3
View File
@@ -86,7 +86,7 @@ namespace UVtools.Core.Extensions
var index = valStr.IndexOf('.');
if (index < 0) return 0;
return (uint) (valStr.Substring(index).Length - 1);
return (uint) (valStr[index..].Length - 1);
}
public static uint DecimalDigits(this double val)
@@ -97,7 +97,7 @@ namespace UVtools.Core.Extensions
var index = valStr.IndexOf('.');
if (index < 0) return 0;
return (uint)(valStr.Substring(index).Length - 1);
return (uint)(valStr[index..].Length - 1);
}
public static uint DecimalDigits(this decimal val)
@@ -108,7 +108,7 @@ namespace UVtools.Core.Extensions
var index = valStr.IndexOf('.');
if (index < 0) return 0;
return (uint)(valStr.Substring(index).Length - 1);
return (uint)(valStr[index..].Length - 1);
}
public static bool IsInteger(this float val, float tolerance = 0.0001f) => Math.Abs(val - Math.Floor(val)) < tolerance;
+1 -1
View File
@@ -26,7 +26,7 @@ namespace UVtools.Core.Extensions
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static uint SecondsToMillisecondsUint(float value) => (uint)value * 1000;
public static uint SecondsToMillisecondsUint(float value) => (uint)(value * 1000f);
/// <summary>
/// Converts milliseconds to seconds
+1
View File
@@ -1589,6 +1589,7 @@ namespace UVtools.Core.FileFormats
this[layerIndex] = layer;
lock (progress.Mutex)
{
progress++;
+94 -41
View File
@@ -10,6 +10,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
@@ -1048,10 +1049,7 @@ namespace UVtools.Core.FileFormats
e.PropertyName == nameof(LightPWM)
)
{
if (LayerManager is not null)
{
LayerManager.RebuildLayersProperties(false, e.PropertyName);
}
LayerManager?.RebuildLayersProperties(false, e.PropertyName);
if(e.PropertyName != nameof(BottomLightPWM) && e.PropertyName != nameof(LightPWM))
PrintTime = PrintTimeComputed;
@@ -1306,7 +1304,7 @@ namespace UVtools.Core.FileFormats
EncodeInternally(fileFullPath, progress);
LayerManager.Desmodify();
LayerManager.SetAllIsModified(false);
RequireFullEncode = false;
}
@@ -1334,6 +1332,13 @@ namespace UVtools.Core.FileFormats
progress.Token.ThrowIfCancellationRequested();
var layerHeightDigits = LayerHeight.DecimalDigits();
if (layerHeightDigits > Layer.HeightPrecision)
{
throw new FileLoadException($"The layer height ({LayerHeight}mm) have more decimal digits than the supported ({Layer.HeightPrecision}) digits.\n" +
"Lower and fix your layer height on slicer to avoid precision errors.", fileFullPath);
}
// Sanitize
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
@@ -1806,49 +1811,48 @@ namespace UVtools.Core.FileFormats
var slicerFile = (FileFormat)Activator.CreateInstance(to);
if (slicerFile is null) return null;
slicerFile.SuppressRebuildProperties = true;
slicerFile.SuppressRebuildPropertiesWork(() =>
{
slicerFile.LayerManager = _layerManager.Clone();
slicerFile.AntiAliasing = ValidateAntiAliasingLevel();
slicerFile.LayerCount = _layerManager.Count;
slicerFile.BottomLayerCount = BottomLayerCount;
slicerFile.LayerHeight = LayerHeight;
slicerFile.ResolutionX = ResolutionX;
slicerFile.ResolutionY = ResolutionY;
slicerFile.DisplayWidth = DisplayWidth;
slicerFile.DisplayHeight = DisplayHeight;
slicerFile.MaxPrintHeight = MaxPrintHeight;
slicerFile.MirrorDisplay = MirrorDisplay;
slicerFile.BottomExposureTime = BottomExposureTime;
slicerFile.ExposureTime = ExposureTime;
slicerFile.LayerManager = _layerManager.Clone();
slicerFile.AntiAliasing = ValidateAntiAliasingLevel();
slicerFile.LayerCount = _layerManager.Count;
slicerFile.BottomLayerCount = BottomLayerCount;
slicerFile.LayerHeight = LayerHeight;
slicerFile.ResolutionX = ResolutionX;
slicerFile.ResolutionY = ResolutionY;
slicerFile.DisplayWidth = DisplayWidth;
slicerFile.DisplayHeight = DisplayHeight;
slicerFile.MaxPrintHeight = MaxPrintHeight;
slicerFile.MirrorDisplay = MirrorDisplay;
slicerFile.BottomExposureTime = BottomExposureTime;
slicerFile.ExposureTime = ExposureTime;
slicerFile.BottomLiftHeight = BottomLiftHeight;
slicerFile.LiftHeight = LiftHeight;
slicerFile.BottomLiftHeight = BottomLiftHeight;
slicerFile.LiftHeight = LiftHeight;
slicerFile.BottomLiftSpeed = BottomLiftSpeed;
slicerFile.LiftSpeed = LiftSpeed;
slicerFile.RetractSpeed = RetractSpeed;
slicerFile.BottomLiftSpeed = BottomLiftSpeed;
slicerFile.LiftSpeed = LiftSpeed;
slicerFile.RetractSpeed = RetractSpeed;
slicerFile.BottomLightOffDelay = BottomLightOffDelay;
slicerFile.LightOffDelay = LightOffDelay;
slicerFile.BottomLightOffDelay = BottomLightOffDelay;
slicerFile.LightOffDelay = LightOffDelay;
slicerFile.BottomLightPWM = BottomLightPWM;
slicerFile.LightPWM = LightPWM;
slicerFile.BottomLightPWM = BottomLightPWM;
slicerFile.LightPWM = LightPWM;
slicerFile.MachineName = MachineName;
slicerFile.MaterialName = MaterialName;
slicerFile.MaterialMilliliters = MaterialMilliliters;
slicerFile.MaterialGrams = MaterialGrams;
slicerFile.MaterialCost = MaterialCost;
slicerFile.Xppmm = Xppmm;
slicerFile.Yppmm = Yppmm;
slicerFile.PrintTime = PrintTime;
slicerFile.PrintHeight = PrintHeight;
slicerFile.MachineName = MachineName;
slicerFile.MaterialName = MaterialName;
slicerFile.MaterialMilliliters = MaterialMilliliters;
slicerFile.MaterialGrams = MaterialGrams;
slicerFile.MaterialCost = MaterialCost;
slicerFile.Xppmm = Xppmm;
slicerFile.Yppmm = Yppmm;
slicerFile.PrintTime = PrintTime;
slicerFile.PrintHeight = PrintHeight;
slicerFile.SetThumbnails(Thumbnails);
});
slicerFile.SuppressRebuildProperties = false;
slicerFile.SetThumbnails(Thumbnails);
slicerFile.Encode(fileFullPath, progress);
return slicerFile;
@@ -1874,6 +1878,55 @@ namespace UVtools.Core.FileFormats
return AntiAliasing;
}
/// <summary>
/// SuppressRebuildProperties = true, call the invoker and reset SuppressRebuildProperties = false
/// </summary>
/// <param name="action">Action work</param>
/// <param name="callRebuildOnEnd">True to force rebuild the layer properties after the work and before reset to false</param>
/// <param name="recalculateZPos">True to recalculate z position of each layer (requires <paramref name="callRebuildOnEnd"/> = true), otherwise false</param>
/// <param name="property">Property name to change for each layer, use null to update all properties (requires <paramref name="callRebuildOnEnd"/> = true)</param>
public void SuppressRebuildPropertiesWork(Action action, bool callRebuildOnEnd = false, bool recalculateZPos = true, string property = null)
{
/*SuppressRebuildProperties = true;
action.Invoke();
if(callRebuildOnEnd) LayerManager.RebuildLayersProperties(recalculateZPos, property);
SuppressRebuildProperties = false;*/
SuppressRebuildPropertiesWork(() =>
{
action.Invoke();
return true;
}, callRebuildOnEnd, recalculateZPos, property);
}
/// <summary>
/// SuppressRebuildProperties = true, call the invoker and reset SuppressRebuildProperties = false
/// </summary>
/// <param name="action">Action work</param>
/// <param name="callRebuildOnEnd">True to force rebuild the layer properties after the work and before reset to false</param>
/// <param name="recalculateZPos">True to recalculate z position of each layer (requires <paramref name="callRebuildOnEnd"/> = true), otherwise false</param>
/// <param name="property">Property name to change for each layer, use null to update all properties (requires <paramref name="callRebuildOnEnd"/> = true)</param>
public bool SuppressRebuildPropertiesWork(Func<bool> action, bool callRebuildOnEnd = false, bool recalculateZPos = true, string property = null)
{
bool result;
try
{
SuppressRebuildProperties = true;
result = action.Invoke();
if (callRebuildOnEnd && result) LayerManager.RebuildLayersProperties(recalculateZPos, property);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
finally
{
SuppressRebuildProperties = false;
}
return result;
}
#endregion
}
}
+13 -12
View File
@@ -628,18 +628,19 @@ namespace UVtools.Core.FileFormats
throw new FileLoadException($"Malformed file: {IniPrusaslicer} is missing.");
}
SuppressRebuildProperties = true;
BottomLiftHeight = LookupCustomValue(Keyword_BottomLiftHeight, DefaultBottomLiftHeight);
BottomLiftSpeed = LookupCustomValue(Keyword_BottomLiftSpeed, DefaultBottomLiftSpeed);
LiftHeight = LookupCustomValue(Keyword_LiftHeight, DefaultLiftHeight);
LiftSpeed = LookupCustomValue(Keyword_LiftSpeed, DefaultLiftSpeed);
RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, DefaultRetractSpeed);
BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, DefaultBottomLightOffDelay);
LightOffDelay = LookupCustomValue(Keyword_LightOffDelay, DefaultLightOffDelay);
BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, DefaultLightPWM);
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
SuppressRebuildProperties = false;
SuppressRebuildPropertiesWork(() =>
{
BottomLiftHeight = LookupCustomValue(Keyword_BottomLiftHeight, DefaultBottomLiftHeight);
BottomLiftSpeed = LookupCustomValue(Keyword_BottomLiftSpeed, DefaultBottomLiftSpeed);
LiftHeight = LookupCustomValue(Keyword_LiftHeight, DefaultLiftHeight);
LiftSpeed = LookupCustomValue(Keyword_LiftSpeed, DefaultLiftSpeed);
RetractSpeed = LookupCustomValue(Keyword_RetractSpeed, DefaultRetractSpeed);
BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, DefaultBottomLightOffDelay);
LightOffDelay = LookupCustomValue(Keyword_LightOffDelay, DefaultLightOffDelay);
BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, DefaultLightPWM);
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
});
LayerManager = new LayerManager((uint) (OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast), this);
progress.ItemCount = LayerCount;
+22 -22
View File
@@ -756,30 +756,30 @@ namespace UVtools.Core.GCode
if (rebuildGlobalTable)
{
slicerFile.SuppressRebuildProperties = true;
var bottomLayer = slicerFile[0];
if (bottomLayer is not null)
slicerFile.SuppressRebuildPropertiesWork(() =>
{
if (bottomLayer.ExposureTime > 0) slicerFile.BottomExposureTime = bottomLayer.ExposureTime;
if (bottomLayer.LiftHeight > 0) slicerFile.BottomLiftHeight = bottomLayer.LiftHeight;
if (bottomLayer.LiftSpeed > 0) slicerFile.BottomLiftSpeed = bottomLayer.LiftSpeed;
if (bottomLayer.RetractSpeed > 0) slicerFile.RetractSpeed = bottomLayer.RetractSpeed;
if (bottomLayer.LightOffDelay > 0) slicerFile.BottomLightOffDelay = bottomLayer.LightOffDelay;
if (bottomLayer.LightPWM > 0) slicerFile.BottomLightPWM = bottomLayer.LightPWM;
}
var bottomLayer = slicerFile[0];
if (bottomLayer is not null)
{
if (bottomLayer.ExposureTime > 0) slicerFile.BottomExposureTime = bottomLayer.ExposureTime;
if (bottomLayer.LiftHeight > 0) slicerFile.BottomLiftHeight = bottomLayer.LiftHeight;
if (bottomLayer.LiftSpeed > 0) slicerFile.BottomLiftSpeed = bottomLayer.LiftSpeed;
if (bottomLayer.RetractSpeed > 0) slicerFile.RetractSpeed = bottomLayer.RetractSpeed;
if (bottomLayer.LightOffDelay > 0) slicerFile.BottomLightOffDelay = bottomLayer.LightOffDelay;
if (bottomLayer.LightPWM > 0) slicerFile.BottomLightPWM = bottomLayer.LightPWM;
}
var normalLayer = slicerFile[slicerFile.LastLayerIndex];
if (normalLayer is not null)
{
if (normalLayer.ExposureTime > 0) slicerFile.ExposureTime = normalLayer.ExposureTime;
if (normalLayer.LiftHeight > 0) slicerFile.LiftHeight = normalLayer.LiftHeight;
if (normalLayer.LiftSpeed > 0) slicerFile.LiftSpeed = normalLayer.LiftSpeed;
if (normalLayer.RetractSpeed > 0) slicerFile.RetractSpeed = normalLayer.RetractSpeed;
if (normalLayer.LightOffDelay > 0) slicerFile.LightOffDelay = normalLayer.LightOffDelay;
if (normalLayer.LightPWM > 0) slicerFile.LightPWM = normalLayer.LightPWM;
}
slicerFile.SuppressRebuildProperties = false;
var normalLayer = slicerFile[slicerFile.LastLayerIndex];
if (normalLayer is not null)
{
if (normalLayer.ExposureTime > 0) slicerFile.ExposureTime = normalLayer.ExposureTime;
if (normalLayer.LiftHeight > 0) slicerFile.LiftHeight = normalLayer.LiftHeight;
if (normalLayer.LiftSpeed > 0) slicerFile.LiftSpeed = normalLayer.LiftSpeed;
if (normalLayer.RetractSpeed > 0) slicerFile.RetractSpeed = normalLayer.RetractSpeed;
if (normalLayer.LightOffDelay > 0) slicerFile.LightOffDelay = normalLayer.LightOffDelay;
if (normalLayer.LightPWM > 0) slicerFile.LightPWM = normalLayer.LightPWM;
}
});
}
}
+38
View File
@@ -424,4 +424,42 @@ namespace UVtools.Core
}
}
#endregion
#region ResinTrapGround
public sealed class ResinTrapGroup
{
public List<List<LayerHollowArea>> Groups { get; } = new();
public int FindHollowArea(LayerHollowArea hollowArea)
{
for (var i = 0; i < Groups.Count; i++)
{
if (Groups[i].Any(area => ReferenceEquals(area, hollowArea)))
{
return i;
}
}
return -1;
}
public int Add(LayerHollowArea hollowArea)
{
var index = FindHollowArea(hollowArea);
if (index < 0) // Not found
{
index = Groups.Count;
Groups.Add(new List<LayerHollowArea>{hollowArea});
return index;
}
// Exists
Groups[index].Add(hollowArea);
return index;
}
}
#endregion
}
+24 -17
View File
@@ -43,9 +43,15 @@ namespace UVtools.Core
{
_layers = value;
BoundingRectangle = Rectangle.Empty;
SlicerFile.LayerCount = Count;
if (SlicerFile.LayerCount != Count)
{
SlicerFile.LayerCount = Count;
}
SlicerFile.RequireFullEncode = true;
if (value is null) return;
SetAllIsModified(true);
SlicerFile.PrintTime = SlicerFile.PrintTimeComputed;
SlicerFile.RebuildGCode();
}
@@ -1073,7 +1079,6 @@ namespace UVtools.Core
layerHollowAreas.TryAdd(layer.Index, listHollowArea);
}
}
}
progress.LockAndIncrement();
@@ -1084,6 +1089,8 @@ namespace UVtools.Core
{
progress.Reset(OperationProgress.StatusResinTraps, Count);
for (uint layerIndex = 1; layerIndex < Count - 1; layerIndex++) // First and Last layers, always drains
{
if (progress.Token.IsCancellationRequested) break;
@@ -1470,13 +1477,14 @@ namespace UVtools.Core
/// <summary>
/// Desmodify all layers
/// Set the IsModified property for all layers
/// </summary>
public void Desmodify()
public void SetAllIsModified(bool isModified)
{
for (uint i = 0; i < Count; i++)
{
Layers[i].IsModified = false;
if(Layers[i] is null) continue;
Layers[i].IsModified = isModified;
}
}
@@ -1504,20 +1512,19 @@ namespace UVtools.Core
/// <returns></returns>
public void Reallocate(uint insertAtLayerIndex, uint layerCount, bool initBlack = false)
{
var layers = Layers;
Layers = new Layer[Count + layerCount];
var newLayers = new Layer[Count + layerCount];
// Rearrange
for (uint layerIndex = 0; layerIndex < insertAtLayerIndex; layerIndex++)
{
Layers[layerIndex] = layers[layerIndex];
newLayers[layerIndex] = _layers[layerIndex];
}
// Rearrange
for (uint layerIndex = insertAtLayerIndex; layerIndex < layers.Length; layerIndex++)
for (uint layerIndex = insertAtLayerIndex; layerIndex < _layers.Length; layerIndex++)
{
Layers[layerCount + layerIndex] = layers[layerIndex];
Layers[layerCount + layerIndex].Index = layerCount + layerIndex;
newLayers[layerCount + layerIndex] = _layers[layerIndex];
newLayers[layerCount + layerIndex].Index = layerCount + layerIndex;
}
// Allocate new layers
@@ -1525,28 +1532,28 @@ namespace UVtools.Core
{
Parallel.For(insertAtLayerIndex, insertAtLayerIndex + layerCount, layerIndex =>
{
Layers[layerIndex] = new Layer((uint) layerIndex, EmguExtensions.InitMat(SlicerFile.Resolution), this);
newLayers[layerIndex] = new Layer((uint) layerIndex, EmguExtensions.InitMat(SlicerFile.Resolution), this);
});
}
/*for (uint layerIndex = insertAtLayerIndex; layerIndex < insertAtLayerIndex + layerCount; layerIndex++)
{
Layers[layerIndex] = initBlack ? new Layer(layerIndex, EmguExtensions.InitMat(SlicerFile.Resolution), this) : null;
}*/
Layers = newLayers;
}
public void ReallocateRange(uint startLayerIndex, uint endLayerIndex)
{
var layers = Layers;
if ((int)(endLayerIndex - startLayerIndex) < 0) return;
Layers = new Layer[1 + endLayerIndex - startLayerIndex];
var newLayers = new Layer[1 + endLayerIndex - startLayerIndex];
uint currentLayerIndex = 0;
for (uint layerIndex = startLayerIndex; layerIndex <= endLayerIndex; layerIndex++)
{
Layers[currentLayerIndex++] = layers[layerIndex];
newLayers[currentLayerIndex++] = _layers[layerIndex];
}
BoundingRectangle = Rectangle.Empty;
Layers = newLayers;
}
/// <summary>
+1 -3
View File
@@ -262,9 +262,7 @@ namespace UVtools.Core.Managers
}
Add(clip);
slicerFile.SuppressRebuildProperties = true;
CurrentIndex = 0;
slicerFile.SuppressRebuildProperties = false;
slicerFile.SuppressRebuildPropertiesWork(() => CurrentIndex = 0);
}
/// <summary>
+18 -2
View File
@@ -226,7 +226,7 @@ namespace UVtools.Core.Operations
/// <summary>
/// Validates the operation
/// </summary>
/// <returns>null or empty if validates, or else, return a string with error message</returns>
/// <returns>null or empty if validates, otherwise return a string with error message</returns>
public virtual StringTag Validate(params object[] parameters) => null;
public bool CanValidate(params object[] parameters)
@@ -274,6 +274,18 @@ namespace UVtools.Core.Operations
LayerRangeSelection = Enumerations.LayerRangeSelection.Last;
}
public void SelectFirstToCurrentLayer(uint currentLayerIndex)
{
LayerIndexStart = 0;
LayerIndexEnd = Math.Min(currentLayerIndex, SlicerFile.LastLayerIndex);
}
public void SelectCurrentToLastLayer(uint currentLayerIndex)
{
LayerIndexStart = Math.Min(currentLayerIndex, SlicerFile.LastLayerIndex);
LayerIndexEnd = SlicerFile.LastLayerIndex;
}
public void SelectLayers(Enumerations.LayerRangeSelection range)
{
switch (range)
@@ -342,7 +354,11 @@ namespace UVtools.Core.Operations
{
if (mask is null) return;
var originalRoi = GetRoiOrDefault(original);
var resultRoi = GetRoiOrDefault(result);
var resultRoi = result;
if (originalRoi.Size != result.Size) // Accept a ROI mat
{
resultRoi = GetRoiOrDefault(result);
}
resultRoi.CopyTo(originalRoi, mask);
originalRoi.CopyTo(resultRoi);
}
@@ -638,11 +638,12 @@ namespace UVtools.Core.Operations
using (var target = new Mat())
using (var mask = shape.CloneBlank())
{
mask.SetTo(new MCvScalar(brightness));
CvInvoke.Erode(shape, erode, kernel, anchor, DimmingWallThickness, BorderType.Reflect101,
default);
CvInvoke.Subtract(shape, erode, diff);
CvInvoke.BitwiseAnd(diff, mask, target);
mask.SetTo(new MCvScalar(byte.MaxValue-brightness));
CvInvoke.Erode(shape, erode, kernel, anchor, DimmingWallThickness, BorderType.Reflect101, default);
//CvInvoke.Subtract(shape, erode, diff);
//CvInvoke.BitwiseAnd(diff, mask, target);
//CvInvoke.Add(erode, target, target);
CvInvoke.Subtract(shape, mask, target);
CvInvoke.Add(erode, target, target);
target.CopyTo(roi);
//addText(roi, count, $"W: {DimmingWallThickness}", $"B: {brightness}");
@@ -750,16 +751,16 @@ namespace UVtools.Core.Operations
progress++;
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
SlicerFile.LayerManager.RebuildLayersProperties();
SlicerFile.SuppressRebuildProperties = false;
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
return !progress.Token.IsCancellationRequested;
}
@@ -1290,20 +1290,20 @@ namespace UVtools.Core.Operations
if (SlicerFile.ThumbnailsCount > 0)
SlicerFile.SetThumbnails(GetThumbnail());
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers.ToArray();
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers.ToArray();
});
if (_dontLiftSamePositionedLayers)
{
SlicerFile.LayerManager.SetNoLiftForSamePositionedLayers();
}
SlicerFile.SuppressRebuildProperties = false;
if (_mirrorOutput)
{
new OperationFlip(SlicerFile){FlipDirection = Enumerations.FlipDirection.Horizontally}.Execute(progress);
@@ -521,16 +521,16 @@ namespace UVtools.Core.Operations
if (SlicerFile.ThumbnailsCount > 0)
SlicerFile.SetThumbnails(GetThumbnail());
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
SlicerFile.LayerManager.RebuildLayersProperties();
SlicerFile.SuppressRebuildProperties = false;
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
return !progress.Token.IsCancellationRequested;
}
@@ -418,7 +418,7 @@ namespace UVtools.Core.Operations
Parallel.For(0, LayerCount, layerIndex =>
{
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile.LayerManager);
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile.LayerManager) {IsModified = true};
layers[layerIndex].Dispose();
lock (progress)
{
@@ -430,16 +430,15 @@ namespace UVtools.Core.Operations
if (SlicerFile.ThumbnailsCount > 0)
SlicerFile.SetThumbnails(GetThumbnail());
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
SlicerFile.LayerManager.RebuildLayersProperties();
SlicerFile.SuppressRebuildProperties = false;
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
return !progress.Token.IsCancellationRequested;
}
@@ -730,7 +730,7 @@ namespace UVtools.Core.Operations
Parallel.For(0, LayerCount, layerIndex =>
{
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile.LayerManager);
newLayers[layerIndex] = new Layer((uint)layerIndex, layers[layerIndex], SlicerFile.LayerManager) {IsModified = true};
layers[layerIndex].Dispose();
lock (progress)
{
@@ -741,15 +741,15 @@ namespace UVtools.Core.Operations
if (SlicerFile.ThumbnailsCount > 0)
SlicerFile.SetThumbnails(GetThumbnail());
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
SlicerFile.LayerManager.RebuildLayersProperties();
SlicerFile.SuppressRebuildProperties = false;
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
var moveOp = new OperationMove(SlicerFile);
moveOp.Execute(progress);
@@ -769,15 +769,15 @@ namespace UVtools.Core.Operations
if (SlicerFile.ThumbnailsCount > 0)
SlicerFile.SetThumbnails(GetThumbnail());
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
SlicerFile.LayerManager.RebuildLayersProperties();
SlicerFile.SuppressRebuildProperties = false;
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerHeight = (float)LayerHeight;
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
return !progress.Token.IsCancellationRequested;
}
@@ -655,11 +655,12 @@ namespace UVtools.Core.Operations
ReUseLayer(layerIndex);
}
SlicerFile.SuppressRebuildProperties = true;
SlicerFile.LayerManager.Layers = layers.ToArray();
SlicerFile.LayerManager.RebuildLayersProperties(false);
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.LayerManager.Layers = layers.ToArray();
}, true, false);
// Set exposures times
// Set exposures times per layer
var exposureDictionary = ExposureTableDictionary;
for (uint layerIndex = 0; layerIndex < SlicerFile.LayerCount; layerIndex++)
{
@@ -693,8 +694,6 @@ namespace UVtools.Core.Operations
Debug.WriteLine(layer.Index);
}*/
SlicerFile.SuppressRebuildProperties = false;
report.NewLayerCount = SlicerFile.LayerCount;
report.NewPrintTime = SlicerFile.PrintTime;
Tag = report;
+1 -3
View File
@@ -299,12 +299,10 @@ namespace UVtools.Core.Operations
}
}
CvInvoke.Erode(target, erode, kernel, anchor, WallThickness, BorderType.Reflect101,
default);
CvInvoke.Subtract(target, erode, diff);
CvInvoke.BitwiseAnd(erode, patternMask, target, mask);
CvInvoke.Add(target, diff, target, mask);
patternMask?.Dispose();
+254 -255
View File
@@ -224,282 +224,281 @@ namespace UVtools.Core.Operations
protected override bool ExecuteInternally(OperationProgress progress)
{
progress.ItemCount = 0;
SlicerFile.SuppressRebuildProperties = true;
List<FileFormat> fileFormats = new();
List<KeyValuePair<uint, string>> keyImage = new();
int lastProcessedLayerIndex = -1;
bool result = SlicerFile.SuppressRebuildPropertiesWork(() => {
List<FileFormat> fileFormats = new();
List<KeyValuePair<uint, string>> keyImage = new();
int lastProcessedLayerIndex = -1;
// Order raw images
for (int i = 0; i < Count; i++)
{
if (!Files[i].TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) continue;
keyImage.Add(new KeyValuePair<uint, string>((uint) keyImage.Count, Files[i].TagString));
}
// Create virtual file format with images
if (keyImage.Count > 0)
{
progress.Reset("Packing images", (uint) keyImage.Count);
SL1File format = new SL1File();
format.LayerManager = new LayerManager((uint) keyImage.Count, format);
Parallel.ForEach(keyImage, pair =>
// Order raw images
for (int i = 0; i < Count; i++)
{
if (progress.Token.IsCancellationRequested) return;
using var mat = CvInvoke.Imread(pair.Value, ImreadModes.Grayscale);
if (pair.Key == 0) format.Resolution = mat.Size;
format[pair.Key] = new Layer(pair.Key, mat, format);
lock (progress.Mutex)
{
progress++;
}
});
progress.Token.ThrowIfCancellationRequested();
fileFormats.Add(format);
}
// Order remaining possible file formats
for (int i = 0; i < Count; i++)
{
if (Files[i].TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) continue;
var fileFormat = FileFormat.FindByExtension(Files[i].TagString, true, true);
if(fileFormat is null) continue;
fileFormat.FileFullPath = Files[i].TagString;
fileFormats.Add(fileFormat);
}
progress.Token.ThrowIfCancellationRequested();
if (fileFormats.Count == 0) return false;
if (_importType == ImportTypes.Stack)
{
new OperationMove(SlicerFile, Enumerations.Anchor.TopLeft).Execute(progress);
}
foreach (var fileFormat in fileFormats)
{
if (!string.IsNullOrEmpty(fileFormat.FileFullPath))
{
fileFormat.Decode(fileFormat.FileFullPath, progress);
if (!Files[i].TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) continue;
keyImage.Add(new KeyValuePair<uint, string>((uint)keyImage.Count, Files[i].TagString));
}
var boundingRectangle = SlicerFile.LayerManager.GetBoundingRectangle(progress);
var fileFormatBoundingRectangle = fileFormat.LayerManager.GetBoundingRectangle(progress);
var roiRectangle = Rectangle.Empty;
// Check if is possible to process this file
switch (_importType)
// Create virtual file format with images
if (keyImage.Count > 0)
{
case ImportTypes.Insert:
if (SlicerFile.Resolution != fileFormat.Resolution &&
(SlicerFile.Resolution.Width < fileFormatBoundingRectangle.Width ||
SlicerFile.Resolution.Height < fileFormatBoundingRectangle.Height)) continue;
SlicerFile.LayerManager.Reallocate(_startLayerIndex, fileFormat.LayerCount);
break;
case ImportTypes.Replace:
case ImportTypes.Stack:
if (SlicerFile.Resolution != fileFormat.Resolution &&
(SlicerFile.Resolution.Width < fileFormatBoundingRectangle.Width ||
SlicerFile.Resolution.Height < fileFormatBoundingRectangle.Height)) continue;
progress.Reset("Packing images", (uint)keyImage.Count);
SL1File format = new();
format.LayerManager = new LayerManager((uint)keyImage.Count, format);
//if(fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX || fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY)
// continue;
if (_importType == ImportTypes.Stack)
{
int x = 0;
int y = 0;
if (boundingRectangle.Right + _stackMargin + fileFormatBoundingRectangle.Width <
SlicerFile.ResolutionX)
{
x = boundingRectangle.Right + _stackMargin;
}
else
{
y = boundingRectangle.Bottom + _stackMargin;
}
if (x + fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX)
continue;
if (y + fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY)
continue;
roiRectangle = new Rectangle(x, y, fileFormatBoundingRectangle.Width,
fileFormatBoundingRectangle.Height);
}
if (_extendBeyondLayerCount)
{
int layerCountDifference = (int) (_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount);
if (layerCountDifference > 0)
{
SlicerFile.LayerManager.ReallocateEnd((uint) layerCountDifference, _importType == ImportTypes.Stack);
}
}
break;
case ImportTypes.Merge:
if (SlicerFile.Resolution != fileFormat.Resolution) continue;
if (_extendBeyondLayerCount)
{
int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount);
if (layerCountDifference > 0)
{
SlicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, true);
}
}
break;
case ImportTypes.Subtract:
case ImportTypes.BitwiseAnd:
case ImportTypes.BitwiseOr:
case ImportTypes.BitwiseXOr:
if (SlicerFile.Resolution != fileFormat.Resolution) continue;
break;
}
progress.Reset(ProgressAction, fileFormat.LayerCount);
Parallel.For(0, fileFormat.LayerCount,
//new ParallelOptions{MaxDegreeOfParallelism = 1},
i =>
Parallel.ForEach(keyImage, pair =>
{
if (progress.Token.IsCancellationRequested) return;
uint layerIndex = (uint)(_startLayerIndex + i);
switch (_importType)
{
case ImportTypes.Insert:
{
if (layerIndex >= SlicerFile.LayerCount) return;
if (SlicerFile.Resolution == fileFormat.Resolution)
{
SlicerFile[layerIndex] = fileFormat[i];
break;
}
using var layer = fileFormat[i].LayerMat;
using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution, fileFormatBoundingRectangle);
SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile);
break;
}
case ImportTypes.Replace:
{
if (layerIndex >= SlicerFile.LayerCount) return;
if (SlicerFile.Resolution == fileFormat.Resolution)
{
SlicerFile[layerIndex] = fileFormat[i];
break;
}
using var layer = fileFormat[i].LayerMat;
using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution, fileFormatBoundingRectangle);
SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile);
break;
}
case ImportTypes.Stack:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var mat = SlicerFile[layerIndex].LayerMat;
using var importMat = fileFormat[i].LayerMat;
var matRoi = new Mat(mat, roiRectangle);
var importMatRoi = new Mat(importMat, fileFormatBoundingRectangle);
importMatRoi.CopyTo(matRoi);
SlicerFile[layerIndex].LayerMat = mat;
break;
}
case ImportTypes.Merge:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.Add(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.Subtract:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.Subtract(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseAnd:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseAnd(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseOr:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseOr(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseXOr:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseXor(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
default:
throw new ArgumentOutOfRangeException();
}
using var mat = CvInvoke.Imread(pair.Value, ImreadModes.Grayscale);
if (pair.Key == 0) format.Resolution = mat.Size;
format[pair.Key] = new Layer(pair.Key, mat, format);
lock (progress.Mutex)
{
lastProcessedLayerIndex = Math.Max(lastProcessedLayerIndex, (int)layerIndex);
progress++;
}
});
fileFormat.Dispose();
progress.Token.ThrowIfCancellationRequested();
fileFormats.Add(format);
}
// Order remaining possible file formats
for (int i = 0; i < Count; i++)
{
if (Files[i].TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) continue;
var fileFormat = FileFormat.FindByExtension(Files[i].TagString, true, true);
if (fileFormat is null) continue;
fileFormat.FileFullPath = Files[i].TagString;
fileFormats.Add(fileFormat);
}
progress.Token.ThrowIfCancellationRequested();
}
if (_importType == ImportTypes.Stack)
{
new OperationMove(SlicerFile).Execute(progress);
}
if (fileFormats.Count == 0) return false;
if (lastProcessedLayerIndex <= -1) return false;
if (_importType == ImportTypes.Stack)
{
new OperationMove(SlicerFile, Enumerations.Anchor.TopLeft).Execute(progress);
}
if (lastProcessedLayerIndex + 1 < SlicerFile.LayerCount && _discardUnmodifiedLayers)
{
SlicerFile.LayerManager.ReallocateRange(0, (uint) lastProcessedLayerIndex);
}
foreach (var fileFormat in fileFormats)
{
if (!string.IsNullOrEmpty(fileFormat.FileFullPath))
{
fileFormat.Decode(fileFormat.FileFullPath, progress);
}
SlicerFile.LayerManager.RebuildLayersProperties();
SlicerFile.SuppressRebuildProperties = false;
var boundingRectangle = SlicerFile.LayerManager.GetBoundingRectangle(progress);
var fileFormatBoundingRectangle = fileFormat.LayerManager.GetBoundingRectangle(progress);
var roiRectangle = Rectangle.Empty;
return !progress.Token.IsCancellationRequested;
// Check if is possible to process this file
switch (_importType)
{
case ImportTypes.Insert:
if (SlicerFile.Resolution != fileFormat.Resolution &&
(SlicerFile.Resolution.Width < fileFormatBoundingRectangle.Width ||
SlicerFile.Resolution.Height < fileFormatBoundingRectangle.Height)) continue;
SlicerFile.LayerManager.Reallocate(_startLayerIndex, fileFormat.LayerCount);
break;
case ImportTypes.Replace:
case ImportTypes.Stack:
if (SlicerFile.Resolution != fileFormat.Resolution &&
(SlicerFile.Resolution.Width < fileFormatBoundingRectangle.Width ||
SlicerFile.Resolution.Height < fileFormatBoundingRectangle.Height)) continue;
//if(fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX || fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY)
// continue;
if (_importType == ImportTypes.Stack)
{
int x = 0;
int y = 0;
if (boundingRectangle.Right + _stackMargin + fileFormatBoundingRectangle.Width <
SlicerFile.ResolutionX)
{
x = boundingRectangle.Right + _stackMargin;
}
else
{
y = boundingRectangle.Bottom + _stackMargin;
}
if (x + fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX)
continue;
if (y + fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY)
continue;
roiRectangle = new Rectangle(x, y, fileFormatBoundingRectangle.Width,
fileFormatBoundingRectangle.Height);
}
if (_extendBeyondLayerCount)
{
int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount);
if (layerCountDifference > 0)
{
SlicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, _importType == ImportTypes.Stack);
}
}
break;
case ImportTypes.Merge:
if (SlicerFile.Resolution != fileFormat.Resolution) continue;
if (_extendBeyondLayerCount)
{
int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount);
if (layerCountDifference > 0)
{
SlicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, true);
}
}
break;
case ImportTypes.Subtract:
case ImportTypes.BitwiseAnd:
case ImportTypes.BitwiseOr:
case ImportTypes.BitwiseXOr:
if (SlicerFile.Resolution != fileFormat.Resolution) continue;
break;
}
progress.Reset(ProgressAction, fileFormat.LayerCount);
Parallel.For(0, fileFormat.LayerCount,
//new ParallelOptions{MaxDegreeOfParallelism = 1},
i =>
{
if (progress.Token.IsCancellationRequested) return;
uint layerIndex = (uint)(_startLayerIndex + i);
switch (_importType)
{
case ImportTypes.Insert:
{
if (layerIndex >= SlicerFile.LayerCount) return;
if (SlicerFile.Resolution == fileFormat.Resolution)
{
SlicerFile[layerIndex] = fileFormat[i];
break;
}
using var layer = fileFormat[i].LayerMat;
using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution, fileFormatBoundingRectangle);
SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile);
break;
}
case ImportTypes.Replace:
{
if (layerIndex >= SlicerFile.LayerCount) return;
if (SlicerFile.Resolution == fileFormat.Resolution)
{
SlicerFile[layerIndex] = fileFormat[i];
break;
}
using var layer = fileFormat[i].LayerMat;
using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution, fileFormatBoundingRectangle);
SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile);
break;
}
case ImportTypes.Stack:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var mat = SlicerFile[layerIndex].LayerMat;
using var importMat = fileFormat[i].LayerMat;
var matRoi = new Mat(mat, roiRectangle);
var importMatRoi = new Mat(importMat, fileFormatBoundingRectangle);
importMatRoi.CopyTo(matRoi);
SlicerFile[layerIndex].LayerMat = mat;
break;
}
case ImportTypes.Merge:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.Add(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.Subtract:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.Subtract(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseAnd:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseAnd(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseOr:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseOr(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseXOr:
{
if (layerIndex >= SlicerFile.LayerCount) return;
using var originalMat = SlicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseXor(originalMat, newMat, newMat);
SlicerFile[layerIndex].LayerMat = newMat;
break;
}
default:
throw new ArgumentOutOfRangeException();
}
lock (progress.Mutex)
{
lastProcessedLayerIndex = Math.Max(lastProcessedLayerIndex, (int)layerIndex);
progress++;
}
});
fileFormat.Dispose();
progress.Token.ThrowIfCancellationRequested();
}
if (_importType == ImportTypes.Stack)
{
new OperationMove(SlicerFile).Execute(progress);
}
if (lastProcessedLayerIndex <= -1) return false;
if (lastProcessedLayerIndex + 1 < SlicerFile.LayerCount && _discardUnmodifiedLayers)
{
SlicerFile.LayerManager.ReallocateRange(0, (uint)lastProcessedLayerIndex);
}
return true;
}, true);
return !progress.Token.IsCancellationRequested && result;
}
#endregion
@@ -575,17 +575,23 @@ namespace UVtools.Core.Operations
using var patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height));
using var alternatePatternMask = new Mat(matAlternatePattern, new Rectangle(0, 0, target.Width, target.Height));
/*if (_wallsOnly)
{
CvInvoke.BitwiseNot(patternMask, patternMask);
CvInvoke.BitwiseNot(alternatePatternMask, alternatePatternMask);
}*/
CvInvoke.BitwiseNot(patternMask, patternMask);
CvInvoke.BitwiseNot(alternatePatternMask, alternatePatternMask);
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
using var mat = SlicerFile[layerIndex].LayerMat;
Execute(mat, layerIndex, patternMask, alternatePatternMask);
SlicerFile[layerIndex].LayerMat = mat;
lock (progress.Mutex)
{
progress++;
}
progress.LockAndIncrement();
});
return !progress.Token.IsCancellationRequested;
@@ -611,27 +617,31 @@ namespace UVtools.Core.Operations
);
using Mat erode = new Mat();
using Mat diff = new Mat();
using Mat erode = new();
using Mat diff = new();
var original = mat.Clone();
var target = GetRoiOrDefault(mat);
using var mask = GetMask(mat);
CvInvoke.Erode(target, erode, kernel, anchor, wallThickness, BorderType.Reflect101, default);
CvInvoke.Subtract(target, erode, diff);
if (WallsOnly)
if (_wallsOnly)
{
CvInvoke.BitwiseAnd(diff, IsNormalPattern(layerIndex) ? patternMask : alternatePatternMask, target, mask);
CvInvoke.Add(erode, target, target, mask);
CvInvoke.Subtract(target, IsNormalPattern(layerIndex) ? patternMask : alternatePatternMask, target);
//CvInvoke.BitwiseAnd(diff, IsNormalPattern(layerIndex) ? patternMask : alternatePatternMask, target, mask);
CvInvoke.Add(erode, target, target);
}
else
{
CvInvoke.BitwiseAnd(erode, IsNormalPattern(layerIndex) ? patternMask : alternatePatternMask, target, mask);
CvInvoke.Add(target, diff, target, mask);
//CvInvoke.Subtract(target, erode, diff);
//CvInvoke.BitwiseAnd(erode, IsNormalPattern(layerIndex) ? patternMask : alternatePatternMask, target, mask);
//CvInvoke.Add(target, diff, target, mask);
CvInvoke.Subtract(target, IsNormalPattern(layerIndex) ? patternMask : alternatePatternMask, target, erode);
}
ApplyMask(original, target, mask);
return true;
}
+1 -1
View File
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
<Version>2.7.0</Version>
<Version>2.7.1</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
+5 -3
View File
@@ -86,9 +86,6 @@ $inputFile = read-host "Enter input file"
}
}
######################################
# All user inputs should be put here #
######################################
@@ -114,6 +111,11 @@ $morph = [UVtools.Core.Operations.OperationMorph]::new($slicerFile)
$morph.MorphOperation = [Emgu.CV.CvEnum.MorphOp]::Erode
$morph.IterationsStart = $iterations
$morph.SelectBottomLayers()
$validation = $morph.Validate()
if(![string]::IsNullOrEmpty($validation)) {
Write-Error $validation
return
}
if(!$morph.Execute($progress)){ return; }
+19
View File
@@ -83,22 +83,41 @@ Take **[Erode-Bottom.ps1](https://github.com/sn4k3/UVtools/blob/master/UVtools.S
$morph.MorphOperation = [Emgu.CV.CvEnum.MorphOp]::Erode
$morph.IterationsStart = $iterations
$morph.SelectBottomLayers()
$validation = $morph.Validate()
if(![string]::IsNullOrEmpty($validation)) {
Write-Error $validation
return
}
if(!$morph.Execute($progress)){ return }
# Reuse object and erode normal layers with 1 less iteration
$morph.IterationsStart = $iterations - 1
$morph.SelectNormalLayers()
if(![string]::IsNullOrEmpty($validation)) {
Write-Error $validation
return
}
if(!$morph.Execute($progress)){ return }
# Rotate all layers, 45º
$rotate = [UVtools.Core.Operations.OperationRotate]::new($slicerFile)
$rotate.AngleDegrees = 45;
$validation = $rotate.Validate()
if(![string]::IsNullOrEmpty($validation)) {
Write-Error $validation
return
}
if(!$rotate.Execute($progress)){ return }
# Rotate layer 1, 90º
$rotate.LayerIndexStart = 1
$rotate.LayerIndexEnd = 1
$rotate.AngleDegrees = 90
$validation = $rotate.Validate()
if(![string]::IsNullOrEmpty($validation)) {
Write-Error $validation
return
}
if(!$rotate.Execute($progress)){ return }
```
+1 -1
View File
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<Version>2.7.0</Version>
<Version>2.7.1</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">