Merge branch 'master' into SPE-1597-per-glyph-transformation-over-surface

This commit is contained in:
Filip Sykala - NTB T15p 2023-06-01 13:37:56 +02:00
commit 7d867e5dc2
41 changed files with 26588 additions and 190 deletions

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-05-26 13:11+0200\n"
"PO-Revision-Date: 2023-05-17 19:36+0200\n"
"PO-Revision-Date: 2023-05-27 14:17+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: ca\n"
@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.2.2\n"
"X-Generator: Poedit 3.3.1\n"
#: src/slic3r/GUI/AboutDialog.cpp:46 src/slic3r/GUI/AboutDialog.cpp:304
msgid "Portions copyright"
@ -1498,23 +1498,23 @@ msgstr "Col·loca els rodaments a les ranures i segueix imprimint"
#: src/slic3r/GUI/DoubleSlider.cpp:711 src/libslic3r/Utils.cpp:1015
#, boost-format
msgid "%1%d"
msgstr ""
msgstr "%1%d"
#: src/slic3r/GUI/DoubleSlider.cpp:712 src/libslic3r/Utils.cpp:1016
#, boost-format
msgid "%1%h"
msgstr ""
msgstr "%1%h"
#. TRN "m" means "minutes"
#: src/slic3r/GUI/DoubleSlider.cpp:713 src/libslic3r/Utils.cpp:1018
#, boost-format
msgid "%1%m"
msgstr ""
msgstr "%1%m"
#: src/slic3r/GUI/DoubleSlider.cpp:714 src/libslic3r/Utils.cpp:1026
#, boost-format
msgid "%1%s"
msgstr ""
msgstr "%1%s"
#: src/slic3r/GUI/DoubleSlider.cpp:1448
msgid "One layer mode"
@ -2303,7 +2303,7 @@ msgstr "a"
#: src/slic3r/GUI/GCodeViewer.cpp:3278
msgctxt "Metre"
msgid "m"
msgstr ""
msgstr "m"
#: src/slic3r/GUI/GCodeViewer.cpp:3289
msgid "Click to hide"
@ -2451,11 +2451,11 @@ msgstr "Filament"
#: src/slic3r/GUI/GCodeViewer.cpp:3961
msgid "Hide Custom G-code"
msgstr ""
msgstr "Ocultar Codi G personalitzat"
#: src/slic3r/GUI/GCodeViewer.cpp:3961
msgid "Show Custom G-code"
msgstr ""
msgstr "Mostrar Codi G personalitzat"
#: src/slic3r/GUI/GCodeViewer.cpp:3974
msgid "Estimated printing times"
@ -2614,15 +2614,15 @@ msgstr "Seq."
#: src/slic3r/GUI/GLCanvas3D.cpp:1305
msgid "SLA view"
msgstr ""
msgstr "Vista SLA"
#: src/slic3r/GUI/GLCanvas3D.cpp:1324
msgid "Show as processed"
msgstr ""
msgstr "Mostrar com a processat"
#: src/slic3r/GUI/GLCanvas3D.cpp:1325
msgid "Show as original"
msgstr ""
msgstr "Mostrar com a original"
#: src/slic3r/GUI/GLCanvas3D.cpp:1758
msgid "Variable layer height - Reset"
@ -2948,6 +2948,9 @@ msgid ""
"Drag to move the cut plane\n"
"Right-click a part to assign it to the other side"
msgstr ""
"Feu clic per capgirar el pla de tall\n"
"Arrossegueu per moure el pla tallat\n"
"Feu clic amb el botó dret a una part per assignar-la a l'altre costat"
#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:259 src/libslic3r/PrintConfig.cpp:495
#: src/libslic3r/PrintConfig.cpp:1189 src/libslic3r/PrintConfig.cpp:2324
@ -3836,7 +3839,7 @@ msgstr "La pintura automàtica requereix una configuració d'impressió vàlida.
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:527
msgid "Automatic painting requires printable object."
msgstr ""
msgstr "La pintura automàtica requereix un objecte imprimible."
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:537
msgid "Automatic painting will erase all currently painted areas."
@ -4134,13 +4137,13 @@ msgstr "Farciment de cubs"
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:340
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:356
msgid "Current"
msgstr ""
msgstr "Actual"
#. TRN Means "original color"
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:342
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:356
msgid "Original"
msgstr ""
msgstr "Original"
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:404
msgid "Paints neighboring facets that have the same color."
@ -5129,6 +5132,7 @@ msgstr "Actualment esteu executant l'última versió publicada %1%."
msgid ""
"There are no new released versions online. The latest release version is %1%."
msgstr ""
"No hi ha noves versions en línia. L'última versió de llançament és %1%."
#: src/slic3r/GUI/GUI_App.cpp:3437
#, boost-format
@ -11181,7 +11185,7 @@ msgstr "Connexió de les varetes de suport i unions"
#: src/slic3r/GUI/Tab.cpp:5157
msgid "Branching"
msgstr ""
msgstr "Ramificació"
#: src/slic3r/GUI/Tab.cpp:5159
msgid "Automatic generation"
@ -12099,6 +12103,8 @@ msgid ""
"Couldn't locate index file for vendor %1% when performing updates. The "
"profile will not be installed."
msgstr ""
"No s'ha pogut localitzar el fitxer d'índex per als %1% del proveïdor en "
"realitzar actualitzacions. El perfil no s'instal·larà."
#: src/slic3r/Utils/PresetUpdater.cpp:1344
#, boost-format
@ -12106,6 +12112,8 @@ msgid ""
"Couldn't load index file for vendor %1% when performing updates. The profile "
"will not be installed. Reason: Corrupted index file %2%."
msgstr ""
"No s'ha pogut carregar el fitxer d'índex per al proveïdor %1% en realitzar "
"actualitzacions. El perfil no s'instal·larà. Motiu: fitxer índex malmès %2%."
#: src/slic3r/Utils/PresetUpdater.cpp:1382
#, boost-format
@ -12113,6 +12121,9 @@ msgid ""
"Couldn't open profile file for vendor %1% when performing updates. The "
"profile will not be installed. This installation might be corrupted."
msgstr ""
"No s'ha pogut obrir el fitxer de perfil per al proveïdor %1% en realitzar "
"actualitzacions. El perfil no s'instal·larà. Aquesta instal·lació pot estar "
"corrompuda."
#: src/slic3r/Utils/Http.cpp:73
msgid ""
@ -12276,19 +12287,19 @@ msgstr ""
#: src/libslic3r/ExtrusionRole.cpp:38 src/libslic3r/ExtrusionRole.cpp:59
msgid "Perimeter"
msgstr ""
msgstr "Perímetre"
#: src/libslic3r/ExtrusionRole.cpp:39 src/libslic3r/ExtrusionRole.cpp:61
msgid "External perimeter"
msgstr ""
msgstr "Perímetre extern"
#: src/libslic3r/ExtrusionRole.cpp:40 src/libslic3r/ExtrusionRole.cpp:63
msgid "Overhang perimeter"
msgstr ""
msgstr "Perímetre de voladís"
#: src/libslic3r/ExtrusionRole.cpp:41 src/libslic3r/ExtrusionRole.cpp:65
msgid "Internal infill"
msgstr ""
msgstr "Farciment intern"
#: src/libslic3r/ExtrusionRole.cpp:42 src/libslic3r/ExtrusionRole.cpp:67
#: src/libslic3r/PrintConfig.cpp:1452 src/libslic3r/PrintConfig.cpp:2432
@ -12304,7 +12315,7 @@ msgstr "Farciment sòlid superior"
#: src/libslic3r/ExtrusionRole.cpp:45 src/libslic3r/ExtrusionRole.cpp:73
msgid "Bridge infill"
msgstr ""
msgstr "Farciment del pont"
#: src/libslic3r/ExtrusionRole.cpp:46 src/libslic3r/ExtrusionRole.cpp:75
#: src/libslic3r/PrintConfig.cpp:1380
@ -12313,7 +12324,7 @@ msgstr "Farciment del buit"
#: src/libslic3r/ExtrusionRole.cpp:47 src/libslic3r/ExtrusionRole.cpp:77
msgid "Skirt/Brim"
msgstr ""
msgstr "Faldilla/Bassa"
#: src/libslic3r/ExtrusionRole.cpp:49 src/libslic3r/ExtrusionRole.cpp:81
#: src/libslic3r/PrintConfig.cpp:2781
@ -12570,7 +12581,7 @@ msgstr ""
#: src/libslic3r/Print.cpp:525
#, boost-format
msgid "The object %1% exceeds the maximum build volume height."
msgstr ""
msgstr "L'objecte %1% supera l'alçada màxima de volum de construcció."
#: src/libslic3r/Print.cpp:526
#, boost-format
@ -12578,12 +12589,16 @@ msgid ""
"While the object %1% itself fits the build volume, its last layer exceeds "
"the maximum build volume height."
msgstr ""
"Tot i que l'objecte %1% s'adapta al volum de construcció, la seva última "
"capa supera l'alçada màxima del volum de construcció."
#: src/libslic3r/Print.cpp:527
msgid ""
"You might want to reduce the size of your model or change current print "
"settings and retry."
msgstr ""
"És possible que vulgueu reduir la mida del model o canviar la configuració "
"d'impressió actual i tornar-ho a provar."
#: src/libslic3r/Print.cpp:543
msgid "Variable layer height is not supported with Organic supports."
@ -16410,7 +16425,7 @@ msgstr ""
#: src/libslic3r/PrintConfig.cpp:2943
msgid "Branch Diameter with double walls"
msgstr ""
msgstr "Diàmetre de branca amb parets dobles"
#. TRN PrintSettings: "Organic supports" > "Branch Diameter"
#: src/libslic3r/PrintConfig.cpp:2946
@ -16419,6 +16434,9 @@ msgid ""
"printed with double walls for stability. Set this value to zero for no "
"double walls."
msgstr ""
"Les branques amb una superfície més gran que l'àrea d'un cercle d'aquest "
"diàmetre s'imprimiran amb parets dobles per a l'estabilitat. Establiu aquest "
"valor a zero per a cap paret doble."
#. TRN PrintSettings: #lmFIXME
#: src/libslic3r/PrintConfig.cpp:2959
@ -21360,11 +21378,6 @@ msgstr "S'ha produït un error en imprimir: "
msgid "Error: "
msgstr "Error: "
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:69
msgid "Esc"
msgstr "Esc"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:70
msgid "Escape"
@ -23363,11 +23376,6 @@ msgstr "Nom nou"
msgid "Next page"
msgstr "Pàgina següent"
#: ../include/wx/msgdlg.h:277 ../src/common/stockitem.cpp:177
#: ../src/motif/msgdlg.cpp:196
msgid "No"
msgstr "No"
#. TRANSLATORS: System cursor name
#: ../src/propgrid/advprops.cpp:1764
msgid "No Entry"
@ -26080,11 +26088,6 @@ msgstr "XPM: dades de la imatge truncades a la línia %d!"
msgid "Yellow"
msgstr "Groc"
#: ../include/wx/msgdlg.h:276 ../src/common/stockitem.cpp:206
#: ../src/motif/msgdlg.cpp:196
msgid "Yes"
msgstr "Sí"
#: ../src/osx/carbon/overlay.cpp:155
msgid "You cannot Clear an overlay that is not inited"
msgstr "No podeu netejar una superposició que no s'ha inicialitzat"
@ -27032,3 +27035,18 @@ msgstr "s'ha produït un error de zlib %d"
#: ../src/richtext/richtextbulletspage.cpp:288
msgid "~"
msgstr "~"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:69
msgid "Esc"
msgstr "Esc"
#: ../include/wx/msgdlg.h:277 ../src/common/stockitem.cpp:177
#: ../src/motif/msgdlg.cpp:196
msgid "No"
msgstr "No"
#: ../include/wx/msgdlg.h:276 ../src/common/stockitem.cpp:206
#: ../src/motif/msgdlg.cpp:196
msgid "Yes"
msgstr "Sí"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,5 @@
min_slic3r_version = 2.6.0-beta2
1.9.0-beta2 Added profiles for Original Prusa MK4 Input Shaper (Alpha).
min_slic3r_version = 2.6.0-beta0
1.9.0-beta1 Updated cooling settings for some ASA filaments to increase interlayer adhesion (XL/MK4).
1.9.0-beta0 Updated start g-code script for MK4/XL.

View File

