mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-30 12:22:17 +02:00
v2.4.0
* (Upgrade) EmguCV/OpenCV to v4.5.1
* (Upgrade) AvaloniaUI to 1.0
* (Improvement) GUI re-touched
* (Improvement) Make pixel editor tab to disappear when pixel editor is disabled
* (Improvement) Simplify the output filename from PrusaSlicer profiles
* (Improvement) All operations require a slicer file at constructor rather than on execute, this allow exposure the open file to the operation before run it
* (Improvement) Calibrations: Auto set "Mirror Output" if open file have MirrorDisplay set
* (Change) Tool - Redraw model/supports icon
* (Change) photon and cbddlp to use version 3 by default
* (Add) Tool - Dynamic layer height: Analyze and optimize the model with dynamic layer heights, larger angles will slice at lower layer height
while more straight angles will slice larger layer height. (#131)
* (Add) Calibration - Exposure time finder: Generates test models with various strategies and increments to verify the best exposure time for a given layer height
* (Add) File load checks, trigger error when a file have critical errors and attempt to fix non-critical errors
* Layers must have an valid image, otherwise trigger an error
* Layers must have a incremental or equal position Z than it previous, otherwise trigger an error
* If layer 0 starts at 0mm it will auto fix all layers, it will add Layer Height to the current z at every layer
* (Add) Tool - Edit print parameters: Allow set parameters to each x layers and skip n layers inside the given range.
This allow the use of optimizations in a layer pattern, for example, to set 3s for a layer but 2.5s for the next.
* (Add) Layer height property to "Layer Data" table: Shows layer height for the slice
* (Fix) When automations applied and file is saved, it will not warn user about file overwrite for the first time save
* (Fix) Tool - Redraw model/supports: Disable apply button when no file selected
* (Fix) Tool - Infill: Lack of equality member to test if same infill profile already exists
* (Fix) Auto converted files from SL1 where clipping filename at first dot (.), now it only strips known extensions
* (Fix) SL1 encoded files wasn't generating the right information and lead to printer crash
* (Fix) PrusaSlicer printer "Anycubic Photon S" LiftSpeed was missing and contains a typo (#135)
* (Fix) PrusaSlicer profile manager wasnt marking missing profiles to be installed (#135)
* (Fix) PrusaSlicer folder search on linux to also look at %HOME%/.config/PrusaSlicer (#135, #136)
* (Fix) Operations were revised and some bug fixed, most about can't cancel the progress
* (Fix) Some typos on tooltips
* (Fix) Prevent PhotonS from enconding, it will trigger error now as this format is read-only
* **(Fix) Ctrl + Shift + Z to redo the last operation:**
* The layer range is reseted instead of pull the used values
* Tool - Arithmetic always disabled
* Action - Layer import didn't generate info and always disabled
This commit is contained in:
@@ -6,6 +6,8 @@ labels: enhancement
|
||||
assignees: sn4k3
|
||||
---
|
||||
|
||||
Also look at: https://github.com/sn4k3/UVtools/discussions/categories/ideas
|
||||
|
||||
<span style="color:red">**! Before continue, please look/search on closed topics if your case was already been discussed, if yes and related, comment there instead.**</span>
|
||||
|
||||
## Is your feature request related to a problem? Please describe
|
||||
|
||||
@@ -6,7 +6,7 @@ labels: question
|
||||
assignees: sn4k3
|
||||
---
|
||||
|
||||
<span style="color:red">**! Before continue, please look/search on closed topics if your case was already been discussed, if yes and related, comment there instead.**</span>
|
||||
|
||||
## Describe the question
|
||||
A clear and concise description of your question.
|
||||
## READ THIS
|
||||
Do not use issues to post questions! Use discussions instead!:
|
||||
https://github.com/sn4k3/UVtools/discussions/categories/q-a
|
||||
## READ THIS
|
||||
@@ -6,10 +6,7 @@ labels: script
|
||||
assignees: sn4k3
|
||||
---
|
||||
|
||||
## Describe what your script does
|
||||
A clear and concise description of your script, and all it steps.
|
||||
|
||||
|
||||
```Powershell
|
||||
#Paste your code here or attach the .ps1 file
|
||||
```
|
||||
## READ THIS
|
||||
Do not use issues to post scripts! Use discussions instead!:
|
||||
https://github.com/sn4k3/UVtools/discussions/categories/scripts
|
||||
## READ THIS
|
||||
@@ -1,5 +1,42 @@
|
||||
# Changelog
|
||||
|
||||
## 06/02/2021 - v2.4.0
|
||||
|
||||
* (Upgrade) EmguCV/OpenCV to v4.5.1
|
||||
* (Upgrade) AvaloniaUI to 1.0
|
||||
* (Improvement) GUI re-touched
|
||||
* (Improvement) Make pixel editor tab to disappear when pixel editor is disabled
|
||||
* (Improvement) Simplify the output filename from PrusaSlicer profiles
|
||||
* (Improvement) All operations require a slicer file at constructor rather than on execute, this allow exposure the open file to the operation before run it
|
||||
* (Improvement) Calibrations: Auto set "Mirror Output" if open file have MirrorDisplay set
|
||||
* (Change) Tool - Redraw model/supports icon
|
||||
* (Change) photon and cbddlp to use version 3 by default
|
||||
* (Add) Tool - Dynamic layer height: Analyze and optimize the model with dynamic layer heights, larger angles will slice at lower layer height
|
||||
while more straight angles will slice larger layer height. (#131)
|
||||
* (Add) Calibration - Exposure time finder: Generates test models with various strategies and increments to verify the best exposure time for a given layer height
|
||||
* (Add) File load checks, trigger error when a file have critical errors and attempt to fix non-critical errors
|
||||
* Layers must have an valid image, otherwise trigger an error
|
||||
* Layers must have a incremental or equal position Z than it previous, otherwise trigger an error
|
||||
* If layer 0 starts at 0mm it will auto fix all layers, it will add Layer Height to the current z at every layer
|
||||
* (Add) Tool - Edit print parameters: Allow set parameters to each x layers and skip n layers inside the given range.
|
||||
This allow the use of optimizations in a layer pattern, for example, to set 3s for a layer but 2.5s for the next.
|
||||
* (Add) Layer height property to "Layer Data" table: Shows layer height for the slice
|
||||
* (Fix) When automations applied and file is saved, it will not warn user about file overwrite for the first time save
|
||||
* (Fix) Tool - Redraw model/supports: Disable apply button when no file selected
|
||||
* (Fix) Tool - Infill: Lack of equality member to test if same infill profile already exists
|
||||
* (Fix) Auto converted files from SL1 where clipping filename at first dot (.), now it only strips known extensions
|
||||
* (Fix) SL1 encoded files wasn't generating the right information and lead to printer crash
|
||||
* (Fix) PrusaSlicer printer "Anycubic Photon S" LiftSpeed was missing and contains a typo (#135)
|
||||
* (Fix) PrusaSlicer profile manager wasnt marking missing profiles to be installed (#135)
|
||||
* (Fix) PrusaSlicer folder search on linux to also look at %HOME%/.config/PrusaSlicer (#135, #136)
|
||||
* (Fix) Operations were revised and some bug fixed, most about can't cancel the progress
|
||||
* (Fix) Some typos on tooltips
|
||||
* (Fix) Prevent PhotonS from enconding, it will trigger error now as this format is read-only
|
||||
* **(Fix) Ctrl + Shift + Z to redo the last operation:**
|
||||
* The layer range is reseted instead of pull the used values
|
||||
* Tool - Arithmetic always disabled
|
||||
* Action - Layer import didn't generate info and always disabled
|
||||
|
||||
## 22/01/2021 - v2.3.2
|
||||
|
||||
* (Add) Settings - Automations: Change only light-off delay if value is zero (Enabled by default)
|
||||
|
||||
@@ -30,6 +30,8 @@ class FixedEncoder : System.Text.UTF8Encoding {
|
||||
### Configuration ###
|
||||
####################################
|
||||
$enableMSI = $true
|
||||
$buildOnly = $null
|
||||
#$buildOnly = ""#"win-x64"
|
||||
# Profilling
|
||||
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
|
||||
$deployStopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
|
||||
@@ -83,22 +85,22 @@ $runtimes =
|
||||
@{
|
||||
"win-x64" = @{
|
||||
"extraCmd" = "-p:PublishReadyToRun=true"
|
||||
"exclude" = @("libcvextern.so", "libcvextern.dylib", "UVtools.sh")
|
||||
"exclude" = @("UVtools.sh")
|
||||
"include" = @()
|
||||
}
|
||||
"linux-x64" = @{
|
||||
"extraCmd" = "-p:PublishReadyToRun=true"
|
||||
"exclude" = @("x86", "x64", "libcvextern.dylib")
|
||||
"exclude" = @()
|
||||
"include" = @("libcvextern.so")
|
||||
}
|
||||
"arch-x64" = @{
|
||||
"extraCmd" = "-p:PublishReadyToRun=true"
|
||||
"exclude" = @("x86", "x64", "libcvextern.dylib", "libcvextern.so")
|
||||
"exclude" = @()
|
||||
"include" = @("libcvextern.so")
|
||||
}
|
||||
"rhel-x64" = @{
|
||||
"extraCmd" = "-p:PublishReadyToRun=true"
|
||||
"exclude" = @("x86", "x64", "libcvextern.dylib")
|
||||
"exclude" = @()
|
||||
"include" = @("libcvextern.so")
|
||||
}
|
||||
#"unix-x64" = @{
|
||||
@@ -107,12 +109,13 @@ $runtimes =
|
||||
#}
|
||||
"osx-x64" = @{
|
||||
"extraCmd" = "-p:PublishReadyToRun=true"
|
||||
"exclude" = @("x86", "x64", "libcvextern.so")
|
||||
"exclude" = @()
|
||||
"include" = @("libcvextern.dylib")
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($obj in $runtimes.GetEnumerator()) {
|
||||
if(![string]::IsNullOrWhiteSpace($buildOnly) -and !$buildOnly.Equals($obj.Name)) {continue}
|
||||
# Configuration
|
||||
$deployStopWatch.Restart()
|
||||
$runtime = $obj.Name; # runtime name
|
||||
|
||||
@@ -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_ANYCUBIC\nPRINTER_MODEL_PHOTON_S\nFILEFORMAT_PWS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_1\nLiftHeight_6\nLiftingSpeed_60\nRetractSpeed_150\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_S\nFILEFORMAT_PWS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_1\nLiftHeight_6\nLiftSpeed_60\nRetractSpeed_150\nEND_CUSTOM_VALUES
|
||||
printer_settings_id =
|
||||
printer_technology = SLA
|
||||
printer_variant = default
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:30:16 UTC
|
||||
# generated by PrusaSlicer 2.3.0+win64 on 2021-02-06 at 03:35:53 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_QIDI\nPRINTER_MODEL_I-BOX_MONO\nFILEFORMAT_CTB\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_6\nLiftHeight_6\nBottomLiftSpeed_65\nLiftSpeed_65\nRetractSpeed_100\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_QIDI\nPRINTER_MODEL_I-BOX_MONO\nFILEFORMAT_CTB\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_7\nLiftHeight_7\nBottomLiftSpeed_80\nLiftSpeed_80\nRetractSpeed_120\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES
|
||||
printer_settings_id =
|
||||
printer_technology = SLA
|
||||
printer_variant = default
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.025 UltraDetail
|
||||
layer_height = 0.01
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.025 UltraDetail
|
||||
layer_height = 0.01
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.025 UltraDetail
|
||||
layer_height = 0.01
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.025 UltraDetail
|
||||
layer_height = 0.02
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.025 UltraDetail
|
||||
layer_height = 0.02
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.025 UltraDetail
|
||||
layer_height = 0.02
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.035 Detail
|
||||
layer_height = 0.03
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.035 Detail
|
||||
layer_height = 0.03
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.035 Detail
|
||||
layer_height = 0.03
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.05 Normal
|
||||
layer_height = 0.04
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.05 Normal
|
||||
layer_height = 0.04
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.05 Normal
|
||||
layer_height = 0.04
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.05 Normal
|
||||
layer_height = 0.05
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.05 Normal
|
||||
layer_height = 0.05
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.05 Normal
|
||||
layer_height = 0.05
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.1
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.1
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.1
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.15
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.15
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.15
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.2
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.2
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
@@ -9,7 +9,7 @@ hollowing_min_thickness = 3
|
||||
hollowing_quality = 0.5
|
||||
inherits = 0.1 Fast
|
||||
layer_height = 0.2
|
||||
output_filename_format = {input_filename_base}_{material_type}{layer_height}mm_{printer_model}_{print_time}.sl1
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{print_time}.sl1
|
||||
pad_around_object = 0
|
||||
pad_around_object_everywhere = 0
|
||||
pad_brim_size = 1.6
|
||||
|
||||
Binary file not shown.
@@ -63,10 +63,27 @@ namespace UVtools.Core.Extensions
|
||||
|
||||
public static unsafe Span<T> GetPixelRowSpan<T>(this Mat mat, int y, int length = 0, int offset = 0)
|
||||
{
|
||||
return new Span<T>(IntPtr.Add(mat.DataPointer, y * mat.Step + offset).ToPointer(), length == 0 ? mat.Step : length);
|
||||
return new(IntPtr.Add(mat.DataPointer, y * mat.Step + offset).ToPointer(), length == 0 ? mat.Step : length);
|
||||
//return mat.GetPixelSpan<T>().Slice(offset, mat.Step);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets if a <see cref="Mat"/> is all zeroed
|
||||
/// </summary>
|
||||
/// <param name="mat"></param>
|
||||
/// <param name="threshold">Pixel brightness threshold</param>
|
||||
/// <returns></returns>
|
||||
public static unsafe bool IsZeroed(this Mat mat, byte threshold = 0)
|
||||
{
|
||||
var ptr = mat.GetBytePointer();
|
||||
for (int i = 0; i < mat.GetLength(); i++)
|
||||
{
|
||||
if (ptr[i] > threshold) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static void Transform(this Mat src, double xScale, double yScale, double xTrans = 0, double yTrans = 0, Size dstSize = default, Inter interpolation = Inter.Linear)
|
||||
{
|
||||
//var dst = new Mat(src.Size, src.Depth, src.NumberOfChannels);
|
||||
|
||||
@@ -103,12 +103,16 @@ namespace UVtools.Core.Extensions
|
||||
public static uint DecimalDigits(this decimal val)
|
||||
{
|
||||
var valStr = val.ToString(CultureInfo.InvariantCulture).TrimEnd('0');
|
||||
if (string.IsNullOrEmpty(valStr) || valStr[valStr.Length-1] == '.') return 0;
|
||||
if (string.IsNullOrEmpty(valStr) || valStr[^1] == '.') return 0;
|
||||
|
||||
var index = valStr.IndexOf('.');
|
||||
if (index < 0) return 0;
|
||||
|
||||
return (uint)(valStr.Substring(index).Length - 1);
|
||||
}
|
||||
|
||||
public static bool IsInteger(this float val, float tolerance = 0.0001f) => Math.Abs(val - Math.Floor(val)) < tolerance;
|
||||
public static bool IsInteger(this double val, double tolerance = 0.0001) => Math.Abs(val - Math.Floor(val)) < tolerance;
|
||||
public static bool IsInteger(this decimal val) => val == Math.Floor(val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace UVtools.Core.Extensions
|
||||
@@ -19,5 +20,18 @@ namespace UVtools.Core.Extensions
|
||||
var splitPath = path.Split('.', 2, StringSplitOptions.TrimEntries);
|
||||
return splitPath.Length == 0 ? string.Empty : splitPath[0];
|
||||
}
|
||||
|
||||
public static string GetFileNameStripExtensions(string path, List<string> extensions)
|
||||
{
|
||||
path = Path.GetFileName(path);
|
||||
if (string.IsNullOrEmpty(path)) return string.Empty;
|
||||
foreach (var extension in extensions)
|
||||
{
|
||||
var dotExtension = $".{extension}";
|
||||
if (path.EndsWith(dotExtension)) return path.Remove(path.Length - dotExtension.Length);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
|
||||
namespace UVtools.Core.Extensions
|
||||
@@ -34,5 +35,8 @@ namespace UVtools.Core.Extensions
|
||||
adjustedSize,
|
||||
SizeSuffixes[mag]);
|
||||
}
|
||||
|
||||
public static Size Inflate(this Size size, int pixels) => new (size.Width + pixels, size.Height + pixels);
|
||||
public static Size Inflate(this Size size, int width, int height) => new (size.Width + width, size.Height + height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,12 +540,8 @@ namespace UVtools.Core.FileFormats
|
||||
GCode = null;
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
//var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
|
||||
|
||||
if (Printer == PrinterType.Unknown)
|
||||
@@ -662,20 +658,14 @@ namespace UVtools.Core.FileFormats
|
||||
RebuildGCode();
|
||||
outputFile.PutFileContent($"{filename}.gcode", GCode.ToString(), ZipArchiveMode.Create);
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
if(progress is null) progress = new OperationProgress(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
using (var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry("manifest.xml");
|
||||
if (!ReferenceEquals(entry, null)) // Wanhao
|
||||
if (entry is not null) // Wanhao
|
||||
{
|
||||
//DecodeXML(fileFullPath, inputFile, progress);
|
||||
Printer = PrinterType.Wanhao;
|
||||
|
||||
@@ -1336,17 +1336,13 @@ namespace UVtools.Core.FileFormats
|
||||
LayerDefinitions = null;
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
LayersHash.Clear();
|
||||
|
||||
HeaderSettings.Magic = fileFullPath.EndsWith(".ctb") || fileFullPath.EndsWith($".ctb{TemporaryFileAppend}") ? MAGIC_CBT : MAGIC_CBDDLP;
|
||||
HeaderSettings.PrintParametersSize = (uint)Helpers.Serializer.SizeOf(PrintParametersSettings);
|
||||
|
||||
|
||||
if (IsCbtFile)
|
||||
{
|
||||
if (SlicerInfoSettings.AntiAliasLevel <= 1)
|
||||
@@ -1380,8 +1376,8 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderSettings.Version = 2;
|
||||
HeaderSettings.EncryptionKey = 0;
|
||||
//HeaderSettings.Version = 2;
|
||||
HeaderSettings.EncryptionKey = 0; // Force disable encryption
|
||||
SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CBDDLP;
|
||||
}
|
||||
|
||||
@@ -1511,8 +1507,6 @@ namespace UVtools.Core.FileFormats
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
AfterEncode();
|
||||
|
||||
Debug.WriteLine("Encode Results:");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
Debug.WriteLine(Previews[0]);
|
||||
@@ -1524,13 +1518,8 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
if(progress is null) progress = new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
|
||||
@@ -1659,8 +1648,7 @@ namespace UVtools.Core.FileFormats
|
||||
return;
|
||||
}
|
||||
|
||||
using (var image = LayerDefinitions[0, layerIndex].Decode((uint) layerIndex))
|
||||
{
|
||||
using var image = LayerDefinitions[0, layerIndex].Decode((uint) layerIndex);
|
||||
var layer = new Layer((uint) layerIndex, image, LayerManager)
|
||||
{
|
||||
PositionZ = LayerDefinitions[0, layerIndex].LayerPositionZ,
|
||||
@@ -1686,11 +1674,8 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -400,11 +400,8 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
|
||||
{
|
||||
if (Thumbnails.Length > 0 && !ReferenceEquals(Thumbnails[0], null))
|
||||
@@ -448,21 +445,14 @@ namespace UVtools.Core.FileFormats
|
||||
progress++;
|
||||
}
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
if(progress is null) progress = new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry("run.gcode");
|
||||
if (!ReferenceEquals(entry, null))
|
||||
if (entry is not null)
|
||||
{
|
||||
//Clear();
|
||||
//throw new FileLoadException("run.gcode not found", fileFullPath);
|
||||
|
||||
@@ -999,11 +999,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinitions = null;
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
LayersHash.Clear();
|
||||
|
||||
/*if (HeaderSettings.EncryptionKey == 0)
|
||||
@@ -1118,8 +1115,6 @@ namespace UVtools.Core.FileFormats
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
AfterEncode();
|
||||
|
||||
Debug.WriteLine("Encode Results:");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
Debug.WriteLine(Previews[0]);
|
||||
@@ -1128,11 +1123,8 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
if(progress is null) progress = new OperationProgress(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
|
||||
@@ -1235,8 +1227,6 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace UVtools.Core.FileFormats
|
||||
/// <summary>
|
||||
/// Slicer <see cref="FileFormat"/> representation
|
||||
/// </summary>
|
||||
public abstract class FileFormat : BindableBase, IFileFormat, IDisposable, IEquatable<FileFormat>, IEnumerable<Layer>
|
||||
public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFormat>, IEnumerable<Layer>
|
||||
{
|
||||
#region Constants
|
||||
public const string TemporaryFileAppend = ".tmp";
|
||||
@@ -44,6 +44,9 @@ namespace UVtools.Core.FileFormats
|
||||
public const float DefaultLightOffDelay = 0;
|
||||
public const byte DefaultBottomLightPWM = 255;
|
||||
public const byte DefaultLightPWM = 255;
|
||||
|
||||
public const float MinimumLayerHeight = 0.01f;
|
||||
public const float MaximumLayerHeight = 0.20f;
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
@@ -192,9 +195,9 @@ namespace UVtools.Core.FileFormats
|
||||
new SL1File(), // Prusa SL1
|
||||
new ChituboxZipFile(), // Zip
|
||||
new ChituboxFile(), // cbddlp, cbt, photon
|
||||
new PhotonSFile(), // photons
|
||||
new PHZFile(), // phz
|
||||
new FDGFile(), // fdg
|
||||
new PhotonSFile(), // photons
|
||||
new PhotonWorkshopFile(), // PSW
|
||||
new ZCodexFile(), // zcodex
|
||||
new CWSFile(), // CWS
|
||||
@@ -244,17 +247,26 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
}
|
||||
|
||||
public static List<FileExtension> AllFileExtensions
|
||||
{
|
||||
get
|
||||
{
|
||||
List<FileExtension> extensions = new();
|
||||
foreach (var slicerFile in AvailableFormats)
|
||||
{
|
||||
extensions.AddRange(slicerFile.FileExtensions);
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> AllFileExtensionsString => (from slicerFile in AvailableFormats from extension in slicerFile.FileExtensions select extension.Extension).ToList();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of available file extensions
|
||||
/// </summary>
|
||||
public static byte FileExtensionsCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return AvailableFormats.Aggregate<FileFormat, byte>(0, (current, fileFormat) => (byte) (current + fileFormat.FileExtensions.Length));
|
||||
}
|
||||
}
|
||||
public static byte FileExtensionsCount => AvailableFormats.Aggregate<FileFormat, byte>(0, (current, fileFormat) => (byte) (current + fileFormat.FileExtensions.Length));
|
||||
|
||||
/// <summary>
|
||||
/// Find <see cref="FileFormat"/> by an extension
|
||||
@@ -285,14 +297,54 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
private bool _haveModifiedLayers;
|
||||
private LayerManager _layerManager;
|
||||
private float _printTime;
|
||||
private float _maxPrintHeight;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file format type
|
||||
/// </summary>
|
||||
public abstract FileFormatType FileType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the valid file extensions for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
public abstract FileExtension[] FileExtensions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available <see cref="FileFormat.PrintParameterModifier"/>
|
||||
/// </summary>
|
||||
public abstract PrintParameterModifier[] PrintParameterModifiers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available <see cref="FileFormat.PrintParameterModifier"/> per layer
|
||||
/// </summary>
|
||||
public virtual PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a <see cref="PrintParameterModifier"/> exists on print parameters
|
||||
/// </summary>
|
||||
/// <param name="modifier"></param>
|
||||
/// <returns>True if exists, otherwise false</returns>
|
||||
public bool HavePrintParameterModifier(PrintParameterModifier modifier) =>
|
||||
PrintParameterModifiers is not null && PrintParameterModifiers.Contains(modifier);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a <see cref="PrintParameterModifier"/> exists on print parameters
|
||||
/// </summary>
|
||||
/// <param name="modifier"></param>
|
||||
/// <returns>True if exists, otherwise false</returns>
|
||||
public bool HavePrintParameterPerLayerModifier(PrintParameterModifier modifier) =>
|
||||
PrintParameterPerLayerModifiers is not null && PrintParameterPerLayerModifiers.Contains(modifier);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file filter for open and save dialogs
|
||||
/// </summary>
|
||||
public string FileFilter {
|
||||
get
|
||||
{
|
||||
@@ -311,9 +363,15 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all valid file extensions for Avalonia file dialog
|
||||
/// </summary>
|
||||
public List<KeyValuePair<string, List<string>>> FileFilterAvalonia
|
||||
=> FileExtensions.Select(fileExt => new KeyValuePair<string, List<string>>(fileExt.Description, new List<string> {fileExt.Extension})).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Gets all valid file extensions in "*.extension1;*.extension2" format
|
||||
/// </summary>
|
||||
public string FileFilterExtensionsOnly
|
||||
{
|
||||
get
|
||||
@@ -333,12 +391,24 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if change a global property should rebuild every layer data based on them
|
||||
/// </summary>
|
||||
public bool SuppressRebuildProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input file path loaded into this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
public string FileFullPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails count present in this file format
|
||||
/// </summary>
|
||||
public abstract byte ThumbnailsCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of created thumbnails
|
||||
/// </summary>
|
||||
public byte CreatedThumbnailsCount {
|
||||
get
|
||||
{
|
||||
@@ -355,10 +425,19 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original thumbnail sizes
|
||||
/// </summary>
|
||||
public abstract Size[] ThumbnailsOriginalSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
public Mat[] Thumbnails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached layers into compressed bytes
|
||||
/// </summary>
|
||||
public LayerManager LayerManager
|
||||
{
|
||||
get => _layerManager;
|
||||
@@ -373,10 +452,10 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
private bool _haveModifiedLayers;
|
||||
private LayerManager _layerManager;
|
||||
private float _printTime;
|
||||
private float _maxPrintHeight;
|
||||
/// <summary>
|
||||
/// Gets the bounding rectangle of the object
|
||||
/// </summary>
|
||||
public Rectangle BoundingRectangle => _layerManager?.BoundingRectangle ?? Rectangle.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if modifications require a full encode to save
|
||||
@@ -387,6 +466,9 @@ namespace UVtools.Core.FileFormats
|
||||
set => _haveModifiedLayers = value;
|
||||
} // => LayerManager.IsModified;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image width resolution
|
||||
/// </summary>
|
||||
public Size Resolution
|
||||
{
|
||||
get => new((int)ResolutionX, (int)ResolutionY);
|
||||
@@ -398,10 +480,19 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image width resolution
|
||||
/// </summary>
|
||||
public abstract uint ResolutionX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image height resolution
|
||||
/// </summary>
|
||||
public abstract uint ResolutionY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of display in millimeters
|
||||
/// </summary>
|
||||
public SizeF Display
|
||||
{
|
||||
get => new(DisplayWidth, DisplayHeight);
|
||||
@@ -413,16 +504,33 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display width in millimeters
|
||||
/// </summary>
|
||||
public abstract float DisplayWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display height in millimeters
|
||||
/// </summary>
|
||||
public abstract float DisplayHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if images need to be mirrored on lcd to print on the correct orientation
|
||||
/// </summary>
|
||||
public abstract bool MirrorDisplay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum printer build Z volume
|
||||
/// </summary>
|
||||
public virtual float MaxPrintHeight
|
||||
{
|
||||
get => _maxPrintHeight > 0 ? _maxPrintHeight : PrintHeight;
|
||||
set => RaiseAndSetIfChanged(ref _maxPrintHeight, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixels per mm on X direction
|
||||
/// </summary>
|
||||
public virtual float Xppmm
|
||||
{
|
||||
get => DisplayWidth > 0 ? ResolutionX / DisplayWidth : 0;
|
||||
@@ -433,6 +541,9 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixels per mm on Y direction
|
||||
/// </summary>
|
||||
public virtual float Yppmm
|
||||
{
|
||||
get => DisplayHeight > 0 ? ResolutionY / DisplayHeight : 0;
|
||||
@@ -443,6 +554,9 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixels per mm
|
||||
/// </summary>
|
||||
public SizeF Ppmm
|
||||
{
|
||||
get => new(Xppmm, Yppmm);
|
||||
@@ -454,6 +568,9 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printer XY pixel resolution
|
||||
/// </summary>
|
||||
public decimal XYResolution => DisplayWidth > 0 || DisplayHeight > 0 ?
|
||||
(decimal) Math.Round(Math.Max(
|
||||
DisplayWidth / ResolutionX,
|
||||
@@ -461,6 +578,9 @@ namespace UVtools.Core.FileFormats
|
||||
), 3)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printer XY pixel resolution in microns
|
||||
/// </summary>
|
||||
public decimal XYResolutionUm => DisplayWidth > 0 || DisplayHeight > 0 ?
|
||||
(decimal)Math.Round(Math.Max(
|
||||
DisplayWidth / ResolutionX,
|
||||
@@ -468,11 +588,30 @@ namespace UVtools.Core.FileFormats
|
||||
), 3) * 1000
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this file have AntiAliasing
|
||||
/// </summary>
|
||||
public bool HaveAntiAliasing => AntiAliasing > 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the AntiAliasing level
|
||||
/// </summary>
|
||||
public abstract byte AntiAliasing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Layer Height in mm
|
||||
/// </summary>
|
||||
public abstract float LayerHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Layer Height in um
|
||||
/// </summary>
|
||||
public ushort LayerHeightUm => (ushort) (LayerHeight * 1000);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the print height in mm
|
||||
/// </summary>
|
||||
public virtual float PrintHeight
|
||||
{
|
||||
get => LayerCount == 0 ? 0 : this[LayerCount - 1]?.PositionZ ?? 0;
|
||||
@@ -482,30 +621,97 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last layer index
|
||||
/// </summary>
|
||||
public uint LastLayerIndex => LayerCount - 1;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this file format supports per layer settings
|
||||
/// </summary>
|
||||
public virtual bool SupportPerLayerSettings => !(PrintParameterPerLayerModifiers is null || PrintParameterPerLayerModifiers.Length == 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the layer count
|
||||
/// </summary>
|
||||
public virtual uint LayerCount
|
||||
{
|
||||
get => LayerManager?.Count ?? 0;
|
||||
set { }
|
||||
}
|
||||
|
||||
#region Universal Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of initial layer count
|
||||
/// </summary>
|
||||
public virtual ushort BottomLayerCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of normal layer count
|
||||
/// </summary>
|
||||
public uint NormalLayerCount => LayerCount - BottomLayerCount;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the initial exposure time for <see cref="BottomLayerCount"/> in seconds
|
||||
/// </summary>
|
||||
public virtual float BottomExposureTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the normal layer exposure time in seconds
|
||||
/// </summary>
|
||||
public virtual float ExposureTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom layer off time in seconds
|
||||
/// </summary>
|
||||
public virtual float BottomLightOffDelay { get; set; } = DefaultBottomLightOffDelay;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the layer off time in seconds
|
||||
/// </summary>
|
||||
public virtual float LightOffDelay { get; set; } = DefaultLightOffDelay;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom lift height in mm
|
||||
/// </summary>
|
||||
public virtual float BottomLiftHeight { get; set; } = DefaultBottomLiftHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the lift height in mm
|
||||
/// </summary>
|
||||
public virtual float LiftHeight { get; set; } = DefaultLiftHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom lift speed in mm/min
|
||||
/// </summary>
|
||||
public virtual float BottomLiftSpeed { get; set; } = DefaultBottomLiftSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the speed in mm/min
|
||||
/// </summary>
|
||||
public virtual float LiftSpeed { get; set; } = DefaultLiftSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the speed in mm/min for the retracts
|
||||
/// </summary>
|
||||
public virtual float RetractSpeed { get; set; } = DefaultRetractSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom pwm value from 0 to 255
|
||||
/// </summary>
|
||||
public virtual byte BottomLightPWM { get; set; } = DefaultBottomLightPWM;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pwm value from 0 to 255
|
||||
/// </summary>
|
||||
public virtual byte LightPWM { get; set; } = DefaultLightPWM;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in seconds
|
||||
/// </summary>
|
||||
public virtual float PrintTime
|
||||
{
|
||||
get => _printTime;
|
||||
@@ -520,9 +726,14 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
//(header.numberOfLayers - header.bottomLayers) * (double) header.exposureTimeSeconds + (double) header.bottomLayers * (double) header.exposureBottomTimeSeconds + (double) header.offTimeSeconds * (double) header.numberOfLayers);
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in seconds, if print doesn't support it it will be calculated
|
||||
/// </summary>
|
||||
public float PrintTimeOrComputed => PrintTime > 0 ? PrintTime : PrintTimeComputed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the calculated estimate print time in seconds
|
||||
/// </summary>
|
||||
public float PrintTimeComputed
|
||||
{
|
||||
get
|
||||
@@ -562,27 +773,65 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in hours
|
||||
/// </summary>
|
||||
public float PrintTimeHours => (float) Math.Round(PrintTimeOrComputed / 3600, 2);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in hours and minutes formatted
|
||||
/// </summary>
|
||||
public string PrintTimeString => TimeSpan.FromSeconds(PrintTimeOrComputed).ToString("hh\\hmm\\m");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate used material in ml
|
||||
/// </summary>
|
||||
public virtual float MaterialMilliliters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate material in grams
|
||||
/// </summary>
|
||||
public virtual float MaterialGrams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate material cost
|
||||
/// </summary>
|
||||
public virtual float MaterialCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the material name
|
||||
/// </summary>
|
||||
public virtual string MaterialName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the machine name
|
||||
/// </summary>
|
||||
public virtual string MachineName { get; set; } = "Unknown";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GCode, returns null if not supported
|
||||
/// </summary>
|
||||
public StringBuilder GCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GCode, returns null if not supported
|
||||
/// </summary>
|
||||
public string GCodeStr => GCode?.ToString();
|
||||
|
||||
public bool HaveGCode => !(GCode is null);
|
||||
/// <summary>
|
||||
/// Gets if this file have available gcode
|
||||
/// </summary>
|
||||
public bool HaveGCode => GCode is not null;
|
||||
|
||||
/// <summary>
|
||||
/// Get all configuration objects with properties and values
|
||||
/// </summary>
|
||||
public abstract object[] Configs { get; }
|
||||
|
||||
public bool IsValid => !ReferenceEquals(FileFullPath, null);
|
||||
/// <summary>
|
||||
/// Gets if this file is valid to read
|
||||
/// </summary>
|
||||
public bool IsValid => FileFullPath is not null;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
@@ -675,7 +924,7 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return FileFullPath.Equals(other.FileFullPath);
|
||||
return FileFullPath == other.FileFullPath;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
@@ -691,26 +940,31 @@ namespace UVtools.Core.FileFormats
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Clears all definitions and properties, it also dispose valid candidates
|
||||
/// </summary>
|
||||
public virtual void Clear()
|
||||
{
|
||||
FileFullPath = null;
|
||||
LayerManager = null;
|
||||
GCode = null;
|
||||
|
||||
if (!ReferenceEquals(Thumbnails, null))
|
||||
if (Thumbnails is not null)
|
||||
{
|
||||
for (int i = 0; i < ThumbnailsCount; i++)
|
||||
{
|
||||
Thumbnails[i]?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate if a file is a valid <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Full file path</param>
|
||||
public void FileValidation(string fileFullPath)
|
||||
{
|
||||
if (ReferenceEquals(fileFullPath, null)) throw new ArgumentNullException(nameof(FileFullPath), "fullFilePath can't be null.");
|
||||
if (fileFullPath is null) throw new ArgumentNullException(nameof(FileFullPath), "fullFilePath can't be null.");
|
||||
if (!File.Exists(fileFullPath)) throw new FileNotFoundException("The specified file does not exists.", fileFullPath);
|
||||
|
||||
if (IsExtensionValid(fileFullPath, true))
|
||||
@@ -721,12 +975,21 @@ namespace UVtools.Core.FileFormats
|
||||
throw new FileLoadException($"The specified file is not valid.", fileFullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a extension is valid under the <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
/// <param name="extension">Extension to check</param>
|
||||
/// <param name="isFilePath">True if <see cref="extension"/> is a full file path, otherwise false for extension only</param>
|
||||
/// <returns>True if valid, otherwise false</returns>
|
||||
public bool IsExtensionValid(string extension, bool isFilePath = false)
|
||||
{
|
||||
extension = isFilePath ? Path.GetExtension(extension)?.Remove(0, 1) : extension;
|
||||
return FileExtensions.Any(fileExtension => fileExtension.Equals(extension));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all valid file extensions in a specified format
|
||||
/// </summary>
|
||||
public string GetFileExtensions(string prepend = ".", string separator = ", ")
|
||||
{
|
||||
var result = string.Empty;
|
||||
@@ -743,6 +1006,11 @@ namespace UVtools.Core.FileFormats
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a thumbnail by it height or lower
|
||||
/// </summary>
|
||||
/// <param name="maxHeight">Max height allowed</param>
|
||||
/// <returns></returns>
|
||||
public Mat GetThumbnail(uint maxHeight = 400)
|
||||
{
|
||||
for (int i = 0; i < ThumbnailsCount; i++)
|
||||
@@ -754,6 +1022,11 @@ namespace UVtools.Core.FileFormats
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a thumbnail by the largest or smallest
|
||||
/// </summary>
|
||||
/// <param name="largest">True to get the largest, otherwise false</param>
|
||||
/// <returns></returns>
|
||||
public Mat GetThumbnail(bool largest)
|
||||
{
|
||||
switch (CreatedThumbnailsCount)
|
||||
@@ -774,6 +1047,10 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets thumbnails from a list of thumbnails and clone them
|
||||
/// </summary>
|
||||
/// <param name="images"></param>
|
||||
public void SetThumbnails(Mat[] images)
|
||||
{
|
||||
for (var i = 0; i < ThumbnailsCount; i++)
|
||||
@@ -786,6 +1063,10 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets all thumbnails the same image
|
||||
/// </summary>
|
||||
/// <param name="images">Image to set</param>
|
||||
public void SetThumbnails(Mat image)
|
||||
{
|
||||
for (var i = 0; i < ThumbnailsCount; i++)
|
||||
@@ -798,6 +1079,11 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a thumbnail from a disk file
|
||||
/// </summary>
|
||||
/// <param name="index">Thumbnail index</param>
|
||||
/// <param name="filePath"></param>
|
||||
public void SetThumbnail(int index, string filePath)
|
||||
{
|
||||
Thumbnails[index] = CvInvoke.Imread(filePath, ImreadModes.AnyColor);
|
||||
@@ -807,8 +1093,23 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
/// <summary>
|
||||
/// Encode to an output file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Output file</param>
|
||||
/// <param name="progress"></param>
|
||||
protected abstract void EncodeInternally(string fileFullPath, OperationProgress progress);
|
||||
|
||||
/// <summary>
|
||||
/// Encode to an output file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Output file</param>
|
||||
/// <param name="progress"></param>
|
||||
public void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
if (File.Exists(fileFullPath))
|
||||
@@ -822,25 +1123,69 @@ namespace UVtools.Core.FileFormats
|
||||
if(Thumbnails[i].Size == ThumbnailsOriginalSize[i]) continue;
|
||||
CvInvoke.Resize(Thumbnails[i], Thumbnails[i], new Size(ThumbnailsOriginalSize[i].Width, ThumbnailsOriginalSize[i].Height));
|
||||
}
|
||||
}
|
||||
|
||||
public void AfterEncode()
|
||||
{
|
||||
EncodeInternally(fileFullPath, progress);
|
||||
|
||||
LayerManager.Desmodify();
|
||||
RequireFullEncode = false;
|
||||
}
|
||||
|
||||
public virtual void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
/// <summary>
|
||||
/// Decode a slicer file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="progress"></param>
|
||||
protected abstract void DecodeInternally(string fileFullPath, OperationProgress progress);
|
||||
|
||||
/// <summary>
|
||||
/// Decode a slicer file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="progress"></param>
|
||||
public void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
Clear();
|
||||
FileValidation(fileFullPath);
|
||||
FileFullPath = fileFullPath;
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
DecodeInternally(fileFullPath, progress);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
// Sanitize
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
// Check for null layers
|
||||
if(this[layerIndex] is null) throw new FileLoadException($"Layer {layerIndex} was defined but doesn't contain a valid image.", fileFullPath);
|
||||
if(layerIndex <= 0) continue;
|
||||
// Check for bigger position z than it successor
|
||||
if(this[layerIndex-1].PositionZ > this[layerIndex].PositionZ) throw new FileLoadException($"Layer {layerIndex-1} ({this[layerIndex - 1].PositionZ}mm) have a higher Z position than the successor layer {layerIndex} ({this[layerIndex].PositionZ}mm).\n", fileFullPath);
|
||||
}
|
||||
|
||||
// Fix 0mm positions at layer 0
|
||||
if(this[0].PositionZ == 0)
|
||||
{
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
this[layerIndex].PositionZ += LayerHeight;
|
||||
}
|
||||
Save(progress);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract contents to a folder
|
||||
/// </summary>
|
||||
/// <param name="path">Path to folder where content will be extracted</param>
|
||||
/// <param name="genericConfigExtract"></param>
|
||||
/// <param name="genericLayersExtract"></param>
|
||||
/// <param name="progress"></param>
|
||||
public virtual void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true,
|
||||
OperationProgress progress = null)
|
||||
{
|
||||
if (ReferenceEquals(progress, null)) progress = new OperationProgress();
|
||||
progress ??= new OperationProgress();
|
||||
progress.ItemName = OperationProgress.StatusExtracting;
|
||||
/*if (emptyFirst)
|
||||
{
|
||||
@@ -955,16 +1300,33 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get height in mm from layer height
|
||||
/// </summary>
|
||||
/// <param name="layerIndex"></param>
|
||||
/// <param name="realHeight"></param>
|
||||
/// <returns>The height in mm</returns>
|
||||
public float GetHeightFromLayer(uint layerIndex, bool realHeight = true)
|
||||
{
|
||||
return (float)Math.Round((layerIndex+(realHeight ? 1 : 0)) * LayerHeight, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value for initial layer or normal layers based on layer index
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of value</typeparam>
|
||||
/// <param name="layerIndex">Layer index</param>
|
||||
/// <param name="initialLayerValue">Initial value</param>
|
||||
/// <param name="normalLayerValue">Normal value</param>
|
||||
/// <returns></returns>
|
||||
public T GetInitialLayerValueOrNormal<T>(uint layerIndex, T initialLayerValue, T normalLayerValue)
|
||||
{
|
||||
return layerIndex < BottomLayerCount ? initialLayerValue : normalLayerValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh print parameters globals with this file settings
|
||||
/// </summary>
|
||||
public void RefreshPrintParametersModifiersValues()
|
||||
{
|
||||
if (PrintParameterModifiers is null) return;
|
||||
@@ -1029,6 +1391,9 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh print parameters per layer globals with this file settings
|
||||
/// </summary>
|
||||
public void RefreshPrintParametersPerLayerModifiersValues(uint layerIndex)
|
||||
{
|
||||
if (PrintParameterPerLayerModifiers is null) return;
|
||||
@@ -1065,6 +1430,11 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value attributed to <see cref="FileFormat.PrintParameterModifier"/>
|
||||
/// </summary>
|
||||
/// <param name="modifier">Modifier to use</param>
|
||||
/// <returns>A value</returns>
|
||||
public object GetValueFromPrintParameterModifier(PrintParameterModifier modifier)
|
||||
{
|
||||
if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerCount))
|
||||
@@ -1098,6 +1468,12 @@ namespace UVtools.Core.FileFormats
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a property value attributed to <see cref="modifier"/>
|
||||
/// </summary>
|
||||
/// <param name="modifier">Modifier to use</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <returns>True if set, otherwise false = <see cref="modifier"/> not found</returns>
|
||||
public bool SetValueFromPrintParameterModifier(PrintParameterModifier modifier, decimal value)
|
||||
{
|
||||
if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerCount))
|
||||
@@ -1167,6 +1543,10 @@ namespace UVtools.Core.FileFormats
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets properties from print parameters
|
||||
/// </summary>
|
||||
/// <returns>Number of affected parameters</returns>
|
||||
public byte SetValuesFromPrintParametersModifiers()
|
||||
{
|
||||
if (PrintParameterModifiers is null) return 0;
|
||||
@@ -1182,36 +1562,34 @@ namespace UVtools.Core.FileFormats
|
||||
return changed;
|
||||
}
|
||||
|
||||
public void EditPrintParameters(OperationEditParameters operation)
|
||||
{
|
||||
if (operation.PerLayerOverride)
|
||||
{
|
||||
for (uint layerIndex = operation.LayerIndexStart; layerIndex <= operation.LayerIndexEnd; layerIndex++)
|
||||
{
|
||||
this[layerIndex].SetValuesFromPrintParametersModifiers(operation.Modifiers);
|
||||
}
|
||||
|
||||
foreach (var modifier in operation.Modifiers)
|
||||
{
|
||||
modifier.OldValue = modifier.NewValue;
|
||||
}
|
||||
RebuildGCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValuesFromPrintParametersModifiers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds GCode based on current settings
|
||||
/// </summary>
|
||||
public virtual void RebuildGCode() { }
|
||||
|
||||
/// <summary>
|
||||
/// Saves current configuration on input file
|
||||
/// </summary>
|
||||
/// <param name="progress"></param>
|
||||
public void Save(OperationProgress progress = null)
|
||||
{
|
||||
SaveAs(null, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves current configuration on a copy
|
||||
/// </summary>
|
||||
/// <param name="filePath">File path to save copy as, use null to overwrite active file (Same as <see cref="Save"/>)</param>
|
||||
/// <param name="progress"></param>
|
||||
public abstract void SaveAs(string filePath = null, OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Converts this file type to another file type
|
||||
/// </summary>
|
||||
/// <param name="to">Target file format</param>
|
||||
/// <param name="fileFullPath">Output path file</param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns>The converted file if successful, otherwise null</returns>
|
||||
public virtual FileFormat Convert(Type to, string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
if (!IsValid) return null;
|
||||
@@ -1270,9 +1648,20 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
return slicerFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this file type to another file type
|
||||
/// </summary>
|
||||
/// <param name="to">Target file format</param>
|
||||
/// <param name="fileFullPath">Output path file</param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns>TThe converted file if successful, otherwise null</returns>
|
||||
public FileFormat Convert(FileFormat to, string fileFullPath, OperationProgress progress = null)
|
||||
=> Convert(to.GetType(), fileFullPath, progress);
|
||||
|
||||
/// <summary>
|
||||
/// Validate AntiAlias Level
|
||||
/// </summary>
|
||||
public byte ValidateAntiAliasingLevel()
|
||||
{
|
||||
if (AntiAliasing < 2) return 1;
|
||||
|
||||
@@ -1,510 +0,0 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using Emgu.CV;
|
||||
using UVtools.Core.Operations;
|
||||
|
||||
namespace UVtools.Core.FileFormats
|
||||
{
|
||||
/// <summary>
|
||||
/// Slicer file format representation interface
|
||||
/// </summary>
|
||||
public interface IFileFormat
|
||||
{
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the file format type
|
||||
/// </summary>
|
||||
FileFormat.FileFormatType FileType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the valid file extensions for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
FileExtension[] FileExtensions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available <see cref="FileFormat.PrintParameterModifier"/>
|
||||
/// </summary>
|
||||
FileFormat.PrintParameterModifier[] PrintParameterModifiers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available <see cref="FileFormat.PrintParameterModifier"/> per layer
|
||||
/// </summary>
|
||||
FileFormat.PrintParameterModifier[] PrintParameterPerLayerModifiers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file filter for open and save dialogs
|
||||
/// </summary>
|
||||
string FileFilter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all valid file extensions in "*.extension1;*.extension2" format
|
||||
/// </summary>
|
||||
|
||||
string FileFilterExtensionsOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if change a global property should rebuild every layer data based on them
|
||||
/// </summary>
|
||||
bool SuppressRebuildProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input file path loaded into this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
string FileFullPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails count present in this file format
|
||||
/// </summary>
|
||||
byte ThumbnailsCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of created thumbnails
|
||||
/// </summary>
|
||||
byte CreatedThumbnailsCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original thumbnail sizes
|
||||
/// </summary>
|
||||
System.Drawing.Size[] ThumbnailsOriginalSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the thumbnails for this <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
Mat[] Thumbnails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached layers into compressed bytes
|
||||
/// </summary>
|
||||
LayerManager LayerManager { get; set; }
|
||||
|
||||
Size Resolution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image width resolution
|
||||
/// </summary>
|
||||
uint ResolutionX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image height resolution
|
||||
/// </summary>
|
||||
uint ResolutionY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of display in millimeters
|
||||
/// </summary>
|
||||
SizeF Display { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display width in millimeters
|
||||
/// </summary>
|
||||
float DisplayWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display height in millimeters
|
||||
/// </summary>
|
||||
float DisplayHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if images need to be mirrored on lcd to print on the correct orientation
|
||||
/// </summary>
|
||||
bool MirrorDisplay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum printer build Z volume
|
||||
/// </summary>
|
||||
float MaxPrintHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixels per mm on X direction
|
||||
/// </summary>
|
||||
float Xppmm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixels per mm on Y direction
|
||||
/// </summary>
|
||||
float Yppmm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixels per mm
|
||||
/// </summary>
|
||||
SizeF Ppmm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printer XY pixel resolution
|
||||
/// </summary>
|
||||
decimal XYResolution { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printer XY pixel resolution in microns
|
||||
/// </summary>
|
||||
decimal XYResolutionUm { get; }
|
||||
|
||||
bool HaveAntiAliasing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the AntiAliasing level
|
||||
/// </summary>
|
||||
byte AntiAliasing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Layer Height in mm
|
||||
/// </summary>
|
||||
float LayerHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the print height in mm
|
||||
/// </summary>
|
||||
float PrintHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last layer index
|
||||
/// </summary>
|
||||
uint LastLayerIndex { get; }
|
||||
|
||||
#region Universal Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this format support per layer override settings
|
||||
/// </summary>
|
||||
bool SupportPerLayerSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of layers present in this file
|
||||
/// </summary>
|
||||
uint LayerCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of initial layer count
|
||||
/// </summary>
|
||||
ushort BottomLayerCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of normal layer count
|
||||
/// </summary>
|
||||
uint NormalLayerCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the initial exposure time for <see cref="BottomLayerCount"/> in seconds
|
||||
/// </summary>
|
||||
float BottomExposureTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the normal layer exposure time in seconds
|
||||
/// </summary>
|
||||
float ExposureTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom layer off time in seconds
|
||||
/// </summary>
|
||||
float BottomLightOffDelay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the layer off time in seconds
|
||||
/// </summary>
|
||||
float LightOffDelay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom lift height in mm
|
||||
/// </summary>
|
||||
float BottomLiftHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the lift height in mm
|
||||
/// </summary>
|
||||
float LiftHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom lift speed in mm/min
|
||||
/// </summary>
|
||||
float BottomLiftSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the speed in mm/min
|
||||
/// </summary>
|
||||
float LiftSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the speed in mm/min for the retracts
|
||||
/// </summary>
|
||||
float RetractSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom pwm value from 0 to 255
|
||||
/// </summary>
|
||||
byte BottomLightPWM { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pwm value from 0 to 255
|
||||
/// </summary>
|
||||
byte LightPWM { get; set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in seconds
|
||||
/// </summary>
|
||||
float PrintTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in seconds, if print doesn't support it it will be calculated
|
||||
/// </summary>
|
||||
float PrintTimeOrComputed { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the calculated estimate print time in seconds
|
||||
/// </summary>
|
||||
float PrintTimeComputed { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in hours
|
||||
/// </summary>
|
||||
float PrintTimeHours { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate print time in hours and minutes formatted
|
||||
/// </summary>
|
||||
string PrintTimeString { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate used material in ml
|
||||
/// </summary>
|
||||
float MaterialMilliliters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate material in grams
|
||||
/// </summary>
|
||||
float MaterialGrams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate material cost
|
||||
/// </summary>
|
||||
float MaterialCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the material name
|
||||
/// </summary>
|
||||
string MaterialName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the machine name
|
||||
/// </summary>
|
||||
string MachineName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GCode, returns null if not supported
|
||||
/// </summary>
|
||||
StringBuilder GCode { get; set; }
|
||||
string GCodeStr { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this file have available gcode
|
||||
/// </summary>
|
||||
bool HaveGCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get all configuration objects with properties and values
|
||||
/// </summary>
|
||||
object[] Configs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this file is valid to read
|
||||
/// </summary>
|
||||
bool IsValid { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Clears all definitions and properties, it also dispose valid candidates
|
||||
/// </summary>
|
||||
void Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Validate if a file is a valid <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Full file path</param>
|
||||
void FileValidation(string fileFullPath);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a extension is valid under the <see cref="FileFormat"/>
|
||||
/// </summary>
|
||||
/// <param name="extension">Extension to check</param>
|
||||
/// <param name="isFilePath">True if <see cref="extension"/> is a full file path, otherwise false for extension only</param>
|
||||
/// <returns>True if valid, otherwise false</returns>
|
||||
bool IsExtensionValid(string extension, bool isFilePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all valid file extensions in a specified format
|
||||
/// </summary>
|
||||
|
||||
string GetFileExtensions(string prepend = ".", string separator = ", ");
|
||||
|
||||
/// <summary>
|
||||
/// Gets a thumbnail by it height or lower
|
||||
/// </summary>
|
||||
/// <param name="maxHeight">Max height allowed</param>
|
||||
/// <returns></returns>
|
||||
Mat GetThumbnail(uint maxHeight = 400);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a thumbnail by the largest or smallest
|
||||
/// </summary>
|
||||
/// <param name="largest">True to get the largest, otherwise false</param>
|
||||
/// <returns></returns>
|
||||
Mat GetThumbnail(bool largest);
|
||||
|
||||
/// <summary>
|
||||
/// Sets thumbnails from a list of thumbnails and clone them
|
||||
/// </summary>
|
||||
/// <param name="images"></param>
|
||||
void SetThumbnails(Mat[] images);
|
||||
|
||||
/// <summary>
|
||||
/// Sets all thumbnails the same image
|
||||
/// </summary>
|
||||
/// <param name="images">Image to set</param>
|
||||
void SetThumbnails(Mat images);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a thumbnail from a disk file
|
||||
/// </summary>
|
||||
/// <param name="index">Thumbnail index</param>
|
||||
/// <param name="filePath"></param>
|
||||
void SetThumbnail(int index, string filePath);
|
||||
|
||||
/// <summary>
|
||||
/// Encode to an output file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Output file</param>
|
||||
/// <param name="progress"></param>
|
||||
void Encode(string fileFullPath, OperationProgress progress = null);
|
||||
void AfterEncode();
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Begin encode to an output file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Output file</param>
|
||||
//void BeginEncode(string fileFullPath);
|
||||
|
||||
/// <summary>
|
||||
/// Insert a layer image to be encoded
|
||||
/// </summary>
|
||||
/// <param name="image"></param>
|
||||
/// <param name="layerIndex"></param>
|
||||
//void InsertLayerImageEncode(Image<L8> image, uint layerIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Finish the encoding procedure
|
||||
/// </summary>
|
||||
//void EndEncode();*/
|
||||
|
||||
/// <summary>
|
||||
/// Decode a slicer file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="progress"></param>
|
||||
void Decode(string fileFullPath, OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Extract contents to a folder
|
||||
/// </summary>
|
||||
/// <param name="path">Path to folder where content will be extracted</param>
|
||||
/// <param name="genericConfigExtract"></param>
|
||||
/// <param name="genericLayersExtract"></param>
|
||||
/// <param name="progress"></param>
|
||||
void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true,
|
||||
OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Get height in mm from layer height
|
||||
/// </summary>
|
||||
/// <param name="layerIndex"></param>
|
||||
/// <param name="realHeight"></param>
|
||||
/// <returns>The height in mm</returns>
|
||||
float GetHeightFromLayer(uint layerIndex, bool realHeight = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value for initial layer or normal layers based on layer index
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of value</typeparam>
|
||||
/// <param name="layerIndex">Layer index</param>
|
||||
/// <param name="initialLayerValue">Initial value</param>
|
||||
/// <param name="normalLayerValue">Normal value</param>
|
||||
/// <returns></returns>
|
||||
T GetInitialLayerValueOrNormal<T>(uint layerIndex, T initialLayerValue, T normalLayerValue);
|
||||
|
||||
void RefreshPrintParametersModifiersValues();
|
||||
void RefreshPrintParametersPerLayerModifiersValues(uint layerIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value attributed to <see cref="FileFormat.PrintParameterModifier"/>
|
||||
/// </summary>
|
||||
/// <param name="modifier">Modifier to use</param>
|
||||
/// <returns>A value</returns>
|
||||
object GetValueFromPrintParameterModifier(FileFormat.PrintParameterModifier modifier);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a property value attributed to <see cref="modifier"/>
|
||||
/// </summary>
|
||||
/// <param name="modifier">Modifier to use</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <returns>True if set, otherwise false = <see cref="modifier"/> not found</returns>
|
||||
bool SetValueFromPrintParameterModifier(FileFormat.PrintParameterModifier modifier, decimal value);
|
||||
|
||||
byte SetValuesFromPrintParametersModifiers();
|
||||
|
||||
void EditPrintParameters(OperationEditParameters operation);
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds GCode based on current settings
|
||||
/// </summary>
|
||||
void RebuildGCode();
|
||||
|
||||
/// <summary>
|
||||
/// Saves current configuration on input file
|
||||
/// </summary>
|
||||
/// <param name="progress"></param>
|
||||
void Save(OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Saves current configuration on a copy
|
||||
/// </summary>
|
||||
/// <param name="filePath">File path to save copy as, use null to overwrite active file (Same as <see cref="Save"/>)</param>
|
||||
/// <param name="progress"></param>
|
||||
void SaveAs(string filePath = null, OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Converts this file type to another file type
|
||||
/// </summary>
|
||||
/// <param name="to">Target file format</param>
|
||||
/// <param name="fileFullPath">Output path file</param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns>The converted file if successful, otherwise null</returns>
|
||||
FileFormat Convert(Type to, string fileFullPath, OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Converts this file type to another file type
|
||||
/// </summary>
|
||||
/// <param name="to">Target file format</param>
|
||||
/// <param name="fileFullPath">Output path file</param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns>TThe converted file if successful, otherwise null</returns>
|
||||
FileFormat Convert(FileFormat to, string fileFullPath, OperationProgress progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Validate AntiAlias Level
|
||||
/// </summary>
|
||||
byte ValidateAntiAliasingLevel();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -76,10 +76,13 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
private Mat ImageMat { get; set; }
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
ImageMat = CvInvoke.Imread(fileFullPath, ImreadModes.Grayscale);
|
||||
const byte startDivisor = 2;
|
||||
for (int i = 0; i < ThumbnailsCount; i++)
|
||||
@@ -106,7 +109,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override FileFormat Convert(Type to, string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -450,12 +450,9 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
return bytes;
|
||||
}
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
if (ResolutionY >= 2560) // Longer Orange 30
|
||||
{
|
||||
HeaderSettings.Float_94 = 170;
|
||||
@@ -495,8 +492,6 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
|
||||
Debug.WriteLine("Encode Results:");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
Debug.WriteLine("-End-");
|
||||
@@ -522,10 +517,8 @@ namespace UVtools.Core.FileFormats
|
||||
return mat;
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
@@ -570,25 +563,17 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using (var image = layerData[layerIndex].Decode())
|
||||
{
|
||||
using var image = layerData[layerIndex].Decode();
|
||||
this[layerIndex] = new Layer((uint) layerIndex, image, LayerManager);
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
LayerManager.RebuildLayersProperties();
|
||||
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -150,10 +150,8 @@ namespace UVtools.Core.FileFormats
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
@@ -164,8 +162,6 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
|
||||
Debug.WriteLine("Encode Results:");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
Debug.WriteLine("-End-");
|
||||
@@ -173,10 +169,8 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
|
||||
@@ -186,13 +180,7 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
throw new FileLoadException("Not a valid Makerfile file!", fileFullPath);
|
||||
}
|
||||
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -1017,11 +1017,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinitions = null;
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
LayersHash.Clear();
|
||||
|
||||
/*if (HeaderSettings.EncryptionKey == 0)
|
||||
@@ -1139,8 +1136,6 @@ namespace UVtools.Core.FileFormats
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
AfterEncode();
|
||||
|
||||
Debug.WriteLine("Encode Results:");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
Debug.WriteLine(Previews[0]);
|
||||
@@ -1149,11 +1144,8 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
if(progress is null) progress = new OperationProgress(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
|
||||
@@ -1167,9 +1159,6 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
HeaderSettings.AntiAliasLevel = 1;
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeThumbnails, ThumbnailsCount);
|
||||
Debug.Write("Header -> ");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
@@ -1256,8 +1245,6 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -125,11 +125,12 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
for (int i = 0; i < imageLength; i++)
|
||||
{
|
||||
color = color <= 127 ? 0 : 255; // Sanitize no AA
|
||||
if (spanMat[i] != color)
|
||||
//color = color <= 127 ? 0 : 255; // Sanitize no AA
|
||||
byte thisColor = spanMat[i] <= 127 ? 0 : 255; // Sanitize no AA
|
||||
if (thisColor != color)
|
||||
{
|
||||
AddRep();
|
||||
color = spanMat[i];
|
||||
color = thisColor; // Sanitize no AA
|
||||
rep = 1;
|
||||
}
|
||||
else
|
||||
@@ -420,12 +421,10 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
return bytes;
|
||||
}
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
throw new NotSupportedException("PhotonS is read-only format, please use pws instead!");
|
||||
//uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
@@ -463,8 +462,6 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
|
||||
Debug.WriteLine("Encode Results:");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
Debug.WriteLine("-End-");
|
||||
@@ -495,10 +492,8 @@ namespace UVtools.Core.FileFormats
|
||||
return mat;
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
@@ -546,24 +541,16 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using (var image = layerData[layerIndex].Decode())
|
||||
{
|
||||
using var image = layerData[layerIndex].Decode();
|
||||
this[layerIndex] = new Layer((uint) layerIndex, image, LayerManager);
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
LayerManager.RebuildLayersProperties();
|
||||
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -1048,11 +1048,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinition = null;
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
LayersHash.Clear();
|
||||
|
||||
LayersDefinition = new LayerDefinition(LayerCount);
|
||||
@@ -1124,14 +1121,10 @@ namespace UVtools.Core.FileFormats
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, FileMarkSettings);
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
|
||||
using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
FileMarkSettings = Helpers.Deserialize<FileMark>(inputFile);
|
||||
@@ -1235,8 +1228,6 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
|
||||
@@ -252,22 +252,30 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public class OutputConfig
|
||||
{
|
||||
public string Action { get; set; }
|
||||
public string Action { get; set; } = "print";
|
||||
public string JobDir { get; set; }
|
||||
public float ExpTime { get; set; }
|
||||
public float ExpTimeFirst { get; set; }
|
||||
public string FileCreationTimestamp { get; set; }
|
||||
//public string FileCreationTimestamp { get; set; }
|
||||
public string FileCreationTimestamp {
|
||||
get
|
||||
{
|
||||
//2021-01-23 at 04:07:36 UTC
|
||||
var now = DateTime.Now;
|
||||
return $"{now.Year}-{now.Month:D2}-{now.Day:D2} at {now.Hour:D2}:{now.Minute:D2}:{now.Second:D2} {now.Kind}";
|
||||
}
|
||||
}
|
||||
public float LayerHeight { get; set; }
|
||||
public string MaterialName { get; set; }
|
||||
public string MaterialName { get; set; } = About.Software;
|
||||
public ushort NumFade { get; set; }
|
||||
public ushort NumFast { get; set; }
|
||||
public ushort NumSlow { get; set; }
|
||||
public string PrintProfile { get; set; }
|
||||
public string PrintProfile { get; set; } = About.Software;
|
||||
public float PrintTime { get; set; }
|
||||
public string PrinterModel { get; set; }
|
||||
public string PrinterProfile { get; set; }
|
||||
public string PrinterVariant { get; set; }
|
||||
public string PrusaSlicerVersion { get; set; }
|
||||
public string PrinterModel { get; set; } = "SL1";
|
||||
public string PrinterProfile { get; set; } = About.Software;
|
||||
public string PrinterVariant { get; set; } = "default";
|
||||
public string PrusaSlicerVersion { get; set; } = "PrusaSlicer-2.3.0+win64-202101111315";
|
||||
public float UsedMaterial { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
@@ -519,10 +527,12 @@ namespace UVtools.Core.FileFormats
|
||||
Statistics.Clear();
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
var filename = fileFullPath;
|
||||
if (filename.EndsWith(TemporaryFileAppend)) filename = Path.GetFileNameWithoutExtension(filename); // tmp
|
||||
filename = Path.GetFileNameWithoutExtension(filename); // sl1
|
||||
OutputConfigSettings.JobDir = filename;
|
||||
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
|
||||
{
|
||||
var entry = outputFile.CreateEntry("config.ini");
|
||||
@@ -562,39 +572,28 @@ namespace UVtools.Core.FileFormats
|
||||
foreach (var thumbnail in Thumbnails)
|
||||
{
|
||||
if (ReferenceEquals(thumbnail, null)) continue;
|
||||
using (var stream = outputFile.CreateEntry($"thumbnail/thumbnail{thumbnail.Width}x{thumbnail.Height}.png").Open())
|
||||
{
|
||||
using var stream = outputFile.CreateEntry($"thumbnail/thumbnail{thumbnail.Width}x{thumbnail.Height}.png").Open();
|
||||
var vec = new VectorOfByte();
|
||||
CvInvoke.Imencode(".png", thumbnail, vec);
|
||||
stream.WriteBytes(vec.ToArray());
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
Layer layer = this[layerIndex];
|
||||
var layerImagePath = $"{Path.GetFileNameWithoutExtension(fileFullPath)}{layerIndex:D5}.png";
|
||||
var layerImagePath = $"{filename}{layerIndex:D5}.png";
|
||||
//layer.Filename = layerImagePath;
|
||||
outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create);
|
||||
progress++;
|
||||
}
|
||||
}
|
||||
|
||||
AfterEncode();
|
||||
}
|
||||
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
PrinterSettings = new Printer();
|
||||
MaterialSettings = new Material();
|
||||
PrintSettings = new Print();
|
||||
@@ -602,7 +601,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
Statistics.ExecutionTime.Restart();
|
||||
|
||||
using (var inputFile = ZipFile.OpenRead(FileFullPath))
|
||||
using (var inputFile = ZipFile.OpenRead(fileFullPath))
|
||||
{
|
||||
List<string> iniFiles = new();
|
||||
foreach (ZipArchiveEntry entity in inputFile.Entries)
|
||||
@@ -625,7 +624,7 @@ namespace UVtools.Core.FileFormats
|
||||
foreach (var obj in Configs)
|
||||
{
|
||||
var attribute = obj.GetType().GetProperty(fieldName);
|
||||
if (ReferenceEquals(attribute, null)) continue;
|
||||
if (attribute is null || !attribute.CanWrite) continue;
|
||||
//Debug.WriteLine(attribute.Name);
|
||||
Helpers.SetPropertyValue(attribute, obj, keyValue[1]);
|
||||
|
||||
|
||||
@@ -360,13 +360,8 @@ namespace UVtools.Core.FileFormats
|
||||
JsonSettings.Layers = new List<LayerData>();
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
// Redo layer data
|
||||
JsonSettings.Layers.Clear();
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
@@ -430,17 +425,11 @@ namespace UVtools.Core.FileFormats
|
||||
progress++;
|
||||
}
|
||||
}
|
||||
AfterEncode();
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
if(progress is null) progress = new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
using (var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry(FileConfigName);
|
||||
if (ReferenceEquals(entry, null))
|
||||
@@ -466,21 +455,19 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
entry = inputFile.GetEntry(FilePreviewHugeName);
|
||||
if (!ReferenceEquals(entry, null))
|
||||
{
|
||||
using (Stream stream = entry.Open())
|
||||
if (entry is not null)
|
||||
{
|
||||
using Stream stream = entry.Open();
|
||||
Mat image = new Mat();
|
||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
||||
Thumbnails[1] = image;
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
entry = inputFile.GetEntry($"{FolderImageName}/{layerIndex:D8}.png");
|
||||
if (ReferenceEquals(entry, null)) continue;
|
||||
if (entry is null) continue;
|
||||
|
||||
this[layerIndex] = new Layer(layerIndex, entry.Open(), LayerManager)
|
||||
{
|
||||
|
||||
@@ -382,12 +382,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayersSettings.Clear();
|
||||
}
|
||||
|
||||
public override void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
base.Encode(fileFullPath, progress);
|
||||
|
||||
float usedMaterial = MaterialMilliliters / LayerCount;
|
||||
ResinMetadataSettings.Layers.Clear();
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
@@ -471,18 +467,14 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Create);
|
||||
}
|
||||
AfterEncode();
|
||||
}
|
||||
|
||||
public override void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
base.Decode(fileFullPath, progress);
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
using (var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry("ResinMetadata");
|
||||
if (ReferenceEquals(entry, null))
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("ResinMetadata not found", fileFullPath);
|
||||
@@ -491,7 +483,7 @@ namespace UVtools.Core.FileFormats
|
||||
ResinMetadataSettings = Helpers.JsonDeserializeObject<ResinMetadata>(entry.Open());
|
||||
|
||||
entry = inputFile.GetEntry("UserSettingsData");
|
||||
if (ReferenceEquals(entry, null))
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("UserSettingsData not found", fileFullPath);
|
||||
@@ -500,7 +492,7 @@ namespace UVtools.Core.FileFormats
|
||||
UserSettings = Helpers.JsonDeserializeObject<UserSettingsdata>(entry.Open());
|
||||
|
||||
entry = inputFile.GetEntry("ZCodeMetadata");
|
||||
if (ReferenceEquals(entry, null))
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("ZCodeMetadata not found", fileFullPath);
|
||||
@@ -509,7 +501,7 @@ namespace UVtools.Core.FileFormats
|
||||
ZCodeMetadataSettings = Helpers.JsonDeserializeObject<ZCodeMetadata>(entry.Open());
|
||||
|
||||
entry = inputFile.GetEntry("ResinGCodeData");
|
||||
if (ReferenceEquals(entry, null))
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("ResinGCodeData not found", fileFullPath);
|
||||
@@ -615,14 +607,11 @@ M106 S0
|
||||
entry = inputFile.GetEntry("Preview.png");
|
||||
if (!ReferenceEquals(entry, null))
|
||||
{
|
||||
using (Stream stream = entry.Open())
|
||||
{
|
||||
|
||||
using Stream stream = entry.Open();
|
||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager.GetBoundingRectangle(progress);
|
||||
}
|
||||
|
||||
+49
-22
@@ -7,17 +7,15 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using UVtools.Core.Extensions;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Objects;
|
||||
using UVtools.Core.Operations;
|
||||
using Stream = System.IO.Stream;
|
||||
|
||||
namespace UVtools.Core
|
||||
@@ -27,9 +25,24 @@ namespace UVtools.Core
|
||||
/// </summary>
|
||||
public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
|
||||
{
|
||||
#region Members
|
||||
private byte[] _compressedBytes;
|
||||
private uint _nonZeroPixelCount;
|
||||
private Rectangle _boundingRectangle = Rectangle.Empty;
|
||||
private bool _isModified;
|
||||
private uint _index;
|
||||
private float _positionZ;
|
||||
private float _exposureTime;
|
||||
private float _lightOffDelay = FileFormat.DefaultLightOffDelay;
|
||||
private float _liftHeight = FileFormat.DefaultLiftHeight;
|
||||
private float _liftSpeed = FileFormat.DefaultLiftSpeed;
|
||||
private float _retractSpeed = FileFormat.DefaultRetractSpeed;
|
||||
private byte _lightPwm = FileFormat.DefaultLightPWM;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public object Mutex = new object();
|
||||
public object Mutex = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent layer manager
|
||||
@@ -152,21 +165,35 @@ namespace UVtools.Core
|
||||
public float PositionZ
|
||||
{
|
||||
get => _positionZ;
|
||||
set => RaiseAndSetIfChanged(ref _positionZ, value);
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _positionZ, value)) return;
|
||||
RaisePropertyChanged(nameof(LayerHeight));
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] _compressedBytes;
|
||||
private uint _nonZeroPixelCount;
|
||||
private Rectangle _boundingRectangle = Rectangle.Empty;
|
||||
private bool _isModified;
|
||||
private uint _index;
|
||||
private float _positionZ;
|
||||
private float _exposureTime;
|
||||
private float _lightOffDelay = FileFormat.DefaultLightOffDelay;
|
||||
private float _liftHeight = FileFormat.DefaultLiftHeight;
|
||||
private float _liftSpeed = FileFormat.DefaultLiftSpeed;
|
||||
private float _retractSpeed = FileFormat.DefaultRetractSpeed;
|
||||
private byte _lightPwm = FileFormat.DefaultLightPWM;
|
||||
/// <summary>
|
||||
/// Gets the layer height in millimeters of this layer
|
||||
/// </summary>
|
||||
public float LayerHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_index == 0) return _positionZ;
|
||||
Layer previousLayer = this;
|
||||
|
||||
while ((previousLayer = previousLayer.PreviousLayer()) is not null) // This cycle returns the correct layer height if two or more layers have the same position z
|
||||
{
|
||||
var layerHeight = (float)Math.Round(_positionZ - previousLayer.PositionZ, 2);
|
||||
//Debug.WriteLine($"Layer {_index}-{previousLayer.Index}: {_positionZ} - {previousLayer.PositionZ}: {layerHeight}");
|
||||
if (layerHeight == 0f) continue;
|
||||
if (layerHeight < 0f) break;
|
||||
return layerHeight;
|
||||
}
|
||||
|
||||
return ParentLayerManager.SlicerFile.LayerHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets layer image compressed data
|
||||
@@ -348,7 +375,7 @@ namespace UVtools.Core
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Index)}: {Index}, {nameof(Filename)}: {Filename}, {nameof(NonZeroPixelCount)}: {NonZeroPixelCount}, {nameof(BoundingRectangle)}: {BoundingRectangle}, {nameof(IsBottomLayer)}: {IsBottomLayer}, {nameof(IsNormalLayer)}: {IsNormalLayer}, {nameof(PositionZ)}: {PositionZ}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(LightPWM)}: {LightPWM}, {nameof(IsModified)}: {IsModified}";
|
||||
return $"{nameof(Index)}: {Index}, {nameof(Filename)}: {Filename}, {nameof(NonZeroPixelCount)}: {NonZeroPixelCount}, {nameof(BoundingRectangle)}: {BoundingRectangle}, {nameof(IsBottomLayer)}: {IsBottomLayer}, {nameof(IsNormalLayer)}: {IsNormalLayer}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(PositionZ)}: {PositionZ}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(LightPWM)}: {LightPWM}, {nameof(IsModified)}: {IsModified}";
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -388,18 +415,18 @@ namespace UVtools.Core
|
||||
|
||||
public Layer PreviousLayer()
|
||||
{
|
||||
if (ReferenceEquals(ParentLayerManager, null) || Index == 0)
|
||||
if (ParentLayerManager is null || _index == 0)
|
||||
return null;
|
||||
|
||||
return ParentLayerManager[Index - 1];
|
||||
return ParentLayerManager[_index - 1];
|
||||
}
|
||||
|
||||
public Layer NextLayer()
|
||||
{
|
||||
if (ReferenceEquals(ParentLayerManager, null) || Index >= ParentLayerManager.Count - 1)
|
||||
if (ParentLayerManager is null || _index >= ParentLayerManager.Count - 1)
|
||||
return null;
|
||||
|
||||
return ParentLayerManager[Index + 1];
|
||||
return ParentLayerManager[_index + 1];
|
||||
}
|
||||
|
||||
public bool SetValueFromPrintParameterModifier(FileFormat.PrintParameterModifier modifier, decimal value)
|
||||
|
||||
@@ -49,8 +49,14 @@ namespace UVtools.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bounding rectangle of the object
|
||||
/// </summary>
|
||||
private Rectangle _boundingRectangle = Rectangle.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bounding rectangle of the object
|
||||
/// </summary>
|
||||
public Rectangle BoundingRectangle
|
||||
{
|
||||
get => GetBoundingRectangle();
|
||||
@@ -79,7 +85,7 @@ namespace UVtools.Core
|
||||
}
|
||||
}
|
||||
|
||||
public float LayerHeight => Layers[0].PositionZ;
|
||||
//public float LayerHeight => Layers[0].PositionZ;
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -1293,6 +1299,15 @@ namespace UVtools.Core
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Formater
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(BoundingRectangle)}: {BoundingRectangle}, {nameof(Count)}: {Count}, {nameof(IsModified)}: {IsModified}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace UVtools.Core.Objects
|
||||
|
||||
public string TagString
|
||||
{
|
||||
get => Tag.ToString();
|
||||
get => Tag?.ToString();
|
||||
set => Tag = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using UVtools.Core.FileFormats;
|
||||
@@ -19,13 +18,31 @@ namespace UVtools.Core.Operations
|
||||
[Serializable]
|
||||
public abstract class Operation : BindableBase, IDisposable
|
||||
{
|
||||
#region Members
|
||||
private Rectangle _roi = Rectangle.Empty;
|
||||
private uint _layerIndexEnd;
|
||||
private uint _layerIndexStart;
|
||||
private string _profileName;
|
||||
private bool _profileIsDefault;
|
||||
private Enumerations.LayerRangeSelection _layerRangeSelection = Enumerations.LayerRangeSelection.All;
|
||||
private FileFormat _slicerFile;
|
||||
public const byte ClassNameLength = 9;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
[XmlIgnore]
|
||||
public FileFormat SlicerFile
|
||||
{
|
||||
get => _slicerFile;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _slicerFile, value)) return;
|
||||
InitWithSlicerFile();
|
||||
}
|
||||
}
|
||||
|
||||
[XmlIgnore]
|
||||
public object Tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID name of this operation, this comes from class name with "Operation" removed
|
||||
@@ -43,6 +60,19 @@ namespace UVtools.Core.Operations
|
||||
set => RaiseAndSetIfChanged(ref _layerRangeSelection, value);
|
||||
}
|
||||
|
||||
public virtual string LayerRangeString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LayerRangeSelection == Enumerations.LayerRangeSelection.None)
|
||||
{
|
||||
return $" [Layers: {LayerIndexStart}-{LayerIndexEnd}]";
|
||||
}
|
||||
|
||||
return $" [Layers: {LayerRangeSelection}]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this operation should set layer range to the actual layer index on layer preview
|
||||
/// </summary>
|
||||
@@ -95,18 +125,6 @@ namespace UVtools.Core.Operations
|
||||
|
||||
public bool HaveAction => !string.IsNullOrEmpty(ProgressAction);
|
||||
|
||||
/// <summary>
|
||||
/// Validates the operation
|
||||
/// </summary>
|
||||
/// <returns>null or empty if validates, or else, return a string with error message</returns>
|
||||
public virtual StringTag Validate(params object[] parameters) => null;
|
||||
|
||||
public bool CanValidate(params object[] parameters)
|
||||
{
|
||||
var result = Validate(parameters);
|
||||
return result is null || string.IsNullOrEmpty(result.Content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start layer index where operation will starts in
|
||||
/// </summary>
|
||||
@@ -153,6 +171,105 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
public bool HaveROI => !ROI.IsEmpty;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
protected Operation() { }
|
||||
|
||||
protected Operation(FileFormat slicerFile)
|
||||
{
|
||||
_slicerFile = slicerFile;
|
||||
SelectAllLayers();
|
||||
InitWithSlicerFile();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Validates the operation
|
||||
/// </summary>
|
||||
/// <returns>null or empty if validates, or else, return a string with error message</returns>
|
||||
public virtual StringTag Validate(params object[] parameters) => null;
|
||||
|
||||
public bool CanValidate(params object[] parameters)
|
||||
{
|
||||
var result = Validate(parameters);
|
||||
return result is null || string.IsNullOrEmpty(result.Content);
|
||||
}
|
||||
|
||||
public void SelectAllLayers()
|
||||
{
|
||||
LayerIndexStart = 0;
|
||||
LayerIndexEnd = SlicerFile.LastLayerIndex;
|
||||
LayerRangeSelection = Enumerations.LayerRangeSelection.All;
|
||||
}
|
||||
|
||||
public void SelectCurrentLayer(uint layerIndex)
|
||||
{
|
||||
LayerIndexStart = LayerIndexEnd = layerIndex;
|
||||
LayerRangeSelection = Enumerations.LayerRangeSelection.Current;
|
||||
}
|
||||
|
||||
public void SelectBottomLayers()
|
||||
{
|
||||
LayerIndexStart = 0;
|
||||
LayerIndexEnd = SlicerFile.BottomLayerCount - 1u;
|
||||
LayerRangeSelection = Enumerations.LayerRangeSelection.Bottom;
|
||||
}
|
||||
|
||||
public void SelectNormalLayers()
|
||||
{
|
||||
LayerIndexStart = SlicerFile.BottomLayerCount;
|
||||
LayerIndexEnd = SlicerFile.LastLayerIndex;
|
||||
LayerRangeSelection = Enumerations.LayerRangeSelection.Normal;
|
||||
}
|
||||
|
||||
public void SelectFirstLayer()
|
||||
{
|
||||
LayerIndexStart = LayerIndexEnd = 0;
|
||||
LayerRangeSelection = Enumerations.LayerRangeSelection.First;
|
||||
}
|
||||
|
||||
public void SelectLastLayer()
|
||||
{
|
||||
LayerIndexStart = LayerIndexEnd = SlicerFile.LastLayerIndex;
|
||||
LayerRangeSelection = Enumerations.LayerRangeSelection.Last;
|
||||
}
|
||||
|
||||
public void SelectLayers(Enumerations.LayerRangeSelection range)
|
||||
{
|
||||
switch (range)
|
||||
{
|
||||
case Enumerations.LayerRangeSelection.None:
|
||||
break;
|
||||
case Enumerations.LayerRangeSelection.All:
|
||||
SelectAllLayers();
|
||||
break;
|
||||
case Enumerations.LayerRangeSelection.Current:
|
||||
//SelectCurrentLayer();
|
||||
break;
|
||||
case Enumerations.LayerRangeSelection.Bottom:
|
||||
SelectBottomLayers();
|
||||
break;
|
||||
case Enumerations.LayerRangeSelection.Normal:
|
||||
SelectNormalLayers();
|
||||
break;
|
||||
case Enumerations.LayerRangeSelection.First:
|
||||
SelectFirstLayer();
|
||||
break;
|
||||
case Enumerations.LayerRangeSelection.Last:
|
||||
SelectLastLayer();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called to init the object when <see cref="SlicerFile"/> changes
|
||||
/// </summary>
|
||||
public virtual void InitWithSlicerFile() { }
|
||||
|
||||
public Mat GetRoiOrDefault(Mat defaultMat)
|
||||
{
|
||||
@@ -161,7 +278,9 @@ namespace UVtools.Core.Operations
|
||||
|
||||
public virtual Operation Clone()
|
||||
{
|
||||
return MemberwiseClone() as Operation;
|
||||
var operation = MemberwiseClone() as Operation;
|
||||
operation.SlicerFile = _slicerFile;
|
||||
return operation;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -172,29 +291,30 @@ namespace UVtools.Core.Operations
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual string LayerRangeString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LayerRangeSelection == Enumerations.LayerRangeSelection.None)
|
||||
{
|
||||
return $" [Layers: {LayerIndexStart}-{LayerIndexEnd}]";
|
||||
}
|
||||
|
||||
return $" [Layers: {LayerRangeSelection}]";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected virtual bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Execute(OperationProgress progress = null)
|
||||
{
|
||||
if (_slicerFile is null) throw new InvalidOperationException($"{Title} can't execute due the lacking of file parent.");
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
var result = ExecuteInternally(progress);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual bool Execute(Mat mat, params object[] arguments)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual void Dispose() { }
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,14 @@ namespace UVtools.Core.Operations
|
||||
public bool IsValid => SetLayers.Count > 0 & Operations.Count > 0;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationArithmetic() { }
|
||||
|
||||
public OperationArithmetic(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public bool Parse()
|
||||
@@ -205,17 +213,16 @@ namespace UVtools.Core.Operations
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
if (!IsValid) return false;
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, (uint)Operations.Count);
|
||||
|
||||
using Mat result = slicerFile[Operations[0].LayerIndex].LayerMat;
|
||||
using Mat result = SlicerFile[Operations[0].LayerIndex].LayerMat;
|
||||
Mat resultRoi = GetRoiOrDefault(result);
|
||||
for (int i = 1; i < Operations.Count; i++)
|
||||
{
|
||||
using var image = slicerFile[Operations[i].LayerIndex].LayerMat;
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
using var image = SlicerFile[Operations[i].LayerIndex].LayerMat;
|
||||
Mat imageRoi = GetRoiOrDefault(image);
|
||||
switch (Operations[i - 1].Operator)
|
||||
{
|
||||
@@ -245,18 +252,19 @@ namespace UVtools.Core.Operations
|
||||
|
||||
Parallel.ForEach(SetLayers, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
if (Operations.Count == 1 && HaveROI)
|
||||
{
|
||||
var mat = slicerFile[layerIndex].LayerMat;
|
||||
var mat = SlicerFile[layerIndex].LayerMat;
|
||||
var matRoi = GetRoiOrDefault(mat);
|
||||
resultRoi.CopyTo(matRoi);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
return;
|
||||
}
|
||||
slicerFile[layerIndex].LayerMat = result;
|
||||
SlicerFile[layerIndex].LayerMat = result;
|
||||
});
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -124,28 +124,33 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationBlur() { }
|
||||
|
||||
public OperationBlur(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = slicerFile[layerIndex].LayerMat)
|
||||
using (var mat = SlicerFile[layerIndex].LayerMat)
|
||||
{
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
}
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Objects;
|
||||
|
||||
namespace UVtools.Core.Operations
|
||||
@@ -15,6 +16,7 @@ namespace UVtools.Core.Operations
|
||||
[Serializable]
|
||||
public class OperationCalculator : Operation
|
||||
{
|
||||
#region Overrides
|
||||
public override string Title => "Calculator";
|
||||
public override string Description => null;
|
||||
|
||||
@@ -28,15 +30,31 @@ namespace UVtools.Core.Operations
|
||||
public override bool CanROI => false;
|
||||
|
||||
public override bool CanHaveProfiles => false;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public MillimetersToPixels CalcMillimetersToPixels { get; set; }
|
||||
public LightOffDelayC CalcLightOffDelay { get; set; }
|
||||
public OptimalModelTilt CalcOptimalModelTilt { get; set; }
|
||||
#endregion
|
||||
|
||||
public OperationCalculator()
|
||||
#region Constructor
|
||||
|
||||
public OperationCalculator() { }
|
||||
|
||||
public OperationCalculator(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
CalcMillimetersToPixels = new MillimetersToPixels(slicerFile.Resolution, slicerFile.Display);
|
||||
CalcLightOffDelay = new LightOffDelayC(
|
||||
(decimal) SlicerFile.LiftHeight, (decimal) slicerFile.BottomLiftHeight,
|
||||
(decimal) SlicerFile.LiftSpeed, (decimal) slicerFile.BottomLiftSpeed,
|
||||
(decimal) SlicerFile.RetractSpeed, (decimal) slicerFile.RetractSpeed);
|
||||
CalcOptimalModelTilt = new OptimalModelTilt(slicerFile.Resolution, slicerFile.Display,
|
||||
(decimal) slicerFile.LayerHeight);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public abstract class Calculation : BindableBase
|
||||
{
|
||||
public abstract string Description { get; }
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace UVtools.Core.Operations
|
||||
public sealed class OperationCalibrateElephantFoot : Operation
|
||||
{
|
||||
#region Members
|
||||
private Size _resolution = Size.Empty;
|
||||
private decimal _layerHeight = 0.05M;
|
||||
private bool _syncLayers;
|
||||
private ushort _bottomLayers = 10;
|
||||
@@ -112,14 +111,6 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Properties
|
||||
|
||||
[XmlIgnore]
|
||||
public Size Resolution
|
||||
{
|
||||
get => _resolution;
|
||||
set => RaiseAndSetIfChanged(ref _resolution, value);
|
||||
}
|
||||
|
||||
|
||||
public decimal LayerHeight
|
||||
{
|
||||
get => _layerHeight;
|
||||
@@ -347,6 +338,21 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationCalibrateElephantFoot() { }
|
||||
|
||||
public OperationCalibrateElephantFoot(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
_layerHeight = (decimal)slicerFile.LayerHeight;
|
||||
//_bottomLayers = slicerFile.BottomLayerCount;
|
||||
_bottomExposure = (decimal)slicerFile.BottomExposureTime;
|
||||
_normalExposure = (decimal)slicerFile.ExposureTime;
|
||||
_mirrorOutput = slicerFile.MirrorDisplay;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
private bool Equals(OperationCalibrateElephantFoot other)
|
||||
@@ -400,7 +406,7 @@ namespace UVtools.Core.Operations
|
||||
var anchor = new Point(-1, -1);
|
||||
var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor);
|
||||
|
||||
layers[0] = EmguExtensions.InitMat(Resolution);
|
||||
layers[0] = EmguExtensions.InitMat(SlicerFile.Resolution);
|
||||
LineType lineType = _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected;
|
||||
int length = (int) (250 * _partScale);
|
||||
int triangleLength = (int) (50 * _partScale);
|
||||
@@ -633,32 +639,25 @@ namespace UVtools.Core.Operations
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, 3);
|
||||
slicerFile.SuppressRebuildProperties = true;
|
||||
progress.ItemCount = 3;
|
||||
|
||||
var newLayers = new Layer[LayerCount];
|
||||
|
||||
slicerFile.LayerHeight = (float)LayerHeight;
|
||||
slicerFile.BottomExposureTime = (float)BottomExposure;
|
||||
slicerFile.ExposureTime = (float)NormalExposure;
|
||||
slicerFile.BottomLayerCount = BottomLayers;
|
||||
|
||||
var layers = GetLayers();
|
||||
progress++;
|
||||
|
||||
|
||||
var bottomLayer = new Layer(0, layers[0], slicerFile.LayerManager)
|
||||
var bottomLayer = new Layer(0, layers[0], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
};
|
||||
var layer = new Layer(0, layers[1], slicerFile.LayerManager)
|
||||
var layer = new Layer(0, layers[1], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
};
|
||||
var moveOp = new OperationMove(bottomLayer.BoundingRectangle, layers[0].Size);
|
||||
var moveOp = new OperationMove(SlicerFile, bottomLayer.BoundingRectangle);
|
||||
moveOp.Execute(layers[0]);
|
||||
moveOp.Execute(layers[1]);
|
||||
|
||||
@@ -671,7 +670,7 @@ namespace UVtools.Core.Operations
|
||||
layerIndex < LayerCount;
|
||||
layerIndex++)
|
||||
{
|
||||
newLayers[layerIndex] = slicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(), layer.Clone());
|
||||
newLayers[layerIndex] = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(), layer.Clone());
|
||||
}
|
||||
|
||||
foreach (var mat in layers)
|
||||
@@ -680,16 +679,22 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
|
||||
if (slicerFile.ThumbnailsCount > 0)
|
||||
slicerFile.SetThumbnails(GetThumbnail());
|
||||
if (SlicerFile.ThumbnailsCount > 0)
|
||||
SlicerFile.SetThumbnails(GetThumbnail());
|
||||
|
||||
progress++;
|
||||
|
||||
slicerFile.LayerManager.Layers = newLayers;
|
||||
slicerFile.SuppressRebuildProperties = false;
|
||||
slicerFile.LayerManager.RebuildLayersProperties();
|
||||
SlicerFile.SuppressRebuildProperties = true;
|
||||
SlicerFile.LayerHeight = (float)LayerHeight;
|
||||
SlicerFile.BottomExposureTime = (float)BottomExposure;
|
||||
SlicerFile.ExposureTime = (float)NormalExposure;
|
||||
SlicerFile.BottomLayerCount = BottomLayers;
|
||||
|
||||
return true;
|
||||
SlicerFile.LayerManager.Layers = newLayers;
|
||||
SlicerFile.LayerManager.RebuildLayersProperties();
|
||||
SlicerFile.SuppressRebuildProperties = false;
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
|
||||
using UVtools.Core.FileFormats;
|
||||
|
||||
namespace UVtools.Core.Operations
|
||||
{
|
||||
public class OperationCalibrateExternalTests : Operation
|
||||
@@ -32,6 +34,14 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationCalibrateExternalTests() { }
|
||||
|
||||
public OperationCalibrateExternalTests(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -10,7 +10,6 @@ using System;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
@@ -25,7 +24,6 @@ namespace UVtools.Core.Operations
|
||||
public sealed class OperationCalibrateGrayscale : Operation
|
||||
{
|
||||
#region Members
|
||||
private Size _resolution = Size.Empty;
|
||||
private decimal _layerHeight = 0.05M;
|
||||
private ushort _bottomLayers = 10;
|
||||
private ushort _interfaceLayers = 5;
|
||||
@@ -100,15 +98,21 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
#region Constructor
|
||||
|
||||
[XmlIgnore]
|
||||
public Size Resolution
|
||||
public OperationCalibrateGrayscale() { }
|
||||
|
||||
public OperationCalibrateGrayscale(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
get => _resolution;
|
||||
set => RaiseAndSetIfChanged(ref _resolution, value);
|
||||
_layerHeight = (decimal)slicerFile.LayerHeight;
|
||||
_bottomLayers = slicerFile.BottomLayerCount;
|
||||
_bottomExposure = (decimal)slicerFile.BottomExposureTime;
|
||||
_normalExposure = (decimal)slicerFile.ExposureTime;
|
||||
_mirrorOutput = slicerFile.MirrorDisplay;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public decimal LayerHeight
|
||||
{
|
||||
@@ -340,10 +344,10 @@ namespace UVtools.Core.Operations
|
||||
{
|
||||
Mat[] layers = new Mat[3];
|
||||
|
||||
layers[0] = EmguExtensions.InitMat(Resolution);
|
||||
layers[0] = EmguExtensions.InitMat(SlicerFile.Resolution);
|
||||
|
||||
int radius = Math.Max(100, Math.Min(Resolution.Width, Resolution.Height) - _outerMargin * 2) / 2 ;
|
||||
Point center = new Point(Resolution.Width / 2, Resolution.Height / 2);
|
||||
int radius = Math.Max(100, Math.Min(SlicerFile.Resolution.Width, SlicerFile.Resolution.Height) - _outerMargin * 2) / 2 ;
|
||||
Point center = new Point(SlicerFile.Resolution.Width / 2, SlicerFile.Resolution.Height / 2);
|
||||
int innerRadius = Math.Max(100, radius - _innerMargin);
|
||||
double topLineLength = 0;
|
||||
|
||||
@@ -452,32 +456,22 @@ namespace UVtools.Core.Operations
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerCount);
|
||||
slicerFile.SuppressRebuildProperties = true;
|
||||
|
||||
progress.ItemCount = LayerCount;
|
||||
var newLayers = new Layer[LayerCount];
|
||||
|
||||
slicerFile.LayerHeight = (float)LayerHeight;
|
||||
slicerFile.BottomExposureTime = (float)BottomExposure;
|
||||
slicerFile.ExposureTime = (float)NormalExposure;
|
||||
slicerFile.BottomLayerCount = BottomLayers;
|
||||
|
||||
var layers = GetLayers();
|
||||
progress++;
|
||||
|
||||
|
||||
var bottomLayer = new Layer(0, layers[0], slicerFile.LayerManager)
|
||||
var bottomLayer = new Layer(0, layers[0], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
};
|
||||
var interfaceLayer = InterfaceLayers > 0 && layers[1] is not null ? new Layer(0, layers[1], slicerFile.LayerManager)
|
||||
var interfaceLayer = InterfaceLayers > 0 && layers[1] is not null ? new Layer(0, layers[1], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
} : null;
|
||||
var layer = new Layer(0, layers[2], slicerFile.LayerManager)
|
||||
var layer = new Layer(0, layers[2], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
};
|
||||
@@ -511,17 +505,20 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
|
||||
if (slicerFile.ThumbnailsCount > 0)
|
||||
slicerFile.SetThumbnails(GetThumbnail());
|
||||
if (SlicerFile.ThumbnailsCount > 0)
|
||||
SlicerFile.SetThumbnails(GetThumbnail());
|
||||
|
||||
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.LayerManager.Layers = newLayers;
|
||||
slicerFile.SuppressRebuildProperties = false;
|
||||
slicerFile.LayerManager.RebuildLayersProperties();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -10,7 +10,6 @@ using System;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
@@ -98,10 +97,31 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
#region Constructor
|
||||
|
||||
[XmlIgnore]
|
||||
public Size Resolution { get; set; } = Size.Empty;
|
||||
public OperationCalibrateStressTower() { }
|
||||
|
||||
public OperationCalibrateStressTower(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
_layerHeight = (decimal)slicerFile.LayerHeight;
|
||||
_bottomLayers = slicerFile.BottomLayerCount;
|
||||
_bottomExposure = (decimal)slicerFile.BottomExposureTime;
|
||||
_normalExposure = (decimal)slicerFile.ExposureTime;
|
||||
_mirrorOutput = slicerFile.MirrorDisplay;
|
||||
}
|
||||
|
||||
public override void InitWithSlicerFile()
|
||||
{
|
||||
base.InitWithSlicerFile();
|
||||
if (SlicerFile.DisplayWidth > 0)
|
||||
DisplayWidth = (decimal)SlicerFile.DisplayWidth;
|
||||
if (SlicerFile.DisplayHeight > 0)
|
||||
DisplayHeight = (decimal)SlicerFile.DisplayHeight;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public decimal DisplayWidth
|
||||
{
|
||||
@@ -294,8 +314,8 @@ namespace UVtools.Core.Operations
|
||||
{
|
||||
var layers = new Mat[LayerCount];
|
||||
|
||||
Slicer slicer = new(Resolution, new SizeF((float) DisplayWidth, (float) DisplayHeight));
|
||||
Point center = new Point(Resolution.Width / 2, Resolution.Height / 2);
|
||||
Slicer slicer = new(SlicerFile.Resolution, new SizeF((float) DisplayWidth, (float) DisplayHeight));
|
||||
Point center = new Point(SlicerFile.Resolution.Width / 2, SlicerFile.Resolution.Height / 2);
|
||||
uint baseRadius = slicer.PixelsFromMillimeters(_baseDiameter) / 2;
|
||||
uint baseLayers = (ushort) Math.Floor(_baseHeight / _layerHeight);
|
||||
uint bodyLayers = (ushort) Math.Floor(_bodyHeight / _layerHeight);
|
||||
@@ -315,7 +335,7 @@ namespace UVtools.Core.Operations
|
||||
var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor);*/
|
||||
Parallel.For(0, LayerCount, layerIndex =>
|
||||
{
|
||||
layers[layerIndex] = EmguExtensions.InitMat(Resolution);
|
||||
layers[layerIndex] = EmguExtensions.InitMat(SlicerFile.Resolution);
|
||||
});
|
||||
|
||||
Parallel.For(0, baseLayers, layerIndex =>
|
||||
@@ -389,24 +409,16 @@ namespace UVtools.Core.Operations
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerCount);
|
||||
slicerFile.SuppressRebuildProperties = true;
|
||||
|
||||
progress.ItemCount = LayerCount;
|
||||
var newLayers = new Layer[LayerCount];
|
||||
|
||||
slicerFile.LayerHeight = (float)LayerHeight;
|
||||
slicerFile.BottomExposureTime = (float)BottomExposure;
|
||||
slicerFile.ExposureTime = (float)NormalExposure;
|
||||
slicerFile.BottomLayerCount = BottomLayers;
|
||||
|
||||
var layers = GetLayers();
|
||||
|
||||
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);
|
||||
layers[layerIndex].Dispose();
|
||||
lock (progress)
|
||||
{
|
||||
@@ -414,22 +426,21 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
slicerFile.LayerManager.Layers = newLayers;
|
||||
slicerFile.LayerManager.RebuildLayersProperties();
|
||||
|
||||
/*var moveOp = new OperationMove(slicerFile.LayerManager.BoundingRectangle, slicerFile.Resolution)
|
||||
{
|
||||
IsCutMove = true,
|
||||
LayerIndexEnd = slicerFile.LayerCount - 1
|
||||
};
|
||||
moveOp.Execute(slicerFile, progress);*/
|
||||
if (SlicerFile.ThumbnailsCount > 0)
|
||||
SlicerFile.SetThumbnails(GetThumbnail());
|
||||
|
||||
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.SuppressRebuildProperties = false;
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -128,9 +128,6 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Properties
|
||||
|
||||
[XmlIgnore]
|
||||
public Size Resolution { get; set; } = Size.Empty;
|
||||
|
||||
public decimal DisplayWidth
|
||||
{
|
||||
get => _displayWidth;
|
||||
@@ -151,8 +148,8 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
public decimal Xppmm => DisplayWidth > 0 ? Math.Round(Resolution.Width / DisplayWidth, 2) : 0;
|
||||
public decimal Yppmm => DisplayHeight > 0 ? Math.Round(Resolution.Height / DisplayHeight, 2) : 0;
|
||||
public decimal Xppmm => DisplayWidth > 0 ? Math.Round(SlicerFile.Resolution.Width / DisplayWidth, 2) : 0;
|
||||
public decimal Yppmm => DisplayHeight > 0 ? Math.Round(SlicerFile.Resolution.Height / DisplayHeight, 2) : 0;
|
||||
|
||||
public decimal LayerHeight
|
||||
{
|
||||
@@ -425,6 +422,30 @@ namespace UVtools.Core.Operations
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationCalibrateTolerance() { }
|
||||
|
||||
public OperationCalibrateTolerance(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
_layerHeight = (decimal)slicerFile.LayerHeight;
|
||||
_bottomLayers = slicerFile.BottomLayerCount;
|
||||
_bottomExposure = (decimal)slicerFile.BottomExposureTime;
|
||||
_normalExposure = (decimal)slicerFile.ExposureTime;
|
||||
_mirrorOutput = slicerFile.MirrorDisplay;
|
||||
}
|
||||
|
||||
public override void InitWithSlicerFile()
|
||||
{
|
||||
base.InitWithSlicerFile();
|
||||
if (SlicerFile.DisplayWidth > 0)
|
||||
DisplayWidth = (decimal)SlicerFile.DisplayWidth;
|
||||
if (SlicerFile.DisplayHeight > 0)
|
||||
DisplayHeight = (decimal)SlicerFile.DisplayHeight;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
public enum Shapes : byte
|
||||
@@ -483,7 +504,7 @@ namespace UVtools.Core.Operations
|
||||
public Mat[] GetLayers()
|
||||
{
|
||||
var layers = new Mat[LayerCount];
|
||||
var layer = EmguExtensions.InitMat(Resolution);
|
||||
var layer = EmguExtensions.InitMat(SlicerFile.Resolution);
|
||||
|
||||
ushort startX = Math.Max((ushort)2, _leftRightMargin);
|
||||
ushort startY = Math.Max((ushort)2, _topBottomMargin);
|
||||
@@ -534,13 +555,13 @@ namespace UVtools.Core.Operations
|
||||
if (_fuseParts)
|
||||
{
|
||||
if (xPixels >= FemaleHoleDiameterXPixels || yPixels >= FemaleHoleDiameterYPixels) return false;
|
||||
if (currentX + FemaleDiameterXPixels + _leftRightMargin >= Resolution.Width)
|
||||
if (currentX + FemaleDiameterXPixels + _leftRightMargin >= SlicerFile.Resolution.Width)
|
||||
{
|
||||
currentX = startX;
|
||||
currentY += (int)FemaleDiameterYPixels + PartMargin;
|
||||
}
|
||||
|
||||
if (currentY + FemaleDiameterYPixels + _topBottomMargin >= Resolution.Height)
|
||||
if (currentY + FemaleDiameterYPixels + _topBottomMargin >= SlicerFile.Resolution.Height)
|
||||
{
|
||||
return false; // Insufficient size
|
||||
}
|
||||
@@ -571,13 +592,13 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentX + xPixels + _leftRightMargin >= Resolution.Width)
|
||||
if (currentX + xPixels + _leftRightMargin >= SlicerFile.Resolution.Width)
|
||||
{
|
||||
currentX = startX;
|
||||
currentY += yPixels + PartMargin;
|
||||
}
|
||||
|
||||
if (currentY + yPixels + _topBottomMargin >= Resolution.Height)
|
||||
if (currentY + yPixels + _topBottomMargin >= SlicerFile.Resolution.Height)
|
||||
{
|
||||
return false; // Insufficient size
|
||||
}
|
||||
@@ -704,24 +725,17 @@ namespace UVtools.Core.Operations
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerCount);
|
||||
slicerFile.SuppressRebuildProperties = true;
|
||||
progress.ItemCount = LayerCount;
|
||||
|
||||
var newLayers = new Layer[LayerCount];
|
||||
|
||||
slicerFile.LayerHeight = (float)LayerHeight;
|
||||
slicerFile.BottomExposureTime = (float)BottomExposure;
|
||||
slicerFile.ExposureTime = (float)NormalExposure;
|
||||
slicerFile.BottomLayerCount = BottomLayers;
|
||||
|
||||
var layers = GetLayers();
|
||||
|
||||
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);
|
||||
layers[layerIndex].Dispose();
|
||||
lock (progress)
|
||||
{
|
||||
@@ -729,22 +743,23 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
slicerFile.LayerManager.Layers = newLayers;
|
||||
slicerFile.LayerManager.RebuildLayersProperties();
|
||||
if (SlicerFile.ThumbnailsCount > 0)
|
||||
SlicerFile.SetThumbnails(GetThumbnail());
|
||||
|
||||
var moveOp = new OperationMove(slicerFile.LayerManager.BoundingRectangle, slicerFile.Resolution)
|
||||
{
|
||||
IsCutMove = true,
|
||||
LayerIndexEnd = slicerFile.LayerCount - 1
|
||||
};
|
||||
moveOp.Execute(slicerFile, 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;
|
||||
|
||||
if (slicerFile.ThumbnailsCount > 0)
|
||||
slicerFile.SetThumbnails(GetThumbnail());
|
||||
var moveOp = new OperationMove(SlicerFile);
|
||||
moveOp.Execute(progress);
|
||||
|
||||
slicerFile.SuppressRebuildProperties = false;
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -118,9 +118,6 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Properties
|
||||
|
||||
[XmlIgnore]
|
||||
public Size Resolution { get; set; } = Size.Empty;
|
||||
|
||||
public decimal DisplayWidth
|
||||
{
|
||||
get => _displayWidth;
|
||||
@@ -141,8 +138,8 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
public decimal Xppmm => DisplayWidth > 0 ? Math.Round(Resolution.Width / DisplayWidth, 2) : 0;
|
||||
public decimal Yppmm => DisplayHeight > 0 ? Math.Round(Resolution.Height / DisplayHeight, 2) : 0;
|
||||
public decimal Xppmm => DisplayWidth > 0 ? Math.Round(SlicerFile.Resolution.Width / DisplayWidth, 2) : 0;
|
||||
public decimal Yppmm => DisplayHeight > 0 ? Math.Round(SlicerFile.Resolution.Height / DisplayHeight, 2) : 0;
|
||||
|
||||
public decimal LayerHeight
|
||||
{
|
||||
@@ -447,6 +444,30 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationCalibrateXYZAccuracy() { }
|
||||
|
||||
public OperationCalibrateXYZAccuracy(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
_layerHeight = (decimal)slicerFile.LayerHeight;
|
||||
_bottomLayers = slicerFile.BottomLayerCount;
|
||||
_bottomExposure = (decimal)slicerFile.BottomExposureTime;
|
||||
_normalExposure = (decimal)slicerFile.ExposureTime;
|
||||
_mirrorOutput = slicerFile.MirrorDisplay;
|
||||
}
|
||||
|
||||
public override void InitWithSlicerFile()
|
||||
{
|
||||
base.InitWithSlicerFile();
|
||||
if (SlicerFile.DisplayWidth > 0)
|
||||
DisplayWidth = (decimal)SlicerFile.DisplayWidth;
|
||||
if (SlicerFile.DisplayHeight > 0)
|
||||
DisplayHeight = (decimal)SlicerFile.DisplayHeight;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
#endregion
|
||||
@@ -586,7 +607,7 @@ namespace UVtools.Core.Operations
|
||||
var layers = new Mat[2];
|
||||
for (byte i = 0; i < layers.Length; i++)
|
||||
{
|
||||
layers[i] = EmguExtensions.InitMat(Resolution);
|
||||
layers[i] = EmguExtensions.InitMat(SlicerFile.Resolution);
|
||||
}
|
||||
|
||||
|
||||
@@ -610,11 +631,11 @@ namespace UVtools.Core.Operations
|
||||
positionYStr = "T";
|
||||
break;
|
||||
case 1:
|
||||
currentY = (int)(Resolution.Height / 2 - YPixels / 2);
|
||||
currentY = (int)(SlicerFile.Resolution.Height / 2 - YPixels / 2);
|
||||
positionYStr = "M";
|
||||
break;
|
||||
case 2:
|
||||
currentY = (int)(Resolution.Height - YPixels - _topBottomMargin);
|
||||
currentY = (int)(SlicerFile.Resolution.Height - YPixels - _topBottomMargin);
|
||||
positionYStr = "B";
|
||||
break;
|
||||
}
|
||||
@@ -627,11 +648,11 @@ namespace UVtools.Core.Operations
|
||||
positionStr = $"{positionYStr}L";
|
||||
break;
|
||||
case 1:
|
||||
currentX = (int)(Resolution.Width / 2 - XPixels / 2);
|
||||
currentX = (int)(SlicerFile.Resolution.Width / 2 - XPixels / 2);
|
||||
positionStr = $"{positionYStr}C";
|
||||
break;
|
||||
case 2:
|
||||
currentX = (int)(Resolution.Width - XPixels - _leftRightMargin);
|
||||
currentX = (int)(SlicerFile.Resolution.Width - XPixels - _leftRightMargin);
|
||||
positionStr = $"{positionYStr}R";
|
||||
break;
|
||||
}
|
||||
@@ -716,34 +737,27 @@ namespace UVtools.Core.Operations
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerCount);
|
||||
progress.ItemCount = LayerCount;
|
||||
|
||||
slicerFile.SuppressRebuildProperties = true;
|
||||
|
||||
var newLayers = new Layer[LayerCount];
|
||||
|
||||
slicerFile.LayerHeight = (float)LayerHeight;
|
||||
slicerFile.BottomExposureTime = (float)BottomExposure;
|
||||
slicerFile.ExposureTime = (float)NormalExposure;
|
||||
slicerFile.BottomLayerCount = BottomLayers;
|
||||
|
||||
var layers = GetLayers();
|
||||
|
||||
var bottomLayer = new Layer(0, layers[0], slicerFile.LayerManager)
|
||||
var bottomLayer = new Layer(0, layers[0], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
};
|
||||
var layer = new Layer(0, layers[1], slicerFile.LayerManager)
|
||||
var layer = new Layer(0, layers[1], SlicerFile.LayerManager)
|
||||
{
|
||||
IsModified = true
|
||||
};
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
newLayers[layerIndex] = slicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(), layer.Clone());
|
||||
newLayers[layerIndex] = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(), layer.Clone());
|
||||
progress++;
|
||||
}
|
||||
|
||||
@@ -752,13 +766,19 @@ namespace UVtools.Core.Operations
|
||||
mat.Dispose();
|
||||
}
|
||||
|
||||
if (slicerFile.ThumbnailsCount > 0)
|
||||
slicerFile.SetThumbnails(GetThumbnail());
|
||||
if (SlicerFile.ThumbnailsCount > 0)
|
||||
SlicerFile.SetThumbnails(GetThumbnail());
|
||||
|
||||
slicerFile.LayerManager.Layers = newLayers;
|
||||
slicerFile.LayerManager.RebuildLayersProperties();
|
||||
slicerFile.SuppressRebuildProperties = false;
|
||||
return true;
|
||||
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;
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -64,25 +64,25 @@ namespace UVtools.Core.Operations
|
||||
|
||||
public override string ConfirmationText =>
|
||||
"change print resolution " +
|
||||
$"from {OldResolution.Width}x{OldResolution.Height} " +
|
||||
$"from {SlicerFile.ResolutionX}x{SlicerFile.ResolutionY} " +
|
||||
$"to {NewResolutionX}x{NewResolutionY}?";
|
||||
|
||||
public override string ProgressTitle =>
|
||||
$"Changing print resolution from ({OldResolution.Width}x{OldResolution.Height}) to ({NewResolutionX}x{NewResolutionY})";
|
||||
$"Changing print resolution from ({SlicerFile.ResolutionX}x{SlicerFile.ResolutionY}) to ({NewResolutionX}x{NewResolutionY})";
|
||||
|
||||
public override string ProgressAction => "Changed layers";
|
||||
|
||||
public override StringTag Validate(params object[] parameters)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (OldResolution.Width == NewResolutionX && OldResolution.Height == NewResolutionY)
|
||||
if (SlicerFile.ResolutionX == NewResolutionX && SlicerFile.ResolutionY == NewResolutionY)
|
||||
{
|
||||
sb.AppendLine($"The new resolution must be different from current resolution ({OldResolution.Width} x {OldResolution.Height}).");
|
||||
sb.AppendLine($"The new resolution must be different from current resolution ({SlicerFile.ResolutionX} x {SlicerFile.ResolutionY}).");
|
||||
}
|
||||
|
||||
if (NewResolutionX < VolumeBonds.Width || NewResolutionY < VolumeBonds.Height)
|
||||
if (NewResolutionX < SlicerFile.BoundingRectangle.Width || NewResolutionY < SlicerFile.BoundingRectangle.Height)
|
||||
{
|
||||
sb.AppendLine($"The new resolution ({NewResolutionX} x {NewResolutionY}) is not large enough to hold the model volume ({VolumeBonds.Width} x {VolumeBonds.Height}), continuing operation would clip the model");
|
||||
sb.AppendLine($"The new resolution ({NewResolutionX} x {NewResolutionY}) is not large enough to hold the model volume ({SlicerFile.BoundingRectangle.Width} x {SlicerFile.BoundingRectangle.Height}), continuing operation would clip the model");
|
||||
sb.AppendLine("To fix this, try to rotate the object and/or resize to fit on this new resolution.");
|
||||
}
|
||||
|
||||
@@ -99,8 +99,6 @@ namespace UVtools.Core.Operations
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public Size OldResolution { get; }
|
||||
|
||||
public uint NewResolutionX
|
||||
{
|
||||
get => _newResolutionX;
|
||||
@@ -113,25 +111,20 @@ namespace UVtools.Core.Operations
|
||||
set => RaiseAndSetIfChanged(ref _newResolutionY, value);
|
||||
}
|
||||
|
||||
public Rectangle VolumeBonds { get; }
|
||||
|
||||
public Size VolumeBondsSize => VolumeBonds.Size;
|
||||
public Size VolumeBondsSize => SlicerFile.BoundingRectangle.Size;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationChangeResolution()
|
||||
public OperationChangeResolution() { }
|
||||
|
||||
public OperationChangeResolution(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
NewResolutionX = SlicerFile.ResolutionX;
|
||||
NewResolutionY = SlicerFile.ResolutionY;
|
||||
}
|
||||
|
||||
public OperationChangeResolution(Size oldResolution, Rectangle volumeBonds)
|
||||
{
|
||||
OldResolution = oldResolution;
|
||||
VolumeBonds = volumeBonds;
|
||||
NewResolutionX = (uint) oldResolution.Width;
|
||||
NewResolutionY = (uint) oldResolution.Height;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
@@ -159,25 +152,24 @@ namespace UVtools.Core.Operations
|
||||
public static Resolution[] Presets => GetResolutions();
|
||||
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, slicerFile.LayerCount);
|
||||
progress.ItemCount = SlicerFile.LayerCount;
|
||||
|
||||
Parallel.For(0, slicerFile.LayerCount, layerIndex =>
|
||||
Parallel.For(0, SlicerFile.LayerCount, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var matRoi = new Mat(mat, VolumeBonds);
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
using var matRoi = new Mat(mat, SlicerFile.BoundingRectangle);
|
||||
using var matDst = new Mat(new Size((int)NewResolutionX, (int)NewResolutionY), mat.Depth, mat.NumberOfChannels);
|
||||
using var matDstRoi = new Mat(matDst,
|
||||
new Rectangle((int)(NewResolutionX / 2 - VolumeBonds.Width / 2),
|
||||
(int)NewResolutionY / 2 - VolumeBonds.Height / 2,
|
||||
VolumeBonds.Width, VolumeBonds.Height));
|
||||
new Rectangle((int)(NewResolutionX / 2 - SlicerFile.BoundingRectangle.Width / 2),
|
||||
(int)NewResolutionY / 2 - SlicerFile.BoundingRectangle.Height / 2,
|
||||
SlicerFile.BoundingRectangle.Width, SlicerFile.BoundingRectangle.Height));
|
||||
matRoi.CopyTo(matDstRoi);
|
||||
//Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = matDst;
|
||||
SlicerFile[layerIndex].LayerMat = matDst;
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
@@ -187,10 +179,10 @@ namespace UVtools.Core.Operations
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
slicerFile.ResolutionX = NewResolutionX;
|
||||
slicerFile.ResolutionY = NewResolutionY;
|
||||
SlicerFile.ResolutionX = NewResolutionX;
|
||||
SlicerFile.ResolutionY = NewResolutionY;
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
/*public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -0,0 +1,760 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using UVtools.Core.Extensions;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Objects;
|
||||
|
||||
namespace UVtools.Core.Operations
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class OperationDynamicLayerHeight : Operation
|
||||
{
|
||||
#region Sub Classes
|
||||
public sealed class Report
|
||||
{
|
||||
public uint OldLayerCount { get; set; }
|
||||
public uint NewLayerCount { get; set; }
|
||||
public uint StackedLayers { get; set; }
|
||||
public uint ReusedLayers => OldLayerCount - StackedLayers;
|
||||
public float MaximumLayerHeight { get; set; }
|
||||
public float OldPrintTime { get; set; }
|
||||
public float NewPrintTime { get; set; }
|
||||
public double SparedPrintTime => Math.Round(OldPrintTime - NewPrintTime, 2);
|
||||
|
||||
public double CompressionRatio => Math.Round((double)OldLayerCount / NewLayerCount * 100.0, 2);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var oldTime = TimeSpan.FromSeconds(OldPrintTime);
|
||||
var newTime = TimeSpan.FromSeconds(NewPrintTime);
|
||||
var sparedTime = TimeSpan.FromSeconds(SparedPrintTime);
|
||||
return
|
||||
$"From {OldLayerCount} layers, {ReusedLayers} got reused, {StackedLayers} got stacked and optimized with dynamic layer height's\n" +
|
||||
$"Resultant layers: {NewLayerCount}\n" +
|
||||
$"Compression ratio: {CompressionRatio}%\n" +
|
||||
$"Maximum layer height reached: {MaximumLayerHeight}mm\n" +
|
||||
$"Print time: {oldTime.Hours}h{oldTime.Minutes}m{oldTime.Seconds}s -> {newTime.Hours}h{newTime.Minutes}m{newTime.Seconds}s (- {sparedTime.Hours}h{sparedTime.Minutes}m{sparedTime.Seconds}s)";
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class ExposureItem : BindableBase
|
||||
{
|
||||
private decimal _layerHeight;
|
||||
private decimal _bottomExposure;
|
||||
private decimal _exposure;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the layer height in millimeters
|
||||
/// </summary>
|
||||
public decimal LayerHeight
|
||||
{
|
||||
get => _layerHeight;
|
||||
set => RaiseAndSetIfChanged(ref _layerHeight, Math.Round(value, 2));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom exposure in seconds
|
||||
/// </summary>
|
||||
public decimal BottomExposure
|
||||
{
|
||||
get => _bottomExposure;
|
||||
set => RaiseAndSetIfChanged(ref _bottomExposure, Math.Round(value, 2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom exposure in seconds
|
||||
/// </summary>
|
||||
public decimal Exposure
|
||||
{
|
||||
get => _exposure;
|
||||
set => RaiseAndSetIfChanged(ref _exposure, Math.Round(value, 2));
|
||||
}
|
||||
|
||||
public ExposureItem() { }
|
||||
|
||||
public ExposureItem(decimal layerHeight, decimal bottomExposure = 0, decimal exposure = 0)
|
||||
{
|
||||
_layerHeight = Math.Round(layerHeight, 2);
|
||||
_bottomExposure = Math.Round(bottomExposure, 2);
|
||||
_exposure = Math.Round(exposure, 2);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(LayerHeight)}: {LayerHeight}mm, {nameof(BottomExposure)}: {BottomExposure}s, {nameof(Exposure)}: {Exposure}s";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
public const byte ObjectsPerCache = 2;
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
|
||||
//private decimal _displayWidth;
|
||||
//private decimal _displayHeight;
|
||||
private decimal _minimumLayerHeight = 0.03m;
|
||||
private decimal _maximumLayerHeight = 0.10m;
|
||||
private decimal _cacheRamSize = 1.5m;
|
||||
private ExposureSetTypes _exposureSetType = ExposureSetTypes.Linear;
|
||||
private decimal _bottomExposureStep = 0.5m;
|
||||
private decimal _exposureStep = 0.2m;
|
||||
private ObservableCollection<ExposureItem> _automaticExposureTable = new();
|
||||
private ObservableCollection<ExposureItem> _manualExposureTable = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override bool CanROI => false;
|
||||
|
||||
public override string Title => "Dynamic layer height";
|
||||
|
||||
public override string Description =>
|
||||
"Analyze and optimize the model with dynamic layer heights, larger angles will slice at lower layer height" +
|
||||
" while more straight angles will slice larger layer height.\n" +
|
||||
"Note: The model should be sliced at the lowest layer height possible (0.01mm).\n" +
|
||||
"After this, do not apply any modification which reconstruct the z positions of the layers. " +
|
||||
"Only few printers support this, make sure your is supported or else it will print a malformed model.";
|
||||
|
||||
public override string ConfirmationText =>
|
||||
$"dynamic layers from layers {LayerIndexStart} through {LayerIndexEnd}?";
|
||||
|
||||
public override string ProgressTitle =>
|
||||
$"Analyzing and optimizing layers height from layers {LayerIndexStart} through {LayerIndexEnd}";
|
||||
|
||||
public override string ProgressAction => "Processed layers";
|
||||
|
||||
public override StringTag Validate(params object[] parameters)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
/*if (XYResolutionUm <= 0)
|
||||
{
|
||||
sb.AppendLine($"Display width and height must be a positive value.");
|
||||
}*/
|
||||
|
||||
decimal layerHeight = (decimal) SlicerFile.LayerHeight;
|
||||
if (_minimumLayerHeight < layerHeight)
|
||||
{
|
||||
sb.AppendLine(
|
||||
$"Minimum layer height ({_minimumLayerHeight}mm) must be equal or higher than file layer height ({layerHeight}mm)");
|
||||
}
|
||||
if (_minimumLayerHeight > _maximumLayerHeight)
|
||||
{
|
||||
sb.AppendLine(
|
||||
$"Minimum layer height ({_minimumLayerHeight}mm) can't be higher than maximum layer height ({_maximumLayerHeight}mm)");
|
||||
}
|
||||
if (layerHeight >= _maximumLayerHeight)
|
||||
{
|
||||
sb.AppendLine(
|
||||
$"Maximum layer height ({_maximumLayerHeight}mm) can't be the same or less than current file layer height ({SlicerFile.LayerHeight}mm)");
|
||||
}
|
||||
|
||||
var exposureTable = ExposureTableDictionary;
|
||||
|
||||
for (layerHeight = (decimal) SlicerFile.LayerHeight;
|
||||
layerHeight <= _maximumLayerHeight;
|
||||
layerHeight = layerHeight + (decimal) SlicerFile.LayerHeight)
|
||||
{
|
||||
layerHeight = Math.Round(layerHeight, 2);
|
||||
if (exposureTable.TryGetValue(layerHeight, out var exposure))
|
||||
{
|
||||
if (exposure.BottomExposure <= 0 || exposure.Exposure <= 0)
|
||||
{
|
||||
sb.AppendLine($"Layer height {layerHeight}mm exposures must be a positive value, current: {exposure.BottomExposure}s/{exposure.Exposure}s");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine($"Layer height {layerHeight}mm exposures are missing.");
|
||||
}
|
||||
}
|
||||
|
||||
return new StringTag(sb.ToString());
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var result = $"[Layer Height: Min: {_minimumLayerHeight}mm Max: {_maximumLayerHeight}mm] [RAM: {_cacheRamSize}Gb] [Exposure type: {_exposureSetType}, Steps: {_bottomExposureStep}s/{_exposureStep}s]" + LayerRangeString;
|
||||
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
public enum ExposureSetTypes: byte
|
||||
{
|
||||
Linear,
|
||||
Multiplier,
|
||||
Manual
|
||||
}
|
||||
|
||||
public static Array ExposureSetTypeItems => Enum.GetValues(typeof(ExposureSetTypes));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/*public decimal DisplayWidth
|
||||
{
|
||||
get => _displayWidth;
|
||||
set
|
||||
{
|
||||
if (!RaiseAndSetIfChanged(ref _displayWidth, Math.Round(value, 2))) return;
|
||||
//RaisePropertyChanged(nameof(XYResolutionUm));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal DisplayHeight
|
||||
{
|
||||
get => _displayHeight;
|
||||
set
|
||||
{
|
||||
if (!RaiseAndSetIfChanged(ref _displayHeight, Math.Round(value, 2))) return;
|
||||
//RaisePropertyChanged(nameof(XYResolutionUm));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal XYResolutionUm => DisplayWidth > 0 || DisplayHeight > 0 ?
|
||||
Math.Round(Math.Max(
|
||||
DisplayWidth / SlicerFile.ResolutionX,
|
||||
DisplayHeight / SlicerFile.ResolutionY
|
||||
), 3) * 1000
|
||||
: 0;
|
||||
*/
|
||||
|
||||
public decimal MinimumLayerHeight
|
||||
{
|
||||
get => _minimumLayerHeight;
|
||||
set
|
||||
{
|
||||
if (!RaiseAndSetIfChanged(ref _minimumLayerHeight, Math.Round(value, 2))) return;
|
||||
//RaisePropertyChanged(nameof(ExposureData));
|
||||
//if (!IsExposureSetTypeManual) RebuildAutoExposureTable();
|
||||
}
|
||||
}
|
||||
|
||||
public decimal MaximumLayerHeight
|
||||
{
|
||||
get => _maximumLayerHeight;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _maximumLayerHeight, Math.Round(value, 2))) return;
|
||||
//RaisePropertyChanged(nameof(ExposureData));
|
||||
if(!IsExposureSetTypeManual) RebuildAutoExposureTable();
|
||||
}
|
||||
}
|
||||
|
||||
public uint CacheObjectCount => (uint) (_cacheRamSize * 1000000000L / SlicerFile.Resolution.GetArea() / ObjectsPerCache);
|
||||
|
||||
public decimal CacheRAMSize
|
||||
{
|
||||
get => _cacheRamSize;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _cacheRamSize, Math.Round(value, 2))) return;
|
||||
RaisePropertyChanged(nameof(CacheObjectCount));
|
||||
}
|
||||
}
|
||||
|
||||
public ExposureSetTypes ExposureSetType
|
||||
{
|
||||
get => _exposureSetType;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _exposureSetType, value)) return;
|
||||
RaisePropertyChanged(nameof(IsExposureSetTypeManual));
|
||||
RaisePropertyChanged(nameof(ExposureTable));
|
||||
RaisePropertyChanged(nameof(ExposureTableDictionary));
|
||||
//RaisePropertyChanged(nameof(ExposureData));
|
||||
if (!IsExposureSetTypeManual) RebuildAutoExposureTable();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsExposureSetTypeManual => _exposureSetType == ExposureSetTypes.Manual;
|
||||
|
||||
public decimal BottomExposureStep
|
||||
{
|
||||
get => _bottomExposureStep;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _bottomExposureStep, value)) return;
|
||||
//RaisePropertyChanged(nameof(ExposureData));
|
||||
if (!IsExposureSetTypeManual) RebuildAutoExposureTable();
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ExposureStep
|
||||
{
|
||||
get => _exposureStep;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _exposureStep, value)) return;
|
||||
//RaisePropertyChanged(nameof(ExposureData));
|
||||
if (!IsExposureSetTypeManual) RebuildAutoExposureTable();
|
||||
}
|
||||
}
|
||||
|
||||
[XmlIgnore]
|
||||
public ObservableCollection<ExposureItem> AutomaticExposureTable
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_automaticExposureTable.Count == 0) RebuildAutoExposureTable();
|
||||
return _automaticExposureTable;
|
||||
}
|
||||
set => RaiseAndSetIfChanged(ref _automaticExposureTable, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ExposureItem> ManualExposureTable
|
||||
{
|
||||
get => _manualExposureTable;
|
||||
set => RaiseAndSetIfChanged(ref _manualExposureTable, value);
|
||||
}
|
||||
|
||||
[XmlIgnore]
|
||||
public ObservableCollection<ExposureItem> ExposureTable => IsExposureSetTypeManual ? _manualExposureTable : AutomaticExposureTable;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exposure table into a dictionary where key is the layer height
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public Dictionary<decimal, ExposureItem> ExposureTableDictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
Dictionary<decimal, ExposureItem> dictionary = new();
|
||||
foreach (var exposure in ExposureTable)
|
||||
{
|
||||
dictionary.TryAdd(exposure.LayerHeight, exposure);
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
|
||||
public string ExposureData
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
byte count = 0;
|
||||
for (decimal layerHeight = (decimal) SlicerFile.LayerHeight; layerHeight <= _maximumLayerHeight; layerHeight+= (decimal)SlicerFile.LayerHeight)
|
||||
{
|
||||
decimal bottomExposure = 0;
|
||||
decimal exposure = 0;
|
||||
switch (_exposureSetType)
|
||||
{
|
||||
case ExposureSetTypes.Linear:
|
||||
bottomExposure = (decimal)SlicerFile.BottomExposureTime + count * _bottomExposureStep;
|
||||
exposure = (decimal)SlicerFile.ExposureTime + count * _exposureStep;
|
||||
break;
|
||||
case ExposureSetTypes.Multiplier:
|
||||
bottomExposure = (decimal)SlicerFile.BottomExposureTime + (decimal)SlicerFile.BottomExposureTime * count * layerHeight * _bottomExposureStep;
|
||||
exposure = (decimal)SlicerFile.BottomExposureTime + (decimal)SlicerFile.ExposureTime * count * layerHeight * _exposureStep;
|
||||
break;
|
||||
case ExposureSetTypes.Manual:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
sb.AppendLine($"{layerHeight:F2}mm: {bottomExposure:F2}s / {exposure:F2}s");
|
||||
count++;
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationDynamicLayerHeight()
|
||||
{
|
||||
//InitManualTable();
|
||||
}
|
||||
|
||||
public OperationDynamicLayerHeight(FileFormat slicerFile) : base(slicerFile)
|
||||
{
|
||||
InitManualTable();
|
||||
}
|
||||
|
||||
public override void InitWithSlicerFile()
|
||||
{
|
||||
base.InitWithSlicerFile();
|
||||
|
||||
/*if (SlicerFile.DisplayWidth > 0)
|
||||
_displayWidth = (decimal)SlicerFile.DisplayWidth;
|
||||
if (SlicerFile.DisplayHeight > 0)
|
||||
_displayHeight = (decimal)SlicerFile.DisplayHeight;*/
|
||||
|
||||
var layerHeight = (decimal)SlicerFile.LayerHeight;
|
||||
if (_minimumLayerHeight < layerHeight)
|
||||
{
|
||||
_minimumLayerHeight = layerHeight;
|
||||
}
|
||||
if (layerHeight * 2 > _maximumLayerHeight)
|
||||
{
|
||||
_maximumLayerHeight = Math.Min((decimal) FileFormat.MaximumLayerHeight, _maximumLayerHeight*2);
|
||||
}
|
||||
}
|
||||
|
||||
public void InitManualTable()
|
||||
{
|
||||
for (decimal layerHeight = (decimal)FileFormat.MinimumLayerHeight;
|
||||
layerHeight <= (decimal) FileFormat.MaximumLayerHeight;
|
||||
layerHeight += (decimal)FileFormat.MinimumLayerHeight)
|
||||
{
|
||||
var item = new ExposureItem(layerHeight);
|
||||
if (layerHeight == (decimal) SlicerFile.LayerHeight)
|
||||
{
|
||||
item.BottomExposure = (decimal) SlicerFile.BottomExposureTime;
|
||||
item.Exposure = (decimal) SlicerFile.ExposureTime;
|
||||
}
|
||||
_manualExposureTable.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
private bool Equals(OperationDynamicLayerHeight other)
|
||||
{
|
||||
return _minimumLayerHeight == other._minimumLayerHeight && _maximumLayerHeight == other._maximumLayerHeight && _cacheRamSize == other._cacheRamSize && _exposureSetType == other._exposureSetType && _bottomExposureStep == other._bottomExposureStep && _exposureStep == other._exposureStep && Equals(_manualExposureTable, other._manualExposureTable);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return ReferenceEquals(this, obj) || obj is OperationDynamicLayerHeight other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(_minimumLayerHeight, _maximumLayerHeight, _cacheRamSize, (int) _exposureSetType, _bottomExposureStep, _exposureStep, _manualExposureTable);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void RebuildAutoExposureTable()
|
||||
{
|
||||
if (SlicerFile is null) return;
|
||||
_automaticExposureTable.Clear();
|
||||
byte count = 0;
|
||||
for (decimal layerHeight = (decimal)SlicerFile.LayerHeight; layerHeight <= _maximumLayerHeight; layerHeight += (decimal)SlicerFile.LayerHeight)
|
||||
{
|
||||
decimal bottomExposure = 0;
|
||||
decimal exposure = 0;
|
||||
switch (_exposureSetType)
|
||||
{
|
||||
case ExposureSetTypes.Linear:
|
||||
bottomExposure = (decimal)SlicerFile.BottomExposureTime + count * _bottomExposureStep;
|
||||
exposure = (decimal)SlicerFile.ExposureTime + count * _exposureStep;
|
||||
break;
|
||||
case ExposureSetTypes.Multiplier:
|
||||
bottomExposure = (decimal)SlicerFile.BottomExposureTime + (decimal)SlicerFile.BottomExposureTime * count * layerHeight * _bottomExposureStep;
|
||||
exposure = (decimal)SlicerFile.BottomExposureTime + (decimal)SlicerFile.ExposureTime * count * layerHeight * _exposureStep;
|
||||
break;
|
||||
case ExposureSetTypes.Manual:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_automaticExposureTable.Add(new ExposureItem(layerHeight, Math.Round(bottomExposure, 2), Math.Round(exposure, 2)));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
Report report = new()
|
||||
{
|
||||
OldLayerCount = SlicerFile.LayerCount,
|
||||
OldPrintTime = SlicerFile.PrintTimeOrComputed
|
||||
};
|
||||
|
||||
var anchor = new Point(-1, -1);
|
||||
using var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor);
|
||||
|
||||
var matCache = new Mat[SlicerFile.LayerCount];
|
||||
var matThresholdCache = new Mat[SlicerFile.LayerCount];
|
||||
|
||||
List<Layer> layers = new();
|
||||
|
||||
using Mat matXor = new();
|
||||
Mat matXorSum = null;
|
||||
Mat matSum = null;
|
||||
|
||||
const byte _maximumErodes = 10;
|
||||
//decimal xyResolutionUm = XYResolutionUm;
|
||||
|
||||
//const double xyRes = 35;
|
||||
//var stepAngle = Math.Atan(SlicerFile.LayerHeight*1000 / xyRes) * (180 / Math.PI);
|
||||
//byte maximumErodes = (byte) (_maximumLayerHeight * 100 - (decimal) (slicerFile.LayerHeight * 100f));
|
||||
|
||||
void CacheLayers(uint fromLayerIndex)
|
||||
{
|
||||
for (int layerIndex = (int) fromLayerIndex-2; layerIndex >= 0; layerIndex--) // clean up only the required layers
|
||||
{
|
||||
if (matCache[layerIndex] is null) break;
|
||||
matCache[layerIndex].Dispose();
|
||||
matCache[layerIndex] = null;
|
||||
matThresholdCache[layerIndex].Dispose();
|
||||
matThresholdCache[layerIndex] = null;
|
||||
}
|
||||
Parallel.For(fromLayerIndex, Math.Min(fromLayerIndex + CacheObjectCount, SlicerFile.LayerCount), layerIndex =>
|
||||
{
|
||||
if (matCache[layerIndex] is not null) return; // Already cached
|
||||
matCache[layerIndex] = SlicerFile[layerIndex].LayerMat;
|
||||
matThresholdCache[layerIndex] = new Mat();
|
||||
|
||||
// Clean AA
|
||||
CvInvoke.Threshold(matCache[layerIndex], matThresholdCache[layerIndex], 128, 255, ThresholdType.Binary);
|
||||
});
|
||||
}
|
||||
|
||||
float GetLastPositionZ(float layerHeight) => layers.Count > 0 ? (float)Math.Round(layers[^1].PositionZ + layerHeight, 2) : layerHeight;
|
||||
|
||||
(Mat, Mat) GetLayer(uint layerIndex)
|
||||
{
|
||||
if (matCache[layerIndex] is null)
|
||||
{
|
||||
CacheLayers(layerIndex);
|
||||
}
|
||||
|
||||
return (matCache[layerIndex], matThresholdCache[layerIndex]);
|
||||
}
|
||||
|
||||
void AddNewLayer(Mat mat, float layerHeight)
|
||||
{
|
||||
report.MaximumLayerHeight = Math.Max(report.MaximumLayerHeight, layerHeight);
|
||||
var positionZ = GetLastPositionZ(layerHeight);
|
||||
var layer = new Layer((uint) layers.Count, mat, SlicerFile)
|
||||
{
|
||||
IsModified = true,
|
||||
PositionZ = positionZ
|
||||
|
||||
};
|
||||
layers.Add(layer);
|
||||
}
|
||||
|
||||
void ReUseLayer(uint layerIndex)
|
||||
{
|
||||
SlicerFile[layerIndex].PositionZ = GetLastPositionZ(SlicerFile.LayerHeight);
|
||||
SlicerFile[layerIndex].Index = (uint) layers.Count;
|
||||
SlicerFile[layerIndex].IsModified = true;
|
||||
layers.Add(SlicerFile[layerIndex]);
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerIndexStart; layerIndex++) // Skip layers and re-use layers
|
||||
{
|
||||
ReUseLayer(layerIndex);
|
||||
}
|
||||
|
||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; )
|
||||
{
|
||||
Debug.WriteLine($"Head Layer: {layerIndex} ({SlicerFile.LayerHeight}mm)");
|
||||
|
||||
if (layerIndex == LayerIndexEnd)
|
||||
{
|
||||
ReUseLayer(layerIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
var currentLayerHeight = SlicerFile.LayerHeight;
|
||||
byte layerSum = 1;
|
||||
byte erodeCount = 0;
|
||||
//byte maxErodeCount = 0;
|
||||
//double maxSlop = 90;
|
||||
matSum?.Dispose();
|
||||
matSum = null;
|
||||
matXorSum?.Dispose();
|
||||
matXorSum = null;
|
||||
|
||||
while (true)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
progress.ProcessedItems = layerIndex;
|
||||
|
||||
if (currentLayerHeight >= (float)_maximumLayerHeight || layerIndex == LayerIndexEnd)
|
||||
{
|
||||
// Cant perform any additional stack. Maximum layer height reached!
|
||||
// Break this cycle and restart from same layer
|
||||
matSum ??= GetLayer(layerIndex).Item1.Clone(); // This only happen when layer height is already the maximum supported layer height
|
||||
layerIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
var previousLayerHeight = currentLayerHeight;
|
||||
currentLayerHeight = (float)Math.Round(currentLayerHeight + SlicerFile.LayerHeight, 2);
|
||||
|
||||
var (mat1, mat1Threshold) = GetLayer(layerIndex);
|
||||
var (mat2, mat2Threshold) = GetLayer(++layerIndex);
|
||||
|
||||
Debug.Write($" Stacking layer: {layerIndex} ({currentLayerHeight}mm)");
|
||||
|
||||
matSum ??= mat1.Clone();
|
||||
|
||||
CvInvoke.BitwiseXor(mat1Threshold, mat2Threshold, matXor);
|
||||
if (matXorSum is null)
|
||||
{
|
||||
matXorSum = matXor.Clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
CvInvoke.Add(matXorSum, matXor, matXorSum);
|
||||
}
|
||||
|
||||
var currentLayerHeigthUm = currentLayerHeight * 1000.0;
|
||||
|
||||
if (CvInvoke.CountNonZero(matXorSum) > 0) // Layers are different
|
||||
{
|
||||
bool meetRequirement = false;
|
||||
for (; erodeCount <= _maximumErodes; )
|
||||
{
|
||||
erodeCount++;
|
||||
//maxErodeCount = Math.Max(maxErodeCount, erodeCount);
|
||||
|
||||
/*var slope = Math.Atan(currentLayerHeigthUm / (double) (xyResolutionUm * erodeCount)) * (180 / Math.PI);
|
||||
var stepover = Math.Round(currentLayerHeigthUm / Math.Tan(slope * (Math.PI / 180)));
|
||||
Debug.Write($" [Slope: {slope:F2} Stepover: {stepover} <= {xyResolutionUm} = {stepover <= (double) xyResolutionUm}]");
|
||||
|
||||
if (stepover > (double) xyResolutionUm)
|
||||
{
|
||||
meetRequirement = false;
|
||||
break;
|
||||
}*/
|
||||
|
||||
CvInvoke.Erode(matXorSum, matXor, kernel, anchor, 1, BorderType.Reflect101, default);
|
||||
if (CvInvoke.CountNonZero(matXor) == 0) // Image pixels exhausted and got empty image, can pack and go next
|
||||
{
|
||||
meetRequirement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if ((!meetRequirement || erodeCount >= _maximumErodes) && _minimumLayerHeight < (decimal) currentLayerHeight
|
||||
// To many pixels, image still not blank, pack the previous group and start again from current height
|
||||
if (!meetRequirement && _minimumLayerHeight < (decimal) currentLayerHeight)
|
||||
{
|
||||
currentLayerHeight = previousLayerHeight;
|
||||
Debug.WriteLine(string.Empty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//erodeCount++; // Safe check
|
||||
Debug.Write(" [Equal layer]");
|
||||
}
|
||||
|
||||
layerSum++;
|
||||
CvInvoke.Add(matSum, mat2, matSum);
|
||||
Debug.WriteLine(string.Empty);
|
||||
}
|
||||
|
||||
if (layerSum > 1) report.StackedLayers += layerSum;
|
||||
Debug.WriteLine($" Packing {layerSum} layers with {currentLayerHeight}mm");
|
||||
// Add the result
|
||||
/*var thisPosZ = Math.Round(layers[^1].PositionZ + currentLayerHeight, 2);
|
||||
if (layers.Count > 0 && thisPosZ != slicerFile[layerIndex].PositionZ)
|
||||
{
|
||||
Debug.WriteLine($"{layerIndex}: ({thisPosZ} != {slicerFile[layerIndex].PositionZ}) Height mismatch!!");
|
||||
}*/
|
||||
var positionZ = GetLastPositionZ(currentLayerHeight);
|
||||
if ((decimal)positionZ != (decimal)SlicerFile[layerIndex-1].PositionZ)
|
||||
{
|
||||
Debug.WriteLine($"{layerIndex}: ({positionZ}mm != {SlicerFile[layerIndex-1].PositionZ}mm) Height mismatch!!");
|
||||
throw new InvalidOperationException($"Model height integrity has been violated at layer {layerIndex}/{layers.Count} ({positionZ}mm != {SlicerFile[layerIndex - 1].PositionZ}mm), this operation will not proceed.");
|
||||
}
|
||||
AddNewLayer(matSum, currentLayerHeight);
|
||||
}
|
||||
|
||||
for (int i = (int) LayerIndexEnd; i >= 0; i--)
|
||||
{
|
||||
if(matCache[i] is null) break;
|
||||
matCache[i].Dispose();
|
||||
matThresholdCache[i].Dispose();
|
||||
}
|
||||
|
||||
for (uint layerIndex = LayerIndexEnd+1; layerIndex < SlicerFile.LayerCount; layerIndex++) // Add left-overs
|
||||
{
|
||||
ReUseLayer(layerIndex);
|
||||
}
|
||||
|
||||
SlicerFile.SuppressRebuildProperties = true;
|
||||
SlicerFile.LayerManager.Layers = layers.ToArray();
|
||||
SlicerFile.LayerManager.RebuildLayersProperties(false);
|
||||
|
||||
// Set exposures times
|
||||
var exposureDictionary = ExposureTableDictionary;
|
||||
for (uint layerIndex = 0; layerIndex < SlicerFile.LayerCount; layerIndex++)
|
||||
{
|
||||
float bottomExposure = SlicerFile.BottomExposureTime;
|
||||
float exposure = SlicerFile.ExposureTime;
|
||||
if(exposureDictionary.TryGetValue((decimal)SlicerFile[layerIndex].LayerHeight, out var item))
|
||||
{
|
||||
bottomExposure = (float) item.BottomExposure;
|
||||
exposure = (float) item.Exposure;
|
||||
}
|
||||
|
||||
SlicerFile[layerIndex].ExposureTime = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomExposure, exposure);
|
||||
}
|
||||
//var layer = slicerFile.LayerManager.Layers[^1];
|
||||
|
||||
/*Debug.WriteLine(layer.ExposureTime);
|
||||
Debug.WriteLine(layer.Index);
|
||||
Debug.WriteLine(layer.Filename);
|
||||
Debug.WriteLine(layer.IsNormalLayer);
|
||||
Debug.WriteLine(layer.IsBottomLayer);
|
||||
Debug.WriteLine(layer.LiftHeight);
|
||||
Debug.WriteLine(layer.LiftSpeed);
|
||||
Debug.WriteLine(layer.LightOffDelay);
|
||||
Debug.WriteLine(layer.LightPWM);
|
||||
Debug.WriteLine(layer.BoundingRectangle);*/
|
||||
//Debug.WriteLine(layer.LayerHeight);
|
||||
//Debug.WriteLine(layer);
|
||||
/*Debug.WriteLine(slicerFile.LayerManager);
|
||||
foreach (var layer in slicerFile)
|
||||
{
|
||||
Debug.WriteLine(layer.Index);
|
||||
}*/
|
||||
|
||||
SlicerFile.SuppressRebuildProperties = false;
|
||||
|
||||
report.NewLayerCount = SlicerFile.LayerCount;
|
||||
report.NewPrintTime = SlicerFile.PrintTimeOrComputed;
|
||||
Tag = report;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,9 @@ namespace UVtools.Core.Operations
|
||||
{
|
||||
#region Members
|
||||
private bool _perLayerOverride;
|
||||
private uint _setNumberOfLayer = 1;
|
||||
private uint _skipNumberOfLayer = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
@@ -92,23 +95,73 @@ namespace UVtools.Core.Operations
|
||||
get => _perLayerOverride;
|
||||
set => RaiseAndSetIfChanged(ref _perLayerOverride, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of sequential layers to set the parameters
|
||||
/// </summary>
|
||||
public uint SetNumberOfLayer
|
||||
{
|
||||
get => _setNumberOfLayer;
|
||||
set => RaiseAndSetIfChanged(ref _setNumberOfLayer, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of sequential layers to skip after set a layer
|
||||
/// </summary>
|
||||
public uint SkipNumberOfLayer
|
||||
{
|
||||
get => _skipNumberOfLayer;
|
||||
set => RaiseAndSetIfChanged(ref _skipNumberOfLayer, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public OperationEditParameters()
|
||||
#region Constructor
|
||||
|
||||
public OperationEditParameters() { }
|
||||
|
||||
public OperationEditParameters(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
public override void InitWithSlicerFile()
|
||||
{
|
||||
base.InitWithSlicerFile();
|
||||
SlicerFile.RefreshPrintParametersModifiersValues();
|
||||
Modifiers = SlicerFile.PrintParameterModifiers;
|
||||
}
|
||||
|
||||
public OperationEditParameters(FileFormat.PrintParameterModifier[] modifiers)
|
||||
{
|
||||
Modifiers = modifiers;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
slicerFile.EditPrintParameters(this);
|
||||
return true;
|
||||
if (PerLayerOverride)
|
||||
{
|
||||
uint setLayers = 0;
|
||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
||||
{
|
||||
SlicerFile[layerIndex].SetValuesFromPrintParametersModifiers(Modifiers);
|
||||
if (SkipNumberOfLayer <= 0) continue;
|
||||
setLayers++;
|
||||
if (setLayers >= SetNumberOfLayer)
|
||||
{
|
||||
setLayers = 0;
|
||||
layerIndex += SkipNumberOfLayer;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var modifier in Modifiers)
|
||||
{
|
||||
modifier.OldValue = modifier.NewValue;
|
||||
}
|
||||
SlicerFile.RebuildGCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
SlicerFile.SetValuesFromPrintParametersModifiers();
|
||||
}
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -87,6 +87,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationFlip() { }
|
||||
|
||||
public OperationFlip(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
protected bool Equals(OperationFlip other)
|
||||
@@ -113,24 +121,22 @@ namespace UVtools.Core.Operations
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return true;
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -97,24 +97,44 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationInfill() { }
|
||||
|
||||
public OperationInfill(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
private bool Equals(OperationInfill other)
|
||||
{
|
||||
return _infillType == other._infillType && _wallThickness == other._wallThickness && _infillThickness == other._infillThickness && _infillSpacing == other._infillSpacing && _infillBrightness == other._infillBrightness;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return ReferenceEquals(this, obj) || obj is OperationInfill other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine((int) _infillType, _wallThickness, _infillThickness, _infillSpacing, _infillBrightness);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat, layerIndex);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
@@ -122,7 +142,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -76,11 +76,19 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationLayerClone() { }
|
||||
|
||||
public OperationLayerClone(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
var oldLayers = slicerFile.LayerManager.Layers;
|
||||
var oldLayers = SlicerFile.LayerManager.Layers;
|
||||
|
||||
uint totalClones = (LayerIndexEnd - LayerIndexStart + 1) * Clones;
|
||||
uint newLayerCount = (uint) (oldLayers.Length + totalClones);
|
||||
@@ -107,11 +115,9 @@ namespace UVtools.Core.Operations
|
||||
newLayerIndex++;
|
||||
}
|
||||
|
||||
slicerFile.LayerManager.Layers = layers;
|
||||
SlicerFile.LayerManager.Layers = layers;
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -39,12 +39,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
private ImportTypes _importType = ImportTypes.Stack;
|
||||
private uint _startLayerIndex;
|
||||
private bool _extendBeyondLayerCount = true;
|
||||
private bool _discardUnmodifiedLayers;
|
||||
private ushort _stackMargin = 50;
|
||||
private ObservableCollection<StringTag> _files = new();
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
@@ -115,9 +117,6 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Properties
|
||||
|
||||
[XmlIgnore]
|
||||
public Size FileResolution { get; }
|
||||
|
||||
public ImportTypes ImportType
|
||||
{
|
||||
get => _importType;
|
||||
@@ -172,14 +171,11 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationLayerImport()
|
||||
{
|
||||
}
|
||||
public OperationLayerImport() { }
|
||||
|
||||
public OperationLayerImport(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
|
||||
public OperationLayerImport(Size fileResolution)
|
||||
{
|
||||
FileResolution = fileResolution;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
@@ -224,10 +220,10 @@ namespace UVtools.Core.Operations
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
slicerFile.SuppressRebuildProperties = true;
|
||||
progress.ItemCount = 0;
|
||||
SlicerFile.SuppressRebuildProperties = true;
|
||||
|
||||
List<FileFormat> fileFormats = new();
|
||||
List<KeyValuePair<uint, string>> keyImage = new();
|
||||
@@ -289,7 +285,7 @@ namespace UVtools.Core.Operations
|
||||
|
||||
if (_importType == ImportTypes.Stack)
|
||||
{
|
||||
new OperationMove(slicerFile, Enumerations.Anchor.TopLeft){LayerIndexEnd = slicerFile.LastLayerIndex}.Execute(slicerFile, progress);
|
||||
new OperationMove(SlicerFile, Enumerations.Anchor.TopLeft).Execute(progress);
|
||||
}
|
||||
|
||||
foreach (var fileFormat in fileFormats)
|
||||
@@ -299,7 +295,7 @@ namespace UVtools.Core.Operations
|
||||
fileFormat.Decode(fileFormat.FileFullPath, progress);
|
||||
}
|
||||
|
||||
var boundingRectangle = slicerFile.LayerManager.GetBoundingRectangle(progress);
|
||||
var boundingRectangle = SlicerFile.LayerManager.GetBoundingRectangle(progress);
|
||||
var fileFormatBoundingRectangle = fileFormat.LayerManager.GetBoundingRectangle(progress);
|
||||
var roiRectangle = Rectangle.Empty;
|
||||
|
||||
@@ -307,26 +303,26 @@ namespace UVtools.Core.Operations
|
||||
switch (_importType)
|
||||
{
|
||||
case ImportTypes.Insert:
|
||||
if (slicerFile.Resolution != fileFormat.Resolution &&
|
||||
(slicerFile.Resolution.Width < fileFormat.LayerManager.BoundingRectangle.Width ||
|
||||
slicerFile.Resolution.Height < fileFormat.LayerManager.BoundingRectangle.Height)) continue;
|
||||
slicerFile.LayerManager.Reallocate(_startLayerIndex, fileFormat.LayerCount);
|
||||
if (SlicerFile.Resolution != fileFormat.Resolution &&
|
||||
(SlicerFile.Resolution.Width < fileFormat.LayerManager.BoundingRectangle.Width ||
|
||||
SlicerFile.Resolution.Height < fileFormat.LayerManager.BoundingRectangle.Height)) continue;
|
||||
SlicerFile.LayerManager.Reallocate(_startLayerIndex, fileFormat.LayerCount);
|
||||
break;
|
||||
case ImportTypes.Replace:
|
||||
case ImportTypes.Stack:
|
||||
if (slicerFile.Resolution != fileFormat.Resolution &&
|
||||
(slicerFile.Resolution.Width < fileFormat.LayerManager.BoundingRectangle.Width ||
|
||||
slicerFile.Resolution.Height < fileFormat.LayerManager.BoundingRectangle.Height)) continue;
|
||||
if (SlicerFile.Resolution != fileFormat.Resolution &&
|
||||
(SlicerFile.Resolution.Width < fileFormat.LayerManager.BoundingRectangle.Width ||
|
||||
SlicerFile.Resolution.Height < fileFormat.LayerManager.BoundingRectangle.Height)) continue;
|
||||
|
||||
|
||||
if(fileFormatBoundingRectangle.Width >= slicerFile.ResolutionX || fileFormatBoundingRectangle.Height >= slicerFile.ResolutionY)
|
||||
if(fileFormatBoundingRectangle.Width >= SlicerFile.ResolutionX || fileFormatBoundingRectangle.Height >= SlicerFile.ResolutionY)
|
||||
continue;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
if (boundingRectangle.Right + _stackMargin + fileFormatBoundingRectangle.Width <
|
||||
slicerFile.ResolutionX)
|
||||
SlicerFile.ResolutionX)
|
||||
{
|
||||
x = boundingRectangle.Right + _stackMargin;
|
||||
}
|
||||
@@ -335,29 +331,29 @@ namespace UVtools.Core.Operations
|
||||
y = boundingRectangle.Bottom + _stackMargin;
|
||||
}
|
||||
|
||||
if (y >= slicerFile.ResolutionY)
|
||||
if (y >= SlicerFile.ResolutionY)
|
||||
continue;
|
||||
|
||||
roiRectangle = new Rectangle(x, y, fileFormatBoundingRectangle.Width, fileFormatBoundingRectangle.Height);
|
||||
|
||||
if (_extendBeyondLayerCount)
|
||||
{
|
||||
int layerCountDifference = (int) (_startLayerIndex + fileFormat.LayerCount - slicerFile.LayerCount);
|
||||
int layerCountDifference = (int) (_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount);
|
||||
if (layerCountDifference > 0)
|
||||
{
|
||||
slicerFile.LayerManager.ReallocateEnd((uint) layerCountDifference, _importType == ImportTypes.Stack);
|
||||
SlicerFile.LayerManager.ReallocateEnd((uint) layerCountDifference, _importType == ImportTypes.Stack);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case ImportTypes.Merge:
|
||||
if (slicerFile.Resolution != fileFormat.Resolution) continue;
|
||||
if (SlicerFile.Resolution != fileFormat.Resolution) continue;
|
||||
if (_extendBeyondLayerCount)
|
||||
{
|
||||
int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - slicerFile.LayerCount);
|
||||
int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - SlicerFile.LayerCount);
|
||||
if (layerCountDifference > 0)
|
||||
{
|
||||
slicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, true);
|
||||
SlicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -365,7 +361,7 @@ namespace UVtools.Core.Operations
|
||||
case ImportTypes.BitwiseAnd:
|
||||
case ImportTypes.BitwiseOr:
|
||||
case ImportTypes.BitwiseXOr:
|
||||
if (slicerFile.Resolution != fileFormat.Resolution) continue;
|
||||
if (SlicerFile.Resolution != fileFormat.Resolution) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -381,88 +377,88 @@ namespace UVtools.Core.Operations
|
||||
{
|
||||
case ImportTypes.Insert:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
if (slicerFile.Resolution == fileFormat.Resolution)
|
||||
if (layerIndex >= SlicerFile.LayerCount) return;
|
||||
if (SlicerFile.Resolution == fileFormat.Resolution)
|
||||
{
|
||||
slicerFile[layerIndex] = fileFormat[i];
|
||||
SlicerFile[layerIndex] = fileFormat[i];
|
||||
break;
|
||||
}
|
||||
|
||||
using var layer = fileFormat[i].LayerMat;
|
||||
using var layerRoi = layer.RoiFromCenter(slicerFile.Resolution);
|
||||
slicerFile[layerIndex] = new Layer(layerIndex, layerRoi, slicerFile);
|
||||
using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution);
|
||||
SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile);
|
||||
|
||||
break;
|
||||
}
|
||||
case ImportTypes.Replace:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
if (slicerFile.Resolution == fileFormat.Resolution)
|
||||
if (layerIndex >= SlicerFile.LayerCount) return;
|
||||
if (SlicerFile.Resolution == fileFormat.Resolution)
|
||||
{
|
||||
slicerFile[layerIndex] = fileFormat[i];
|
||||
SlicerFile[layerIndex] = fileFormat[i];
|
||||
break;
|
||||
}
|
||||
|
||||
using var layer = fileFormat[i].LayerMat;
|
||||
using var layerRoi = layer.RoiFromCenter(slicerFile.Resolution);
|
||||
slicerFile[layerIndex] = new Layer(layerIndex, layerRoi, slicerFile);
|
||||
using var layerRoi = layer.RoiFromCenter(SlicerFile.Resolution);
|
||||
SlicerFile[layerIndex] = new Layer(layerIndex, layerRoi, SlicerFile);
|
||||
break;
|
||||
}
|
||||
case ImportTypes.Stack:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
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;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
|
||||
break;
|
||||
}
|
||||
case ImportTypes.Merge:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
using var originalMat = slicerFile[layerIndex].LayerMat;
|
||||
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;
|
||||
SlicerFile[layerIndex].LayerMat = newMat;
|
||||
break;
|
||||
}
|
||||
case ImportTypes.Subtract:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
using var originalMat = slicerFile[layerIndex].LayerMat;
|
||||
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;
|
||||
SlicerFile[layerIndex].LayerMat = newMat;
|
||||
break;
|
||||
}
|
||||
case ImportTypes.BitwiseAnd:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
using var originalMat = slicerFile[layerIndex].LayerMat;
|
||||
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;
|
||||
SlicerFile[layerIndex].LayerMat = newMat;
|
||||
break;
|
||||
}
|
||||
case ImportTypes.BitwiseOr:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
using var originalMat = slicerFile[layerIndex].LayerMat;
|
||||
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;
|
||||
SlicerFile[layerIndex].LayerMat = newMat;
|
||||
break;
|
||||
}
|
||||
case ImportTypes.BitwiseXOr:
|
||||
{
|
||||
if (layerIndex >= slicerFile.LayerCount) return;
|
||||
using var originalMat = slicerFile[layerIndex].LayerMat;
|
||||
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;
|
||||
SlicerFile[layerIndex].LayerMat = newMat;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -483,20 +479,20 @@ namespace UVtools.Core.Operations
|
||||
|
||||
if (_importType == ImportTypes.Stack)
|
||||
{
|
||||
new OperationMove(slicerFile) { LayerIndexEnd = slicerFile.LastLayerIndex }.Execute(slicerFile, progress);
|
||||
new OperationMove(SlicerFile).Execute(progress);
|
||||
}
|
||||
|
||||
if (lastProcessedLayerIndex <= -1) return false;
|
||||
|
||||
if (lastProcessedLayerIndex + 1 < slicerFile.LayerCount && _discardUnmodifiedLayers)
|
||||
if (lastProcessedLayerIndex + 1 < SlicerFile.LayerCount && _discardUnmodifiedLayers)
|
||||
{
|
||||
slicerFile.LayerManager.ReallocateRange(0, (uint) lastProcessedLayerIndex);
|
||||
SlicerFile.LayerManager.ReallocateRange(0, (uint) lastProcessedLayerIndex);
|
||||
}
|
||||
|
||||
slicerFile.LayerManager.RebuildLayersProperties();
|
||||
slicerFile.SuppressRebuildProperties = false;
|
||||
SlicerFile.LayerManager.RebuildLayersProperties();
|
||||
SlicerFile.SuppressRebuildProperties = false;
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -99,6 +99,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationLayerReHeight() { }
|
||||
|
||||
public OperationLayerReHeight(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Subclasses
|
||||
public class OperationLayerReHeightItem
|
||||
{
|
||||
@@ -124,12 +132,11 @@ namespace UVtools.Core.Operations
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, Item.LayerCount);
|
||||
progress.ItemCount = Item.LayerCount;
|
||||
|
||||
var oldLayers = slicerFile.LayerManager.Layers;
|
||||
var oldLayers = SlicerFile.LayerManager.Layers;
|
||||
|
||||
var layers = new Layer[Item.LayerCount];
|
||||
|
||||
@@ -171,10 +178,10 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
slicerFile.LayerManager.Layers = layers;
|
||||
slicerFile.LayerHeight = (float)Item.LayerHeight;
|
||||
SlicerFile.LayerManager.Layers = layers;
|
||||
SlicerFile.LayerHeight = (float)Item.LayerHeight;
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -45,20 +45,28 @@ namespace UVtools.Core.Operations
|
||||
#region Properties
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationLayerRemove() { }
|
||||
|
||||
public OperationLayerRemove(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress(false);
|
||||
progress.CanCancel = false;
|
||||
var layersRemove = new List<uint>();
|
||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
||||
{
|
||||
layersRemove.Add(layerIndex);
|
||||
}
|
||||
|
||||
return RemoveLayers(slicerFile, layersRemove, progress);
|
||||
return RemoveLayers(SlicerFile, layersRemove, progress);
|
||||
}
|
||||
|
||||
public static bool RemoveLayers(FileFormat slicerFile, List<uint> layersRemove, OperationProgress progress = null)
|
||||
@@ -70,7 +78,7 @@ namespace UVtools.Core.Operations
|
||||
progress.Reset("removed layers", (uint)layersRemove.Count);
|
||||
|
||||
var oldLayers = slicerFile.LayerManager.Layers;
|
||||
float layerHeight = slicerFile.LayerHeight;
|
||||
var layerHeight = slicerFile.LayerHeight;
|
||||
|
||||
var layers = new Layer[oldLayers.Length - layersRemove.Count];
|
||||
|
||||
@@ -92,7 +100,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
else
|
||||
{
|
||||
posZ = (float)Math.Round(layers[newLayerIndex - 1].PositionZ + layerHeight, 2);
|
||||
posZ = layers[newLayerIndex - 1].PositionZ + layerHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,14 @@ namespace UVtools.Core.Operations
|
||||
public bool HaveMask => !(Mask is null);
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationMask() { }
|
||||
|
||||
public OperationMask(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void InvertMask()
|
||||
@@ -65,25 +73,21 @@ namespace UVtools.Core.Operations
|
||||
CvInvoke.BitwiseNot(Mask, Mask);
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -109,6 +109,14 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationMorph() { }
|
||||
|
||||
public OperationMorph(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
private bool Equals(OperationMorph other)
|
||||
@@ -137,11 +145,8 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
var isFade = Chamfer;
|
||||
LayerManager.MutateGetVarsIterationChamfer(
|
||||
LayerIndexStart,
|
||||
@@ -160,17 +165,17 @@ namespace UVtools.Core.Operations
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
int iterations = LayerManager.MutateGetIterationVar(isFade, (int)IterationsStart, (int)IterationsEnd, iterationSteps, maxIteration, LayerIndexStart, (uint)layerIndex);
|
||||
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat, iterations);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return true;
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -170,6 +170,31 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationMove() { }
|
||||
|
||||
public OperationMove(FileFormat slicerFile, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter) : base(slicerFile)
|
||||
{
|
||||
ROI = slicerFile.LayerManager.BoundingRectangle;
|
||||
_imageWidth = slicerFile.ResolutionX;
|
||||
_imageHeight = slicerFile.ResolutionY;
|
||||
_anchor = anchor;
|
||||
}
|
||||
|
||||
public OperationMove(FileFormat slicerFile, Rectangle srcRoi, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter) : this(slicerFile, anchor)
|
||||
{
|
||||
if(!srcRoi.IsEmpty) ROI = srcRoi;
|
||||
}
|
||||
|
||||
/*public OperationMove(FileFormat slicerFile, Rectangle srcRoi, Mat mat, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter) : this(slicerFile, srcRoi, anchor)
|
||||
{
|
||||
ImageWidth = (uint) mat.Width;
|
||||
ImageHeight = (uint) mat.Height;
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public void CalculateDstRoi()
|
||||
{
|
||||
@@ -214,42 +239,15 @@ namespace UVtools.Core.Operations
|
||||
_dstRoi.Y += MarginTop;
|
||||
_dstRoi.Y -= MarginBottom;
|
||||
|
||||
IsWithinBoundary = !(DstRoi.IsEmpty || DstRoi.X < 0 || DstRoi.Y < 0 ||
|
||||
DstRoi.Width == 0 || DstRoi.Right > ImageWidth ||
|
||||
DstRoi.Height == 0 || DstRoi.Bottom > ImageHeight);
|
||||
IsWithinBoundary = !(_dstRoi.IsEmpty || _dstRoi.X < 0 || _dstRoi.Y < 0 ||
|
||||
_dstRoi.Width == 0 || _dstRoi.Right > ImageWidth ||
|
||||
_dstRoi.Height == 0 || _dstRoi.Bottom > ImageHeight);
|
||||
|
||||
RaisePropertyChanged(nameof(DstRoi));
|
||||
RaisePropertyChanged(nameof(LocationXStr));
|
||||
RaisePropertyChanged(nameof(LocationYStr));
|
||||
}
|
||||
|
||||
public OperationMove()
|
||||
{
|
||||
}
|
||||
|
||||
public OperationMove(FileFormat slicerFile, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter)
|
||||
{
|
||||
ROI = slicerFile.LayerManager.BoundingRectangle;
|
||||
ImageWidth = slicerFile.ResolutionX;
|
||||
ImageHeight = slicerFile.ResolutionY;
|
||||
Anchor = anchor;
|
||||
}
|
||||
|
||||
public OperationMove(Rectangle srcRoi, uint imageWidth, uint imageHeight, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter)
|
||||
{
|
||||
ROI = srcRoi;
|
||||
ImageWidth = imageWidth;
|
||||
ImageHeight = imageHeight;
|
||||
Anchor = anchor;
|
||||
}
|
||||
|
||||
public OperationMove(Rectangle srcRoi, Size resolution, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter)
|
||||
{
|
||||
ROI = srcRoi;
|
||||
ImageWidth = (uint)resolution.Width;
|
||||
ImageHeight = (uint)resolution.Height;
|
||||
Anchor = anchor;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
@@ -271,21 +269,19 @@ namespace UVtools.Core.Operations
|
||||
return IsWithinBoundary;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
if (ROI == Rectangle.Empty) ROI = slicerFile.LayerManager.GetBoundingRectangle(progress);
|
||||
if (ROI.IsEmpty) ROI = SlicerFile.LayerManager.GetBoundingRectangle(progress);
|
||||
CalculateDstRoi();
|
||||
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using (var mat = slicerFile[layerIndex].LayerMat)
|
||||
using (var mat = SlicerFile[layerIndex].LayerMat)
|
||||
{
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
}
|
||||
|
||||
lock (progress.Mutex)
|
||||
@@ -294,18 +290,15 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
slicerFile.LayerManager.BoundingRectangle = Rectangle.Empty;
|
||||
SlicerFile.LayerManager.BoundingRectangle = Rectangle.Empty;
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
{
|
||||
|
||||
if (ImageWidth == 0) ImageWidth = (uint) mat.Width;
|
||||
if (ImageHeight == 0) ImageHeight = (uint) mat.Height;
|
||||
if (_imageWidth == 0) _imageWidth = (uint) mat.Width;
|
||||
if (_imageHeight == 0) _imageHeight = (uint) mat.Height;
|
||||
|
||||
using var srcRoi = new Mat(mat, ROI);
|
||||
using var dstRoi = new Mat(mat, DstRoi);
|
||||
|
||||
@@ -186,19 +186,21 @@ namespace UVtools.Core.Operations
|
||||
public Size GetPatternVolume => new(Cols * ROI.Width + (Cols - 1) * ColSpacing, Rows * ROI.Height + (Rows - 1) * RowSpacing);
|
||||
#endregion
|
||||
|
||||
public OperationPattern()
|
||||
{
|
||||
}
|
||||
#region Constructor
|
||||
|
||||
public OperationPattern(Rectangle srcRoi, Size resolution)
|
||||
{
|
||||
ImageWidth = (uint) resolution.Width;
|
||||
ImageHeight = (uint) resolution.Height;
|
||||
public OperationPattern() { }
|
||||
|
||||
SetRoi(srcRoi);
|
||||
public OperationPattern(FileFormat slicerFile, Rectangle srcRoi = default) : base(slicerFile)
|
||||
{
|
||||
ImageWidth = slicerFile.ResolutionX;
|
||||
ImageHeight = slicerFile.ResolutionY;
|
||||
|
||||
SetRoi(srcRoi.IsEmpty ? slicerFile.BoundingRectangle : srcRoi);
|
||||
Fill();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public void SetAnchor(byte value)
|
||||
{
|
||||
@@ -272,16 +274,13 @@ namespace UVtools.Core.Operations
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
using var layerRoi = new Mat(mat, ROI);
|
||||
using var dstLayer = mat.CloneBlank();
|
||||
for (ushort col = 0; col < Cols; col++)
|
||||
@@ -292,7 +291,7 @@ namespace UVtools.Core.Operations
|
||||
layerRoi.CopyTo(dstRoi);
|
||||
}
|
||||
//Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = dstLayer;
|
||||
SlicerFile[layerIndex].LayerMat = dstLayer;
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
@@ -300,19 +299,19 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
slicerFile.LayerManager.BoundingRectangle = Rectangle.Empty;
|
||||
SlicerFile.LayerManager.BoundingRectangle = Rectangle.Empty;
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
if (Anchor == Enumerations.Anchor.None) return true;
|
||||
var operationMove = new OperationMove(slicerFile.LayerManager.BoundingRectangle, ImageWidth, ImageHeight, Anchor)
|
||||
var operationMove = new OperationMove(SlicerFile, Anchor)
|
||||
{
|
||||
LayerIndexStart = LayerIndexStart,
|
||||
LayerIndexEnd = LayerIndexEnd
|
||||
};
|
||||
operationMove.Execute(slicerFile, progress);
|
||||
operationMove.Execute(progress);
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
/*public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -138,6 +138,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationPixelDimming() { }
|
||||
|
||||
public OperationPixelDimming(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public uint WallThicknessStart
|
||||
@@ -534,11 +542,8 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
if (Pattern is null)
|
||||
{
|
||||
Pattern = new Matrix<byte>(2, 2)
|
||||
@@ -560,7 +565,7 @@ namespace UVtools.Core.Operations
|
||||
|
||||
AlternatePattern ??= Pattern;
|
||||
|
||||
using var blankMat = EmguExtensions.InitMat(slicerFile.Resolution);
|
||||
using var blankMat = EmguExtensions.InitMat(SlicerFile.Resolution);
|
||||
using var matPattern = blankMat.CloneBlank();
|
||||
using var matAlternatePattern = blankMat.CloneBlank();
|
||||
var target = GetRoiOrDefault(blankMat);
|
||||
@@ -573,9 +578,9 @@ namespace UVtools.Core.Operations
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat, layerIndex, patternMask, alternatePatternMask);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
@@ -583,8 +588,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace UVtools.Core.Operations
|
||||
_canCancel = canCancel;
|
||||
}
|
||||
|
||||
public Stopwatch StopWatch { get; } = new Stopwatch();
|
||||
public Stopwatch StopWatch { get; } = new ();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if operation can be cancelled
|
||||
@@ -82,7 +82,8 @@ namespace UVtools.Core.Operations
|
||||
set => RaiseAndSetIfChanged(ref _title, value);
|
||||
}
|
||||
|
||||
public string ElapsedTimeStr => $"{StopWatch.Elapsed.Minutes}m {StopWatch.Elapsed.Seconds}s {StopWatch.Elapsed.Milliseconds}ms";
|
||||
public string ElapsedTimeStr => $"{StopWatch.Elapsed.Minutes}m {StopWatch.Elapsed.Seconds}s";
|
||||
//{StopWatch.Elapsed.Milliseconds} ms
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item name for the operation
|
||||
@@ -123,21 +124,26 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an tag
|
||||
/// </summary>
|
||||
public object Tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the remaining items to be processed
|
||||
/// </summary>
|
||||
public uint RemainingItems => ItemCount - ProcessedItems;
|
||||
public uint RemainingItems => _itemCount - _processedItems;
|
||||
|
||||
public int ProgressStep => (int)ProgressPercent;
|
||||
|
||||
public string Description => ToString();
|
||||
|
||||
public bool IsIndeterminate => ItemCount == 0;
|
||||
public bool IsIndeterminate => _itemCount == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the progress from 0 to 100%
|
||||
/// </summary>
|
||||
public double ProgressPercent => ItemCount == 0 ? 0 : Math.Round(ProcessedItems * 100.0 / ItemCount, 2).Clamp(0, 100);
|
||||
public double ProgressPercent => _itemCount == 0 ? 0 : Math.Round(_processedItems * 100.0 / _itemCount, 2).Clamp(0, 100);
|
||||
|
||||
public static OperationProgress operator +(OperationProgress progress, uint value)
|
||||
{
|
||||
@@ -167,9 +173,9 @@ namespace UVtools.Core.Operations
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ItemCount == 0 ?
|
||||
$"{ProcessedItems}/? {ItemName}" :
|
||||
$"{ProcessedItems}/{ItemCount} {ItemName} | {ProgressPercent:0.00}%";
|
||||
return _itemCount == 0 ?
|
||||
$"{_processedItems}/? {_itemName}" :
|
||||
$"{_processedItems.ToString().PadLeft(_itemCount.ToString().Length, '0')}/{_itemCount} {_itemName} | {ProgressPercent:0.00}%";
|
||||
}
|
||||
|
||||
public void TriggerRefresh()
|
||||
|
||||
@@ -63,6 +63,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationRaftRelief() { }
|
||||
|
||||
public OperationRaftRelief(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public static Array RaftReliefItems => Enum.GetValues(typeof(RaftReliefTypes));
|
||||
|
||||
@@ -149,11 +157,10 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress.ItemCount = 0;
|
||||
const uint minLength = 5;
|
||||
progress ??= new OperationProgress();
|
||||
//progress.Reset(operation.ProgressAction);
|
||||
|
||||
Mat supportsMat = null;
|
||||
var anchor = new Point(-1, -1);
|
||||
@@ -161,11 +168,11 @@ namespace UVtools.Core.Operations
|
||||
|
||||
|
||||
uint firstSupportLayerIndex = 0;
|
||||
for (; firstSupportLayerIndex < slicerFile.LayerCount; firstSupportLayerIndex++)
|
||||
for (; firstSupportLayerIndex < SlicerFile.LayerCount; firstSupportLayerIndex++)
|
||||
{
|
||||
progress.Reset("Tracing raft", slicerFile.LayerCount, firstSupportLayerIndex);
|
||||
progress.Reset("Tracing raft", SlicerFile.LayerCount, firstSupportLayerIndex);
|
||||
if (progress.Token.IsCancellationRequested) return false;
|
||||
supportsMat = GetRoiOrDefault(slicerFile[firstSupportLayerIndex].LayerMat);
|
||||
supportsMat = GetRoiOrDefault(SlicerFile[firstSupportLayerIndex].LayerMat);
|
||||
var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.Gradient, 1, 20, 100, 30, 5, 200);
|
||||
if (circles.Length >= minLength) break;
|
||||
|
||||
@@ -187,7 +194,7 @@ namespace UVtools.Core.Operations
|
||||
|
||||
switch (ReliefType)
|
||||
{
|
||||
case OperationRaftRelief.RaftReliefTypes.Relief:
|
||||
case RaftReliefTypes.Relief:
|
||||
patternMat = EmguExtensions.InitMat(supportsMat.Size);
|
||||
int shapeSize = HoleDiameter + HoleSpacing;
|
||||
using (var shape = EmguExtensions.InitMat(new Size(shapeSize, shapeSize)))
|
||||
@@ -208,7 +215,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
break;
|
||||
case OperationRaftRelief.RaftReliefTypes.Dimming:
|
||||
case RaftReliefTypes.Dimming:
|
||||
patternMat = EmguExtensions.InitMat(supportsMat.Size, color);
|
||||
break;
|
||||
}
|
||||
@@ -216,7 +223,8 @@ namespace UVtools.Core.Operations
|
||||
progress.Reset(ProgressAction, firstSupportLayerIndex);
|
||||
Parallel.For(IgnoreFirstLayers, firstSupportLayerIndex, layerIndex =>
|
||||
{
|
||||
using (Mat dst = slicerFile[layerIndex].LayerMat)
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (Mat dst = SlicerFile[layerIndex].LayerMat)
|
||||
{
|
||||
var target = GetRoiOrDefault(dst);
|
||||
|
||||
@@ -242,7 +250,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
|
||||
slicerFile[layerIndex].LayerMat = dst;
|
||||
SlicerFile[layerIndex].LayerMat = dst;
|
||||
}
|
||||
|
||||
lock (progress.Mutex)
|
||||
@@ -255,7 +263,7 @@ namespace UVtools.Core.Operations
|
||||
supportsMat.Dispose();
|
||||
patternMat?.Dispose();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -81,6 +81,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationRedrawModel() { }
|
||||
|
||||
public OperationRedrawModel(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
[XmlIgnore]
|
||||
@@ -151,21 +159,20 @@ namespace UVtools.Core.Operations
|
||||
public FileFormat IsFileValid(bool returnNewInstance = false) =>
|
||||
FileFormat.FindByExtension(_filePath, true, returnNewInstance);
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
|
||||
var otherFile = IsFileValid(true);
|
||||
otherFile.Decode(_filePath, progress);
|
||||
|
||||
progress.Reset(ProgressAction, otherFile.LayerCount);
|
||||
|
||||
int startLayerIndex = (int)(slicerFile.LayerCount - otherFile.LayerCount);
|
||||
int startLayerIndex = (int)(SlicerFile.LayerCount - otherFile.LayerCount);
|
||||
if (startLayerIndex < 0) return false;
|
||||
Parallel.For(0, otherFile.LayerCount, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
var fullMatLayerIndex = startLayerIndex + layerIndex;
|
||||
using var fullMat = slicerFile[fullMatLayerIndex].LayerMat;
|
||||
using var fullMat = SlicerFile[fullMatLayerIndex].LayerMat;
|
||||
using var bodyMat = otherFile[layerIndex].LayerMat;
|
||||
using var fullMatRoi = GetRoiOrDefault(fullMat);
|
||||
using var bodyMatRoi = GetRoiOrDefault(bodyMat);
|
||||
@@ -232,7 +239,7 @@ namespace UVtools.Core.Operations
|
||||
|
||||
if (modified)
|
||||
{
|
||||
slicerFile[fullMatLayerIndex].LayerMat = fullMat;
|
||||
SlicerFile[fullMatLayerIndex].LayerMat = fullMat;
|
||||
}
|
||||
|
||||
lock (progress.Mutex)
|
||||
@@ -241,7 +248,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -16,7 +16,6 @@ using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using UVtools.Core.Extensions;
|
||||
using UVtools.Core.FileFormats;
|
||||
@@ -64,6 +63,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationRepairLayers() { }
|
||||
|
||||
public OperationRepairLayers(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public bool RepairIslands
|
||||
{
|
||||
@@ -116,10 +123,8 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
|
||||
// Remove islands
|
||||
if (!ReferenceEquals(Issues, null)
|
||||
&& !ReferenceEquals(IslandDetectionConfig, null)
|
||||
@@ -127,7 +132,7 @@ namespace UVtools.Core.Operations
|
||||
&& RemoveIslandsBelowEqualPixelCount > 0
|
||||
&& RemoveIslandsRecursiveIterations != 1)
|
||||
{
|
||||
progress.Reset("Removed recursive islands", 0);
|
||||
progress.Reset("Removed recursive islands");
|
||||
ushort limit = RemoveIslandsRecursiveIterations == 0
|
||||
? ushort.MaxValue
|
||||
: RemoveIslandsRecursiveIterations;
|
||||
@@ -152,7 +157,7 @@ namespace UVtools.Core.Operations
|
||||
.Select(grp => grp.First())
|
||||
.ToList();*/
|
||||
islandConfig.WhiteListLayers = islandsToRecompute.ToList();
|
||||
recursiveIssues = slicerFile.LayerManager.GetAllIssues(islandConfig, overhangConfig, resinTrapsConfig, touchingBoundsConfig, emptyLayersConfig);
|
||||
recursiveIssues = SlicerFile.LayerManager.GetAllIssues(islandConfig, overhangConfig, resinTrapsConfig, touchingBoundsConfig, emptyLayersConfig);
|
||||
//Debug.WriteLine(i);
|
||||
}
|
||||
|
||||
@@ -167,7 +172,7 @@ namespace UVtools.Core.Operations
|
||||
Parallel.ForEach(issuesGroup, group =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
Layer layer = slicerFile[group.Key];
|
||||
Layer layer = SlicerFile[group.Key];
|
||||
Mat image = layer.LayerMat;
|
||||
Span<byte> bytes = image.GetPixelSpan<byte>();
|
||||
foreach (var issue in group)
|
||||
@@ -184,7 +189,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
var nextLayerIndex = group.Key + 1;
|
||||
if (nextLayerIndex < slicerFile.LayerCount)
|
||||
if (nextLayerIndex < SlicerFile.LayerCount)
|
||||
islandsToRecompute.Add(nextLayerIndex);
|
||||
|
||||
layer.LayerMat = image;
|
||||
@@ -200,7 +205,7 @@ namespace UVtools.Core.Operations
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
Layer layer = slicerFile[layerIndex];
|
||||
Layer layer = SlicerFile[layerIndex];
|
||||
Mat image = null;
|
||||
|
||||
void initImage()
|
||||
@@ -294,7 +299,7 @@ namespace UVtools.Core.Operations
|
||||
List<uint> removeLayers = new List<uint>();
|
||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
||||
{
|
||||
if (slicerFile[layerIndex].NonZeroPixelCount == 0)
|
||||
if (SlicerFile[layerIndex].NonZeroPixelCount == 0)
|
||||
{
|
||||
removeLayers.Add(layerIndex);
|
||||
}
|
||||
@@ -302,13 +307,11 @@ namespace UVtools.Core.Operations
|
||||
|
||||
if (removeLayers.Count > 0)
|
||||
{
|
||||
OperationLayerRemove.RemoveLayers(slicerFile, removeLayers, progress);
|
||||
OperationLayerRemove.RemoveLayers(SlicerFile, removeLayers, progress);
|
||||
}
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -103,9 +103,13 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
public OperationResize()
|
||||
{
|
||||
}
|
||||
#region Constructor
|
||||
|
||||
public OperationResize() { }
|
||||
|
||||
public OperationResize(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
@@ -145,11 +149,9 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
if (X == 1m && Y == 1m) return false;
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
|
||||
decimal xSteps = Math.Abs(X - 1) / (LayerIndexEnd - LayerIndexStart);
|
||||
decimal ySteps = Math.Abs(Y - 1) / (LayerIndexEnd - LayerIndexStart);
|
||||
@@ -195,12 +197,12 @@ namespace UVtools.Core.Operations
|
||||
|
||||
if (newX == 1.0m && newY == 1.0m) return;
|
||||
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat, newX / 100m, newY / 100m);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return true;
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -42,6 +42,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationRotate() { }
|
||||
|
||||
public OperationRotate(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public decimal AngleDegrees
|
||||
{
|
||||
@@ -74,24 +82,21 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -20,13 +20,18 @@ namespace UVtools.Core.Operations
|
||||
[Serializable]
|
||||
public sealed class OperationSolidify : Operation
|
||||
{
|
||||
#region Enums
|
||||
public enum AreaCheckTypes
|
||||
{
|
||||
More,
|
||||
Less
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
private uint _minimumArea = 1;
|
||||
private AreaCheckTypes _areaCheckType = AreaCheckTypes.More;
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
@@ -70,25 +75,31 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationSolidify() { }
|
||||
|
||||
public OperationSolidify(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = slicerFile[layerIndex].LayerMat;
|
||||
using var mat = SlicerFile[layerIndex].LayerMat;
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
lock (progress.Mutex)
|
||||
{
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
return true;
|
||||
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -47,6 +47,14 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationThreshold() { }
|
||||
|
||||
public OperationThreshold(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public byte Threshold
|
||||
{
|
||||
@@ -71,17 +79,15 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Methods
|
||||
|
||||
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = slicerFile[layerIndex].LayerMat)
|
||||
using (var mat = SlicerFile[layerIndex].LayerMat)
|
||||
{
|
||||
Execute(mat);
|
||||
slicerFile[layerIndex].LayerMat = mat;
|
||||
SlicerFile[layerIndex].LayerMat = mat;
|
||||
}
|
||||
|
||||
lock (progress.Mutex)
|
||||
@@ -89,9 +95,8 @@ namespace UVtools.Core.Operations
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
return true;
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
public override bool Execute(Mat mat, params object[] arguments)
|
||||
|
||||
@@ -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.3.2</Version>
|
||||
<Version>2.4.0</Version>
|
||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinarySerializer" Version="8.5.3" />
|
||||
<PackageReference Include="Emgu.CV" Version="4.4.0.4099" />
|
||||
<PackageReference Include="Emgu.CV" Version="4.5.1.4349" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
|
||||
|
||||
@@ -152,6 +152,9 @@
|
||||
<Component Id="owc27A5D1506739847D9D7688256879A937" Guid="30f2e89f-1e95-77b9-1c3b-90bd4d875160">
|
||||
<File Id="owf27A5D1506739847D9D7688256879A937" Source="$(var.SourceDir)\Avalonia.DesktopRuntime.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcAA73F8E2C0EE78F802BAA8B361043211" Guid="536d2de0-51e7-19c8-3a8e-466146777c64">
|
||||
<File Id="owfAA73F8E2C0EE78F802BAA8B361043211" Source="$(var.SourceDir)\Avalonia.Diagnostics.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc6C15ADD7A5EE7A0CBEFD35B0027BBEB7" Guid="9c4a8ab3-598c-8e7c-0295-5c068334ab67">
|
||||
<File Id="owf6C15ADD7A5EE7A0CBEFD35B0027BBEB7" Source="$(var.SourceDir)\Avalonia.Dialogs.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
@@ -227,12 +230,18 @@
|
||||
<Component Id="owc80EC8AEA1BFB8077812CDD06F9128A53" Guid="afbd2d79-629c-90a1-57a9-d68edc2d1437">
|
||||
<File Id="owf80EC8AEA1BFB8077812CDD06F9128A53" Source="$(var.SourceDir)\clrjit.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcD89DA7DE2D69AFC05DD5D46B6072C05C" Guid="ff72b568-c40c-3d50-c5af-049f64b476ea">
|
||||
<File Id="owfD89DA7DE2D69AFC05DD5D46B6072C05C" Source="$(var.SourceDir)\concrt140.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc6135A13B8E29883ED57BF3FE20578EED" Guid="cd1aae2e-a4de-1bd1-9680-014bccf80e32">
|
||||
<File Id="owf6135A13B8E29883ED57BF3FE20578EED" Source="$(var.SourceDir)\coreclr.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc5E8FBF42F9BCF40914849582C19906B8" Guid="f7a08052-6afc-fe5e-291c-07137533ab79">
|
||||
<File Id="owf5E8FBF42F9BCF40914849582C19906B8" Source="$(var.SourceDir)\createdump.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcF9E82F0BAE95DEABBEA8012A0994676C" Guid="edd1fddd-c05b-dc01-33b2-52e715b79615">
|
||||
<File Id="owfF9E82F0BAE95DEABBEA8012A0994676C" Source="$(var.SourceDir)\cvextern.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc3883419A2BFFE7013C2194A99728AB11" Guid="dd137337-4b74-c76b-c87e-6b5f42697dd4">
|
||||
<File Id="owf3883419A2BFFE7013C2194A99728AB11" Source="$(var.SourceDir)\dbgshim.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
@@ -263,6 +272,18 @@
|
||||
<Component Id="owc6262D65DF7B3DF80C034B72467CAE882" Guid="4941cd5b-5666-87fe-5a6a-5ebdd5ee2524">
|
||||
<File Id="owf6262D65DF7B3DF80C034B72467CAE882" Source="$(var.SourceDir)\MessageBox.Avalonia.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcBED5500FCECB7551175681E93EC9B191" Guid="e84e4591-8227-e9c2-b052-dc4583553c9a">
|
||||
<File Id="owfBED5500FCECB7551175681E93EC9B191" Source="$(var.SourceDir)\Microsoft.CodeAnalysis.CSharp.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcD48DD5DDA2BA4C83F4A98D4BE87BA462" Guid="effc6a72-2186-a73f-ee7f-c05c95de6c6e">
|
||||
<File Id="owfD48DD5DDA2BA4C83F4A98D4BE87BA462" Source="$(var.SourceDir)\Microsoft.CodeAnalysis.CSharp.Scripting.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcDC0782CCA5E596145FD1FDFB67EDC2AF" Guid="8bfcc8b6-6693-60fe-2af9-d0e34ab6f421">
|
||||
<File Id="owfDC0782CCA5E596145FD1FDFB67EDC2AF" Source="$(var.SourceDir)\Microsoft.CodeAnalysis.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcB9CA98C685BDD7D3E9DD3EBD5C5A3B84" Guid="434ec6c6-a47b-5321-63d1-6d30a2f8a9bf">
|
||||
<File Id="owfB9CA98C685BDD7D3E9DD3EBD5C5A3B84" Source="$(var.SourceDir)\Microsoft.CodeAnalysis.Scripting.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc27AE8A53D94DD8A3E4AEAF6F7C27FB60" Guid="80e5ef0e-84a5-2bce-9923-0fd54d243e45">
|
||||
<File Id="owf27AE8A53D94DD8A3E4AEAF6F7C27FB60" Source="$(var.SourceDir)\Microsoft.CSharp.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
@@ -299,12 +320,30 @@
|
||||
<Component Id="owcE382B0CF482F0E7C3AF33E6EEEBD26B0" Guid="7433845c-c763-9b7e-e2c9-7b06986570bf">
|
||||
<File Id="owfE382B0CF482F0E7C3AF33E6EEEBD26B0" Source="$(var.SourceDir)\mscorrc.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc4EDD870826B23A7EFC3FACD1E199E883" Guid="587324f3-ed59-f000-c241-8dc6a66501de">
|
||||
<File Id="owf4EDD870826B23A7EFC3FACD1E199E883" Source="$(var.SourceDir)\msvcp140.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc57B8051D45DF8A094B6F6F64CD58D9E6" Guid="b19c1e08-c2ee-ae27-0014-d5180ae56935">
|
||||
<File Id="owf57B8051D45DF8A094B6F6F64CD58D9E6" Source="$(var.SourceDir)\msvcp140_1.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcE2F8C74ADC2AF2357936D93D9E417BB4" Guid="01e22654-976b-0b52-7f65-17a93b4d19ab">
|
||||
<File Id="owfE2F8C74ADC2AF2357936D93D9E417BB4" Source="$(var.SourceDir)\msvcp140_2.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcD748ECCC1ECBC6ACAF796527AC8E18D3" Guid="53347251-3752-30e8-051d-71050378624d">
|
||||
<File Id="owfD748ECCC1ECBC6ACAF796527AC8E18D3" Source="$(var.SourceDir)\msvcp140_atomic_wait.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc3FDD5303B44770B8890DCDE0685AF1EB" Guid="50c83bf3-3054-7dd7-6eda-a39108edb2c2">
|
||||
<File Id="owf3FDD5303B44770B8890DCDE0685AF1EB" Source="$(var.SourceDir)\msvcp140_codecvt_ids.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc79156F385239CEA4DEA3C87C1DA3E1D8" Guid="68380c80-6708-5eb6-415d-10e278417679">
|
||||
<File Id="owf79156F385239CEA4DEA3C87C1DA3E1D8" Source="$(var.SourceDir)\netstandard.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc3FC8434C1A84605AEEBC6A100CA2F3E1" Guid="47d7e276-db6d-424e-d797-1a69e1e24b3b">
|
||||
<File Id="owf3FC8434C1A84605AEEBC6A100CA2F3E1" Source="$(var.SourceDir)\Newtonsoft.Json.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc29161E83FC02784120326979FF285358" Guid="a8d30e75-1063-4d27-60b6-13d4bd4f52eb">
|
||||
<File Id="owf29161E83FC02784120326979FF285358" Source="$(var.SourceDir)\opencv_videoio_ffmpeg451_64.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcBFCA0BB8CBE4A68414FA088B4F7F3D22" Guid="babeb74f-9861-b222-a49a-ec268c3cd3ca">
|
||||
<File Id="owfBFCA0BB8CBE4A68414FA088B4F7F3D22" Source="$(var.SourceDir)\ReactiveUI.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
@@ -811,9 +850,9 @@
|
||||
</Component>
|
||||
<Component Id="owc21B8C8C0F69E3CD1398B9A0674DF07BD" Guid="1e472543-e636-904d-da5b-cddaac2d36b1">
|
||||
<File Id="owf21B8C8C0F69E3CD1398B9A0674DF07BD" Source="$(var.SourceDir)\UVtools.exe" KeyPath="yes">
|
||||
<Shortcut Id="sc218BF75801887335D1B30BAFB94BA631" Name="UVtools" Directory="scd220707349D4C8FA275285514283F3E2A" WorkingDirectory="MergeRedirectFolder" Description="MSLA/DLP, file analysis, calibration, repair, conversion and manipulation" />
|
||||
<Shortcut Id="sc2F2092C02FDD8EB21E756F58C31B70A7" Name="UVtools" Directory="StartMenuFolder" WorkingDirectory="MergeRedirectFolder" Description="MSLA/DLP, file analysis, calibration, repair, conversion and manipulation" />
|
||||
<Shortcut Id="sc6327849DA5C02D2396E91B8B1892E03C" Name="UVtools" Directory="DesktopFolder" Description="MSLA/DLP, file analysis, calibration, repair, conversion and manipulation" WorkingDirectory="MergeRedirectFolder" />
|
||||
<Shortcut Id="sc218BF75801887335D1B30BAFB94BA631" Name="UVtools" Directory="scd220707349D4C8FA275285514283F3E2A" WorkingDirectory="MergeRedirectFolder" Description="MSLA/DLP, file analysis, calibration, repair, conversion and manipulation" />
|
||||
<Shortcut Id="sc6327849DA5C02D2396E91B8B1892E03C" Name="UVtools" Directory="DesktopFolder" WorkingDirectory="MergeRedirectFolder" Description="MSLA/DLP, file analysis, calibration, repair, conversion and manipulation" />
|
||||
</File>
|
||||
</Component>
|
||||
<Component Id="owc0C1077539E2B54F2460D2C0993613EFB" Guid="fc6ae2db-2865-9eb4-5753-4f2f941fdf16">
|
||||
@@ -825,6 +864,15 @@
|
||||
<Component Id="owc1FE1E0B70F7D880A2FB9AFA8E0E36EF5" Guid="545300b7-5398-2ce2-788f-02287a83e8a7">
|
||||
<File Id="owf1FE1E0B70F7D880A2FB9AFA8E0E36EF5" Source="$(var.SourceDir)\UVtools_demo_file.sl1" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc507468650B23000B702AAAE48E658343" Guid="dba8edf4-02a3-c04a-50fc-896025548077">
|
||||
<File Id="owf507468650B23000B702AAAE48E658343" Source="$(var.SourceDir)\vccorlib140.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcEB2D9343E9BF3366381E9864468EFB9A" Guid="c4f85169-dfa6-1369-3b95-34e28199fa0f">
|
||||
<File Id="owfEB2D9343E9BF3366381E9864468EFB9A" Source="$(var.SourceDir)\vcruntime140.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc41A749EF7C055C135F6C13882684CE39" Guid="d0346e8a-b7e9-6a98-fefd-48957d30e340">
|
||||
<File Id="owf41A749EF7C055C135F6C13882684CE39" Source="$(var.SourceDir)\vcruntime140_1.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc9AF7D2C52438BF24F3FA3132D7C0E6A9" Guid="892f88e7-cf94-fad1-08d3-b26c1b5913d3">
|
||||
<File Id="owf9AF7D2C52438BF24F3FA3132D7C0E6A9" Source="$(var.SourceDir)\WindowsBase.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
@@ -1090,59 +1138,186 @@
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
<Directory Id="owd37EA32A018DF9B31395A1FCE42233062" Name="x64">
|
||||
<Component Id="owcCD1854F2CC6C7F17F61397E23B6C598A" Guid="0a98d274-6f18-ee97-f14c-410e8fd2060d">
|
||||
<File Id="owfCD1854F2CC6C7F17F61397E23B6C598A" Source="$(var.SourceDir)\x64\concrt140.dll" KeyPath="yes" />
|
||||
<Directory Id="owd799F60633DE3314CD962556CD118A45D" Name="cs">
|
||||
<Component Id="owc99CE72FDB30C8FD0902CE01843ED4D88" Guid="c4c2d2ce-4eae-325d-f83e-f5d17907fa7d">
|
||||
<File Id="owf99CE72FDB30C8FD0902CE01843ED4D88" Source="$(var.SourceDir)\cs\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcE1790624963D540C427806C2B2809EBA" Guid="00de945a-e306-4840-1dd3-b8e968184b74">
|
||||
<File Id="owfE1790624963D540C427806C2B2809EBA" Source="$(var.SourceDir)\x64\cvextern.dll" KeyPath="yes" />
|
||||
<Component Id="owc5A8A23B0047B0D17D2E388C7647E2495" Guid="0bc611bd-4c59-08df-c64a-8fa2236aa7a5">
|
||||
<File Id="owf5A8A23B0047B0D17D2E388C7647E2495" Source="$(var.SourceDir)\cs\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc5F1F538D5D53D69031C503A5A647FA86" Guid="4e9e9fdc-8d0c-3ba0-a240-9e6ef5842194">
|
||||
<File Id="owf5F1F538D5D53D69031C503A5A647FA86" Source="$(var.SourceDir)\x64\msvcp140.dll" KeyPath="yes" />
|
||||
<Component Id="owc86B8E7B458701723CB9EC03C1690DC6E" Guid="cdd72de0-864d-fb89-212f-4bd06f0dcd10">
|
||||
<File Id="owf86B8E7B458701723CB9EC03C1690DC6E" Source="$(var.SourceDir)\cs\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc8F40E3E29777D025A9F18E5B6042F30D" Guid="e05981f2-643b-ca90-e066-2434e056751a">
|
||||
<File Id="owf8F40E3E29777D025A9F18E5B6042F30D" Source="$(var.SourceDir)\x64\msvcp140_1.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc0881D1B926887713CEA1FB8CE1244020" Guid="3baf74a4-81ca-d0a7-70ea-912a08d3dc3c">
|
||||
<File Id="owf0881D1B926887713CEA1FB8CE1244020" Source="$(var.SourceDir)\x64\msvcp140_2.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc2FF8EDA65751914E3C80D405856A37CE" Guid="283d40b2-5948-d5e0-9173-53dbd88d6e13">
|
||||
<File Id="owf2FF8EDA65751914E3C80D405856A37CE" Source="$(var.SourceDir)\x64\msvcp140_codecvt_ids.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcA66BA6B6AE2CB062F1DEE173EBAC6013" Guid="2c9e44cd-17bb-ac7b-b524-b8d94f9cf180">
|
||||
<File Id="owfA66BA6B6AE2CB062F1DEE173EBAC6013" Source="$(var.SourceDir)\x64\opencv_videoio_ffmpeg440_64.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc8C50C7464818ADC2267594B33B7B1EE6" Guid="049c0f0d-c410-daa8-b6ec-1c515fdfce03">
|
||||
<File Id="owf8C50C7464818ADC2267594B33B7B1EE6" Source="$(var.SourceDir)\x64\vcruntime140.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcBF69387AE1C9C06910622B5629DAAA62" Guid="051ca95f-4aa8-18b1-56da-7788687d06e0">
|
||||
<File Id="owfBF69387AE1C9C06910622B5629DAAA62" Source="$(var.SourceDir)\x64\vcruntime140_1.dll" KeyPath="yes" />
|
||||
<Component Id="owc8370BED3D17A58E88E193350B14A5450" Guid="cc521992-26e9-bf12-e777-68f8e2102405">
|
||||
<File Id="owf8370BED3D17A58E88E193350B14A5450" Source="$(var.SourceDir)\cs\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owd3BCA71FC1DDF940F5FD535BAC750E17B" Name="x86">
|
||||
<Component Id="owcFBC3B4CD533BC131080BCB572CEE8474" Guid="8b12ad7e-4019-3cca-c71d-82e5f3e6a080">
|
||||
<File Id="owfFBC3B4CD533BC131080BCB572CEE8474" Source="$(var.SourceDir)\x86\concrt140.dll" KeyPath="yes" />
|
||||
<Directory Id="owd17C6A2D314297F8FF3C608803909F7BE" Name="de">
|
||||
<Component Id="owc6A8D7823467C066EA1EC2F740C66084D" Guid="82c152c6-97bf-f75d-44fc-294474d9a7cb">
|
||||
<File Id="owf6A8D7823467C066EA1EC2F740C66084D" Source="$(var.SourceDir)\de\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc326B123F4EAB21E3B400B7357CCFCB69" Guid="7acba6ad-3e71-b056-9a79-7e53f7d4585b">
|
||||
<File Id="owf326B123F4EAB21E3B400B7357CCFCB69" Source="$(var.SourceDir)\x86\cvextern.dll" KeyPath="yes" />
|
||||
<Component Id="owc9116F5B9D0D06FDD8B9116F3E0951A24" Guid="05d40bda-9c56-78d7-90ac-dd3c0b6e32c8">
|
||||
<File Id="owf9116F5B9D0D06FDD8B9116F3E0951A24" Source="$(var.SourceDir)\de\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcEBF7D14133500BEDB79449CCE2A5B412" Guid="3cfe7baa-8f60-50d4-0c7c-41e7f7409b69">
|
||||
<File Id="owfEBF7D14133500BEDB79449CCE2A5B412" Source="$(var.SourceDir)\x86\msvcp140.dll" KeyPath="yes" />
|
||||
<Component Id="owc201B77F8A5FFED898E7D6ABA98A1C719" Guid="db330e27-4a94-1662-79dc-50425953f203">
|
||||
<File Id="owf201B77F8A5FFED898E7D6ABA98A1C719" Source="$(var.SourceDir)\de\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcA62A9E2DCF3C1092572B9BA8A90AF2CC" Guid="a5901167-af03-d482-e4a2-55e2fd2dab37">
|
||||
<File Id="owfA62A9E2DCF3C1092572B9BA8A90AF2CC" Source="$(var.SourceDir)\x86\msvcp140_1.dll" KeyPath="yes" />
|
||||
<Component Id="owcF790A17350C2437C0E1E354B9D980161" Guid="627f2dc4-5b88-d3f7-3acf-7630111e30e8">
|
||||
<File Id="owfF790A17350C2437C0E1E354B9D980161" Source="$(var.SourceDir)\de\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc4E55EDBDDABF300437BC351C60EA1BBB" Guid="253ff45b-49b3-cf8c-4b98-7ac426bdb997">
|
||||
<File Id="owf4E55EDBDDABF300437BC351C60EA1BBB" Source="$(var.SourceDir)\x86\msvcp140_2.dll" KeyPath="yes" />
|
||||
</Directory>
|
||||
<Directory Id="owdF542F1E9B1CF46F5EC5BF0998941ED93" Name="es">
|
||||
<Component Id="owcDD2F3A9E1BC6C55110A95C76B075BB2A" Guid="1082627f-113d-241a-abee-cb25d4b696fe">
|
||||
<File Id="owfDD2F3A9E1BC6C55110A95C76B075BB2A" Source="$(var.SourceDir)\es\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcDE8398D0FE76287635F64D20414A83A9" Guid="b3a19e5c-5f5b-984b-06fc-91ec029138fe">
|
||||
<File Id="owfDE8398D0FE76287635F64D20414A83A9" Source="$(var.SourceDir)\x86\msvcp140_codecvt_ids.dll" KeyPath="yes" />
|
||||
<Component Id="owcAF0B9E9C8764DB03240C3233FA91FC3F" Guid="61f4d403-eb00-dd15-8880-b8ae920ff3b3">
|
||||
<File Id="owfAF0B9E9C8764DB03240C3233FA91FC3F" Source="$(var.SourceDir)\es\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcB3105100F274DC6C121EB91815CE430E" Guid="17155558-2ffd-5452-640e-b77c2e2b86e5">
|
||||
<File Id="owfB3105100F274DC6C121EB91815CE430E" Source="$(var.SourceDir)\x86\opencv_videoio_ffmpeg440.dll" KeyPath="yes" />
|
||||
<Component Id="owcA9E6FC4859E34CE57D4623D60AB82100" Guid="6e39d6b9-6efc-9ed5-3392-971358498061">
|
||||
<File Id="owfA9E6FC4859E34CE57D4623D60AB82100" Source="$(var.SourceDir)\es\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcFE2AD2B6C739ABAFD86DE40F4D5B83C9" Guid="30610dbe-339b-b1be-a4a6-626e8fc07490">
|
||||
<File Id="owfFE2AD2B6C739ABAFD86DE40F4D5B83C9" Source="$(var.SourceDir)\x86\vcruntime140.dll" KeyPath="yes" />
|
||||
<Component Id="owcB59CB618361B113CFA57D75E883608EA" Guid="ddc56db3-e6a2-c7aa-dc21-3b247964758c">
|
||||
<File Id="owfB59CB618361B113CFA57D75E883608EA" Source="$(var.SourceDir)\es\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owdA426C3729D5D59516430C8F667ED8DE8" Name="fr">
|
||||
<Component Id="owcFECC4FDE99CBE3816D982D1FF8E5E196" Guid="703ebe68-adaa-3f9c-606b-b42fec5159e8">
|
||||
<File Id="owfFECC4FDE99CBE3816D982D1FF8E5E196" Source="$(var.SourceDir)\fr\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcDDEF75A5FE4B5C43A5794EC0494F1E2C" Guid="56a9d29d-436d-4319-1a0d-cf5306a85f60">
|
||||
<File Id="owfDDEF75A5FE4B5C43A5794EC0494F1E2C" Source="$(var.SourceDir)\fr\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcF108244D2CA24AF9CCC6DA95FF283CA3" Guid="8a5a7aca-1013-145f-3a57-49946c024af2">
|
||||
<File Id="owfF108244D2CA24AF9CCC6DA95FF283CA3" Source="$(var.SourceDir)\fr\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcE8E57F27B5A0C2D7A27A164639AA95F9" Guid="caac4561-da90-4c7b-02cd-bdfca5be1694">
|
||||
<File Id="owfE8E57F27B5A0C2D7A27A164639AA95F9" Source="$(var.SourceDir)\fr\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owd74DAE01CDA8C981B3918AC92ED360AA1" Name="it">
|
||||
<Component Id="owc4DD3418A4620DABCBBB6CCAA8ECA2707" Guid="421c92b6-85d7-3733-b9a5-ed10229c89a5">
|
||||
<File Id="owf4DD3418A4620DABCBBB6CCAA8ECA2707" Source="$(var.SourceDir)\it\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc70A38979F7888C6B171A3C37DBD35061" Guid="d19c3295-b474-4fab-9af6-93c9257dfd18">
|
||||
<File Id="owf70A38979F7888C6B171A3C37DBD35061" Source="$(var.SourceDir)\it\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcE089DC47E89BFE9044FEC67CE8379D17" Guid="15a0d64c-a68c-9780-ddd0-e40920cd6a68">
|
||||
<File Id="owfE089DC47E89BFE9044FEC67CE8379D17" Source="$(var.SourceDir)\it\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc8B74032559230C1C0C2B5082475A5CD4" Guid="39eabb54-8dd8-65e8-fe00-359ad09cae2a">
|
||||
<File Id="owf8B74032559230C1C0C2B5082475A5CD4" Source="$(var.SourceDir)\it\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owd939A7C952EF97FFE1E5F44BC8281E343" Name="ja">
|
||||
<Component Id="owc51FE3ECF820BD499CDE7DBB22A69167D" Guid="3201321c-b8c7-5cbb-2ad8-f8bf5b451b3d">
|
||||
<File Id="owf51FE3ECF820BD499CDE7DBB22A69167D" Source="$(var.SourceDir)\ja\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc8549DE5E566B16C0AD0E61BE120D8555" Guid="8b4fc791-bf38-333f-a84f-d78fedc6efe3">
|
||||
<File Id="owf8549DE5E566B16C0AD0E61BE120D8555" Source="$(var.SourceDir)\ja\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcD50AC7A96B0FC09970B32B3681AF3FF4" Guid="1f8ff321-6287-1fbe-4f8d-86eb390bf641">
|
||||
<File Id="owfD50AC7A96B0FC09970B32B3681AF3FF4" Source="$(var.SourceDir)\ja\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc0A9733AEBD37AD14413D6F786BB5FA8A" Guid="f57405c2-169e-0504-01db-e115d156226b">
|
||||
<File Id="owf0A9733AEBD37AD14413D6F786BB5FA8A" Source="$(var.SourceDir)\ja\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owd26824DD7BA688994CEC324C96033C66B" Name="ko">
|
||||
<Component Id="owc82B969E8D4D535732FCF01718B7E606D" Guid="993f9efe-f89f-7b95-8443-2341e293e7a6">
|
||||
<File Id="owf82B969E8D4D535732FCF01718B7E606D" Source="$(var.SourceDir)\ko\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcABF888E5C49C7DDDF2FB5AA8071F21D9" Guid="13a4540c-353f-31db-f76e-3017c15fe9df">
|
||||
<File Id="owfABF888E5C49C7DDDF2FB5AA8071F21D9" Source="$(var.SourceDir)\ko\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc1F4AA2DE2CA82FAFEC017FB9E5159A16" Guid="b96179dd-f81f-6158-e087-b01eeb552325">
|
||||
<File Id="owf1F4AA2DE2CA82FAFEC017FB9E5159A16" Source="$(var.SourceDir)\ko\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc49136EC48B42F29310D5FAB96EB39C77" Guid="7d59fb12-e36d-3b98-1b54-8182dc102913">
|
||||
<File Id="owf49136EC48B42F29310D5FAB96EB39C77" Source="$(var.SourceDir)\ko\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owdC3B37D0EB36BEDA1B06A324A062DC94D" Name="pl">
|
||||
<Component Id="owc4D2D720AD4B25046F5C3A8337C58558F" Guid="f9f595eb-39b5-e326-d983-3aca9a6bb500">
|
||||
<File Id="owf4D2D720AD4B25046F5C3A8337C58558F" Source="$(var.SourceDir)\pl\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc247996509C92190D211D51C687663973" Guid="d3d661d6-e99e-91e3-9512-9a35c05b5d78">
|
||||
<File Id="owf247996509C92190D211D51C687663973" Source="$(var.SourceDir)\pl\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc75290668850934E95D9C36037C6CA10D" Guid="8be98fcf-1714-97ea-9e3f-6337e8a79c4a">
|
||||
<File Id="owf75290668850934E95D9C36037C6CA10D" Source="$(var.SourceDir)\pl\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc01C7CE26E845E06F3A50D520FB278BCF" Guid="d1ddafed-c698-3973-d2a4-4c4d00620030">
|
||||
<File Id="owf01C7CE26E845E06F3A50D520FB278BCF" Source="$(var.SourceDir)\pl\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owdE3101CE52C8B10FCC8A2CC81C4C96F39" Name="pt-BR">
|
||||
<Component Id="owc66101D80AE2357408A5C5CDB0D87BEB0" Guid="9fa0b68e-9b5f-699d-79d5-b93a4344d2eb">
|
||||
<File Id="owf66101D80AE2357408A5C5CDB0D87BEB0" Source="$(var.SourceDir)\pt-BR\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcFF7C74C94543248FAB00F923E96F0218" Guid="4dbc0468-33ed-1ad7-80c8-e7589d99ef83">
|
||||
<File Id="owfFF7C74C94543248FAB00F923E96F0218" Source="$(var.SourceDir)\pt-BR\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc537BEF6F05522283FE8F47F86399668A" Guid="960db198-afc4-40f9-f20e-a5d537c5702a">
|
||||
<File Id="owf537BEF6F05522283FE8F47F86399668A" Source="$(var.SourceDir)\pt-BR\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc233F59943A3FA33488E78259D09163C6" Guid="e99cb644-a268-a6af-face-e2e7834333cb">
|
||||
<File Id="owf233F59943A3FA33488E78259D09163C6" Source="$(var.SourceDir)\pt-BR\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owdEAE4E7B6D44EEB507A9E5B7539B1C34A" Name="ru">
|
||||
<Component Id="owcB065F45686216D7224FE9E57071535B1" Guid="e96c2dc1-7b2a-91cf-dfb2-add81e62ac2b">
|
||||
<File Id="owfB065F45686216D7224FE9E57071535B1" Source="$(var.SourceDir)\ru\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc1810998919C2A9C80EFE093BE92CBEF2" Guid="88c73b6a-b6a5-87f8-ffed-c028f0b6c0e4">
|
||||
<File Id="owf1810998919C2A9C80EFE093BE92CBEF2" Source="$(var.SourceDir)\ru\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc56892873DDC66705A32DD13C1A40B9F3" Guid="b92e9a16-6e47-a12b-354b-4624ba27ebfd">
|
||||
<File Id="owf56892873DDC66705A32DD13C1A40B9F3" Source="$(var.SourceDir)\ru\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc53575A00E0697BB0E07983D26C103FEA" Guid="64e7fa95-8227-2c96-6a82-e914b6ce047c">
|
||||
<File Id="owf53575A00E0697BB0E07983D26C103FEA" Source="$(var.SourceDir)\ru\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owdFCC3FD9F99A4D5BEDEAC61F3322D2D93" Name="tr">
|
||||
<Component Id="owcEC06D7EB1988F1B550C8B3569B0261D3" Guid="07379a43-cb0f-ea5f-0cfe-d71fddfe14e6">
|
||||
<File Id="owfEC06D7EB1988F1B550C8B3569B0261D3" Source="$(var.SourceDir)\tr\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcBA8A623686D1AEABEB47E9B2FB674C3A" Guid="14f5bbbe-61a0-2e13-aa01-612beea284ea">
|
||||
<File Id="owfBA8A623686D1AEABEB47E9B2FB674C3A" Source="$(var.SourceDir)\tr\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc618B2DBE7EB4D4F7E675C5D04CD64E7E" Guid="197802f2-556a-5b71-650c-faf644c38863">
|
||||
<File Id="owf618B2DBE7EB4D4F7E675C5D04CD64E7E" Source="$(var.SourceDir)\tr\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc91567B2B4E8154089395D1A78358BE89" Guid="1c327c0f-a510-b334-7130-5c9e6609dc7b">
|
||||
<File Id="owf91567B2B4E8154089395D1A78358BE89" Source="$(var.SourceDir)\tr\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owd7142663FADDFFB05CCE01DC370DE4995" Name="zh-Hans">
|
||||
<Component Id="owc28B8853BEB28067D4AB79B73216A3AC8" Guid="f6b6af15-bb3a-3eda-972d-47cb28af6c03">
|
||||
<File Id="owf28B8853BEB28067D4AB79B73216A3AC8" Source="$(var.SourceDir)\zh-Hans\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcDA343DBA19E680B537006D75B50A616D" Guid="898f5dc8-48bd-913f-968d-10e37f8347f7">
|
||||
<File Id="owfDA343DBA19E680B537006D75B50A616D" Source="$(var.SourceDir)\zh-Hans\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc074201B7ECF4E55183EF1FC13FC03B70" Guid="ef2d2267-19a2-0443-6ae4-16cfed6b8091">
|
||||
<File Id="owf074201B7ECF4E55183EF1FC13FC03B70" Source="$(var.SourceDir)\zh-Hans\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc5371E4C6A9B06D411E8EAC3E5A48E7EA" Guid="a7649dfb-52b9-08d3-6f03-f7aed4d2cce3">
|
||||
<File Id="owf5371E4C6A9B06D411E8EAC3E5A48E7EA" Source="$(var.SourceDir)\zh-Hans\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="owdA86DB5E08AB73906A10F69BC4AA81DE2" Name="zh-Hant">
|
||||
<Component Id="owc18EA70FFACC7303C11A678723F8E1919" Guid="71c1ee6c-af04-89be-a2f7-20205b5f371e">
|
||||
<File Id="owf18EA70FFACC7303C11A678723F8E1919" Source="$(var.SourceDir)\zh-Hant\Microsoft.CodeAnalysis.CSharp.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc7B45E327235A25974959071E8D015643" Guid="ebc62531-8adf-6e26-4b07-8c8ae1b1645c">
|
||||
<File Id="owf7B45E327235A25974959071E8D015643" Source="$(var.SourceDir)\zh-Hant\Microsoft.CodeAnalysis.CSharp.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc35485D602BBBDC5C5F40469EC390B90C" Guid="48279d95-5026-06e5-350f-7fb5d19fe1c1">
|
||||
<File Id="owf35485D602BBBDC5C5F40469EC390B90C" Source="$(var.SourceDir)\zh-Hant\Microsoft.CodeAnalysis.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc505D5854210A555AEF782935C164E813" Guid="778f403b-5deb-df93-7dc7-44b5fa099c25">
|
||||
<File Id="owf505D5854210A555AEF782935C164E813" Source="$(var.SourceDir)\zh-Hant\Microsoft.CodeAnalysis.Scripting.resources.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -110,19 +110,19 @@ $slicerFile.Decode($inputFile, $progress);
|
||||
###################################################
|
||||
# Morph bottom erode
|
||||
Write-Output "Eroding bottoms with ${iterations} iterations, please wait..."
|
||||
$morph = New-Object UVtools.Core.Operations.OperationMorph
|
||||
$morph = [UVtools.Core.Operations.OperationMorph]::new($slicerFile)
|
||||
$morph.MorphOperation = [Emgu.CV.CvEnum.MorphOp]::Erode
|
||||
$morph.IterationsStart = $iterations
|
||||
$morph.LayerIndexEnd = $slicerFile.BottomLayerCount - 1
|
||||
if(!$morph.Execute($slicerFile, $progress)){ return; }
|
||||
$morph.SelectBottomLayers()
|
||||
if(!$morph.Execute($progress)){ return; }
|
||||
|
||||
|
||||
##############
|
||||
# Dont touch #
|
||||
##############
|
||||
# Save file with _modified name appended
|
||||
$filePath = [System.IO.Path]::GetDirectoryName($inputFile);
|
||||
$fileExt = [System.IO.Path]::GetExtension($inputFile);
|
||||
$filePath = [System.IO.Path]::GetDirectoryName($inputFile)
|
||||
$fileExt = [System.IO.Path]::GetExtension($inputFile)
|
||||
$fileNoExt = [System.IO.Path]::GetFileNameWithoutExtension($inputFile)
|
||||
$fileOutput = "${filePath}${dirSeparator}${fileNoExt}_modified${fileExt}"
|
||||
Write-Output "Saving as ${fileNoExt}_modified${fileExt}, please wait..."
|
||||
|
||||
+10
-11
@@ -79,31 +79,30 @@ Take **[Erode-Bottom.ps1](https://github.com/sn4k3/UVtools/blob/master/UVtools.S
|
||||
* Example:
|
||||
```Powershell
|
||||
# Erode bottom layers
|
||||
$morph = New-Object UVtools.Core.Operations.OperationMorph
|
||||
$morph = [UVtools.Core.Operations.OperationMorph]::new($slicerFile)
|
||||
$morph.MorphOperation = [Emgu.CV.CvEnum.MorphOp]::Erode
|
||||
$morph.IterationsStart = $iterations
|
||||
$morph.LayerIndexEnd = $slicerFile.BottomLayerCount - 1
|
||||
if(!$morph.Execute($slicerFile, $progress)){ return; }
|
||||
$morph.SelectBottomLayers()
|
||||
if(!$morph.Execute($progress)){ return }
|
||||
|
||||
# Reuse object and erode normal layers with 1 less iteration
|
||||
$morph.IterationsStart = $iterations - 1
|
||||
$morph.LayerIndexStart = $slicerFile.BottomLayerCount
|
||||
$morph.LayerIndexEnd = $slicerFile.LayerCount - 1
|
||||
if(!$morph.Execute($slicerFile, $progress)){ return }
|
||||
$morph.SelectNormalLayers()
|
||||
if(!$morph.Execute($progress)){ return }
|
||||
|
||||
# Rotate layer 0, 45º
|
||||
$rotate = New-Object UVtools.Core.Operations.OperationRotate
|
||||
# Rotate all layers, 45º
|
||||
$rotate = [UVtools.Core.Operations.OperationRotate]::new($slicerFile)
|
||||
$rotate.AngleDegrees = 45;
|
||||
if(!$rotate.Execute($slicerFile, $progress)){ return }
|
||||
if(!$rotate.Execute($progress)){ return }
|
||||
|
||||
# Rotate layer 1, 90º
|
||||
$rotate.LayerIndexStart = 1
|
||||
$rotate.LayerIndexEnd = 1
|
||||
$rotate.AngleDegrees = 90
|
||||
if(!$rotate.Execute($slicerFile, $progress)){ return }
|
||||
if(!$rotate.Execute($progress)){ return }
|
||||
```
|
||||
|
||||
## Contribute with your scripts
|
||||
|
||||
If you make a usefull script and want to contribute you can share and publish your script under [github - issues](https://github.com/sn4k3/UVtools/issues/new?assignees=sn4k3&labels=script&template=script.md&title=%5BSCRIPT%5D+).
|
||||
If you make a usefull script and want to contribute you can share and publish your script under [github - discussions - scripts](https://github.com/sn4k3/UVtools/discussions/categories/scripts).
|
||||
After analyzation it will be published on the repository
|
||||
@@ -2,9 +2,10 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="UVtools.WPF.App">
|
||||
<Application.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
|
||||
<StyleInclude Source="avares://ThemeEditor.Controls.ColorPicker/ColorPicker.xaml"/>
|
||||
<FluentTheme Mode="Light"/>
|
||||
<StyleInclude Source="avares://ThemeEditor.Controls.ColorPicker/ColorPicker.axaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
|
||||
<StyleInclude Source="/Assets/Styles/Styles.xaml" />
|
||||
<StyleInclude Source="/Assets/Styles/StylesLight.xaml" />
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
|
||||
@@ -24,13 +24,12 @@ using UVtools.Core;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.WPF.Extensions;
|
||||
using UVtools.WPF.Structures;
|
||||
using Size = System.Drawing.Size;
|
||||
|
||||
namespace UVtools.WPF
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
public static IThemeSelector? ThemeSelector { get; set; }
|
||||
public static ThemeSelector ThemeSelector { get; set; }
|
||||
public static MainWindow MainWindow;
|
||||
public static FileFormat SlicerFile = null;
|
||||
|
||||
@@ -53,7 +52,7 @@ namespace UVtools.WPF
|
||||
|
||||
OperationProfiles.Load();
|
||||
|
||||
ThemeSelector = Avalonia.ThemeManager.ThemeSelector.Create(Path.Combine(ApplicationPath, "Assets", "Themes"));
|
||||
/*ThemeSelector = ThemeSelector.Create(Path.Combine(ApplicationPath, "Assets", "Themes"));
|
||||
ThemeSelector.LoadSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme"));
|
||||
if (ThemeSelector.SelectedTheme.Name == "UVtoolsDark" || ThemeSelector.SelectedTheme.Name == "Light")
|
||||
{
|
||||
@@ -63,13 +62,16 @@ namespace UVtools.WPF
|
||||
theme.ApplyTheme();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
MainWindow = new MainWindow();
|
||||
|
||||
try
|
||||
{
|
||||
CvInvoke.CheckLibraryLoaded();
|
||||
if(!CvInvoke.Init())
|
||||
await MainWindow.MessageBoxError("UVtools can not init OpenCV library\n" +
|
||||
"Please build or install this dependencies in order to run UVtools\n" +
|
||||
"Check manual or page at 'Requirements' section for help",
|
||||
"UVtools can not run");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -82,8 +84,7 @@ namespace UVtools.WPF
|
||||
}
|
||||
|
||||
desktop.MainWindow = MainWindow;
|
||||
desktop.Exit += (sender, e)
|
||||
=> ThemeSelector.SaveSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme"));
|
||||
//desktop.Exit += (sender, e) => ThemeSelector.SaveSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme"));
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
@@ -191,6 +192,8 @@ namespace UVtools.WPF
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
var folder1 = $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}{Path.DirectorySeparatorChar}.config{Path.DirectorySeparatorChar}PrusaSlicer";
|
||||
if (Directory.Exists(folder1)) return folder1;
|
||||
return $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}{Path.DirectorySeparatorChar}.PrusaSlicer";
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 113 B |
@@ -0,0 +1,53 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20"></Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="Expander[IsExpanded=true] /template/ ToggleButton#PART_toggle /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForeground}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Border.GroupBox">
|
||||
<Setter Property="BorderThickness" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.GroupBoxHeader">
|
||||
<Setter Property="Padding" Value="10" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Border.FooterActions">
|
||||
<Setter Property="Padding" Value="5,20" />
|
||||
<Setter Property="Margin" Value="0,10,0, 0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBox.TransparentReadOnly">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="IsReadOnly" Value="True" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="CaretBrush" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="AcceptsReturn" Value="True" />
|
||||
<Setter Property="AcceptsTab" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="RadioButton">
|
||||
<Setter Property="MinWidth" Value="30"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox">
|
||||
<Setter Property="MinWidth" Value="30"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="NumericUpDown">
|
||||
<Setter Property="MinWidth" Value="130"></Setter>
|
||||
<Setter Property="ClipValueToMinMax" Value="True"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TabControl">
|
||||
<Setter Property="Padding" Value="0"></Setter>
|
||||
</Style>
|
||||
|
||||
</Styles>
|
||||
@@ -0,0 +1,20 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20"></Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="Border.GroupBox">
|
||||
<Setter Property="BorderBrush" Value="LightBlue" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.GroupBoxHeader">
|
||||
<Setter Property="Background" Value="LightBlue" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Border.FooterActions">
|
||||
<Setter Property="Background" Value="LightGray" />
|
||||
</Style>
|
||||
|
||||
</Styles>
|
||||
@@ -10,18 +10,17 @@
|
||||
<StackPanel Spacing="10">
|
||||
<Grid
|
||||
RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto"
|
||||
ColumnDefinitions="Auto,10,100,5,Auto,20,Auto,10,100,5,Auto"
|
||||
ColumnDefinitions="Auto,10,150,5,Auto,20,Auto,10,150,5,Auto"
|
||||
>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="Layer height:"/>
|
||||
<NumericUpDown Grid.Row="0" Grid.Column="2"
|
||||
ClipValueToMinMax="True"
|
||||
Increment="0.01"
|
||||
Minimum="0.01"
|
||||
Maximum="0.30"
|
||||
FormatString="\{0:0.00\}"
|
||||
FormatString="F02"
|
||||
Value="{Binding Operation.LayerHeight}"
|
||||
/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="4"
|
||||
@@ -41,7 +40,7 @@
|
||||
Increment="1"
|
||||
Minimum="1"
|
||||
Maximum="1000"
|
||||
FormatString="\{0:0.00\}"
|
||||
FormatString="F02"
|
||||
Value="{Binding Operation.BottomLayers}"
|
||||
/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="4"
|
||||
@@ -60,7 +59,7 @@
|
||||
Increment="1"
|
||||
Minimum="1"
|
||||
Maximum="1000"
|
||||
FormatString="\{0:0.00\}"
|
||||
FormatString="F02"
|
||||
Value="{Binding Operation.NormalLayers}"
|
||||
/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="10"
|
||||
@@ -181,7 +180,7 @@
|
||||
<Grid
|
||||
Margin="0,10,0,0"
|
||||
RowDefinitions="Auto,10,Auto"
|
||||
ColumnDefinitions="Auto,10,80,5,Auto,5,80,5,Auto,40,Auto,10,80"
|
||||
ColumnDefinitions="Auto,10,Auto,5,Auto,5,Auto,5,Auto,30,Auto,10,Auto"
|
||||
>
|
||||
|
||||
<CheckBox Grid.Row="0" Grid.Column="2"
|
||||
@@ -265,7 +264,7 @@
|
||||
<Grid
|
||||
Margin="0,10,0,0"
|
||||
RowDefinitions="Auto,10,Auto,10,Auto,5,Auto"
|
||||
ColumnDefinitions="Auto,10,80,5,Auto,5,80,5,Auto,20,Auto,10,80"
|
||||
ColumnDefinitions="Auto,10,Auto,5,Auto,5,Auto,5,Auto,20,Auto,10,Auto"
|
||||
>
|
||||
|
||||
<CheckBox Grid.Row="0" Grid.Column="2"
|
||||
|
||||
@@ -29,15 +29,9 @@ namespace UVtools.WPF.Controls.Calibrators
|
||||
|
||||
public CalibrateElephantFootControl()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
BaseOperation = new OperationCalibrateElephantFoot();
|
||||
InitializeComponent();
|
||||
|
||||
if(App.SlicerFile is not null)
|
||||
{
|
||||
Operation.LayerHeight = (decimal) App.SlicerFile.LayerHeight;
|
||||
Operation.BottomExposure = (decimal) App.SlicerFile.BottomExposureTime;
|
||||
Operation.NormalExposure = (decimal) App.SlicerFile.ExposureTime;
|
||||
}
|
||||
BaseOperation = new OperationCalibrateElephantFoot(SlicerFile);
|
||||
|
||||
_kernelCtrl = this.Find<KernelControl>("KernelCtrl");
|
||||
|
||||
@@ -60,7 +54,6 @@ namespace UVtools.WPF.Controls.Calibrators
|
||||
{
|
||||
case ToolWindow.Callbacks.Init:
|
||||
case ToolWindow.Callbacks.ProfileLoaded:
|
||||
Operation.Resolution = App.SlicerFile.Resolution;
|
||||
Operation.PropertyChanged += (sender, e) =>
|
||||
{
|
||||
_timer.Stop();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user