From 2231fdaca309cec03bb02e59a52ed6685a906cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Wed, 24 Mar 2021 03:25:41 +0000 Subject: 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) --- CHANGELOG.md | 15 +- PrusaSlicer/printer/Phrozen Sonic Mini.ini | 4 +- .../sla_print/Universal 0.01 - Heavy Supports.ini | 6 +- .../sla_print/Universal 0.01 - Light Supports.ini | 6 +- .../sla_print/Universal 0.01 - Medium Supports.ini | 6 +- .../sla_print/Universal 0.02 - Heavy Supports.ini | 4 +- .../sla_print/Universal 0.02 - Light Supports.ini | 4 +- .../sla_print/Universal 0.02 - Medium Supports.ini | 4 +- .../sla_print/Universal 0.03 - Heavy Supports.ini | 6 +- .../sla_print/Universal 0.03 - Light Supports.ini | 6 +- .../sla_print/Universal 0.03 - Medium Supports.ini | 6 +- .../sla_print/Universal 0.04 - Heavy Supports.ini | 6 +- .../sla_print/Universal 0.04 - Light Supports.ini | 6 +- .../sla_print/Universal 0.04 - Medium Supports.ini | 6 +- .../sla_print/Universal 0.05 - Heavy Supports.ini | 6 +- .../sla_print/Universal 0.05 - Light Supports.ini | 6 +- .../sla_print/Universal 0.05 - Medium Supports.ini | 6 +- .../sla_print/Universal 0.10 - Heavy Supports.ini | 6 +- .../sla_print/Universal 0.10 - Light Supports.ini | 6 +- .../sla_print/Universal 0.10 - Medium Supports.ini | 6 +- .../sla_print/Universal 0.15 - Heavy Supports.ini | 6 +- .../sla_print/Universal 0.15 - Light Supports.ini | 6 +- .../sla_print/Universal 0.15 - Medium Supports.ini | 6 +- .../sla_print/Universal 0.20 - Heavy Supports.ini | 4 +- .../sla_print/Universal 0.20 - Light Supports.ini | 4 +- .../sla_print/Universal 0.20 - Medium Supports.ini | 4 +- UVtools.Core/Extensions/MathExtensions.cs | 6 +- UVtools.Core/Extensions/TimeExtensions.cs | 2 +- UVtools.Core/FileFormats/ChituboxFile.cs | 1 + UVtools.Core/FileFormats/FileFormat.cs | 147 +++++-- UVtools.Core/FileFormats/SL1File.cs | 25 +- UVtools.Core/GCode/GCodeBuilder.cs | 44 +- UVtools.Core/Layer/LayerIssue.cs | 38 ++ UVtools.Core/Layer/LayerManager.cs | 41 +- UVtools.Core/Managers/ClipboardManager.cs | 4 +- UVtools.Core/Operations/Operation.cs | 20 +- .../Operations/OperationCalibrateElephantFoot.cs | 29 +- .../Operations/OperationCalibrateExposureFinder.cs | 16 +- .../Operations/OperationCalibrateGrayscale.cs | 18 +- .../Operations/OperationCalibrateStressTower.cs | 21 +- .../Operations/OperationCalibrateTolerance.cs | 20 +- .../Operations/OperationCalibrateXYZAccuracy.cs | 18 +- .../Operations/OperationDynamicLayerHeight.cs | 11 +- UVtools.Core/Operations/OperationInfill.cs | 4 +- UVtools.Core/Operations/OperationLayerImport.cs | 475 ++++++++++----------- UVtools.Core/Operations/OperationPixelDimming.cs | 38 +- UVtools.Core/UVtools.Core.csproj | 2 +- UVtools.Scripts/Erode-Bottom.ps1 | 8 +- UVtools.Scripts/README.md | 19 + UVtools.WPF/UVtools.WPF.csproj | 2 +- 50 files changed, 657 insertions(+), 503 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 676cce4..bf60600 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/PrusaSlicer/printer/Phrozen Sonic Mini.ini b/PrusaSlicer/printer/Phrozen Sonic Mini.ini index 48baf59..bb8a159 100644 --- a/PrusaSlicer/printer/Phrozen Sonic Mini.ini +++ b/PrusaSlicer/printer/Phrozen Sonic Mini.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.01 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.01 - Heavy Supports.ini index 330e5b4..4d6b9e2 100644 --- a/PrusaSlicer/sla_print/Universal 0.01 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.01 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.01 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.01 - Light Supports.ini index 639cc29..9751fae 100644 --- a/PrusaSlicer/sla_print/Universal 0.01 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.01 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.01 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.01 - Medium Supports.ini index 9ad3b32..29152f2 100644 --- a/PrusaSlicer/sla_print/Universal 0.01 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.01 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.02 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.02 - Heavy Supports.ini index c77c787..5006b16 100644 --- a/PrusaSlicer/sla_print/Universal 0.02 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.02 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.02 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.02 - Light Supports.ini index dd7fad1..efac90b 100644 --- a/PrusaSlicer/sla_print/Universal 0.02 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.02 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.02 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.02 - Medium Supports.ini index ec58cf6..8ce99af 100644 --- a/PrusaSlicer/sla_print/Universal 0.02 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.02 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.03 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.03 - Heavy Supports.ini index 5f059ee..e4461be 100644 --- a/PrusaSlicer/sla_print/Universal 0.03 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.03 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.03 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.03 - Light Supports.ini index f6cf26b..9470443 100644 --- a/PrusaSlicer/sla_print/Universal 0.03 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.03 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.03 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.03 - Medium Supports.ini index fa95d0d..ad4320a 100644 --- a/PrusaSlicer/sla_print/Universal 0.03 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.03 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.04 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.04 - Heavy Supports.ini index 596f540..e676ae0 100644 --- a/PrusaSlicer/sla_print/Universal 0.04 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.04 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.04 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.04 - Light Supports.ini index f384ae1..c708e7c 100644 --- a/PrusaSlicer/sla_print/Universal 0.04 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.04 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.04 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.04 - Medium Supports.ini index 49cc824..ca05814 100644 --- a/PrusaSlicer/sla_print/Universal 0.04 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.04 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.05 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.05 - Heavy Supports.ini index 7ae04f5..d977dbd 100644 --- a/PrusaSlicer/sla_print/Universal 0.05 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.05 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.05 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.05 - Light Supports.ini index fd821fc..d43277a 100644 --- a/PrusaSlicer/sla_print/Universal 0.05 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.05 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.05 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.05 - Medium Supports.ini index 34c70d1..8ba705a 100644 --- a/PrusaSlicer/sla_print/Universal 0.05 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.05 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.10 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.10 - Heavy Supports.ini index 993832f..1bb6068 100644 --- a/PrusaSlicer/sla_print/Universal 0.10 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.10 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.10 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.10 - Light Supports.ini index 60c151b..a7d2e15 100644 --- a/PrusaSlicer/sla_print/Universal 0.10 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.10 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.10 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.10 - Medium Supports.ini index 65dc102..fad4920 100644 --- a/PrusaSlicer/sla_print/Universal 0.10 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.10 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.15 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.15 - Heavy Supports.ini index 8beb433..785b846 100644 --- a/PrusaSlicer/sla_print/Universal 0.15 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.15 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.15 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.15 - Light Supports.ini index 3c34639..b7f7e0d 100644 --- a/PrusaSlicer/sla_print/Universal 0.15 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.15 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.15 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.15 - Medium Supports.ini index 3b0061a..4d96921 100644 --- a/PrusaSlicer/sla_print/Universal 0.15 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.15 - Medium Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.20 - Heavy Supports.ini b/PrusaSlicer/sla_print/Universal 0.20 - Heavy Supports.ini index abce98c..10dfe45 100644 --- a/PrusaSlicer/sla_print/Universal 0.20 - Heavy Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.20 - Heavy Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.20 - Light Supports.ini b/PrusaSlicer/sla_print/Universal 0.20 - Light Supports.ini index 8e81454..5ff962f 100644 --- a/PrusaSlicer/sla_print/Universal 0.20 - Light Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.20 - Light Supports.ini @@ -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 diff --git a/PrusaSlicer/sla_print/Universal 0.20 - Medium Supports.ini b/PrusaSlicer/sla_print/Universal 0.20 - Medium Supports.ini index 00cced8..406fb98 100644 --- a/PrusaSlicer/sla_print/Universal 0.20 - Medium Supports.ini +++ b/PrusaSlicer/sla_print/Universal 0.20 - Medium Supports.ini @@ -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 diff --git a/UVtools.Core/Extensions/MathExtensions.cs b/UVtools.Core/Extensions/MathExtensions.cs index 4bb6c92..f38bc90 100644 --- a/UVtools.Core/Extensions/MathExtensions.cs +++ b/UVtools.Core/Extensions/MathExtensions.cs @@ -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; diff --git a/UVtools.Core/Extensions/TimeExtensions.cs b/UVtools.Core/Extensions/TimeExtensions.cs index 6b85322..cc90453 100644 --- a/UVtools.Core/Extensions/TimeExtensions.cs +++ b/UVtools.Core/Extensions/TimeExtensions.cs @@ -26,7 +26,7 @@ namespace UVtools.Core.Extensions /// /// /// - public static uint SecondsToMillisecondsUint(float value) => (uint)value * 1000; + public static uint SecondsToMillisecondsUint(float value) => (uint)(value * 1000f); /// /// Converts milliseconds to seconds diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs index de0a898..070d08f 100644 --- a/UVtools.Core/FileFormats/ChituboxFile.cs +++ b/UVtools.Core/FileFormats/ChituboxFile.cs @@ -1589,6 +1589,7 @@ namespace UVtools.Core.FileFormats this[layerIndex] = layer; + lock (progress.Mutex) { progress++; diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index e6c7dd7..a99f567 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -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.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.BottomLiftSpeed = BottomLiftSpeed; - slicerFile.LiftSpeed = LiftSpeed; - slicerFile.RetractSpeed = RetractSpeed; - - slicerFile.BottomLightOffDelay = BottomLightOffDelay; - slicerFile.LightOffDelay = LightOffDelay; - - 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.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.BottomLiftHeight = BottomLiftHeight; + slicerFile.LiftHeight = LiftHeight; + + slicerFile.BottomLiftSpeed = BottomLiftSpeed; + slicerFile.LiftSpeed = LiftSpeed; + slicerFile.RetractSpeed = RetractSpeed; + + slicerFile.BottomLightOffDelay = BottomLightOffDelay; + slicerFile.LightOffDelay = LightOffDelay; + + 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.SetThumbnails(Thumbnails); + }); - slicerFile.SuppressRebuildProperties = false; - slicerFile.SetThumbnails(Thumbnails); slicerFile.Encode(fileFullPath, progress); return slicerFile; @@ -1874,6 +1878,55 @@ namespace UVtools.Core.FileFormats return AntiAliasing; } + /// + /// SuppressRebuildProperties = true, call the invoker and reset SuppressRebuildProperties = false + /// + /// Action work + /// True to force rebuild the layer properties after the work and before reset to false + /// True to recalculate z position of each layer (requires = true), otherwise false + /// Property name to change for each layer, use null to update all properties (requires = true) + 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); + } + + /// + /// SuppressRebuildProperties = true, call the invoker and reset SuppressRebuildProperties = false + /// + /// Action work + /// True to force rebuild the layer properties after the work and before reset to false + /// True to recalculate z position of each layer (requires = true), otherwise false + /// Property name to change for each layer, use null to update all properties (requires = true) + public bool SuppressRebuildPropertiesWork(Func 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 } } diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs index 0c083bc..7f854f1 100644 --- a/UVtools.Core/FileFormats/SL1File.cs +++ b/UVtools.Core/FileFormats/SL1File.cs @@ -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; diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs index 6f86920..33b5cc0 100644 --- a/UVtools.Core/GCode/GCodeBuilder.cs +++ b/UVtools.Core/GCode/GCodeBuilder.cs @@ -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 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; - } + 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; + } - 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; + } + }); } } diff --git a/UVtools.Core/Layer/LayerIssue.cs b/UVtools.Core/Layer/LayerIssue.cs index fb55675..5bac5e8 100644 --- a/UVtools.Core/Layer/LayerIssue.cs +++ b/UVtools.Core/Layer/LayerIssue.cs @@ -424,4 +424,42 @@ namespace UVtools.Core } } #endregion + + #region ResinTrapGround + + public sealed class ResinTrapGroup + { + public List> 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{hollowArea}); + return index; + } + + // Exists + Groups[index].Add(hollowArea); + + return index; + } + } + #endregion + } diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index 600647c..9a60479 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -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 /// - /// Desmodify all layers + /// Set the IsModified property for all layers /// - 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 /// 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; } /// diff --git a/UVtools.Core/Managers/ClipboardManager.cs b/UVtools.Core/Managers/ClipboardManager.cs index d27c512..cb851fa 100644 --- a/UVtools.Core/Managers/ClipboardManager.cs +++ b/UVtools.Core/Managers/ClipboardManager.cs @@ -262,9 +262,7 @@ namespace UVtools.Core.Managers } Add(clip); - slicerFile.SuppressRebuildProperties = true; - CurrentIndex = 0; - slicerFile.SuppressRebuildProperties = false; + slicerFile.SuppressRebuildPropertiesWork(() => CurrentIndex = 0); } /// diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs index 99079de..168d629 100644 --- a/UVtools.Core/Operations/Operation.cs +++ b/UVtools.Core/Operations/Operation.cs @@ -226,7 +226,7 @@ namespace UVtools.Core.Operations /// /// Validates the operation /// - /// null or empty if validates, or else, return a string with error message + /// null or empty if validates, otherwise return a string with error message 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); } diff --git a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs index e5e3caa..5da95f4 100644 --- a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs +++ b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs @@ -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; } diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs index 28df4f2..539c270 100644 --- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs +++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs @@ -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); diff --git a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs index 68075b8..215bccd 100644 --- a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs +++ b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs @@ -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; } diff --git a/UVtools.Core/Operations/OperationCalibrateStressTower.cs b/UVtools.Core/Operations/OperationCalibrateStressTower.cs index 231ba70..e588b19 100644 --- a/UVtools.Core/Operations/OperationCalibrateStressTower.cs +++ b/UVtools.Core/Operations/OperationCalibrateStressTower.cs @@ -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; } diff --git a/UVtools.Core/Operations/OperationCalibrateTolerance.cs b/UVtools.Core/Operations/OperationCalibrateTolerance.cs index f5d7a13..13ad30d 100644 --- a/UVtools.Core/Operations/OperationCalibrateTolerance.cs +++ b/UVtools.Core/Operations/OperationCalibrateTolerance.cs @@ -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); diff --git a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs index 0c9c1e2..40756dd 100644 --- a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs +++ b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs @@ -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; } diff --git a/UVtools.Core/Operations/OperationDynamicLayerHeight.cs b/UVtools.Core/Operations/OperationDynamicLayerHeight.cs index c53ecdf..24930d6 100644 --- a/UVtools.Core/Operations/OperationDynamicLayerHeight.cs +++ b/UVtools.Core/Operations/OperationDynamicLayerHeight.cs @@ -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; diff --git a/UVtools.Core/Operations/OperationInfill.cs b/UVtools.Core/Operations/OperationInfill.cs index 8ffdde1..745750e 100644 --- a/UVtools.Core/Operations/OperationInfill.cs +++ b/UVtools.Core/Operations/OperationInfill.cs @@ -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(); diff --git a/UVtools.Core/Operations/OperationLayerImport.cs b/UVtools.Core/Operations/OperationLayerImport.cs index c85273d..c3be204 100644 --- a/UVtools.Core/Operations/OperationLayerImport.cs +++ b/UVtools.Core/Operations/OperationLayerImport.cs @@ -224,282 +224,281 @@ namespace UVtools.Core.Operations protected override bool ExecuteInternally(OperationProgress progress) { progress.ItemCount = 0; - SlicerFile.SuppressRebuildProperties = true; - - List fileFormats = new(); - List> 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) keyImage.Count, Files[i].TagString)); - } + bool result = SlicerFile.SuppressRebuildPropertiesWork(() => { + List fileFormats = new(); + List> keyImage = new(); + int lastProcessedLayerIndex = -1; - // 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); + // 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)keyImage.Count, Files[i].TagString)); + } - Parallel.ForEach(keyImage, pair => + // Create virtual file format with images + if (keyImage.Count > 0) { - 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); + progress.Reset("Packing images", (uint)keyImage.Count); + SL1File format = new(); + format.LayerManager = new LayerManager((uint)keyImage.Count, format); - lock (progress.Mutex) + Parallel.ForEach(keyImage, pair => { - 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 (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); - if (_importType == ImportTypes.Stack) - { - new OperationMove(SlicerFile, Enumerations.Anchor.TopLeft).Execute(progress); - } + lock (progress.Mutex) + { + progress++; + } + }); - foreach (var fileFormat in fileFormats) - { - if (!string.IsNullOrEmpty(fileFormat.FileFullPath)) - { - fileFormat.Decode(fileFormat.FileFullPath, progress); + progress.Token.ThrowIfCancellationRequested(); + fileFormats.Add(format); } - 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) + // Order remaining possible file formats + for (int i = 0; i < Count; i++) { - 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 (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); + } - if (boundingRectangle.Right + _stackMargin + fileFormatBoundingRectangle.Width < - SlicerFile.ResolutionX) - { - x = boundingRectangle.Right + _stackMargin; - } - else - { - y = boundingRectangle.Bottom + _stackMargin; - } + progress.Token.ThrowIfCancellationRequested(); - if (x + fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX) - continue; - if (y + fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY) - continue; + if (fileFormats.Count == 0) return false; - roiRectangle = new Rectangle(x, y, fileFormatBoundingRectangle.Width, - fileFormatBoundingRectangle.Height); - } + if (_importType == ImportTypes.Stack) + { + new OperationMove(SlicerFile, Enumerations.Anchor.TopLeft).Execute(progress); + } - if (_extendBeyondLayerCount) - { - int layerCountDifference = (int) (_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount); - if (layerCountDifference > 0) - { - SlicerFile.LayerManager.ReallocateEnd((uint) layerCountDifference, _importType == ImportTypes.Stack); - } - } + foreach (var fileFormat in fileFormats) + { + if (!string.IsNullOrEmpty(fileFormat.FileFullPath)) + { + fileFormat.Decode(fileFormat.FileFullPath, progress); + } - 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; - } + var boundingRectangle = SlicerFile.LayerManager.GetBoundingRectangle(progress); + var fileFormatBoundingRectangle = fileFormat.LayerManager.GetBoundingRectangle(progress); + var roiRectangle = Rectangle.Empty; - progress.Reset(ProgressAction, fileFormat.LayerCount); - Parallel.For(0, fileFormat.LayerCount, - //new ParallelOptions{MaxDegreeOfParallelism = 1}, - i => + // Check if is possible to process this file + switch (_importType) { - if (progress.Token.IsCancellationRequested) return; - uint layerIndex = (uint)(_startLayerIndex + i); - - switch (_importType) - { - case ImportTypes.Insert: + 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) { - if (layerIndex >= SlicerFile.LayerCount) return; - if (SlicerFile.Resolution == fileFormat.Resolution) + int x = 0; + int y = 0; + + if (boundingRectangle.Right + _stackMargin + fileFormatBoundingRectangle.Width < + SlicerFile.ResolutionX) { - SlicerFile[layerIndex] = fileFormat[i]; - break; + x = boundingRectangle.Right + _stackMargin; + } + else + { + y = boundingRectangle.Bottom + _stackMargin; } - using var layer = fileFormat[i].LayerMat; - using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution, fileFormatBoundingRectangle); - SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile); + if (x + fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX) + continue; + if (y + fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY) + continue; - break; + roiRectangle = new Rectangle(x, y, fileFormatBoundingRectangle.Width, + fileFormatBoundingRectangle.Height); } - case ImportTypes.Replace: + + if (_extendBeyondLayerCount) { - if (layerIndex >= SlicerFile.LayerCount) return; - if (SlicerFile.Resolution == fileFormat.Resolution) + int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount); + if (layerCountDifference > 0) { - SlicerFile[layerIndex] = fileFormat[i]; - break; + SlicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, _importType == ImportTypes.Stack); } - - 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: + + break; + case ImportTypes.Merge: + if (SlicerFile.Resolution != fileFormat.Resolution) continue; + if (_extendBeyondLayerCount) { - 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; + int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount); + if (layerCountDifference > 0) + { + SlicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, true); + } } - case ImportTypes.BitwiseXOr: + 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) { - 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; + 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(); } - default: - throw new ArgumentOutOfRangeException(); - } - lock (progress.Mutex) - { - lastProcessedLayerIndex = Math.Max(lastProcessedLayerIndex, (int)layerIndex); - progress++; - } - }); - - fileFormat.Dispose(); - progress.Token.ThrowIfCancellationRequested(); - } + lock (progress.Mutex) + { + lastProcessedLayerIndex = Math.Max(lastProcessedLayerIndex, (int)layerIndex); + progress++; + } + }); - if (_importType == ImportTypes.Stack) - { - new OperationMove(SlicerFile).Execute(progress); - } + fileFormat.Dispose(); + progress.Token.ThrowIfCancellationRequested(); + } - if (lastProcessedLayerIndex <= -1) return false; + if (_importType == ImportTypes.Stack) + { + new OperationMove(SlicerFile).Execute(progress); + } - if (lastProcessedLayerIndex + 1 < SlicerFile.LayerCount && _discardUnmodifiedLayers) - { - SlicerFile.LayerManager.ReallocateRange(0, (uint) lastProcessedLayerIndex); - } + if (lastProcessedLayerIndex <= -1) return false; - SlicerFile.LayerManager.RebuildLayersProperties(); - SlicerFile.SuppressRebuildProperties = false; + if (lastProcessedLayerIndex + 1 < SlicerFile.LayerCount && _discardUnmodifiedLayers) + { + SlicerFile.LayerManager.ReallocateRange(0, (uint)lastProcessedLayerIndex); + } - return !progress.Token.IsCancellationRequested; + return true; + }, true); + + return !progress.Token.IsCancellationRequested && result; } #endregion diff --git a/UVtools.Core/Operations/OperationPixelDimming.cs b/UVtools.Core/Operations/OperationPixelDimming.cs index 8dd158a..95341a3 100644 --- a/UVtools.Core/Operations/OperationPixelDimming.cs +++ b/UVtools.Core/Operations/OperationPixelDimming.cs @@ -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; } diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 4ba8152..67e3169 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, calibration, repair, conversion and manipulation - 2.7.0 + 2.7.1 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 diff --git a/UVtools.Scripts/Erode-Bottom.ps1 b/UVtools.Scripts/Erode-Bottom.ps1 index 5f72bcd..84bce80 100644 --- a/UVtools.Scripts/Erode-Bottom.ps1 +++ b/UVtools.Scripts/Erode-Bottom.ps1 @@ -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; } diff --git a/UVtools.Scripts/README.md b/UVtools.Scripts/README.md index b89927b..0659626 100644 --- a/UVtools.Scripts/README.md +++ b/UVtools.Scripts/README.md @@ -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 } ``` diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 129509f..f6ff058 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ LICENSE https://github.com/sn4k3/UVtools Git - 2.7.0 + 2.7.1 -- cgit v1.2.3