@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 1.9.0-beta1
config_version = 1.9.0-beta2
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -23,6 +23,16 @@ bed_model = mk4_bed.stl
bed_texture = mk4.svg
default_materials = Generic PLA @PG; Generic ABS @MK4; Generic PETG @PG; Prusament PLA @PG; Prusament PETG @PG; Prusament ASA @MK4; Prusament PC Blend @MK4; Prusament PC Blend Carbon Fiber @MK4; Prusament PVB @PG; Prusament PA11 Carbon Fiber @PG
[printer_model:MK4IS]
name = Original Prusa MK4 Input Shaper (Alpha)
variants = 0.4
technology = FFF
family = MK4
bed_model = mk4_bed.stl
bed_texture = mk4is.svg
thumbnail = MK4IS_thumbnail.png
default_materials = Prusament PLA @MK4IS; Prusament PLA Blend @MK4IS; Prusament PETG @MK4IS; Generic PLA @MK4IS; Prusa PLA @MK4IS; Prusa PETG @MK4IS; Generic ASA @MK4; Generic PETG @MK4IS; Prusa PLA @MK4IS; Generic PLA Silk @MK4IS
[printer_model:MINI]
name = Original Prusa MINI && MINI+
variants = 0.4; 0.25; 0.6; 0.8
@ -452,6 +462,7 @@ thick_bridges = 1
bridge_flow_ratio = 0.95
bridge_speed = 25
infill_overlap = 15%
support_tree_branch_diameter_double_wall = 0
[print:*0.6nozzleMK3*]
inherits = *0.6nozzle*
@ -528,6 +539,7 @@ bottom_solid_min_thickness = 0.8
single_extruder_multi_material_priming = 0
thick_bridges = 1
overhangs = 0
support_tree_branch_diameter_double_wall = 0
[print:*0.8nozzleXL*]
inherits = *0.8nozzle*
@ -3564,6 +3576,135 @@ solid_infill_acceleration = 1500
infill_acceleration = 2000
compatible_printers_condition = printer_model=="MK4" and nozzle_diameter[0]==0.8
## MK4 - Input Shaper 0.4mm nozzle
[print:0.20mm Input Shaper @MK4IS 0.4]
bottom_solid_layers = 4
bottom_solid_min_thickness = 0
bridge_acceleration = 1500
bridge_flow_ratio = 1
bridge_speed = 50
brim_separation = 0.1
default_acceleration = 4000
dont_support_bridges = 0
elefant_foot_compensation = 0.2
enable_dynamic_overhang_speeds = 1
external_perimeter_acceleration = 4000
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 170
external_perimeters_first = 0
extra_perimeters = 0
extruder_clearance_height = 14
extruder_clearance_radius = 45
extrusion_width = 0.45
fill_angle = 45
fill_density = 15%
fill_pattern = grid
first_layer_acceleration = 500
first_layer_acceleration_over_raft = 0
first_layer_extrusion_width = 0.5
first_layer_height = 0.2
first_layer_speed = 40
first_layer_speed_over_raft = 30
gap_fill_enabled = 1
gap_fill_speed = 120
gcode_comments = 0
gcode_label_objects = 0
gcode_resolution = 0.008
infill_acceleration = 4000
infill_anchor = 2
infill_anchor_max = 12
infill_every_layers = 1
infill_extruder = 1
infill_extrusion_width = 0.45
infill_first = 0
infill_overlap = 15%
infill_speed = 200
interface_shells = 0
ironing_type = top
layer_height = 0.2
max_print_speed = 200
max_volumetric_extrusion_rate_slope_negative = 0
max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0
min_bead_width = 85%
min_feature_size = 25%
min_skirt_length = 4
mmu_segmented_region_max_width = 0
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
overhang_speed_0 = 15
overhang_speed_1 = 25
overhang_speed_2 = 30
overhang_speed_3 = 120
overhangs = 1
perimeter_acceleration = 4000
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
perimeter_generator = arachne
perimeter_speed = 170
perimeters = 2
raft_contact_distance = 0.15
raft_expansion = 1.5
raft_first_layer_density = 80%
raft_first_layer_expansion = 3.5
seam_position = aligned
slice_closing_radius = 0.049
small_perimeter_speed = 170
solid_infill_acceleration = 4000
solid_infill_below_area = 0
solid_infill_every_layers = 0
solid_infill_extruder = 1
solid_infill_extrusion_width = 0.45
solid_infill_speed = 200
skirts = 0
support_material = 0
support_material_angle = 0
support_material_auto = 1
support_material_bottom_contact_distance = 0
support_material_bottom_interface_layers = 0
support_material_buildplate_only = 0
support_material_closing_radius = 2
support_material_contact_distance = 0.2
support_material_enforce_layers = 0
support_material_extruder = 0
support_material_extrusion_width = 0.36
support_material_interface_contact_loops = 0
support_material_interface_extruder = 0
support_material_interface_layers = 0
support_material_interface_pattern = auto
support_material_interface_spacing = 0.2
support_material_interface_speed = 50%
support_material_pattern = rectilinear
support_material_spacing = 2
support_material_speed = 120
support_material_style = organic
support_material_synchronize_layers = 0
support_material_threshold = 40
support_material_with_sheath = 0
support_material_xy_spacing = 80%
support_tree_angle = 40
support_tree_angle_slow = 25
support_tree_branch_diameter = 2
support_tree_branch_diameter_angle = 5
support_tree_branch_diameter_double_wall = 3
support_tree_branch_distance = 1
support_tree_tip_diameter = 0.8
support_tree_top_rate = 30%
top_fill_pattern = monotoniclines
top_infill_extrusion_width = 0.42
top_solid_infill_acceleration = 1000
top_solid_infill_speed = 100
top_solid_layers = 5
top_solid_min_thickness = 0
travel_acceleration = 4000
travel_speed = 300
travel_speed_z = 12
thick_bridges = 0
thin_walls = 0
compatible_printers_condition = printer_model=="MK4IS" and nozzle_diameter[0]==0.4
# XXXXXXxxXXXXXXXXXXXXXX
# XXX--- filament ---XXX
# XXXXXXXXxxXXXXXXXXXXXX
@ -3618,7 +3759,7 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and no
compatible_printers_condition = ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) and printer_notes!~/.*PG.*/
[filament:*PLAPG*]
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.05{elsif nozzle_diameter[0]==0.25}0.14{elsif nozzle_diameter[0]==0.3}0.07{elsif nozzle_diameter[0]==0.35}0.06{elsif nozzle_diameter[0]==0.6}0.03{elsif nozzle_diameter[0]==0.5}0.035{elsif nozzle_diameter[0]==0.8}0.015{else}0{endif} ; Filament gcode\n\nM142 S36 ; set heatbreak target temp"
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.05{elsif nozzle_diameter[0]==0.25}0.14{elsif nozzle_diameter[0]==0.3}0.07{elsif nozzle_diameter[0]==0.35}0.06{elsif nozzle_diameter[0]==0.6}0.03{elsif nozzle_diameter[0]==0.5}0.035{elsif nozzle_diameter[0]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.04{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
compatible_printers_condition = printer_notes=~/.*PG.*/ and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
slowdown_below_layer_time = 8
filament_cooling_final_speed = 2
@ -3632,7 +3773,8 @@ filament_unloading_speed = 20
filament_loading_speed_start = 19
filament_minimal_purge_on_wipe_tower = 15
filament_unloading_speed_start = 100
## idle_temperature = 170
idle_temperature = 70
full_fan_speed_layer = 3
[filament:*PLA06PG*]
inherits = *PLAPG*
@ -3675,7 +3817,7 @@ filament_max_volumetric_speed = 15
[filament:*PETPG*]
compatible_printers_condition = printer_notes=~/.*PG.*/ and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.8
filament_max_volumetric_speed = 10
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.25}0.12{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\nM142 S40 ; set heatbreak target temp"
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.25}0.12{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.055{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
filament_cooling_final_speed = 1
filament_cooling_initial_speed = 2
filament_cooling_moves = 1
@ -3686,7 +3828,7 @@ filament_unload_time = 12
filament_unloading_speed = 20
filament_unloading_speed_start = 120
filament_loading_speed_start = 19
## idle_temperature = 170
idle_temperature = 70
filament_retract_length = 1
filament_retract_lift = 0.15
filament_retract_before_wipe = 0
@ -3823,7 +3965,7 @@ compatible_printers_condition = printer_model!="MINI" and printer_notes!~/.*PG.*
[filament:*ABSPG*]
compatible_printers_condition = printer_model=="XL" and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.8
filament_max_volumetric_speed = 12
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.04{elsif nozzle_diameter[0]==0.25}0.1{elsif nozzle_diameter[0]==0.3}0.06{elsif nozzle_diameter[0]==0.35}0.05{elsif nozzle_diameter[0]==0.5}0.03{elsif nozzle_diameter[0]==0.6}0.02{elsif nozzle_diameter[0]==0.8}0.01{else}0{endif} ; Filament gcode\n\nM142 S40 ; set heatbreak target temp"
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.04{elsif nozzle_diameter[0]==0.25}0.1{elsif nozzle_diameter[0]==0.3}0.06{elsif nozzle_diameter[0]==0.35}0.05{elsif nozzle_diameter[0]==0.5}0.03{elsif nozzle_diameter[0]==0.6}0.02{elsif nozzle_diameter[0]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.02{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
filament_cooling_final_speed = 50
filament_cooling_initial_speed = 10
filament_cooling_moves = 5
@ -3833,7 +3975,7 @@ filament_load_time = 15
filament_unload_time = 12
filament_loading_speed = 14
filament_unloading_speed = 20
## idle_temperature = 170
idle_temperature = 100
[filament:*ABS06PG*]
inherits = *ABSPG*
@ -3848,7 +3990,7 @@ slowdown_below_layer_time = 25
[filament:*ABSMK4*]
inherits = *ABSPG*
compatible_printers_condition = printer_model=="MK4" and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.8
compatible_printers_condition = printer_model=~/(MK4|MK4IS)/ and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.8
[filament:*ABS06MK4*]
inherits = *ABSMK4*
@ -3864,10 +4006,10 @@ slowdown_below_layer_time = 25
[filament:*PCPG*]
inherits = *ABSPG*
filament_max_volumetric_speed = 8
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\nM142 S45 ; set heatbreak target temp\n"
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.05{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp\n"
first_layer_bed_temperature = 100
bed_temperature = 105
## idle_temperature = 170
idle_temperature = 150
[filament:*PC06PG*]
inherits = *PCPG*
@ -3882,8 +4024,8 @@ compatible_printers_condition = printer_model=="XL" and nozzle_diameter[0]==0.8
[filament:*PCMK4*]
inherits = *ABSMK4*
filament_max_volumetric_speed = 8
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\nM142 S45 ; set heatbreak target temp\n"
## idle_temperature = 170
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.05{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp\n"
idle_temperature = 150
[filament:*PC06MK4*]
inherits = *PCMK4*
@ -3898,9 +4040,9 @@ compatible_printers_condition = printer_model=="MK4" and nozzle_diameter[0]==0.8
[filament:*PAPG*]
inherits = *ABSPG*
filament_max_volumetric_speed = 5
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\nM142 S45 ; set heatbreak target temp\n"
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.05{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp\n"
bed_temperature = 105
## idle_temperature = 170
idle_temperature = 150
[filament:*PA06PG*]
inherits = *PAPG*
@ -3915,8 +4057,8 @@ compatible_printers_condition = printer_model=="XL" and nozzle_diameter[0]==0.8
[filament:*PAMK4*]
inherits = *ABSMK4*
filament_max_volumetric_speed = 5
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\nM142 S45 ; set heatbreak target temp\n"
## idle_temperature = 170
start_filament_gcode = "M900 K{if nozzle_diameter[0]==0.4}0.07{elsif nozzle_diameter[0]==0.3}0.09{elsif nozzle_diameter[0]==0.35}0.08{elsif nozzle_diameter[0]==0.6}0.04{elsif nozzle_diameter[0]==0.5}0.05{elsif nozzle_diameter[0]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*PRINTER_MODEL_MK4IS.*/}\nM572 S{if nozzle_diameter[0]==0.4}0.05{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp\n"
idle_temperature = 70
[filament:*PA06MK4*]
inherits = *PAMK4*
@ -3959,7 +4101,7 @@ filament_retract_speed = 60
filament_deretract_speed = 20
filament_retract_before_travel = 2
compatible_printers_condition = printer_model=="XL" and nozzle_diameter[0]>=0.3 and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.8
## idle_temperature = 170
idle_temperature = 70
start_filament_gcode = "M900 K0 ; Filament gcode\n\nM142 S36 ; set heatbreak target temp"
[filament:*FLEX06PG*]
@ -3978,7 +4120,7 @@ filament_retract_speed = 60
filament_deretract_speed = 20
filament_retract_before_travel = 2
compatible_printers_condition = printer_model=="MK4" and nozzle_diameter[0]>=0.3 and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.8
## idle_temperature = 170
idle_temperature = 70
start_filament_gcode = "M900 K0 ; Filament gcode\n\nM142 S36 ; set heatbreak target temp"
[filament:*FLEX06MK4*]
@ -4950,6 +5092,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_model!="MK2S
[filament:Generic PETG @PG]
inherits = Generic PETG; *PETPG*
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model!="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Generic PETG @PG 0.6]
inherits = Generic PETG; *PET06PG*
@ -4960,6 +5103,19 @@ inherits = Generic PETG; *PET08PG*
first_layer_temperature = 240
temperature = 250
[filament:Generic PETG @MK4IS]
inherits = Generic PETG @PG
filament_max_volumetric_speed = 13
min_fan_speed = 35
max_fan_speed = 60
first_layer_temperature = 240
temperature = 245
filament_retract_length = 0.8
filament_wipe = 1
filament_retract_before_wipe = 20
filament_retract_lift = nil
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Extrudr DuraPro ASA]
inherits = Fillamentum ASA
filament_vendor = Extrudr
@ -5870,6 +6026,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes!~/.*PG
[filament:Generic PLA @PG]
inherits = Generic PLA; *PLAPG*
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model!="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Generic PLA @PG 0.6]
inherits = Generic PLA; *PLA06PG*
@ -5880,6 +6037,21 @@ inherits = Generic PLA; *PLA08PG*
first_layer_temperature = 220
temperature = 220
[filament:Generic PLA @MK4IS]
inherits = Generic PLA @PG
first_layer_temperature = 230
temperature = 220
slowdown_below_layer_time = 5
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Generic PLA Silk @MK4IS]
inherits = Generic PLA @PG
first_layer_temperature = 230
temperature = 220
slowdown_below_layer_time = 8
filament_max_volumetric_speed = 7
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:3D-Fuel Standard PLA]
inherits = *PLA*
filament_vendor = 3D-Fuel
@ -8218,6 +8390,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=
[filament:Prusa PETG @PG]
inherits = Prusa PETG; *PETPG*
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model!="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusa PETG @PG 0.6]
inherits = Prusa PETG; *PET06PG*
@ -8225,6 +8398,19 @@ inherits = Prusa PETG; *PET06PG*
[filament:Prusa PETG @PG 0.8]
inherits = Prusa PETG; *PET08PG*
[filament:Prusa PETG @MK4IS]
inherits = Generic PETG @PG
filament_max_volumetric_speed = 15
min_fan_speed = 35
max_fan_speed = 60
first_layer_temperature = 240
temperature = 250
filament_retract_length = 0.8
filament_wipe = 1
filament_retract_before_wipe = 20
filament_retract_lift = nil
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Verbatim PETG]
inherits = *PET*
filament_vendor = Verbatim
@ -8255,6 +8441,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=
[filament:Prusament PETG @PG]
inherits = Prusament PETG; *PETPG*
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model!="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusament PETG @PG 0.6]
inherits = Prusament PETG; *PET06PG*
@ -8264,6 +8451,17 @@ inherits = Prusament PETG; *PET08PG*
first_layer_temperature = 250
temperature = 260
[filament:Prusament PETG @MK4IS]
inherits = Prusament PETG @PG
filament_max_volumetric_speed = 15
min_fan_speed = 35
max_fan_speed = 60
filament_retract_length = 0.8
filament_wipe = 1
filament_retract_before_wipe = 20
filament_retract_lift = nil
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusament PETG Carbon Fiber]
inherits = Prusament PETG
filament_vendor = Prusa Polymers
@ -8484,6 +8682,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes!~/.*PG
[filament:Prusa PLA @PG]
inherits = Prusa PLA; *PLAPG*
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model!="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusa PLA @PG 0.6]
inherits = Prusa PLA; *PLA06PG*
@ -8492,6 +8691,14 @@ filament_max_volumetric_speed = 15.5
[filament:Prusa PLA @PG 0.8]
inherits = Prusa PLA; *PLA08PG*
[filament:Prusa PLA @MK4IS]
inherits = Prusa PLA @PG
first_layer_temperature = 230
temperature = 220
slowdown_below_layer_time = 5
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Eolas Prints PLA]
inherits = *PLA*
filament_vendor = Eolas Prints
@ -9595,6 +9802,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes!~/.*PG
[filament:Prusament PLA @PG]
inherits = Prusament PLA; *PLAPG*
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model!="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusament PLA @PG 0.6]
inherits = Prusament PLA; *PLA06PG*
@ -9605,6 +9813,21 @@ inherits = Prusament PLA; *PLA08PG*
first_layer_temperature = 225
temperature = 225
[filament:Prusament PLA @MK4IS]
inherits = Prusament PLA @PG
first_layer_temperature = 230
temperature = 225
slowdown_below_layer_time = 5
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusament PLA Blend @MK4IS]
inherits = Prusament PLA @PG
first_layer_temperature = 230
temperature = 220
filament_max_volumetric_speed = 7
slowdown_below_layer_time = 7
compatible_printers_condition = printer_notes=~/.*PG.*/ and printer_model=="MK4IS" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6
[filament:Prusament PVB]
inherits = *PLA*
filament_vendor = Prusa Polymers
@ -15970,6 +16193,41 @@ min_layer_height = 0.2
default_print_profile = 0.40mm QUALITY @MK4 0.8
default_filament_profile = "Prusament PLA @PG 0.8"
[printer:Original Prusa MK4 Input Shaper (Alpha)]
inherits = *commonMK4*
printer_model = MK4IS
printer_variant = 0.4
max_layer_height = 0.30
machine_limits_usage = emit_to_gcode
machine_max_acceleration_e = 2500,5000
machine_max_acceleration_extruding = 4000,2000
machine_max_acceleration_retracting = 1200,2000
machine_max_acceleration_travel = 4000,1250
machine_max_acceleration_x = 4000,2000
machine_max_acceleration_y = 4000,2000
machine_max_acceleration_z = 200,2000
machine_max_feedrate_e = 100,120
machine_max_feedrate_x = 300,100
machine_max_feedrate_y = 300,100
machine_max_feedrate_z = 40,12
machine_max_jerk_e = 10,1.5
machine_max_jerk_x = 8,8
machine_max_jerk_y = 8,8
machine_max_jerk_z = 2,0.4
machine_min_extruding_rate = 0,0
machine_min_travel_rate = 0,0
max_print_height = 220
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_MODEL_MK4IS\nPG
retract_length = 0.7
wipe = 0
retract_speed = 35
deretract_speed = 0
start_gcode = M17 ; enable steppers\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM862.3 P "MK4" ; printer model check\nM862.5 P2 ; g-code level check\nM862.6 P"Input shaper" ; firmware feature check\n\nM555 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)} Y{(max(0, first_layer_print_min[1]) - 4)} W{((min(print_bed_max[0], max(first_layer_print_min[0] + 32, first_layer_print_max[0])))) - ((min(print_bed_max[0], first_layer_print_min[0] + 32) - 32))} H{((first_layer_print_max[1])) - ((max(0, first_layer_print_min[1]) - 4))}\n\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\n\nM140 S[first_layer_bed_temperature] ; set bed temp\n{if filament_type[initial_tool]=="PC" or filament_type[initial_tool]=="PA"}\nM104 S{first_layer_temperature[initial_tool]-25} ; set extruder temp for bed leveling\nM109 R{first_layer_temperature[initial_tool]-25} ; wait for temp\n{elsif filament_type[initial_tool]=="FLEX"}\nM104 S210 ; set extruder temp for bed leveling\nM109 R210 ; wait for temp\n{else}\nM104 S170 ; set extruder temp for bed leveling\nM109 R170 ; wait for temp\n{endif}\n\nM84 E ; turn off E motor\n\nG28 ; home all without mesh bed level\n\n; probe to clean the nozzle\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)+32} Y{((first_layer_print_min[1]) - 4)} Z{5} F4800\n\nM302 S160 ; lower cold extrusion limit to 160C\n\n{if filament_type[initial_tool]=="FLEX"}\nG1 E-4 F2400 ; retraction\n{else}\nG1 E-2 F2400 ; retraction\n{endif}\n\nM84 E ; turn off E motor\n\nG29 P9 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)} Y{(max(0, first_layer_print_min[1]) - 4)} W{32} H{4}\n\n{if first_layer_bed_temperature[initial_tool]<=60}M106 S100{endif}\n\nG0 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)} Y{(max(0, first_layer_print_min[1]) - 4)} Z{40} F10000\n\nM190 S[first_layer_bed_temperature] ; wait for bed temp\n\nM107\n\n;\n; MBL\n;\nM84 E ; turn off E motor\nG29 ; mesh bed leveling\nM104 S[first_layer_temperature] ; set extruder temp\nG0 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)} Y{(max(0, first_layer_print_min[1]) - 4) + 4 - 4.5} Z{30} F4800\n\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 Z0.2 F720\nG92 E0\n\nM569 S0 E ; set spreadcycle mode for extruder\n\n;\n; Extrude purge line\n;\n{if filament_type[initial_tool]=="FLEX"}\nG1 E4 F2400 ; deretraction\n{else}\nG1 E2 F2400 ; deretraction\n{endif}\n\n; move right\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32) + 32} E{32 * 0.15} F1000\n; move down\nG1 Y{(max(0, first_layer_print_min[1]) - 4) + 4 - 4.5 - 1.5} E{1.5 * 0.15} F1000\n; move left\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)} E{32 * 0.30} F800\n\nG92 E0\nM221 S100 ; set flow to 100%\n\nM593 X T2 F50.7\nM593 Y T2 F40.6
end_gcode = {if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X241 Y170 F3600 ; park\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+23, max_print_height)} F300 ; Move print head up{endif}\nG4 ; wait\nM572 S0 ; reset PA\nM593 X T2 F0 ; disable IS\nM593 Y T2 F0 ; disable IS\nM84 X Y E ; disable motors\n; max_layer_z = [max_layer_z]
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\nM593 Y T2 F{interpolate_table(extruded_weight_total, (0,40), (300,30), (800,20), (10000,20)) }\nM201 X{interpolate_table(extruded_weight_total, (0,4000), (1400,2500), (10000,2500))} Y{interpolate_table(extruded_weight_total, (0,4000), (1400,2500), (10000,2500))}\nM74 W[extruded_weight_total]
default_print_profile = 0.20mm Input Shaper @MK4IS 0.4
default_filament_profile = "Prusament PLA @MK4IS"
[printer:Original Prusa SL1]
printer_technology = SLA
printer_model = SL1

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="svg3128" xmlns="http://www.w3.org/2000/svg" width="710.1" height="596.7" viewBox="0 0 710.1 596.7">
<line id="line2794" x1=".7" y1=".7" x2=".7" y2="596" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2796" x1="142.4" y1=".7" x2="142.4" y2="595.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2798" x1="284.2" y1=".7" x2="284.2" y2="595.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2800" x1="709.4" y1="596" x2="709.4" y2=".7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2802" x1="1.2" y1="581.8" x2="709.4" y2="581.8" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2804" x1=".7" y1="596" x2="709.4" y2="596" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2806" x1="1.2" y1="440.1" x2="709.4" y2="440.1" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2808" x1="1.2" y1="298.4" x2="709.4" y2="298.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2810" x1="1.2" y1="156.6" x2="709.4" y2="156.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2812" x1="1.2" y1="14.9" x2="709.4" y2="14.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2814" x1="709.4" y1=".7" x2=".7" y2=".7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2816" x1="425.9" y1=".7" x2="425.9" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2818" x1="425.9" y1="522.5" x2="425.9" y2="595.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2820" x1="567.6" y1=".7" x2="567.6" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2822" x1="567.6" y1="522.5" x2="567.6" y2="527.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2824" x1="567.6" y1="548.6" x2="567.6" y2="595.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4px;"/>
<line id="line2826" x1="85.8" y1=".7" x2="85.8" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2828" x1="114.1" y1=".7" x2="114.1" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2830" x1="170.8" y1=".7" x2="170.8" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2832" x1="199.1" y1=".7" x2="199.1" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2834" x1="227.5" y1=".7" x2="227.5" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2836" x1="255.8" y1=".7" x2="255.8" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2838" x1="312.5" y1=".7" x2="312.5" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2840" x1="340.9" y1=".7" x2="340.9" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2842" x1="681" y1=".7" x2="681" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2844" x1="29.1" y1=".7" x2="29.1" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2846" x1="57.4" y1=".7" x2="57.4" y2="595.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2848" x1="1.5" y1="468.4" x2="709.4" y2="468.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2850" x1="1.5" y1="496.8" x2="709.4" y2="496.8" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2852" x1="1.5" y1="525.1" x2="709.4" y2="525.1" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2854" x1="1.5" y1="553.5" x2="709.4" y2="553.5" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2856" x1="1.5" y1="411.7" x2="709.4" y2="411.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2858" x1="1.5" y1="383.4" x2="709.4" y2="383.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2860" x1="1.5" y1="355" x2="709.4" y2="355" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2862" x1="1.5" y1="326.7" x2="709.4" y2="326.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2864" x1="1.5" y1="270" x2="709.4" y2="270" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2866" x1="1.5" y1="241.6" x2="709.4" y2="241.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2868" x1="1.5" y1="213.3" x2="709.4" y2="213.3" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2870" x1="1.5" y1="185" x2="709.4" y2="185" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2872" x1="1.5" y1="128.3" x2="709.4" y2="128.3" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2874" x1="1.5" y1="99.9" x2="709.4" y2="99.9" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2876" x1="1.5" y1="71.6" x2="709.4" y2="71.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2878" x1="1.5" y1="43.2" x2="709.4" y2="43.2" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2880" x1="369.2" y1=".7" x2="369.2" y2="522.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2882" x1="369.2" y1="522.6" x2="369.2" y2="595.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2884" x1="397.6" y1=".7" x2="397.6" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2886" x1="397.5" y1="522.6" x2="397.5" y2="595.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2888" x1="454.2" y1=".7" x2="454.2" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2890" x1="454.3" y1="522.6" x2="454.3" y2="595.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2892" x1="482.6" y1=".7" x2="482.6" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2894" x1="482.6" y1="522.6" x2="482.6" y2="595.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2896" x1="510.9" y1=".7" x2="510.9" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2898" x1="510.9" y1="522.6" x2="510.9" y2="595.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2900" x1="539.3" y1=".7" x2="539.3" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2902" x1="539.3" y1="522.6" x2="539.3" y2="595.6" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2904" x1="596" y1=".7" x2="596" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2906" x1="624.3" y1=".7" x2="624.3" y2="499.4" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2908" x1="652.7" y1=".7" x2="652.7" y2="522.5" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2910" x1="652.7" y1="522.5" x2="652.7" y2="527.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2912" x1="652.6" y1="548.3" x2="652.6" y2="596" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2914" x1="624.3" y1="522.5" x2="624.3" y2="527.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2916" x1="624.3" y1="548.3" x2="624.3" y2="596" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2918" x1="596" y1="522.5" x2="596" y2="527.7" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<line id="line2920" x1="596" y1="548.3" x2="596" y2="596" style="fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; stroke-width: .4px;"/>
<path id="path3098" d="m548.6,532h2.1v4.8h0c.1-.2.3-.4.5-.6.2-.2.4-.3.7-.5.2-.1.5-.2.8-.3.3,0,.5-.1.8,0,.7,0,1.3.1,1.9.4.5.2,1,.6,1.4,1.1.4.5.6,1,.8,1.6.2.6.3,1.3.3,1.9,0,.6,0,1.2-.2,1.8-.2.6-.4,1.1-.7,1.6-.7,1-1.8,1.5-3,1.5-.3,0-.6,0-1,0-.3,0-.6-.1-.9-.2-.3-.1-.5-.3-.8-.5-.2-.2-.4-.5-.6-.8h0v1.3h-2v-12.9Zm7.2,8.2c0-.4,0-.8-.2-1.2-.1-.4-.3-.7-.5-1-.2-.3-.5-.6-.8-.7-.3-.2-.7-.3-1.1-.3-.8,0-1.5.3-2,.9-.5.7-.7,1.6-.7,2.4,0,.4,0,.9.2,1.3.1.4.3.7.5,1,.2.3.5.5.8.7.3.2.7.3,1.1.2.4,0,.8,0,1.2-.3.3-.2.6-.4.8-.7.2-.3.4-.7.5-1,0-.4.1-.8.1-1.2Z" style="fill: #fff;"/>
<path id="path3100" d="m558.5,535.6h2.2l2.4,7h0l2.4-7h2.1l-3.6,9.8c-.2.4-.3.8-.5,1.2-.2.4-.4.7-.6,1-.2.3-.5.5-.9.7-.4.2-.9.3-1.3.3-.5,0-1,0-1.4-.1v-1.7h.5c.2,0,.3,0,.5,0,.2,0,.4,0,.6,0,.1,0,.3-.1.4-.3.1-.1.2-.3.3-.4,0-.2.1-.4.2-.5l.2-.7-3.5-9.2Z" style="fill: #fff;"/>
<path id="path3102" d="m581.1,540.8c0,.5,0,1.1-.1,1.6,0,.5-.3,1-.6,1.4-.3.4-.8.8-1.3,1-.7.3-1.5.4-2.2.4-.6,0-1.2,0-1.7-.3-.5-.2-.9-.5-1.2-.9-.3-.4-.6-.8-.7-1.3-.1-.5-.2-1.1-.2-1.6v-.7h2.2v.7c0,.6,0,1.2.4,1.7.3.4.9.7,1.4.6.3,0,.6,0,.9-.2.2-.1.4-.3.6-.5.1-.2.2-.5.3-.8,0-.4,0-.7,0-1.1v-8.8h2.2v8.7Z" style="fill: #fff;"/>
<path id="path3104" d="m587.8,545.1c-.7,0-1.4-.1-2-.4-.6-.2-1.1-.6-1.5-1-.4-.4-.7-1-.9-1.5-.2-.6-.3-1.3-.3-2,0-.7,0-1.4.3-2,.2-.6.5-1.1.9-1.5.4-.4.9-.8,1.5-1,1.3-.5,2.7-.5,4,0,.6.2,1.1.6,1.5,1,.4.4.7,1,.9,1.5.2.6.3,1.3.3,2,0,.7,0,1.4-.3,2-.2.6-.5,1.1-.9,1.5-.4.4-.9.8-1.5,1-.6.3-1.3.4-2,.4Zm0-1.6c.4,0,.8,0,1.2-.3.3-.2.6-.4.8-.8.2-.3.4-.7.5-1.1.1-.4.2-.8.2-1.2,0-.4,0-.8-.2-1.2,0-.4-.3-.7-.5-1-.2-.3-.5-.6-.8-.8-.7-.4-1.6-.4-2.4,0-.3.2-.6.4-.8.8-.2.3-.4.6-.5,1,0,.4-.1.8-.2,1.2,0,.4,0,.8.2,1.2,0,.4.3.7.5,1.1.2.3.5.6.8.8.4.2.8.3,1.2.3h0Z" style="fill: #fff;"/>
<path id="path3106" d="m595.7,541.9c0,.5.3,1,.7,1.3.4.2.9.4,1.4.4.2,0,.4,0,.7,0,.2,0,.5,0,.7-.2.2,0,.4-.2.5-.4.3-.4.2-.9,0-1.3-.2-.2-.4-.3-.7-.4-.3-.1-.7-.2-1-.3l-1.1-.2c-.4,0-.7-.2-1.1-.3-.4-.1-.7-.3-1-.5-.3-.2-.5-.5-.6-.9-.2-.4-.3-.8-.2-1.2,0-.5.1-.9.4-1.3.2-.3.6-.6.9-.8.4-.2.8-.4,1.3-.4.4,0,.9-.1,1.3-.1.5,0,.9,0,1.4.2.4,0,.8.3,1.2.5.4.2.7.5.9.9.2.4.4.9.4,1.3h-2.1c0-.4-.3-.8-.7-1-.4-.2-.8-.3-1.2-.2-.2,0-.3,0-.5,0-.2,0-.4,0-.6.1-.2,0-.3.2-.4.3-.1.1-.2.3-.2.5,0,.2,0,.5.3.6.2.2.4.3.7.4.3.1.7.2,1,.3l1.1.2c.4,0,.7.2,1.1.3.4.1.7.3,1,.5.3.2.5.5.7.8.2.4.3.8.3,1.2,0,.5-.1,1-.4,1.4-.3.4-.6.7-1,.9-.4.2-.9.4-1.3.5-.5.1-1,.2-1.5.2-.5,0-1.1,0-1.6-.2-.5-.1-.9-.3-1.3-.6-.4-.3-.7-.6-.9-1-.2-.4-.3-.9-.3-1.4h2Z" style="fill: #fff;"/>
<path id="path3108" d="m605.1,540.8c0,.3,0,.7.2,1,0,.3.3.6.5.9.2.3.5.5.8.6.4.2.7.2,1.1.2.5,0,1.1,0,1.5-.3.4-.3.7-.7.8-1.2h1.9c0,.5-.3.9-.6,1.3-.3.4-.6.7-1,1-.4.3-.8.5-1.2.6-.5.1-1,.2-1.5.2-.7,0-1.3-.1-1.9-.4-.5-.2-1-.6-1.4-1-.4-.4-.7-1-.9-1.5-.2-.6-.3-1.3-.3-2,0-.6.1-1.3.3-1.9.2-.6.5-1.1.9-1.6.8-1,2-1.5,3.3-1.5.7,0,1.4.1,2,.5.6.3,1.1.7,1.5,1.2.4.5.7,1.1.8,1.7.2.7.2,1.3.1,2h-6.9Zm4.8-1.3c0-.3,0-.6-.2-.9-.1-.3-.3-.6-.5-.8-.2-.2-.4-.4-.7-.5-.3-.1-.6-.2-.9-.2-.3,0-.7,0-1,.2-.3.1-.5.3-.8.5-.2.2-.4.5-.5.8-.1.3-.2.7-.2,1h4.8Z" style="fill: #fff;"/>
<path id="path3110" d="m612.6,535.6h1.5v-.8c0-.5,0-1,.2-1.4.1-.3.3-.6.6-.8.2-.2.5-.3.8-.4.3,0,.7-.1,1,0,.5,0,.9,0,1.4,0v1.6c-.1,0-.3,0-.4,0h-.5c-.3,0-.5,0-.7.2-.2.2-.3.5-.3.8v1h1.7v1.5h-1.7v7.8h-2v-7.8h-1.5v-1.5Z" style="fill: #fff;"/>
<path id="path3112" d="m624.5,532h5.7c.8,0,1.5.1,2.2.4.5.2,1,.6,1.3,1,.3.4.5.8.6,1.3.1.4.2.9.2,1.3,0,.4,0,.9-.2,1.3-.1.5-.3.9-.6,1.3-.4.4-.8.8-1.3,1-.7.3-1.5.4-2.2.4h-3.4v4.9h-2.2v-12.9Zm2.2,6.1h3.3c.3,0,.5,0,.8-.1.3,0,.5-.2.7-.3.2-.2.4-.4.5-.7.1-.3.2-.7.2-1,0-.3,0-.7-.2-1-.2-.5-.7-.9-1.2-1-.3,0-.6,0-.8,0h-3.3v4.2Z" style="fill: #fff;"/>
<path id="path3114" d="m636.2,535.6h1.9v1.8h0c0-.3.2-.5.4-.7.2-.2.4-.5.6-.7.2-.2.5-.4.8-.5.3-.1.6-.2.9-.2h.8v2h-.4c-.1,0-.3,0-.5,0-.7,0-1.3.3-1.8.8-.2.3-.4.6-.5,1-.1.4-.2.9-.2,1.4v4.4h-2v-9.3Z" style="fill: #fff;"/>
<path id="path3116" d="m650.7,544.9h-2v-1.3h0c-.3.5-.7.9-1.1,1.1-.5.3-1,.4-1.5.4-1,0-1.9-.2-2.7-.9-.6-.8-.9-1.8-.8-2.7v-5.9h2v5.7c0,.6.1,1.2.5,1.7.3.3.8.5,1.3.5.4,0,.7,0,1.1-.2.3-.1.5-.3.7-.5.2-.2.3-.5.4-.8,0-.3.1-.7.1-1v-5.4h2v9.3Z" style="fill: #fff;"/>
<path id="path3118" d="m654.4,541.9c0,.5.3,1,.7,1.2.4.2.9.4,1.4.4.2,0,.4,0,.7,0,.2,0,.5,0,.7-.2.2,0,.4-.2.5-.4.1-.2.2-.4.2-.6,0-.2-.1-.5-.3-.7-.2-.2-.4-.3-.7-.4-.3-.1-.7-.2-1-.3l-1.1-.2c-.4,0-.7-.2-1.1-.3-.4-.1-.7-.3-1-.5-.3-.2-.5-.5-.7-.8-.2-.4-.3-.8-.3-1.2,0-.5.1-.9.4-1.3.2-.3.6-.6.9-.8.4-.2.8-.4,1.3-.4.4,0,.9-.1,1.3-.1.5,0,.9,0,1.4.2.4.1.8.3,1.2.5.4.2.7.5.9.9.2.4.4.9.4,1.3h-2.1c0-.4-.3-.8-.7-1-.4-.2-.8-.3-1.2-.2-.2,0-.3,0-.5,0-.2,0-.4,0-.5.1-.2,0-.3.2-.4.3-.1.1-.2.3-.2.5,0,.2,0,.5.3.6.2.2.4.3.7.4.3.1.7.2,1,.3l1.1.2c.4,0,.7.2,1.1.3.4.1.7.3,1,.5.3.2.5.5.7.8.2.4.3.8.3,1.2,0,.5-.1,1-.4,1.4-.3.4-.6.7-1,.9-.4.2-.9.4-1.3.5-.5.1-1,.2-1.5.2-.6,0-1.1,0-1.6-.2-.5-.1-.9-.3-1.3-.6-.4-.3-.7-.6-.9-1-.2-.4-.3-.9-.3-1.4h2.1Z" style="fill: #fff;"/>
<path id="path3120" d="m670,542.8c0,.2,0,.4,0,.5,0,.1.2.2.4.2h.5v1.4h-.3c0,0-.3.2-.3.2h-.4c-.1,0-.2,0-.3,0-.3,0-.7,0-1-.2-.3-.2-.5-.5-.5-.9-.4.4-.9.7-1.5.9-.6.2-1.1.3-1.7.3-.4,0-.8,0-1.2-.2-.4-.1-.7-.3-1-.5-.3-.2-.5-.5-.7-.8-.2-.4-.3-.8-.3-1.2,0-.5,0-1,.3-1.4.2-.3.5-.6.8-.8.4-.2.7-.4,1.2-.4.4,0,.9-.2,1.3-.2.3,0,.7-.1,1.1-.2.3,0,.6,0,.9-.2.2,0,.4-.2.6-.3.2-.2.2-.4.2-.7,0-.2,0-.5-.2-.7-.1-.2-.3-.3-.5-.4-.2,0-.4-.2-.6-.2-.2,0-.4,0-.7,0-.5,0-1,.1-1.4.4-.4.3-.6.7-.6,1.1h-2c0-.5.2-1,.4-1.5.3-.4.6-.7,1-1,.4-.2.9-.4,1.3-.5.5-.1,1-.2,1.5-.2.5,0,.9,0,1.3.2.4,0,.8.2,1.2.5.3.2.6.5.8.8.2.4.3.8.3,1.2v4.8Zm-2.1-2.6c-.3.2-.7.3-1.2.4-.5,0-.9.1-1.4.2-.2,0-.4,0-.6.2-.2,0-.4.1-.5.3-.2.1-.3.3-.4.5,0,.2-.1.4-.1.7,0,.2,0,.4.2.6.1.2.3.3.5.4.2,0,.4.2.6.2.2,0,.4,0,.6,0,.2,0,.5,0,.7,0,.3,0,.5-.2.8-.3.2-.1.4-.3.6-.5.2-.2.2-.5.2-.8v-1.5Z" style="fill: #fff;"/>
<g>
<path d="m385.6,511.3c0-1.3.2-2.6.6-3.7s1-2.1,1.7-3c.7-.9,1.7-1.5,2.8-2,1.1-.5,2.3-.7,3.7-.7s2.6.2,3.7.7c1.1.5,2,1.2,2.8,2s1.3,1.8,1.7,3,.6,2.4.6,3.7-.2,2.5-.6,3.6-1,2.1-1.7,2.9c-.7.8-1.7,1.5-2.8,2-1.1.5-2.3.7-3.7.7s-2.6-.2-3.7-.7c-1.1-.5-2-1.1-2.8-2-.7-.8-1.3-1.8-1.7-2.9-.4-1.1-.6-2.3-.6-3.6Zm3.9,0c0,.7.1,1.5.3,2.2.2.7.4,1.3.9,1.9.4.6.9,1,1.5,1.4s1.4.5,2.2.5,1.6-.2,2.2-.5,1.1-.8,1.5-1.4c.4-.6.6-1.2.9-1.9.2-.7.3-1.4.3-2.2s-.1-1.5-.3-2.3c-.2-.7-.4-1.4-.9-1.9-.4-.6-.9-1-1.5-1.4-.6-.3-1.4-.5-2.2-.5s-1.6.2-2.2.5c-.6.3-1.1.8-1.5,1.4s-.6,1.2-.9,1.9c-.2.7-.3,1.5-.3,2.3Z" style="fill: #959998;"/>
<path d="m404.8,502.3h9.6c.8,0,1.5.1,2.1.4.6.3,1.2.6,1.6,1.1.4.4.8,1,1.1,1.6.2.6.4,1.2.4,1.9,0,1.1-.2,1.9-.6,2.7-.4.7-1.2,1.4-2.1,1.7h0c.5.2.9.4,1.2.6s.6.6.8,1c.2.4.3.8.4,1.2s.2.9.2,1.3,0,.6,0,1,0,.8.1,1.2c0,.4.1.8.2,1.1.1.4.2.7.4.9h-3.9c-.1-.3-.2-.6-.3-.9,0-.3-.1-.7-.1-1.1s0-.7-.1-1.2c0-.4,0-.7-.1-1.1-.1-.9-.4-1.6-.9-2s-1.1-.6-2.1-.6h-3.9v6.9h-3.9v-17.7Zm3.9,8.1h4.3c.9,0,1.6-.2,2-.6.4-.4.7-1.1.7-1.9s-.2-1.5-.7-1.9-1.1-.6-2-.6h-4.3v5Z" style="fill: #959998;"/>
<path d="m421.8,502.3h3.9v17.8h-3.9v-17.8Z" style="fill: #959998;"/>
<path d="m441,518.1c-.7.9-1.5,1.5-2.3,1.9s-1.7.5-2.6.5c-1.4,0-2.6-.2-3.7-.7-1.1-.5-2-1.1-2.8-2-.7-.8-1.3-1.8-1.7-2.9-.4-1.1-.6-2.3-.6-3.6s.2-2.6.6-3.7,1-2.1,1.7-3c.7-.9,1.7-1.5,2.8-2,1.1-.5,2.3-.7,3.7-.7s1.8.1,2.7.4c.9.3,1.6.7,2.3,1.2s1.3,1.2,1.7,2,.7,1.7.9,2.7h-3.7c-.2-1-.7-1.7-1.4-2.2s-1.5-.7-2.4-.7-1.6.2-2.2.5-1.1.8-1.5,1.4c-.4.6-.6,1.2-.9,1.9-.2.7-.3,1.5-.3,2.3s.1,1.5.3,2.2c.2.7.4,1.3.9,1.9.4.6.9,1,1.5,1.4.6.3,1.4.5,2.2.5,1.3,0,2.3-.3,3-1s1.1-1.6,1.3-2.9h-3.9v-2.9h7.5v9.6h-2.5l-.4-2Z" style="fill: #959998;"/>
<path d="m446.3,502.3h3.9v17.8h-3.9v-17.8Z" style="fill: #959998;"/>
<path d="m452.7,502.3h3.9l7.4,11.9h0v-11.9h3.7v17.8h-3.9l-7.4-11.9h0v11.9h-3.7v-17.8Z" style="fill: #959998;"/>
<path d="m475.1,502.3h4l6.6,17.8h-4l-1.4-3.9h-6.6l-1.4,3.9h-3.9l6.7-17.8Zm-.4,10.9h4.6l-2.2-6.5h0l-2.3,6.5Z" style="fill: #959998;"/>
<path d="m486.5,502.3h3.9v14.5h8.6v3.3h-12.6v-17.8h0Z" style="fill: #959998;"/>
</g>
<g>
<path d="m506.9,502.3h8c1.1,0,2.1.2,2.8.5s1.4.7,1.9,1.3c.5.5.9,1.2,1.1,1.8.2.7.3,1.4.3,2.1s-.1,1.4-.3,2.1-.6,1.3-1.1,1.8c-.5.5-1.1,1-1.9,1.3s-1.7.5-2.8.5h-4.1v6.4h-3.9v-17.8Zm3.9,8.4h3c.4,0,.9,0,1.3-.1.4,0,.8-.2,1.1-.4.3-.2.6-.5.7-.8.2-.3.3-.8.3-1.4s-.1-1-.3-1.4c-.2-.3-.4-.6-.7-.8-.3-.2-.7-.3-1.1-.4s-.9-.1-1.3-.1h-3v5.3Z" style="fill: #fff;"/>
<path d="m522.2,502.3h9.6c.8,0,1.5.1,2.1.4.6.3,1.2.6,1.6,1.1.4.4.8,1,1.1,1.6.2.6.4,1.2.4,1.9,0,1.1-.2,1.9-.6,2.7-.4.7-1.2,1.4-2.1,1.7h0c.5.2.9.4,1.2.6s.6.6.8,1c.2.4.3.8.4,1.2s.2.9.2,1.3,0,.6,0,1,0,.8.1,1.2c0,.4.1.8.2,1.1.1.4.2.7.4.9h-3.9c-.1-.3-.2-.6-.3-.9,0-.3-.1-.7-.1-1.1s0-.7-.1-1.2c0-.4,0-.7-.1-1.1-.1-.9-.4-1.6-.9-2s-1.1-.6-2.1-.6h-3.9v6.9h-3.9v-17.7Zm3.9,8.1h4.3c.9,0,1.5-.2,2-.6.4-.4.7-1.1.7-1.9s-.2-1.5-.7-1.9-1.1-.6-2-.6h-4.3v5Z" style="fill: #fff;"/>
<path d="m554.1,513.3c0,2.4-.7,4.2-2,5.4-1.4,1.2-3.2,1.8-5.6,1.8s-4.3-.6-5.6-1.8c-1.3-1.2-2-3-2-5.4v-11.1h3.9v11.1c0,.5,0,1,.1,1.4,0,.5.3.9.5,1.3.3.4.6.6,1.1.9.5.2,1.1.3,1.9.3,1.4,0,2.3-.3,2.9-.9s.8-1.6.8-2.9v-11.1h3.9v11h0Z" style="fill: #fff;"/>
<path d="m559.1,514.2c0,.6.1,1.1.3,1.5.2.4.5.7.9,1s.8.4,1.3.6,1,.2,1.5.2.7,0,1.1-.1.8-.2,1.1-.3.6-.4.9-.7c.2-.3.3-.6.3-1.1s-.2-.9-.5-1.2-.7-.5-1.2-.7c-.5-.2-1.1-.4-1.7-.5s-1.3-.3-1.9-.5c-.7-.2-1.3-.4-1.9-.6-.6-.2-1.2-.5-1.7-.9s-.9-.9-1.2-1.4c-.3-.6-.5-1.3-.5-2.1s.2-1.7.6-2.4.9-1.2,1.5-1.7,1.4-.8,2.1-1,1.6-.3,2.4-.3,1.8.1,2.7.3,1.6.5,2.3,1,1.2,1.1,1.6,1.8.6,1.6.6,2.6h-3.8c0-.5-.1-1-.3-1.3s-.4-.6-.7-.8-.7-.3-1.1-.4-.9-.1-1.3-.1-.6,0-1,.1c-.3,0-.6.2-.9.3-.3.2-.5.4-.6.6s-.2.6-.2.9,0,.6.2.9c.1.2.4.4.8.6s.9.4,1.6.5c.7.2,1.6.4,2.7.7.2,0,.5.1.9.2.3.1.7.2,1.1.4.4.2.8.4,1.2.6.4.2.7.5,1.1.9.3.4.6.8.8,1.3.2.5.3,1.1.3,1.8s-.2,1.6-.5,2.3c-.3.7-.8,1.3-1.4,1.8s-1.4.9-2.3,1.2c-.9.3-2,.4-3.2.4s-1.9-.1-2.9-.4-1.7-.6-2.4-1.2-1.3-1.2-1.7-2c-.4-.8-.6-1.7-.6-2.8h3.8Z" style="fill: #fff;"/>
<path d="m576.5,502.3h4l6.6,17.8h-4l-1.4-3.9h-6.6l-1.4,3.9h-3.9l6.7-17.8Zm-.4,10.9h4.6l-2.2-6.5h0l-2.3,6.5Z" style="fill: #fff;"/>
</g>
<g>
<path d="m594.3,502.3h5.5l4.1,12.2h0l3.9-12.2h5.5v17.8h-3.7v-12.6h0l-4.4,12.6h-3l-4.4-12.5h0v12.5h-3.7v-17.8h0Z" style="fill: #ed6b21;"/>
<path d="m616,502.3h3.9v7.4l6.9-7.4h4.9l-6.9,7,7.6,10.7h-4.9l-5.3-8-2.2,2.3v5.7h-3.9v-17.8Z" style="fill: #ed6b21;"/>
<path d="m638.4,516.1h-7.4v-3.2l7.6-10.2h3.2v10.5h2.3v2.9h-2.3v4h-3.4v-4h0Zm0-9h0l-4.5,6.1h4.6v-6.1Z" style="fill: #ed6b21;"/>
</g>
<rect x="385.6" y="528.9" width="54.9" height="21" style="fill: #ff3c00;"/>
<g>
<path d="m401.3,545.4c0,.2,0,.4-.2.4h-2c-.2,0-.4,0-.4-.3l-.4-1.7h-3.2l-.4,1.7c0,.2-.2.3-.4.3h-2c-.2,0-.3-.1-.2-.4l3.3-11.9c0-.2.2-.3.4-.3h1.7c.2,0,.3,0,.4.3l3.3,11.9Zm-4.5-9.2l-.2,1.2-.9,4.2h2.2l-.9-4.2-.2-1.2Z" style="fill: #fff;"/>
<path d="m402.5,532.1c0-.2.1-.4.3-.4h1.8c.2,0,.3.1.3.4v13.3c0,.2,0,.4-.3.4h-1.8c-.2,0-.3-.1-.3-.4v-13.3Z" style="fill: #fff;"/>
<path d="m415,541.9c0,2.3-1.4,4.1-3.7,4.1s-1.4-.5-1.8-1.1v3.9c0,.2-.2.4-.4.4h-1.7c-.2,0-.3-.1-.3-.4v-13.5c0-.2.1-.4.3-.4h1.3c.2,0,.4.1.4.4l.2.9c.4-.8,1.1-1.5,2.1-1.5,2.2,0,3.6,1.9,3.6,4.1v3.1Zm-2.5-3.2c0-.9-.6-1.7-1.5-1.7s-1.4.8-1.5,1.8v3c0,1,.6,1.9,1.5,1.9s1.5-.8,1.5-1.7v-3.3Z" style="fill: #fff;"/>
<path d="m422,538.6c0-.8-.6-1.6-1.5-1.6s-1.5.9-1.5,1.6v6.8c0,.2-.3.4-.5.4h-1.7c-.2,0-.3-.1-.3-.4v-13.3c0-.2.1-.4.3-.4h1.8c.2,0,.3,0,.3.3v3.9c.5-.8,1.2-1.3,2.2-1.3,1.9,0,3.3,1.3,3.3,4v6.7c0,.2-.1.4-.3.4h-1.8c-.2,0-.3-.1-.3-.4v-6.8Z" style="fill: #fff;"/>
<path d="m426,538.8c0-2.2,1.5-4.1,3.7-4.1s1.6.6,2,1.4v-.8c.2-.2.3-.4.6-.4h1.3c.2,0,.3.1.3.4v10.1c0,.2-.1.4-.3.4h-1.3c-.2,0-.4-.1-.4-.4v-.9c-.5.8-1.1,1.4-2.2,1.4-2.2,0-3.7-1.8-3.7-4.1v-3.1Zm2.5,3.2c0,.9.6,1.7,1.5,1.7s1.4-.8,1.5-1.8v-3.1c0-1-.6-1.8-1.5-1.8s-1.5.8-1.5,1.7v3.3Z" style="fill: #fff;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -138,6 +138,8 @@ set(SLIC3R_SOURCES
GCode/ThumbnailData.hpp
GCode/Thumbnails.cpp
GCode/Thumbnails.hpp
GCode/ConflictChecker.cpp
GCode/ConflictChecker.hpp
GCode/CoolingBuffer.cpp
GCode/CoolingBuffer.hpp
GCode/FindReplace.cpp

View File

@ -0,0 +1,290 @@
#include "libslic3r.h"
#include "ConflictChecker.hpp"
#include <tbb/parallel_for.h>
#include <tbb/concurrent_vector.h>
#include <map>
#include <functional>
#include <atomic>
namespace Slic3r {
namespace RasterizationImpl {
using IndexPair = std::pair<int64_t, int64_t>;
using Grids = std::vector<IndexPair>;
inline constexpr int64_t RasteXDistance = scale_(1);
inline constexpr int64_t RasteYDistance = scale_(1);
inline IndexPair point_map_grid_index(const Point &pt, int64_t xdist, int64_t ydist)
{
auto x = pt.x() / xdist;
auto y = pt.y() / ydist;
return std::make_pair(x, y);
}
inline bool nearly_equal(const Point &p1, const Point &p2) { return std::abs(p1.x() - p2.x()) < SCALED_EPSILON && std::abs(p1.y() - p2.y()) < SCALED_EPSILON; }
inline Grids line_rasterization(const Line &line, int64_t xdist = RasteXDistance, int64_t ydist = RasteYDistance)
{
Grids res;
Point rayStart = line.a;
Point rayEnd = line.b;
IndexPair currentVoxel = point_map_grid_index(rayStart, xdist, ydist);
IndexPair lastVoxel = point_map_grid_index(rayEnd, xdist, ydist);
Point ray = rayEnd - rayStart;
double stepX = ray.x() >= 0 ? 1 : -1;
double stepY = ray.y() >= 0 ? 1 : -1;
double nextVoxelBoundaryX = (currentVoxel.first + stepX) * xdist;
double nextVoxelBoundaryY = (currentVoxel.second + stepY) * ydist;
if (stepX < 0) { nextVoxelBoundaryX += xdist; }
if (stepY < 0) { nextVoxelBoundaryY += ydist; }
double tMaxX = ray.x() != 0 ? (nextVoxelBoundaryX - rayStart.x()) / ray.x() : DBL_MAX;
double tMaxY = ray.y() != 0 ? (nextVoxelBoundaryY - rayStart.y()) / ray.y() : DBL_MAX;
double tDeltaX = ray.x() != 0 ? static_cast<double>(xdist) / ray.x() * stepX : DBL_MAX;
double tDeltaY = ray.y() != 0 ? static_cast<double>(ydist) / ray.y() * stepY : DBL_MAX;
res.push_back(currentVoxel);
double tx = tMaxX;
double ty = tMaxY;
while (lastVoxel != currentVoxel) {
if (lastVoxel.first == currentVoxel.first) {
for (int64_t i = currentVoxel.second; i != lastVoxel.second; i += (int64_t) stepY) {
currentVoxel.second += (int64_t) stepY;
res.push_back(currentVoxel);
}
break;
}
if (lastVoxel.second == currentVoxel.second) {
for (int64_t i = currentVoxel.first; i != lastVoxel.first; i += (int64_t) stepX) {
currentVoxel.first += (int64_t) stepX;
res.push_back(currentVoxel);
}
break;
}
if (tx < ty) {
currentVoxel.first += (int64_t) stepX;
tx += tDeltaX;
} else {
currentVoxel.second += (int64_t) stepY;
ty += tDeltaY;
}
res.push_back(currentVoxel);
if (res.size() >= 100000) { // bug
assert(0);
}
}
return res;
}
} // namespace RasterizationImpl
void LinesBucketQueue::emplace_back_bucket(std::vector<ExtrusionPaths> &&paths, const void *objPtr, Points offsets)
{
if (_objsPtrToId.find(objPtr) == _objsPtrToId.end()) {
_objsPtrToId.insert({objPtr, _objsPtrToId.size()});
_idToObjsPtr.insert({_objsPtrToId.size() - 1, objPtr});
}
_buckets.emplace_back(std::move(paths), _objsPtrToId[objPtr], offsets);
}
void LinesBucketQueue::build_queue()
{
assert(_pq.empty());
for (LinesBucket &bucket : _buckets)
_pq.push(&bucket);
}
double LinesBucketQueue::removeLowests()
{
auto lowest = _pq.top();
_pq.pop();
double curHeight = lowest->curHeight();
std::vector<LinesBucket *> lowests;
lowests.push_back(lowest);
while (_pq.empty() == false && std::abs(_pq.top()->curHeight() - lowest->curHeight()) < EPSILON) {
lowests.push_back(_pq.top());
_pq.pop();
}
for (LinesBucket *bp : lowests) {
bp->raise();
if (bp->valid()) { _pq.push(bp); }
}
return curHeight;
}
LineWithIDs LinesBucketQueue::getCurLines() const
{
LineWithIDs lines;
for (const LinesBucket &bucket : _buckets) {
if (bucket.valid()) {
LineWithIDs tmpLines = bucket.curLines();
lines.insert(lines.end(), tmpLines.begin(), tmpLines.end());
}
}
return lines;
}
void getExtrusionPathsFromEntity(const ExtrusionEntityCollection *entity, ExtrusionPaths &paths)
{
std::function<void(const ExtrusionEntityCollection *, ExtrusionPaths &)> getExtrusionPathImpl = [&](const ExtrusionEntityCollection *entity, ExtrusionPaths &paths) {
for (auto entityPtr : entity->entities) {
if (const ExtrusionEntityCollection *collection = dynamic_cast<ExtrusionEntityCollection *>(entityPtr)) {
getExtrusionPathImpl(collection, paths);
} else if (const ExtrusionPath *path = dynamic_cast<ExtrusionPath *>(entityPtr)) {
paths.push_back(*path);
} else if (const ExtrusionMultiPath *multipath = dynamic_cast<ExtrusionMultiPath *>(entityPtr)) {
for (const ExtrusionPath &path : multipath->paths) { paths.push_back(path); }
} else if (const ExtrusionLoop *loop = dynamic_cast<ExtrusionLoop *>(entityPtr)) {
for (const ExtrusionPath &path : loop->paths) { paths.push_back(path); }
}
}
};
getExtrusionPathImpl(entity, paths);
}
ExtrusionPaths getExtrusionPathsFromLayer(LayerRegionPtrs layerRegionPtrs)
{
ExtrusionPaths paths;
for (auto regionPtr : layerRegionPtrs) {
getExtrusionPathsFromEntity(&regionPtr->perimeters(), paths);
if (!regionPtr->perimeters().empty()) { getExtrusionPathsFromEntity(&regionPtr->fills(), paths); }
}
return paths;
}
ExtrusionPaths getExtrusionPathsFromSupportLayer(SupportLayer *supportLayer)
{
ExtrusionPaths paths;
getExtrusionPathsFromEntity(&supportLayer->support_fills, paths);
return paths;
}
std::pair<std::vector<ExtrusionPaths>, std::vector<ExtrusionPaths>> getAllLayersExtrusionPathsFromObject(PrintObject *obj)
{
std::vector<ExtrusionPaths> objPaths, supportPaths;
for (auto layerPtr : obj->layers()) { objPaths.push_back(getExtrusionPathsFromLayer(layerPtr->regions())); }
for (auto supportLayerPtr : obj->support_layers()) { supportPaths.push_back(getExtrusionPathsFromSupportLayer(supportLayerPtr)); }
return {std::move(objPaths), std::move(supportPaths)};
}
ConflictComputeOpt ConflictChecker::find_inter_of_lines(const LineWithIDs &lines)
{
using namespace RasterizationImpl;
std::map<IndexPair, std::vector<int>> indexToLine;
for (int i = 0; i < (int)lines.size(); ++i) {
const LineWithID &l1 = lines[i];
auto indexes = line_rasterization(l1._line);
for (auto index : indexes) {
const auto &possibleIntersectIdxs = indexToLine[index];
for (auto possibleIntersectIdx : possibleIntersectIdxs) {
const LineWithID &l2 = lines[possibleIntersectIdx];
if (auto interRes = line_intersect(l1, l2); interRes.has_value()) { return interRes; }
}
indexToLine[index].push_back(i);
}
}
return {};
}
ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs,
std::optional<const FakeWipeTower *> wtdptr) // find the first intersection point of lines in different objects
{
if (objs.empty() || (objs.size() == 1 && objs.front()->instances().size() == 1)) { return {}; }
LinesBucketQueue conflictQueue;
if (wtdptr.has_value()) { // wipe tower at 0 by default
std::vector<ExtrusionPaths> wtpaths = (*wtdptr)->getFakeExtrusionPathsFromWipeTower();
conflictQueue.emplace_back_bucket(std::move(wtpaths), *wtdptr, Points{Point((*wtdptr)->plate_origin)});
}
for (PrintObject *obj : objs) {
std::pair<std::vector<ExtrusionPaths>, std::vector<ExtrusionPaths>> layers = getAllLayersExtrusionPathsFromObject(obj);
Points instances_shifts;
for (const PrintInstance& inst : obj->instances())
instances_shifts.emplace_back(inst.shift);
conflictQueue.emplace_back_bucket(std::move(layers.first), obj, instances_shifts);
conflictQueue.emplace_back_bucket(std::move(layers.second), obj, instances_shifts);
}
conflictQueue.build_queue();
std::vector<LineWithIDs> layersLines;
std::vector<double> heights;
while (conflictQueue.valid()) {
LineWithIDs lines = conflictQueue.getCurLines();
double curHeight = conflictQueue.removeLowests();
heights.push_back(curHeight);
layersLines.push_back(std::move(lines));
}
bool find = false;
tbb::concurrent_vector<std::pair<ConflictComputeResult,double>> conflict;
tbb::parallel_for(tbb::blocked_range<size_t>(0, layersLines.size()), [&](tbb::blocked_range<size_t> range) {
for (size_t i = range.begin(); i < range.end(); i++) {
auto interRes = find_inter_of_lines(layersLines[i]);
if (interRes.has_value()) {
find = true;
conflict.emplace_back(*interRes, heights[i]);
break;
}
}
});
if (find) {
std::sort(conflict.begin(), conflict.end(), [](const std::pair<ConflictComputeResult, double>& i1, const std::pair<ConflictComputeResult, double>& i2) {
return i1.second < i2.second;
});
const void *ptr1 = conflictQueue.idToObjsPtr(conflict[0].first._obj1);
const void *ptr2 = conflictQueue.idToObjsPtr(conflict[0].first._obj2);
double conflictHeight = conflict[0].second;
if (wtdptr.has_value()) {
const FakeWipeTower* wtdp = *wtdptr;
if (ptr1 == wtdp || ptr2 == wtdp) {
if (ptr2 == wtdp) { std::swap(ptr1, ptr2); }
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(ptr2);
return std::make_optional<ConflictResult>("WipeTower", obj2->model_object()->name, conflictHeight, nullptr, ptr2);
}
}
const PrintObject *obj1 = reinterpret_cast<const PrintObject *>(ptr1);
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(ptr2);
return std::make_optional<ConflictResult>(obj1->model_object()->name, obj2->model_object()->name, conflictHeight, ptr1, ptr2);
} else
return {};
}
ConflictComputeOpt ConflictChecker::line_intersect(const LineWithID &l1, const LineWithID &l2)
{
if (l1._obj_id == l2._obj_id && l1._inst_id == l2._inst_id) { return {}; } // lines are from same instance
Point inter;
bool intersect = l1._line.intersection(l2._line, &inter);
if (intersect) {
auto dist1 = std::min(unscale(Point(l1._line.a - inter)).norm(), unscale(Point(l1._line.b - inter)).norm());
auto dist2 = std::min(unscale(Point(l2._line.a - inter)).norm(), unscale(Point(l2._line.b - inter)).norm());
auto dist = std::min(dist1, dist2);
if (dist > 0.01) { return std::make_optional<ConflictComputeResult>(l1._obj_id, l2._obj_id); } // the two lines intersects if dist>0.01mm
}
return {};
}
} // namespace Slic3r

View File

@ -0,0 +1,129 @@
#ifndef slic3r_ConflictChecker_hpp_
#define slic3r_ConflictChecker_hpp_
#include "../Utils.hpp"
#include "../Model.hpp"
#include "../Print.hpp"
#include "../Layer.hpp"
#include <queue>
#include <vector>
#include <optional>
namespace Slic3r {
struct LineWithID
{
Line _line;
int _obj_id;
int _inst_id;
ExtrusionRole _role;
LineWithID(const Line& line, int obj_id, int inst_id, const ExtrusionRole& role) :
_line(line), _obj_id(obj_id), _inst_id(inst_id), _role(role) {}
};
using LineWithIDs = std::vector<LineWithID>;
class LinesBucket
{
private:
double _curHeight = 0.0;
unsigned _curPileIdx = 0;
std::vector<ExtrusionPaths> _piles;
int _id;
Points _offsets;
public:
LinesBucket(std::vector<ExtrusionPaths> &&paths, int id, Points offsets) : _piles(paths), _id(id), _offsets(offsets) {}
LinesBucket(LinesBucket &&) = default;
bool valid() const { return _curPileIdx < _piles.size(); }
void raise()
{
if (valid()) {
if (_piles[_curPileIdx].empty() == false) { _curHeight += _piles[_curPileIdx].front().height; }
_curPileIdx++;
}
}
double curHeight() const { return _curHeight; }
LineWithIDs curLines() const
{
LineWithIDs lines;
for (const ExtrusionPath &path : _piles[_curPileIdx]) {
Polyline check_polyline;
for (int i = 0; i < (int)_offsets.size(); ++i) {
check_polyline = path.polyline;
check_polyline.translate(_offsets[i]);
Lines tmpLines = check_polyline.lines();
for (const Line& line : tmpLines) { lines.emplace_back(line, _id, i, path.role()); }
}
}
return lines;
}
friend bool operator>(const LinesBucket &left, const LinesBucket &right) { return left._curHeight > right._curHeight; }
friend bool operator<(const LinesBucket &left, const LinesBucket &right) { return left._curHeight < right._curHeight; }
friend bool operator==(const LinesBucket &left, const LinesBucket &right) { return left._curHeight == right._curHeight; }
};
struct LinesBucketPtrComp
{
bool operator()(const LinesBucket *left, const LinesBucket *right) { return *left > *right; }
};
class LinesBucketQueue
{
private:
std::vector<LinesBucket> _buckets;
std::priority_queue<LinesBucket *, std::vector<LinesBucket *>, LinesBucketPtrComp> _pq;
std::map<int, const void *> _idToObjsPtr;
std::map<const void *, int> _objsPtrToId;
public:
void emplace_back_bucket(std::vector<ExtrusionPaths> &&paths, const void *objPtr, Points offset);
void build_queue();
bool valid() const { return _pq.empty() == false; }
const void *idToObjsPtr(int id)
{
if (_idToObjsPtr.find(id) != _idToObjsPtr.end())
return _idToObjsPtr[id];
else
return nullptr;
}
double removeLowests();
LineWithIDs getCurLines() const;
};
void getExtrusionPathsFromEntity(const ExtrusionEntityCollection *entity, ExtrusionPaths &paths);
ExtrusionPaths getExtrusionPathsFromLayer(LayerRegionPtrs layerRegionPtrs);
ExtrusionPaths getExtrusionPathsFromSupportLayer(SupportLayer *supportLayer);
std::pair<std::vector<ExtrusionPaths>, std::vector<ExtrusionPaths>> getAllLayersExtrusionPathsFromObject(PrintObject *obj);
struct ConflictComputeResult
{
int _obj1;
int _obj2;
ConflictComputeResult(int o1, int o2) : _obj1(o1), _obj2(o2) {}
ConflictComputeResult() = default;
};
using ConflictComputeOpt = std::optional<ConflictComputeResult>;
using ConflictObjName = std::optional<std::pair<std::string, std::string>>;
struct ConflictChecker
{
static ConflictResultOpt find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, std::optional<const FakeWipeTower *> wtdptr);
static ConflictComputeOpt find_inter_of_lines(const LineWithIDs &lines);
static ConflictComputeOpt line_intersect(const LineWithID &l1, const LineWithID &l2);
};
} // namespace Slic3r
#endif

View File

@ -189,13 +189,13 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
head_window_acc -= distances_for_curvature[point_idx - 1];
head_angle_acc -= angles_for_curvature[point_idx - 1];
}
while (tail_window_acc > window_size * 0.5 && tail_point < point_idx) {
while (tail_window_acc > window_size * 0.5 && int(tail_point) < point_idx) {
tail_window_acc -= distances_for_curvature[tail_point];
tail_angle_acc -= angles_for_curvature[tail_point];
tail_point++;
}
while (head_window_acc < window_size * 0.5 && head_point < int(points.size()) - 1) {
while (head_window_acc < window_size * 0.5 && int(head_point) < int(points.size()) - 1) {
head_window_acc += distances_for_curvature[head_point];
head_angle_acc += angles_for_curvature[head_point];
head_point++;

View File

@ -450,6 +450,7 @@ void GCodeProcessorResult::reset() {
filament_cost = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST);
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
spiral_vase_layers = std::vector<std::pair<float, std::pair<size_t, size_t>>>();
conflict_result = std::nullopt;
time = 0;
}
#else
@ -468,6 +469,7 @@ void GCodeProcessorResult::reset() {
filament_cost = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST);
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
spiral_vase_layers = std::vector<std::pair<float, std::pair<size_t, size_t>>>();
conflict_result = std::nullopt;
}
#endif // ENABLE_GCODE_VIEWER_STATISTICS

View File

@ -82,6 +82,22 @@ namespace Slic3r {
}
};
struct ConflictResult
{
std::string _objName1;
std::string _objName2;
double _height;
const void* _obj1; // nullptr means wipe tower
const void* _obj2;
int layer = -1;
ConflictResult(const std::string& objName1, const std::string& objName2, double height, const void* obj1, const void* obj2)
: _objName1(objName1), _objName2(objName2), _height(height), _obj1(obj1), _obj2(obj2)
{}
ConflictResult() = default;
};
using ConflictResultOpt = std::optional<ConflictResult>;
struct GCodeProcessorResult
{
struct SettingsIds
@ -137,6 +153,8 @@ namespace Slic3r {
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
std::vector<std::pair<float, std::pair<size_t, size_t>>> spiral_vase_layers;
ConflictResultOpt conflict_result;
#if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 };
#endif // ENABLE_GCODE_VIEWER_STATISTICS

View File

@ -1563,4 +1563,19 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
}
}
std::vector<std::pair<float, float>> WipeTower::get_z_and_depth_pairs() const
{
std::vector<std::pair<float, float>> out = {{0.f, m_wipe_tower_depth}};
for (const WipeTowerInfo& wti : m_plan) {
assert(wti.depth < wti.depth + WT_EPSILON);
if (wti.depth < out.back().second - WT_EPSILON)
out.emplace_back(wti.z, wti.depth);
}
if (out.back().first < m_wipe_tower_height - WT_EPSILON)
out.emplace_back(m_wipe_tower_height, 0.f);
return out;
}
} // namespace Slic3r

View File

@ -143,6 +143,7 @@ public:
void generate(std::vector<std::vector<ToolChangeResult>> &result);
float get_depth() const { return m_wipe_tower_depth; }
std::vector<std::pair<float, float>> get_z_and_depth_pairs() const;
float get_brim_width() const { return m_wipe_tower_brim_width_real; }
float get_wipe_tower_height() const { return m_wipe_tower_height; }

View File

@ -1353,37 +1353,6 @@ void ModelObject::delete_connectors()
}
}
void ModelObject::synchronize_model_after_cut()
{
for (ModelObject* obj : m_model->objects) {
if (obj == this || obj->cut_id.is_equal(this->cut_id))
continue;
if (obj->is_cut() && obj->cut_id.has_same_id(this->cut_id))
obj->cut_id.copy(this->cut_id);
}
this->invalidate_cut();
}
void ModelObject::apply_cut_attributes(ModelObjectCutAttributes attributes)
{
// we don't save cut information, if result will not contains all parts of initial object
if (!attributes.has(ModelObjectCutAttribute::KeepUpper) ||
!attributes.has(ModelObjectCutAttribute::KeepLower) ||
attributes.has(ModelObjectCutAttribute::InvalidateCutInfo))
return;
if (cut_id.id().invalid())
cut_id.init();
{
int cut_obj_cnt = -1;
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) cut_obj_cnt++;
if (attributes.has(ModelObjectCutAttribute::KeepLower)) cut_obj_cnt++;
if (attributes.has(ModelObjectCutAttribute::CreateDowels)) cut_obj_cnt++;
if (cut_obj_cnt > 0)
cut_id.increase_check_sum(size_t(cut_obj_cnt));
}
}
void ModelObject::clone_for_cut(ModelObject** obj)
{
(*obj) = ModelObject::new_clone(*this);
@ -1636,9 +1605,6 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix,
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - start";
// apply cut attributes for object
apply_cut_attributes(attributes);
// Clone the object to duplicate instances, materials etc.
ModelObject* upper{ nullptr };
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
@ -1709,8 +1675,6 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix,
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end";
synchronize_model_after_cut();
return res;
}

View File

@ -469,13 +469,7 @@ public:
void delete_connectors();
void clone_for_cut(ModelObject **obj);
void apply_cut_attributes(ModelObjectCutAttributes attributes);
private:
// FIXME: These functions would best not be here at all. It might make sense to separate the
// cut-related methods elsewhere. Same holds for cut_connectors data member, which is currently
// just a temporary variable used by cut gizmo only.
void synchronize_model_after_cut();
void process_connector_cut(ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower,
std::vector<ModelObject*>& dowels);

View File

@ -11,6 +11,7 @@
#include "Thread.hpp"
#include "GCode.hpp"
#include "GCode/WipeTower.hpp"
#include "GCode/ConflictChecker.hpp"
#include "Utils.hpp"
#include "BuildVolume.hpp"
#include "format.hpp"
@ -26,7 +27,6 @@
#include <boost/log/trivial.hpp>
#include <boost/regex.hpp>
namespace Slic3r {
template class PrintState<PrintStep, psCount>;
@ -962,6 +962,18 @@ void Print::process()
this->finalize_first_layer_convex_hull();
this->set_done(psSkirtBrim);
}
std::optional<const FakeWipeTower*> wipe_tower_opt = {};
if (this->has_wipe_tower()) {
m_fake_wipe_tower.set_pos_and_rotation({ m_config.wipe_tower_x, m_config.wipe_tower_y }, m_config.wipe_tower_rotation_angle);
wipe_tower_opt = std::make_optional<const FakeWipeTower*>(&m_fake_wipe_tower);
}
auto conflictRes = ConflictChecker::find_inter_of_lines_in_diff_objs(m_objects, wipe_tower_opt);
m_conflict_result = conflictRes;
if (conflictRes.has_value())
BOOST_LOG_TRIVIAL(error) << boost::format("gcode path conflicts found between %1% and %2%") % conflictRes->_objName1 % conflictRes->_objName2;
BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info();
}
@ -987,6 +999,10 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor
// Create GCode on heap, it has quite a lot of data.
std::unique_ptr<GCode> gcode(new GCode);
gcode->do_export(this, path.c_str(), result, thumbnail_cb);
if (m_conflict_result.has_value())
result->conflict_result = *m_conflict_result;
return path.c_str();
}
@ -1485,6 +1501,7 @@ void Print::_make_wipe_tower()
m_wipe_tower_data.tool_changes.reserve(m_wipe_tower_data.tool_ordering.layer_tools().size());
wipe_tower.generate(m_wipe_tower_data.tool_changes);
m_wipe_tower_data.depth = wipe_tower.get_depth();
m_wipe_tower_data.z_and_depth_pairs = wipe_tower.get_z_and_depth_pairs();
m_wipe_tower_data.brim_width = wipe_tower.get_brim_width();
m_wipe_tower_data.height = wipe_tower.get_wipe_tower_height();
@ -1509,6 +1526,10 @@ void Print::_make_wipe_tower()
m_wipe_tower_data.used_filament = wipe_tower.get_used_filament();
m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges();
const Vec3d origin = Vec3d::Zero();
m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(), config().first_layer_height, m_wipe_tower_data.depth,
m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width, config().wipe_tower_rotation_angle, config().wipe_tower_cone_angle, {scale_(origin.x()), scale_(origin.y())});
}
// Generate a recommended G-code output file name based on the format template, default extension, and template parameters
@ -1576,4 +1597,80 @@ std::string PrintStatistics::finalize_output_path(const std::string &path_in) co
return final_path;
}
std::vector<ExtrusionPaths> FakeWipeTower::getFakeExtrusionPathsFromWipeTower() const
{
float h = height;
float lh = layer_height;
int d = scale_(depth);
int w = scale_(width);
int bd = scale_(brim_width);
Point minCorner = { -bd, -bd };
Point maxCorner = { minCorner.x() + w + bd, minCorner.y() + d + bd };
const auto [cone_base_R, cone_scale_x] = WipeTower::get_wipe_tower_cone_base(width, height, depth, cone_angle);
std::vector<ExtrusionPaths> paths;
for (float hh = 0.f; hh < h; hh += lh) {
if (hh != 0.f) {
// The wipe tower may be getting smaller. Find the depth for this layer.
size_t i = 0;
for (i=0; i<z_and_depth_pairs.size()-1; ++i)
if (hh >= z_and_depth_pairs[i].first && hh < z_and_depth_pairs[i+1].first)
break;
d = scale_(z_and_depth_pairs[i].second);
minCorner = {0.f, -d/2 + scale_(z_and_depth_pairs.front().second/2.f)};
maxCorner = { minCorner.x() + w, minCorner.y() + d };
}
ExtrusionPath path(ExtrusionRole::WipeTower, 0.0, 0.0, lh);
path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner };
paths.push_back({ path });
// We added the border, now add several parallel lines so we can detect an object that is fully inside the tower.
// For now, simply use fixed spacing of 3mm.
for (coord_t y=minCorner.y()+scale_(3.); y<maxCorner.y(); y+=scale_(3.)) {
path.polyline = { {minCorner.x(), y}, {maxCorner.x(), y} };
paths.back().emplace_back(path);
}
// And of course the stabilization cone and its base...
if (cone_base_R > 0.) {
path.polyline.clear();
double r = cone_base_R * (1 - hh/height);
for (double alpha=0; alpha<2.01*M_PI; alpha+=2*M_PI/20.)
path.polyline.points.emplace_back(Point::new_scale(width/2. + r * std::cos(alpha)/cone_scale_x, depth/2. + r * std::sin(alpha)));
paths.back().emplace_back(path);
if (hh == 0.f) { // Cone brim.
for (float bw=brim_width; bw>0.f; bw-=3.f) {
path.polyline.clear();
for (double alpha=0; alpha<2.01*M_PI; alpha+=2*M_PI/20.) // see load_wipe_tower_preview, where the same is a bit clearer
path.polyline.points.emplace_back(Point::new_scale(
width/2. + cone_base_R * std::cos(alpha)/cone_scale_x * (1. + cone_scale_x*bw/cone_base_R),
depth/2. + cone_base_R * std::sin(alpha) * (1. + bw/cone_base_R))
);
paths.back().emplace_back(path);
}
}
}
// Only the first layer has brim.
if (hh == 0.f) {
minCorner = minCorner + Point(bd, bd);
maxCorner = maxCorner - Point(bd, bd);
}
}
// Rotate and translate the tower into the final position.
for (ExtrusionPaths& ps : paths) {
for (ExtrusionPath& p : ps) {
p.polyline.rotate(Geometry::deg2rad(rotation_angle));
p.polyline.translate(scale_(pos.x()), scale_(pos.y()));
}
}
return paths;
}
} // namespace Slic3r

View File

@ -418,6 +418,39 @@ private:
FillLightning::GeneratorPtr m_lightning_generator;
};
struct FakeWipeTower
{
// generate fake extrusion
Vec2f pos;
float width;
float height;
float layer_height;
float depth;
std::vector<std::pair<float, float>> z_and_depth_pairs;
float brim_width;
float rotation_angle;
float cone_angle;
Vec2d plate_origin;
void set_fake_extrusion_data(const Vec2f& p, float w, float h, float lh, float d, const std::vector<std::pair<float, float>>& zad, float bd, float ra, float ca, const Vec2d& o)
{
pos = p;
width = w;
height = h;
layer_height = lh;
depth = d;
z_and_depth_pairs = zad;
brim_width = bd;
rotation_angle = ra;
cone_angle = ca;
plate_origin = o;
}
void set_pos_and_rotation(const Vec2f& p, float rotation) { pos = p; rotation_angle = rotation; }
std::vector<ExtrusionPaths> getFakeExtrusionPathsFromWipeTower() const;
};
struct WipeTowerData
{
// Following section will be consumed by the GCodeGenerator.
@ -433,6 +466,7 @@ struct WipeTowerData
// Depth of the wipe tower to pass to GLCanvas3D for exact bounding box:
float depth;
std::vector<std::pair<float, float>> z_and_depth_pairs;
float brim_width;
float height;
@ -668,6 +702,9 @@ private:
friend class GCodeProcessor;
// Allow PrintObject to access m_mutex and m_cancel_callback.
friend class PrintObject;
ConflictResultOpt m_conflict_result;
FakeWipeTower m_fake_wipe_tower;
};
} /* slic3r_Print_hpp_ */

View File

@ -981,12 +981,11 @@ void PrintObject::detect_surfaces_type()
surface_type_bottom_other);
#else
// Any surface lying on the void is a true bottom bridge (an overhang)
surfaces_append(
bottom,
opening_ex(
diff_ex(layerm->slices().surfaces, lower_layer->lslices, ApplySafetyOffset::Yes),
offset),
surface_type_bottom_other);
ExPolygons true_bridge = diff_ex(layerm->slices().surfaces, lower_layer->lslices, ApplySafetyOffset::Yes);
// expand the bridges by one extrusion width, to ensure reasonable anchoring whenever possible
true_bridge = intersection_ex(layerm->slices().surfaces,
offset_ex(true_bridge, layerm->bridging_flow(frSolidInfill).scaled_spacing()));
surfaces_append(bottom, true_bridge, surface_type_bottom_other);
// if user requested internal shells, we need to identify surfaces
// lying on other slices not belonging to this region
if (interface_shells) {

View File

@ -650,7 +650,7 @@ std::tuple<ObjectPart, float> build_object_part_from_slice(const size_t &slice_i
new_object_part.volume += volume;
new_object_part.volume_centroid_accumulator += to_3d(Vec2f((line.a + line.b) / 2.0f), slice_z) * volume;
if (l->id() == params.raft_layers_count) { // layer attached on bed/raft
if (int(l->id()) == params.raft_layers_count) { // layer attached on bed/raft
new_object_part.connected_to_bed = true;
float sticking_area = line.len * flow_width;
new_object_part.sticking_area += sticking_area;
@ -673,7 +673,7 @@ std::tuple<ObjectPart, float> build_object_part_from_slice(const size_t &slice_i
for (const auto &island : slice.islands) {
const LayerRegion *perimeter_region = layer->get_region(island.perimeters.region());
for (const auto &perimeter_idx : island.perimeters) {
for (size_t perimeter_idx : island.perimeters) {
for (const ExtrusionEntity *perimeter :
static_cast<const ExtrusionEntityCollection *>(perimeter_region->perimeters().entities[perimeter_idx])->entities) {
add_extrusions_to_object(perimeter, perimeter_region);
@ -681,20 +681,20 @@ std::tuple<ObjectPart, float> build_object_part_from_slice(const size_t &slice_i
}
for (const LayerExtrusionRange &fill_range : island.fills) {
const LayerRegion *fill_region = layer->get_region(fill_range.region());
for (const auto &fill_idx : fill_range) {
for (size_t fill_idx : fill_range) {
for (const ExtrusionEntity *fill :
static_cast<const ExtrusionEntityCollection *>(fill_region->fills().entities[fill_idx])->entities) {
add_extrusions_to_object(fill, fill_region);
}
}
}
for (const auto &thin_fill_idx : island.thin_fills) {
for (size_t thin_fill_idx : island.thin_fills) {
add_extrusions_to_object(perimeter_region->thin_fills().entities[thin_fill_idx], perimeter_region);
}
}
// BRIM HANDLING
if (layer->id() == params.raft_layers_count && params.raft_layers_count == 0 && params.brim_type != BrimType::btNoBrim &&
if (int(layer->id()) == params.raft_layers_count && params.raft_layers_count == 0 && params.brim_type != BrimType::btNoBrim &&
params.brim_width > 0.0) {
// TODO: The algorithm here should take into account that multiple slices may have coliding Brim areas and the final brim area is
// smaller,
@ -911,7 +911,7 @@ std::tuple<SupportPoints, PartialObjects> check_stability(const PrintObject
for (const auto &island : slice.islands) {
for (const LayerExtrusionRange &fill_range : island.fills) {
const LayerRegion *fill_region = layer->get_region(fill_range.region());
for (const auto &fill_idx : fill_range) {
for (size_t fill_idx : fill_range) {
for (const ExtrusionEntity *e : get_flat_entities(fill_region->fills().entities[fill_idx])) {
if (e->role() == ExtrusionRole::BridgeInfill) {
entities_to_check.push_back({e, fill_region, slice_idx});
@ -921,7 +921,7 @@ std::tuple<SupportPoints, PartialObjects> check_stability(const PrintObject
}
const LayerRegion *perimeter_region = layer->get_region(island.perimeters.region());
for (const size_t &perimeter_idx : island.perimeters) {
for (size_t perimeter_idx : island.perimeters) {
for (const ExtrusionEntity *e : get_flat_entities(perimeter_region->perimeters().entities[perimeter_idx])) {
entities_to_check.push_back({e, perimeter_region, slice_idx});
}

View File

@ -9,6 +9,7 @@
#include "Platform.hpp"
#include "Time.hpp"
#include "format.hpp"
#include "libslic3r.h"
#ifdef WIN32

View File

@ -194,6 +194,7 @@ set(SLIC3R_GUI_SOURCES
GUI/Jobs/BoostThreadWorker.cpp
GUI/Jobs/UIThreadWorker.hpp
GUI/Jobs/BusyCursorJob.hpp
GUI/Jobs/CancellableJob.hpp
GUI/Jobs/PlaterWorker.hpp
GUI/Jobs/ArrangeJob.hpp
GUI/Jobs/ArrangeJob.cpp

View File

@ -480,11 +480,11 @@ int GLVolumeCollection::load_object_volume(
#if ENABLE_OPENGL_ES
int GLVolumeCollection::load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height, float cone_angle,
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle,
float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh)
#else
int GLVolumeCollection::load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height, float cone_angle,
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle,
float rotation_angle, bool size_unknown, float brim_width)
#endif // ENABLE_OPENGL_ES
{
@ -534,8 +534,13 @@ int GLVolumeCollection::load_wipe_tower_preview(
mesh.scale(Vec3f(width / (n * min_width), 1.f, height)); // Scaling to proper width
}
else
mesh = make_cube(width, depth, height);
else {
for (size_t i=1; i<z_and_depth_pairs.size(); ++i) {
TriangleMesh m = make_cube(width, z_and_depth_pairs[i-1].second, z_and_depth_pairs[i].first-z_and_depth_pairs[i-1].first);
m.translate(0.f, -z_and_depth_pairs[i-1].second/2.f + z_and_depth_pairs[0].second/2.f, z_and_depth_pairs[i-1].first);
mesh.merge(m);
}
}
// We'll make another mesh to show the brim (fixed layer height):
TriangleMesh brim_mesh = make_cube(width + 2.f * brim_width, depth + 2.f * brim_width, 0.2f);

View File

@ -396,10 +396,10 @@ public:
#if ENABLE_OPENGL_ES
int load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr);
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr);
#else
int load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width);
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width);
#endif // ENABLE_OPENGL_ES
// Load SLA auxiliary GLVolumes (for support trees or pad).

View File

@ -799,6 +799,9 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr
short_time(get_time_dhms(time)) == short_time(get_time_dhms(m_print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].time)))
m_time_estimate_mode = PrintEstimatedStatistics::ETimeMode::Normal;
}
m_conflict_result = gcode_result.conflict_result;
if (m_conflict_result.has_value()) { m_conflict_result->layer = m_layers.get_l_at(m_conflict_result->_height); }
}
void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors)
@ -2257,9 +2260,11 @@ void GCodeViewer::load_shells(const Print& print)
if (extruders_count > 1 && config.wipe_tower && !config.complete_objects) {
const WipeTowerData& wipe_tower_data = print.wipe_tower_data(extruders_count);
const float depth = wipe_tower_data.depth;
const std::vector<std::pair<float, float>> z_and_depth_pairs = print.wipe_tower_data(extruders_count).z_and_depth_pairs;
const float brim_width = wipe_tower_data.brim_width;
m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_cone_angle, config.wipe_tower_rotation_angle,
!print.is_step_done(psWipeTower), brim_width);
if (depth != 0.)
m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, z_and_depth_pairs, max_z, config.wipe_tower_cone_angle, config.wipe_tower_rotation_angle,
!print.is_step_done(psWipeTower), brim_width);
}
}

View File

@ -526,6 +526,10 @@ class GCodeViewer
std::vector<Range>& get_ranges() { return m_ranges; }
double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; }
Range get_range_at(unsigned int id) const { return (id < m_ranges.size()) ? m_ranges[id] : Range(); }
int get_l_at(double z) const {
auto iter = std::upper_bound(m_zs.begin(), m_zs.end(), z);
return std::distance(m_zs.begin(), iter);
}
bool operator != (const Layers& other) const {
if (m_zs != other.m_zs)
@ -784,6 +788,8 @@ private:
bool m_contained_in_bed{ true };
ConflictResultOpt m_conflict_result;
public:
GCodeViewer();
~GCodeViewer() { reset(); }
@ -841,6 +847,8 @@ public:
void invalidate_legend() { m_legend_resizer.reset(); }
const ConflictResultOpt& get_conflict_result() const { return m_conflict_result; }
private:
void load_toolpaths(const GCodeProcessorResult& gcode_result);
void load_shells(const Print& print);

View File

@ -2554,22 +2554,25 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
const Print *print = m_process->fff_print();
const float depth = print->wipe_tower_data(extruders_count).depth;
const std::vector<std::pair<float, float>> z_and_depth_pairs = print->wipe_tower_data(extruders_count).z_and_depth_pairs;
const float height_real = print->wipe_tower_data(extruders_count).height; // -1.f = unknown
// Height of a print (Show at least a slab).
const double height = height_real < 0.f ? std::max(m_model->max_z(), 10.0) : height_real;
#if ENABLE_OPENGL_ES
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
x, y, w, depth, (float)height, ca, a, !print->is_step_done(psWipeTower),
bw, &m_wipe_tower_mesh);
#else
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
x, y, w, depth, (float)height, ca, a, !print->is_step_done(psWipeTower),
bw);
#endif // ENABLE_OPENGL_ES
if (volume_idx_wipe_tower_old != -1)
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
if (depth != 0.) {
#if ENABLE_OPENGL_ES
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !print->is_step_done(psWipeTower),
bw, &m_wipe_tower_mesh);
#else
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !print->is_step_done(psWipeTower),
bw);
#endif // ENABLE_OPENGL_ES
if (volume_idx_wipe_tower_old != -1)
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
}
}
}
@ -2691,6 +2694,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
if (wxGetApp().is_editor()) {
m_gcode_viewer.update_shells_color_by_extruder(m_config);
_set_warning_notification_if_needed(EWarning::ToolpathOutside);
_set_warning_notification_if_needed(EWarning::GCodeConflict);
}
m_gcode_viewer.refresh(gcode_result, str_tool_colors);
@ -7439,8 +7443,12 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
}
else {
if (wxGetApp().is_editor()) {
if (current_printer_technology() != ptSLA)
show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
if (current_printer_technology() != ptSLA) {
if (warning == EWarning::ToolpathOutside)
show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
else if (warning == EWarning::GCodeConflict)
show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.get_conflict_result().has_value();
}
}
}
@ -7466,8 +7474,53 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
"Resolve the current problem to continue slicing.");
error = ErrorType::PLATER_ERROR;
break;
case EWarning::GCodeConflict: {
const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result();
if (!conflict_result.has_value()) { break; }
std::string objName1 = conflict_result->_objName1;
std::string objName2 = conflict_result->_objName2;
double height = conflict_result->_height;
int layer = conflict_result->layer;
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer %
height % objName1 % objName2).str();
error = ErrorType::SLICING_ERROR;
break;
}
}
auto& notification_manager = *wxGetApp().plater()->get_notification_manager();
const ConflictResultOpt& conflict_result = m_gcode_viewer.get_conflict_result();
if (warning == EWarning::GCodeConflict) {
if (conflict_result.has_value()) {
const PrintObject* obj2 = reinterpret_cast<const PrintObject*>(conflict_result->_obj2);
auto mo = obj2->model_object();
ObjectID id = mo->id();
int layer_id = conflict_result->layer;
auto action_fn = [id, layer_id](wxEvtHandler*) {
auto& objects = wxGetApp().model().objects;
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
if (iter != objects.end()) {
const unsigned int obj_idx = std::distance(objects.begin(), iter);
wxGetApp().CallAfter([obj_idx, layer_id]() {
wxGetApp().plater()->set_preview_layers_slider_values_range(0, layer_id - 1);
wxGetApp().plater()->select_view_3D("3D");
wxGetApp().plater()->canvas3D()->get_selection().add_object(obj_idx, true);
wxGetApp().obj_list()->update_selections();
});
}
return false;
};
auto hypertext = _u8L("Jump to");
hypertext += std::string(" [") + mo->name + "]";
notification_manager.push_notification(NotificationType::SlicingError, NotificationManager::NotificationLevel::ErrorNotificationLevel,
_u8L("ERROR:") + "\n" + text, hypertext, action_fn);
}
else
notification_manager.close_slicing_error_notification(text);
return;
}
switch (error)
{
case PLATER_WARNING:

View File

@ -362,7 +362,8 @@ class GLCanvas3D
ToolpathOutside,
SlaSupportsOutside,
SomethingNotShown,
ObjectClashed
ObjectClashed,
GCodeConflict
};
class RenderStats

View File

@ -2306,38 +2306,18 @@ void ObjectList::merge(bool to_multipart_object)
for (int obj_idx : obj_idxs) {
ModelObject* object = (*m_objects)[obj_idx];
const Geometry::Transformation& transformation = object->instances[0]->get_transformation();
const Vec3d scale = transformation.get_scaling_factor();
const Vec3d mirror = transformation.get_mirror();
const Vec3d rotation = transformation.get_rotation();
if (object->id() == (*m_objects)[obj_idxs.front()]->id()) {
new_object->add_instance();
new_object->instances[0]->printable = false;
}
new_object->instances[0]->printable |= object->instances[0]->printable;
const Transform3d& volume_offset_correction = transformation.get_matrix();
const Transform3d new_inst_trafo = new_object->instances[0]->get_matrix().inverse() * object->instances[0]->get_matrix();
// merge volumes
for (const ModelVolume* volume : object->volumes) {
ModelVolume* new_volume = new_object->add_volume(*volume);
//set rotation
const Vec3d vol_rot = new_volume->get_rotation() + rotation;
new_volume->set_rotation(vol_rot);
// set scale
const Vec3d vol_sc_fact = new_volume->get_scaling_factor().cwiseProduct(scale);
new_volume->set_scaling_factor(vol_sc_fact);
// set mirror
const Vec3d vol_mirror = new_volume->get_mirror().cwiseProduct(mirror);
new_volume->set_mirror(vol_mirror);
// set offset
const Vec3d vol_offset = volume_offset_correction* new_volume->get_offset();
new_volume->set_offset(vol_offset);
new_volume->set_transformation(new_inst_trafo * new_volume->get_matrix());
}
new_object->sort_volumes(wxGetApp().app_config->get_bool("order_volumes"));

View File

@ -181,6 +181,12 @@ Preview::Preview(
load_print();
}
void Preview::set_layers_slider_values_range(int bottom, int top)
{
m_layers_slider->SetHigherValue(std::min(top, m_layers_slider->GetMaxValue()));
m_layers_slider->SetLowerValue(std::max(bottom, m_layers_slider->GetMinValue()));
}
bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
{
if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */))

View File

@ -151,6 +151,8 @@ public:
void set_keep_current_preview_type(bool value) { m_keep_current_preview_type = value; }
void set_layers_slider_values_range(int bottom, int top);
private:
bool init(wxWindow* parent, Bed3D& bed, Model* model);

View File

@ -1488,8 +1488,7 @@ void GLGizmoCut3D::PartSelection::render(const Vec3d* normal, GLModel& sphere_mo
if (!m_parts[id].is_modifier && normal && ((is_looking_forward && m_parts[id].selected) ||
(!is_looking_forward && !m_parts[id].selected) ) )
continue;
const Vec3d volume_offset = model_object()->volumes[id]->get_offset();
shader->set_uniform("view_model_matrix", view_inst_matrix * translation_transform(volume_offset));
shader->set_uniform("view_model_matrix", view_inst_matrix * model_object()->volumes[id]->get_matrix());
if (m_parts[id].is_modifier) {
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
@ -2425,7 +2424,7 @@ bool GLGizmoCut3D::has_valid_contour() const
return clipper && clipper->has_valid_contour();
}
void GLGizmoCut3D::apply_connectors_in_model(ModelObject* mo, bool &create_dowels_as_separate_object)
void GLGizmoCut3D::apply_connectors_in_model(ModelObject* mo, int &dowels_count)
{
if (m_connector_mode == CutConnectorMode::Manual) {
clear_selection();
@ -2436,7 +2435,7 @@ void GLGizmoCut3D::apply_connectors_in_model(ModelObject* mo, bool &create_dowel
if (connector.attribs.type == CutConnectorType::Dowel) {
if (connector.attribs.style == CutConnectorStyle::Prism)
connector.height *= 2;
create_dowels_as_separate_object = true;
dowels_count ++;
}
else {
// calculate shift of the connector center regarding to the position on the cut plane
@ -2465,6 +2464,34 @@ Transform3d GLGizmoCut3D::get_cut_matrix(const Selection& selection)
return translation_transform(cut_center_offset) * m_rotation_m;
}
void update_object_cut_id(CutObjectBase& cut_id, ModelObjectCutAttributes attributes, const int dowels_count)
{
// we don't save cut information, if result will not contains all parts of initial object
if (!attributes.has(ModelObjectCutAttribute::KeepUpper) ||
!attributes.has(ModelObjectCutAttribute::KeepLower) ||
attributes.has(ModelObjectCutAttribute::InvalidateCutInfo))
return;
if (cut_id.id().invalid())
cut_id.init();
// increase check sum, if it's needed
{
int cut_obj_cnt = -1;
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) cut_obj_cnt++;
if (attributes.has(ModelObjectCutAttribute::KeepLower)) cut_obj_cnt++;
if (attributes.has(ModelObjectCutAttribute::CreateDowels)) cut_obj_cnt+= dowels_count;
if (cut_obj_cnt > 0)
cut_id.increase_check_sum(size_t(cut_obj_cnt));
}
}
void synchronize_model_after_cut(Model& model, const CutObjectBase& cut_id)
{
for (ModelObject* obj : model.objects)
if (obj->is_cut() && obj->cut_id.has_same_id(cut_id) && !obj->cut_id.is_equal(cut_id))
obj->cut_id.copy(cut_id);
}
void GLGizmoCut3D::perform_cut(const Selection& selection)
{
if (!can_perform_cut())
@ -2493,11 +2520,13 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
ModelObject* cut_mo = cut_by_contour ? m_part_selection.model_object() : nullptr;
if (cut_mo)
cut_mo->cut_connectors = mo->cut_connectors;
else
cut_mo = mo;
bool create_dowels_as_separate_object = false;
int dowels_count = 0;
const bool has_connectors = !mo->cut_connectors.empty();
// update connectors pos as offset of its center before cut performing
apply_connectors_in_model(cut_mo ? cut_mo : mo , create_dowels_as_separate_object);
apply_connectors_in_model(cut_mo , dowels_count);
wxBusyCursor wait;
@ -2510,33 +2539,27 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
only_if(m_place_on_cut_lower, ModelObjectCutAttribute::PlaceOnCutLower) |
only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) |
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) |
only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels) |
only_if(!has_connectors, ModelObjectCutAttribute::InvalidateCutInfo);
only_if(dowels_count > 0, ModelObjectCutAttribute::CreateDowels) |
only_if(!has_connectors && cut_mo->cut_id.id().invalid(), ModelObjectCutAttribute::InvalidateCutInfo);
// update cut_id for the cut object in respect to the attributes
update_object_cut_id(cut_mo->cut_id, attributes, dowels_count);
ModelObjectPtrs cut_object_ptrs;
if (cut_by_contour) {
// apply cut attributes for object
if (m_keep_upper && m_keep_lower)
cut_mo->apply_cut_attributes(ModelObjectCutAttribute::KeepLower | ModelObjectCutAttribute::KeepUpper |
only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels));
// Clone the object to duplicate instances, materials etc.
ModelObject* upper{ nullptr };
if (m_keep_upper) cut_mo->clone_for_cut(&upper);
ModelObject* lower{ nullptr };
if (m_keep_lower) cut_mo->clone_for_cut(&lower);
auto add_cut_objects = [this, &instance_idx, &cut_matrix](ModelObjectPtrs& cut_objects, ModelObject* upper, ModelObject* lower, bool invalidate_cut = true) {
auto add_cut_objects = [this, &instance_idx, &cut_matrix](ModelObjectPtrs& cut_objects, ModelObject* upper, ModelObject* lower) {
if (upper && !upper->volumes.empty()) {
ModelObject::reset_instance_transformation(upper, instance_idx, cut_matrix, m_place_on_cut_upper, m_rotate_upper);
if (invalidate_cut)
upper->invalidate_cut();
cut_objects.push_back(upper);
}
if (lower && !lower->volumes.empty()) {
ModelObject::reset_instance_transformation(lower, instance_idx, cut_matrix, m_place_on_cut_lower, m_place_on_cut_lower || m_rotate_lower);
if (invalidate_cut)
lower->invalidate_cut();
cut_objects.push_back(lower);
}
};
@ -2574,7 +2597,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
if (volumes.size() == cut_parts_cnt) {
// Means that object is cut without connectors
// Just add Upper and Lower objects to cut_object_ptrs and invalidate any cut information
// Just add Upper and Lower objects to cut_object_ptrs
add_cut_objects(cut_object_ptrs, upper, lower);
}
else if (volumes.size() > cut_parts_cnt) {
@ -2588,7 +2611,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
// Perform cut just to get connectors
const ModelObjectPtrs cut_connectors_obj = cut_mo->cut(instance_idx, get_cut_matrix(selection), attributes);
assert(create_dowels_as_separate_object ? cut_connectors_obj.size() >= 3 : cut_connectors_obj.size() == 2);
assert(dowels_count > 0 ? cut_connectors_obj.size() >= 3 : cut_connectors_obj.size() == 2);
// Connectors from upper object
for (const ModelVolume* volume : cut_connectors_obj[0]->volumes)
@ -2598,8 +2621,8 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
for (const ModelVolume* volume : cut_connectors_obj[1]->volumes)
lower->add_volume(*volume, volume->type());
// Add Upper and Lower objects to cut_object_ptrs with saved cut information
add_cut_objects(cut_object_ptrs, upper, lower, false);
// Add Upper and Lower objects to cut_object_ptrs
add_cut_objects(cut_object_ptrs, upper, lower);
// Add Dowel-connectors as separate objects to cut_object_ptrs
if (cut_connectors_obj.size() >= 3)
@ -2633,14 +2656,18 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
}
}
else
cut_object_ptrs = mo->cut(instance_idx, cut_matrix, attributes);
cut_object_ptrs = cut_mo->cut(instance_idx, cut_matrix, attributes);
// save cut_id to post update synchronization
const CutObjectBase cut_id = cut_mo->cut_id;
// update cut results on plater and in the model
plater->cut(object_idx, cut_object_ptrs);
synchronize_model_after_cut(plater->model(), cut_id);
}
}
// Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal
// Return false if no intersection was found, true otherwise.
bool GLGizmoCut3D::unproject_on_cut_plane(const Vec2d& mouse_position, Vec3d& pos, Vec3d& pos_world, bool respect_disabled_contour/* = true*/)

View File

@ -315,7 +315,7 @@ private:
bool can_perform_cut() const;
bool has_valid_contour() const;
void apply_connectors_in_model(ModelObject* mo, bool &create_dowels_as_separate_object);
void apply_connectors_in_model(ModelObject* mo, int &dowels_count);
bool cut_line_processing() const;
void discard_cut_line_processing();

View File

@ -243,7 +243,7 @@ coord_t get_skirt_offset(const Plater* plater) {
void ArrangeJob::prepare()
{
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
m_selection_only ? prepare_selected() : prepare_all();
coord_t min_offset = 0;
for (auto &ap : m_selected) {
@ -307,7 +307,10 @@ void ArrangeJob::process(Ctl &ctl)
_u8L("Arranging done."));
}
ArrangeJob::ArrangeJob() : m_plater{wxGetApp().plater()} {}
ArrangeJob::ArrangeJob(Mode mode)
: m_plater{wxGetApp().plater()},
m_selection_only{mode == Mode::SelectionOnly}
{}
static std::string concat_strings(const std::set<std::string> &strings,
const std::string &delim = "\n")

View File

@ -24,6 +24,7 @@ class ArrangeJob : public Job
coord_t m_min_bed_inset = 0.;
Plater *m_plater;
bool m_selection_only = false;
// clear m_selected and m_unselected, reserve space for next usage
void clear_input();
@ -39,11 +40,13 @@ class ArrangeJob : public Job
public:
enum Mode { Full, SelectionOnly };
void prepare();
void process(Ctl &ctl) override;
ArrangeJob();
ArrangeJob(Mode mode = Full);
int status_range() const
{

View File

@ -0,0 +1,60 @@
#ifndef CANCELLABLEJOB_HPP
#define CANCELLABLEJOB_HPP
#include <atomic>
#include "Job.hpp"
namespace Slic3r { namespace GUI {
template<class JobSubclass>
class CancellableJob: public Job {
JobSubclass m_job;
std::atomic_bool &m_flag;
public:
template<class... Args>
CancellableJob(std::atomic_bool &flag, Args &&...args)
: m_job{std::forward<Args>(args)...}, m_flag{flag}
{}
void process(Ctl &ctl) override
{
m_flag.store(false);
struct CancelCtl : public Ctl
{
Ctl &basectl;
std::atomic_bool &cflag;
CancelCtl (Ctl &c, std::atomic_bool &f): basectl{c}, cflag{f} {}
void update_status(int st, const std::string &msg = "") override
{
basectl.update_status(st, msg);
}
bool was_canceled() const override
{
return cflag.load() || basectl.was_canceled();
}
std::future<void> call_on_main_thread(
std::function<void()> fn) override
{
return basectl.call_on_main_thread(fn);
}
} cctl(ctl, m_flag);
m_job.process(cctl);
}
void finalize(bool canceled, std::exception_ptr &eptr) override
{
m_job.finalize(m_flag.load() || canceled, eptr);
}
};
}} // namespace Slic3r::GUI
#endif // CANCELLABLEJOB_HPP

View File

@ -1,4 +1,5 @@
#include "Plater.hpp"
#include "slic3r/GUI/Jobs/UIThreadWorker.hpp"
#include <cstddef>
#include <algorithm>
@ -1794,6 +1795,8 @@ struct Plater::priv
bool init_view_toolbar();
bool init_collapse_toolbar();
void set_preview_layers_slider_values_range(int bottom, int top);
void update_preview_moves_slider();
void enable_preview_moves_slider(bool enable);
@ -4632,6 +4635,11 @@ bool Plater::priv::init_collapse_toolbar()
return true;
}
void Plater::priv::set_preview_layers_slider_values_range(int bottom, int top)
{
preview->set_layers_slider_values_range(bottom, top);
}
void Plater::priv::update_preview_moves_slider()
{
preview->update_moves_slider();
@ -6311,7 +6319,9 @@ void Plater::cut(size_t obj_idx, const ModelObjectPtrs& new_objects)
for (size_t i = 0; i < new_objects.size(); ++i)
selection.add_object((unsigned int)(last_id - i), i == 0);
arrange();
UIThreadWorker w;
replace_job(w, std::make_unique<ArrangeJob>(ArrangeJob::SelectionOnly));
w.process_events();
}
void Plater::export_gcode(bool prefer_removable)
@ -7196,7 +7206,11 @@ void Plater::arrange()
if (p->can_arrange()) {
auto &w = get_ui_job_worker();
p->take_snapshot(_L("Arrange"));
replace_job(w, std::make_unique<ArrangeJob>());
auto mode = wxGetKeyState(WXK_SHIFT) ? ArrangeJob::SelectionOnly :
ArrangeJob::Full;
replace_job(w, std::make_unique<ArrangeJob>(mode));
}
}
@ -7506,6 +7520,11 @@ GLToolbar& Plater::get_collapse_toolbar()
return p->collapse_toolbar;
}
void Plater::set_preview_layers_slider_values_range(int bottom, int top)
{
p->set_preview_layers_slider_values_range(bottom, top);
}
void Plater::update_preview_moves_slider()
{
p->update_preview_moves_slider();

View File

@ -399,6 +399,8 @@ public:
const GLToolbar& get_collapse_toolbar() const;
GLToolbar& get_collapse_toolbar();
void set_preview_layers_slider_values_range(int bottom, int top);
void update_preview_moves_slider();
void enable_preview_moves_slider(bool enable);