Merge branch 'et_world_coordinates' into fs_emboss
This commit is contained in:
commit
3e9778b46b
2
.github/ISSUE_TEMPLATE/bug_report_form.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report_form.yml
vendored
@ -22,7 +22,7 @@ body:
|
||||
label: Project file & How to reproduce
|
||||
description: "*Please* upload a ZIP archive containing the project file used when the problem arise. Please export it just before the problem occurs. Even if you did nothing and/or there is no object, export it! (it contains your current configuration)."
|
||||
placeholder: |
|
||||
`File`->`Export project as...` then zip it & drop it here
|
||||
`File`->`Save project as...` then zip it & drop it here
|
||||
Also, if needed include the steps to reproduce the bug:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
|
BIN
doc/seam_placement/corner_penalty_function.png
Normal file
BIN
doc/seam_placement/corner_penalty_function.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
@ -8412,7 +8412,7 @@ msgstr "Überlauf"
|
||||
#: src/slic3r/GUI/GUI_Preview.cpp:241 src/libslic3r/ExtrusionEntity.cpp:320
|
||||
#: src/libslic3r/ExtrusionEntity.cpp:344
|
||||
msgid "Overhang perimeter"
|
||||
msgstr "Überhängende Außenkontur"
|
||||
msgstr "Überhängende Kontur"
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:2767
|
||||
msgid "Overhang threshold"
|
||||
@ -8731,7 +8731,7 @@ msgstr ""
|
||||
#: src/slic3r/GUI/GUI_Preview.cpp:239 src/libslic3r/ExtrusionEntity.cpp:318
|
||||
#: src/libslic3r/ExtrusionEntity.cpp:340
|
||||
msgid "Perimeter"
|
||||
msgstr "Außenkontur"
|
||||
msgstr "Kontur"
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1946
|
||||
msgid "Perimeter extruder"
|
||||
@ -10848,8 +10848,8 @@ msgstr ""
|
||||
"Setzen Sie dies auf einen Nicht-Nullwert, um eine manuelle Extrusionsbreite "
|
||||
"zuzulassen. Falls auf null belassen, wird PrusaSlicer die Extrusionsbreiten "
|
||||
"vom Durchmesser der Druckdüse ableiten (siehe die Hilfstexte für die "
|
||||
"Extrusionsbreite für Außenkonturen, Infill usw.). Falls als Prozentwert (z."
|
||||
"B. 230%) angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
|
||||
"Extrusionsbreite für Konturen, Infill usw.). Falls als Prozentwert (z.B. "
|
||||
"230%) angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:729
|
||||
msgid ""
|
||||
@ -10859,10 +10859,10 @@ msgid ""
|
||||
"(for example 200%), it will be computed over layer height."
|
||||
msgstr ""
|
||||
"Setzen Sie dies auf einen Nicht-Nullwert, um eine manuelle Extrusionsbreite "
|
||||
"für externe Außenkonturen anzugeben. Falls auf null belassen, wird die "
|
||||
"Standard-Extrusionsbreite verwendet (falls angeben), ansonsten wird der "
|
||||
"Durchmesser der Druckdüse x 1,125 verwendet. Falls als Prozentwert (z.B. "
|
||||
"200%) angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
|
||||
"für Außenkonturen anzugeben. Falls auf null belassen, wird die Standard-"
|
||||
"Extrusionsbreite verwendet (falls angeben), ansonsten wird der Durchmesser "
|
||||
"der Druckdüse x 1,125 verwendet. Falls als Prozentwert (z.B. 200%) "
|
||||
"angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1196
|
||||
msgid ""
|
||||
@ -10931,7 +10931,7 @@ msgid ""
|
||||
"it will be computed over layer height."
|
||||
msgstr ""
|
||||
"Setzen Sie dies auf einen Nicht-Nullwert, um eine manuelle Extrusionsbreite "
|
||||
"für Außenkonturen anzugeben. Dünnere Extrusionsbreiten sind vorteilhaft, um "
|
||||
"für Konturen anzugeben. Dünnere Extrusionsbreiten sind vorteilhaft, um "
|
||||
"genauere Oberflächen zu erhalten. Falls auf null belassen, wird die Standard-"
|
||||
"Extrusionsbreite verwendet (falls angeben), ansonsten wird der Durchmesser "
|
||||
"der Druckdüse x 1,125 verwendet. Falls als Prozentwert (z.B. 200%) "
|
||||
@ -11797,7 +11797,7 @@ msgid ""
|
||||
"for auto."
|
||||
msgstr ""
|
||||
"Druckgeschwindigkeit für die oberen massiven Schichten (betrifft nur die "
|
||||
"obersten Außenkonturen und nicht deren innenliegende massiven Schichten). "
|
||||
"obersten Außenschichten und nicht deren innenliegende massiven Schichten). "
|
||||
"Wir empfehlen, diesen Wert zu reduzieren, um eine schönere Oberfläche zu "
|
||||
"erhalten. Dies kann als Prozentwert (z.B. 80%) der oben eingegebenen "
|
||||
"Geschwindigkeit für massives Infill angegeben werden. Für Automatik auf null "
|
||||
@ -12613,8 +12613,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Der Extruder, der verwendet werden soll, falls keine sonstigen "
|
||||
"Extrudereinstellungen angegeben wurden. Dies übersteuert die Angaben für die "
|
||||
"Außenkontur- und Infill-Extruder, aber nicht die Angabe des Extruders für "
|
||||
"die Stützen."
|
||||
"Kontur- und Infill-Extruder, aber nicht die Angabe des Extruders für die "
|
||||
"Stützen."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1448
|
||||
msgid "The extruder to use when printing infill."
|
||||
@ -13554,8 +13554,8 @@ msgid ""
|
||||
"prevent resetting acceleration at all."
|
||||
msgstr ""
|
||||
"Dies ist der Beschleunigungswert, auf den Ihr Drucker zurückgesetzt wird, "
|
||||
"nachdem aufgabenspezifische Beschleunigungswerte (Außenkonturen/Infill) "
|
||||
"verwendet wurden. Setzen Sie dies auf null, um ein Zurückstellen der "
|
||||
"nachdem aufgabenspezifische Beschleunigungswerte (Konturen/Infill) verwendet "
|
||||
"wurden. Setzen Sie dies auf null, um ein Zurückstellen der "
|
||||
"Beschleunigungswerte zu deaktivieren."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:443
|
||||
@ -13679,11 +13679,11 @@ msgid ""
|
||||
"surfaces which benefit from a higher number of perimeters if the Extra "
|
||||
"Perimeters option is enabled."
|
||||
msgstr ""
|
||||
"Diese Stellung bestimmt die Anzahl der Außenkonturen, die für jede Schicht "
|
||||
"Diese Stellung bestimmt die Anzahl der Konturen, die für jede Schicht "
|
||||
"erzeugt werden. PusaSlicer kann diese Zahl automatisch vergrößern, wenn es "
|
||||
"schräge Oberflächen erkennt, die sich mit einer höheren Zahl von "
|
||||
"Außenkonturen besser drucken lassen, wenn die \"Zusätzliche Außenkonturen "
|
||||
"falls notwendig\" Option aktiviert ist."
|
||||
"schräge Oberflächen erkennt, die sich mit einer höheren Zahl von Konturen "
|
||||
"besser drucken lassen, wenn die \"Zusätzliche Konturen falls notwendig\" "
|
||||
"Option aktiviert ist."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1895
|
||||
msgid ""
|
||||
@ -13712,8 +13712,8 @@ msgid ""
|
||||
"This option will switch the print order of perimeters and infill, making the "
|
||||
"latter first."
|
||||
msgstr ""
|
||||
"Diese Einstellungen kehrt die Druckreihenfolge von Außenkonturen und Infill "
|
||||
"um, sodass der Infill zuerst gedruckt wird."
|
||||
"Diese Einstellungen kehrt die Druckreihenfolge von Konturen und Infill um, "
|
||||
"sodass der Infill zuerst gedruckt wird."
|
||||
|
||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:83
|
||||
msgid "This printer will be shown in the presets list as"
|
||||
@ -13726,9 +13726,9 @@ msgid ""
|
||||
"calculated on the perimeters speed setting above. Set to zero for auto."
|
||||
msgstr ""
|
||||
"Diese separate Einstellung wirkt sich auf die Geschwindigkeit der äußeren "
|
||||
"(sichtbaren) Außenkonturen aus. Als Prozentwert eingegeben (z.B. 80%), wird "
|
||||
"sie ausgehend von der obigen Geschwindigkeitseinstellung für Außenkonturen "
|
||||
"berechnet. Für die automatische Berechnung auf null setzen."
|
||||
"(sichtbaren) Konturen aus. Als Prozentwert eingegeben (z.B. 80%), wird sie "
|
||||
"ausgehend von der obigen Geschwindigkeitseinstellung für Konturen berechnet. "
|
||||
"Für die automatische Berechnung auf null setzen."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:2303
|
||||
msgid ""
|
||||
@ -13736,11 +13736,11 @@ msgid ""
|
||||
"6.5mm (usually holes). If expressed as percentage (for example: 80%) it will "
|
||||
"be calculated on the perimeters speed setting above. Set to zero for auto."
|
||||
msgstr ""
|
||||
"Diese separate Einstellung wirkt sich auf die Geschwindigkeit von "
|
||||
"Außenkonturen mit einem Radius <= 6,5 mm (üblicherweise Bohrungen) aus. Als "
|
||||
"Prozentwert eingegeben (z.B. 80%), wird sie ausgehend von der obigen "
|
||||
"Geschwindigkeitseinstellung für Außenkonturen berechnet. Für eine "
|
||||
"automatische Berechnung setzen Sie dies auf null."
|
||||
"Diese separate Einstellung wirkt sich auf die Geschwindigkeit von Konturen "
|
||||
"mit einem Radius <= 6,5 mm (üblicherweise Bohrungen) aus. Als Prozentwert "
|
||||
"eingegeben (z.B. 80%), wird sie ausgehend von der obigen "
|
||||
"Geschwindigkeitseinstellung für Konturen berechnet. Für eine automatische "
|
||||
"Berechnung setzen Sie dies auf null."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1484
|
||||
msgid ""
|
||||
@ -13749,11 +13749,11 @@ msgid ""
|
||||
"cause gaps. If expressed as percentage (example: 15%) it is calculated over "
|
||||
"perimeter extrusion width."
|
||||
msgstr ""
|
||||
"Diese Einstellung fügt eine zusätzliche Überlappung zwischen Außenkonturen "
|
||||
"und Infill ein, um die Haftung zu verbessern. Theoretisch sollte dies nicht "
|
||||
"Diese Einstellung fügt eine zusätzliche Überlappung zwischen Konturen und "
|
||||
"Infill ein, um die Haftung zu verbessern. Theoretisch sollte dies nicht "
|
||||
"notwendig sein, doch vorhandenes Getriebespiel könnte Lücken erzeugen. Als "
|
||||
"Prozentwert eingegeben (z.B. 15%) wird sie ausgehend von der "
|
||||
"Extrusionsbreite für die Außenkontur ausgerechnet."
|
||||
"Extrusionsbreite für die Kontur ausgerechnet."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:265
|
||||
msgid ""
|
||||
@ -15816,7 +15816,7 @@ msgstr "Parametername"
|
||||
|
||||
#: src/slic3r/GUI/PresetHints.cpp:171
|
||||
msgid "perimeters"
|
||||
msgstr "Außenkonturen"
|
||||
msgstr "Konturen"
|
||||
|
||||
#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:64 src/libslic3r/Preset.cpp:1338
|
||||
msgid "print"
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.4.0-rc
|
||||
1.4.5 Added MMU2/S profiles for 0.25mm nozzle. Updated FW version. Enabled g-code thumbnails for MK3 family printers. Updated end g-code.
|
||||
1.4.4 Added multiple Fiberlogy filament profiles. Updated Extrudr filament profiles.
|
||||
1.4.3 Added new filament profiles and SLA materials.
|
||||
1.4.2 Added SLA material profiles.
|
||||
@ -24,6 +25,7 @@ min_slic3r_version = 2.4.0-alpha0
|
||||
1.3.0-alpha1 Added Prusament PCCF. Increased travel acceleration for Prusa MINI. Updated start g-code for Prusa MINI. Added multiple add:north and Extrudr filament profiles. Updated Z travel speed values.
|
||||
1.3.0-alpha0 Disabled thick bridges, updated support settings.
|
||||
min_slic3r_version = 2.3.2-alpha0
|
||||
1.3.7 Updated firmware version.
|
||||
1.3.6 Updated firmware version.
|
||||
1.3.5 Added material profiles for Prusament Resins.
|
||||
1.3.4 Added material profiles for new Prusament Resins. Added profiles for multiple BASF filaments.
|
||||
@ -32,6 +34,7 @@ min_slic3r_version = 2.3.2-alpha0
|
||||
1.3.1 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S).
|
||||
1.3.0 Added SL1S SPEED profiles.
|
||||
min_slic3r_version = 2.3.0-rc1
|
||||
1.2.12 Updated firmware version.
|
||||
1.2.11 Updated firmware version.
|
||||
1.2.10 Added multiple profiles for Filatech filaments. Updated SLA print settings (pad wall slope angle).
|
||||
1.2.9 Added material profiles for Prusament Resin.
|
||||
@ -52,6 +55,7 @@ min_slic3r_version = 2.3.0-alpha4
|
||||
1.2.0-alpha1 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
||||
1.2.0-alpha0 Added filament spool weights
|
||||
min_slic3r_version = 2.2.0-alpha3
|
||||
1.1.16 Updated firmware version.
|
||||
1.1.15 Updated firmware version.
|
||||
1.1.14 Updated firmware version.
|
||||
1.1.13 Updated firmware version. Updated end g-code in MMU2 printer profiles.
|
||||
|
@ -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.4.4
|
||||
config_version = 1.4.5
|
||||
# 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%
|
||||
@ -288,6 +288,7 @@ output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_heig
|
||||
thick_bridges = 0
|
||||
bridge_flow_ratio = 1
|
||||
bridge_speed = 20
|
||||
wipe_tower_bridging = 6
|
||||
|
||||
[print:*0.25nozzleMK3*]
|
||||
inherits = *0.25nozzle*
|
||||
@ -308,6 +309,7 @@ max_print_speed = 80
|
||||
perimeters = 3
|
||||
fill_pattern = grid
|
||||
fill_density = 20%
|
||||
wipe_tower_bridging = 6
|
||||
|
||||
[print:*0.25nozzleMINI*]
|
||||
inherits = *0.25nozzleMK3*
|
||||
@ -691,6 +693,7 @@ solid_infill_speed = 40
|
||||
top_solid_infill_speed = 30
|
||||
support_material_contact_distance = 0.07
|
||||
raft_contact_distance = 0.07
|
||||
single_extruder_multi_material_priming = 0
|
||||
|
||||
[print:0.15mm OPTIMAL @0.25 nozzle]
|
||||
inherits = *0.15mm*; *0.25nozzle*
|
||||
@ -707,6 +710,38 @@ solid_infill_speed = 40
|
||||
top_solid_infill_speed = 30
|
||||
support_material_contact_distance = 0.08
|
||||
raft_contact_distance = 0.07
|
||||
perimeter_extrusion_width = 0.27
|
||||
external_perimeter_extrusion_width = 0.27
|
||||
infill_extrusion_width = 0.27
|
||||
solid_infill_extrusion_width = 0.27
|
||||
single_extruder_multi_material_priming = 0
|
||||
|
||||
[print:0.15mm SOLUBLE FULL @0.25 nozzle]
|
||||
inherits = 0.15mm OPTIMAL @0.25 nozzle
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders>1
|
||||
support_material_contact_distance = 0
|
||||
raft_contact_distance = 0
|
||||
wipe_tower_bridging = 5
|
||||
solid_infill_speed = 40
|
||||
support_material_extruder = 5
|
||||
support_material_interface_extruder = 5
|
||||
support_material_with_sheath = 1
|
||||
support_material_interface_layers = 4
|
||||
support_material_threshold = 60
|
||||
support_material = 1
|
||||
support_material_synchronize_layers = 1
|
||||
support_material_xy_spacing = 100%
|
||||
support_material_style = snug
|
||||
raft_first_layer_expansion = 2
|
||||
support_material_interface_spacing = 0.05
|
||||
single_extruder_multi_material_priming = 0
|
||||
|
||||
[print:0.15mm SOLUBLE INTERFACE @0.25 nozzle]
|
||||
inherits = 0.15mm SOLUBLE FULL @0.25 nozzle
|
||||
support_material_extruder = 0
|
||||
support_material_interface_extruder = 5
|
||||
support_material_with_sheath = 0
|
||||
support_material_style = grid
|
||||
|
||||
## MK2 - 0.6mm nozzle
|
||||
|
||||
@ -992,7 +1027,7 @@ raft_contact_distance = 0.07
|
||||
|
||||
[print:0.07mm ULTRADETAIL @0.25 nozzle MK3]
|
||||
inherits = *0.07mm*; *0.25nozzle*; *MK3*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
|
||||
infill_speed = 30
|
||||
solid_infill_speed = 30
|
||||
support_material_speed = 30
|
||||
@ -1017,6 +1052,36 @@ fill_pattern = grid
|
||||
fill_density = 20%
|
||||
support_material_contact_distance = 0.08
|
||||
raft_contact_distance = 0.07
|
||||
perimeter_extrusion_width = 0.27
|
||||
external_perimeter_extrusion_width = 0.27
|
||||
infill_extrusion_width = 0.27
|
||||
solid_infill_extrusion_width = 0.27
|
||||
|
||||
[print:0.15mm SOLUBLE FULL @0.25 nozzle MK3]
|
||||
inherits = 0.15mm QUALITY @0.25 nozzle MK3
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders>1
|
||||
support_material_contact_distance = 0
|
||||
raft_contact_distance = 0
|
||||
wipe_tower_bridging = 5
|
||||
solid_infill_speed = 40
|
||||
support_material_extruder = 5
|
||||
support_material_interface_extruder = 5
|
||||
support_material_with_sheath = 1
|
||||
support_material_interface_layers = 4
|
||||
support_material_threshold = 60
|
||||
support_material = 1
|
||||
support_material_synchronize_layers = 1
|
||||
support_material_xy_spacing = 100%
|
||||
support_material_style = snug
|
||||
raft_first_layer_expansion = 2
|
||||
support_material_interface_spacing = 0.05
|
||||
|
||||
[print:0.15mm SOLUBLE INTERFACE @0.25 nozzle MK3]
|
||||
inherits = 0.15mm SOLUBLE FULL @0.25 nozzle MK3
|
||||
support_material_extruder = 0
|
||||
support_material_interface_extruder = 5
|
||||
support_material_with_sheath = 0
|
||||
support_material_style = grid
|
||||
|
||||
## MK3 - 0.6mm nozzle
|
||||
|
||||
@ -1315,6 +1380,10 @@ fill_pattern = grid
|
||||
fill_density = 20%
|
||||
support_material_contact_distance = 0.08
|
||||
raft_contact_distance = 0.07
|
||||
perimeter_extrusion_width = 0.27
|
||||
external_perimeter_extrusion_width = 0.27
|
||||
infill_extrusion_width = 0.27
|
||||
solid_infill_extrusion_width = 0.27
|
||||
|
||||
# MINI - 0.6mm nozzle
|
||||
|
||||
@ -3331,7 +3400,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_model!="MINI
|
||||
|
||||
[filament:*ABS MMU2*]
|
||||
inherits = Prusa ABS
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
filament_cooling_final_speed = 50
|
||||
filament_cooling_initial_speed = 10
|
||||
filament_cooling_moves = 5
|
||||
@ -3346,6 +3415,92 @@ filament_unloading_speed = 20
|
||||
inherits = *ABS MMU2*
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Generic ABS @MMU2 0.25]
|
||||
inherits = Generic ABS @MMU2
|
||||
filament_max_volumetric_speed = 1.7
|
||||
filament_ramming_parameters = "200 110 3.41935 3.6129 3.93548 4.35484 4.87097 5.51613 6.25806 7.06452 7.80645 8.35484 8.70968 8.83871| 0.05 3.37419 0.45 3.70322 0.95 4.5742 1.45 5.78387 1.95 7.44194 2.45 8.58065 2.95 8.89045 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Generic PLA @MMU2 0.25]
|
||||
inherits = Generic PLA @MMU2
|
||||
filament_max_volumetric_speed = 3
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 120 2.70968 2.93548 3.29032 3.80645 4.58065 5.54839 6.54839 7.3871 7.93548 8.19355 8.16129 8.03226| 0.05 2.66451 0.45 3.05805 0.95 4.05807 1.45 5.97742 1.95 7.69999 2.45 8.1936 2.95 7.98716 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusa PLA @MMU2 0.25]
|
||||
inherits = Generic PLA @MMU2 0.25
|
||||
|
||||
[filament:Prusament PLA @MMU2 0.25]
|
||||
inherits = Prusament PLA @MMU2
|
||||
filament_max_volumetric_speed = 3
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 120 2.70968 2.93548 3.29032 3.80645 4.58065 5.54839 6.54839 7.3871 7.93548 8.19355 8.16129 8.03226| 0.05 2.66451 0.45 3.05805 0.95 4.05807 1.45 5.97742 1.95 7.69999 2.45 8.1936 2.95 7.98716 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusament PVB @MMU2 0.25]
|
||||
inherits = Prusament PVB @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 110 1.74194 1.90323 2.16129 2.48387 2.83871 3.25806 3.83871 4.6129 5.41935 5.96774| 0.05 1.69677 0.45 1.96128 0.95 2.63872 1.45 3.46129 1.95 4.99031 2.45 6.12908 2.95 8.30974 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusament ASA @MMU2 0.25]
|
||||
inherits = Prusament ASA @MMU2
|
||||
filament_max_volumetric_speed = 1.7
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 110 3.41935 3.6129 3.93548 4.35484 4.87097 5.51613 6.25806 7.06452 7.80645 8.35484 8.70968 8.83871| 0.05 3.37419 0.45 3.70322 0.95 4.5742 1.45 5.78387 1.95 7.44194 2.45 8.58065 2.95 8.89045 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusament PC Blend @MMU2 0.25]
|
||||
inherits = Prusament PC Blend @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 120 2.70968 2.93548 3.32258 3.83871 4.58065 5.54839 6.51613 7.35484 7.93548 8.16129| 0.05 2.66451 0.45 3.05805 0.95 4.05807 1.45 5.97742 1.95 7.69999 2.45 8.1936 2.95 11.342 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusa ABS @MMU2 0.25]
|
||||
inherits = Prusa ABS @MMU2
|
||||
filament_max_volumetric_speed = 1.7
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 110 3.41935 3.6129 3.93548 4.35484 4.87097 5.51613 6.25806 7.06452 7.80645 8.35484 8.70968 8.83871| 0.05 3.37419 0.45 3.70322 0.95 4.5742 1.45 5.78387 1.95 7.44194 2.45 8.58065 2.95 8.89045 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Generic PETG @MMU2 0.25]
|
||||
inherits = Generic PETG @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusa PETG @MMU2 0.25]
|
||||
inherits = Prusa PETG @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Prusament PETG @MMU2 0.25]
|
||||
inherits = Prusament PETG @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Verbatim BVOH @MMU2 0.25]
|
||||
inherits = Verbatim BVOH @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 110 1.74194 1.90323 2.16129 2.48387 2.83871 3.25806 3.83871 4.6129 5.41935 5.96774| 0.05 1.69677 0.45 1.96128 0.95 2.63872 1.45 3.46129 1.95 4.99031 2.45 6.12908 2.95 8.30974 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:PrimaSelect PVA+ @MMU2 0.25]
|
||||
inherits = PrimaSelect PVA+ @MMU2
|
||||
filament_max_volumetric_speed = 2
|
||||
filament_minimal_purge_on_wipe_tower = 10
|
||||
filament_ramming_parameters = "200 110 2.32258 2.48387 2.67742 2.87097 3.03226 3.22581 3.48387 3.80645 4.29032 5 5.93548 7 7.90323 8.48387 8.80645 8.90323| 0.05 2.27741 0.45 2.54192 0.95 2.9613 1.45 3.33225 1.95 4.02257 2.45 5.48393 2.95 7.72915 3.45 8.76139 3.95 8.95485 4.45 7.6 4.95 7.6"
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
|
||||
[filament:Generic HIPS @MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
filament_vendor = Generic
|
||||
@ -3585,7 +3740,7 @@ filament_type = PETG
|
||||
|
||||
[filament:*PET MMU2*]
|
||||
inherits = Prusa PETG
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
temperature = 230
|
||||
first_layer_temperature = 230
|
||||
filament_cooling_final_speed = 1
|
||||
@ -4041,7 +4196,7 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and no
|
||||
|
||||
[filament:*PLA MMU2*]
|
||||
inherits = Prusa PLA
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
temperature = 205
|
||||
filament_cooling_final_speed = 2
|
||||
filament_cooling_initial_speed = 3
|
||||
@ -4290,7 +4445,7 @@ temperature = 210
|
||||
[filament:Verbatim BVOH @MMU2]
|
||||
inherits = Verbatim BVOH
|
||||
filament_vendor = Verbatim
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
temperature = 195
|
||||
fan_always_on = 1
|
||||
first_layer_temperature = 200
|
||||
@ -4310,7 +4465,7 @@ filament_loading_speed_start = 19
|
||||
[filament:PrimaSelect PVA+ @MMU2]
|
||||
inherits = *common*
|
||||
filament_vendor = PrimaSelect
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
bed_temperature = 60
|
||||
bridge_fan_speed = 100
|
||||
cooling = 0
|
||||
@ -8199,7 +8354,7 @@ bed_shape = 0x0,250x0,250x210,0x210
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\n\n
|
||||
between_objects_gcode =
|
||||
deretract_speed = 0
|
||||
end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y200 F3600 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
extruder_offset = 0x0
|
||||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
@ -8280,7 +8435,7 @@ printer_model = MK2SMM
|
||||
|
||||
[printer:*mm-single*]
|
||||
inherits = *multimaterial*
|
||||
end_gcode = G1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n\n
|
||||
end_gcode = G1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+50, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n\n
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0\nM203 E100\nM92 E140\nG1 Z0.25 F7200\nG1 X50 E80 F1000\nG1 X160 E20 F1000\nG1 Z0.2 F7200\nG1 X220 E13 F1000\nG1 X240 E0 F1000\nG92 E0
|
||||
default_print_profile = 0.15mm OPTIMAL
|
||||
@ -8288,7 +8443,7 @@ default_print_profile = 0.15mm OPTIMAL
|
||||
[printer:*mm-multi*]
|
||||
inherits = *multimaterial*
|
||||
high_current_on_filament_swap = 1
|
||||
end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.\nG1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\n{endif}\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.\nG1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\n{endif}\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+50, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
extruder_colour = #FFAA55;#E37BA0;#4ECDD3;#FB7259
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
|
||||
@ -8364,21 +8519,21 @@ inherits = Original Prusa i3 MK2S
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
machine_max_jerk_e = 4.5
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.25 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
machine_max_jerk_e = 4.5
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.6 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
machine_max_jerk_e = 4.5
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.8 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.6 nozzle
|
||||
@ -8390,7 +8545,7 @@ min_layer_height = 0.2
|
||||
retract_length = 1
|
||||
remaining_times = 1
|
||||
machine_max_jerk_e = 4.5
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
|
||||
default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
default_filament_profile = Prusament PLA @0.8 nozzle
|
||||
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
|
||||
@ -8403,8 +8558,8 @@ max_print_height = 200
|
||||
default_print_profile = 0.15mm OPTIMAL @MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; load to nozzle\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.20 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; load to nozzle\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.20 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 Single 0.8 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S Single 0.8 nozzle
|
||||
@ -8427,8 +8582,8 @@ printer_notes = Don't remove the following keywords! These keywords are used in
|
||||
single_extruder_multi_material = 1
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
|
||||
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S]
|
||||
inherits = Original Prusa i3 MK2.5
|
||||
@ -8454,8 +8609,8 @@ max_print_height = 200
|
||||
default_print_profile = 0.15mm OPTIMAL @MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S Single 0.8 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S Single
|
||||
@ -8465,7 +8620,7 @@ min_layer_height = 0.2
|
||||
nozzle_diameter = 0.8
|
||||
printer_variant = 0.8
|
||||
retract_length = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
default_filament_profile = Prusament PLA @0.8 nozzle
|
||||
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
|
||||
@ -8489,7 +8644,7 @@ nozzle_diameter = 0.25
|
||||
printer_variant = 0.25
|
||||
retract_lift = 0.15
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S]
|
||||
@ -8501,8 +8656,8 @@ printer_notes = Don't remove the following keywords! These keywords are used in
|
||||
single_extruder_multi_material = 1
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
|
||||
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S
|
||||
@ -8522,6 +8677,26 @@ printer_variant = 0.6
|
||||
default_print_profile = 0.20mm NORMAL @0.6 nozzle
|
||||
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S
|
||||
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle
|
||||
default_filament_profile = Prusament PLA @MMU2 0.25
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 MMU2
|
||||
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle
|
||||
default_filament_profile = Prusament PLA @MMU2 0.25
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
## 0.8mm nozzle profiles are only available for MMU2 Single mode at the moment.
|
||||
|
||||
## [printer:Original Prusa i3 MK2.5S MMU2S 0.8 nozzle]
|
||||
@ -8532,7 +8707,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
## printer_variant = 0.8
|
||||
## retract_length = 1
|
||||
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
|
||||
## [printer:Original Prusa i3 MK2.5 MMU2 0.8 nozzle]
|
||||
## inherits = Original Prusa i3 MK2.5 MMU2
|
||||
@ -8542,7 +8717,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
## printer_variant = 0.8
|
||||
## retract_length = 1
|
||||
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
|
||||
# XXXXXXXXXXXXXXXXX
|
||||
# XXX--- MK3 ---XXX
|
||||
@ -8550,7 +8725,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
[printer:Original Prusa i3 MK3]
|
||||
inherits = *common*
|
||||
end_gcode = G4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y200 F3600 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM84 ; disable motors
|
||||
machine_max_acceleration_e = 5000,5000
|
||||
machine_max_acceleration_extruding = 1250,1250
|
||||
machine_max_acceleration_retracting = 1250,1250
|
||||
@ -8572,9 +8747,10 @@ remaining_times = 1
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
|
||||
retract_lift_below = 209
|
||||
max_print_height = 210
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
printer_model = MK3
|
||||
default_print_profile = 0.15mm QUALITY @MK3
|
||||
thumbnails = 160x120
|
||||
|
||||
[printer:Original Prusa i3 MK3 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK3
|
||||
@ -8583,7 +8759,7 @@ max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
retract_lift = 0.15
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E8 F700 ; intro line\nG1 X100 E12.5 F700 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E8 F700 ; intro line\nG1 X100 E12.5 F700 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
@ -8593,7 +8769,7 @@ nozzle_diameter = 0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
@ -8604,7 +8780,7 @@ max_layer_height = 0.6
|
||||
min_layer_height = 0.2
|
||||
printer_variant = 0.8
|
||||
retract_length = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S95
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S95
|
||||
default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
default_filament_profile = Prusament PLA @0.8 nozzle
|
||||
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
|
||||
@ -8676,8 +8852,8 @@ default_filament_profile = Prusament PLA @MMU2
|
||||
inherits = *mm2*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2 Single 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3 MMU2 Single
|
||||
@ -8686,7 +8862,7 @@ nozzle_diameter = 0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
@ -8698,7 +8874,7 @@ max_layer_height = 0.6
|
||||
min_layer_height = 0.2
|
||||
printer_variant = 0.8
|
||||
retract_length = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
default_filament_profile = Prusament PLA @0.8 nozzle
|
||||
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
|
||||
@ -8711,7 +8887,7 @@ max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
retract_lift = 0.15
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F1000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F1000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
@ -8720,16 +8896,16 @@ inherits = *mm2*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK3S & MK3S+ MMU2S Single]
|
||||
inherits = *mm2s*
|
||||
renamed_from = "Original Prusa i3 MK3S MMU2S Single"
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3S & MK3S+ MMU2S Single 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3S & MK3S+ MMU2S Single
|
||||
@ -8739,7 +8915,7 @@ nozzle_diameter = 0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
@ -8751,7 +8927,7 @@ max_layer_height = 0.6
|
||||
min_layer_height = 0.2
|
||||
printer_variant = 0.8
|
||||
retract_length = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
default_filament_profile = Prusament PLA @0.8 nozzle
|
||||
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
|
||||
@ -8765,7 +8941,7 @@ max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
retract_lift = 0.15
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
@ -8775,8 +8951,8 @@ renamed_from = "Original Prusa i3 MK3S MMU2S"
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors\n
|
||||
|
||||
## 0.6mm nozzle MMU2/S printer profiles
|
||||
|
||||
@ -8787,7 +8963,7 @@ nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
@ -8797,10 +8973,30 @@ nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
|
||||
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
|
||||
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
|
||||
[printer:Original Prusa i3 MK3S & MK3S+ MMU2S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK3S & MK3S+ MMU2S 0.6 nozzle
|
||||
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
|
||||
default_filament_profile = Prusament PLA @MMU2 0.25
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK3 MMU2 0.6 nozzle
|
||||
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
|
||||
default_filament_profile = Prusament PLA @MMU2 0.25
|
||||
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
|
||||
|
||||
## 0.8mm nozzle MMU2/S printer profiles
|
||||
|
||||
## For later use. 0.8mm nozzle profiles are only available for MMU2 Single mode at the moment.
|
||||
@ -8811,7 +9007,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
## max_layer_height = 0.6
|
||||
## min_layer_height = 0.2
|
||||
## printer_variant = 0.8
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
|
||||
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
|
||||
## [printer:Original Prusa i3 MK3S & MK3S+ MMU2S 0.8 nozzle]
|
||||
@ -8820,7 +9016,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
|
||||
## max_layer_height = 0.6
|
||||
## min_layer_height = 0.2
|
||||
## printer_variant = 0.8
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
|
||||
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
|
||||
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
|
||||
|
||||
## MINI
|
||||
|
@ -1,3 +1,5 @@
|
||||
min_slic3r_version = 2.4.1-rc1
|
||||
1.0.0 Added AzteQ Industrial profiles for 0.8 nozzle, updated spool weight and filament cost, some minor setting improvements
|
||||
min_slic3r_version = 2.3.2-alpha0
|
||||
0.0.9 Added AzteQ Industrial materials PC/ABS (Fillamentum), PC-Max (Polymaker), Nylon FX256 (Fillamentum), Added DeltiQ 2 materials Nylon PA12 (Fiberlogy), Nylon CF15 Carbon (Fillamentum), PEBA 90A - FlexFill (Fillamentum), MoldLay (Wax-Alike), disabled retract only when crossing perimeters, some minor setting improvements
|
||||
0.0.8 Added new AzteQ Industrial printer, added DeltiQ 2 profiles for 0.6mm nozzle, added material ASA 275 (Spectrum), some minor setting improvements
|
||||
|
@ -6,7 +6,7 @@
|
||||
name = TriLAB
|
||||
# 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 = 0.0.9
|
||||
config_version = 1.0.0
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -17,12 +17,12 @@ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/Prus
|
||||
|
||||
[printer_model:AQI]
|
||||
name = AzteQ Industrial
|
||||
variants = 0.4; 0.6
|
||||
variants = 0.4; 0.6; 0.8
|
||||
technology = FFF
|
||||
family = AzteQ
|
||||
bed_model = aq_bed.stl
|
||||
bed_texture = aq_bed_texture.svg
|
||||
default_materials = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum);AzteQ Industrial (Door Opened) - PLA - Generic;AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum);AzteQ Industrial - ABS - ExtraFill (Fillamentum);AzteQ Industrial - ABS - Generic;AzteQ Industrial - ASA - ExtraFill (Fillamentum);AzteQ Industrial - ASA - Generic;AzteQ Industrial - ASA - Prusament (Prusa);AzteQ Industrial - PA - Nylon PA12 (Fiberlogy);AzteQ Industrial - PC Blend - Prusament (Prusa);AzteQ Industrial - PC - PolyMax (Polymaker);AzteQ Industrial - PC - PolyMax (Polymaker) @0.6 nozzle;AzteQ Industrial - PC/ABS - (Fillamentum);AzteQ Industrial - PC/ABS - (Fillamentum) @0.6 nozzle;AzteQ Industrial - PA - Nylon FX256 (Fillamentum);AzteQ Industrial - PA - Nylon FX256 (Fillamentum) @0.6 nozzle
|
||||
default_materials = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum);AzteQ Industrial (Door Opened) - PLA - Generic;AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum);AzteQ Industrial - ABS - ExtraFill (Fillamentum);AzteQ Industrial - ABS - Generic;AzteQ Industrial - ASA - ExtraFill (Fillamentum);AzteQ Industrial - ASA - Generic;AzteQ Industrial - ASA - Prusament (Prusa);AzteQ Industrial - PA - Nylon PA12 (Fiberlogy);AzteQ Industrial - PC Blend - Prusament (Prusa);AzteQ Industrial - PC - PolyMax (Polymaker);AzteQ Industrial - PC - PolyMax (Polymaker) @0.6 nozzle;AzteQ Industrial - PC/ABS - (Fillamentum);AzteQ Industrial - PC/ABS - (Fillamentum) @0.6 nozzle;AzteQ Industrial - PA - Nylon FX256 (Fillamentum);AzteQ Industrial - PA - Nylon FX256 (Fillamentum) @0.6 nozzle;AzteQ Industrial - ABS - Generic @0.8 nozzle;AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - Prusament (Prusa) @0.8 nozzle;AzteQ Industrial - PC Blend - Prusament (Prusa) @0.8 nozzle
|
||||
|
||||
[printer_model:DQ2]
|
||||
name = DeltiQ 2
|
||||
@ -569,6 +569,106 @@ inherits = AzteQ Industrial 0.30mm Normal @0.6 nozzle
|
||||
fill_density = 10%
|
||||
layer_height = 0.35
|
||||
|
||||
[print:AzteQ Industrial 0.40mm Normal @0.8 nozzle]
|
||||
inherits = AzteQ Industrial 0.20mm Normal
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
|
||||
avoid_crossing_perimeters = 0
|
||||
avoid_crossing_perimeters_max_detour = 0
|
||||
bottom_solid_layers = 4
|
||||
bottom_solid_min_thickness = 0.7
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 30
|
||||
dont_support_bridges = 0
|
||||
elefant_foot_compensation = 0
|
||||
ensure_vertical_shell_thickness = 0
|
||||
external_perimeter_extrusion_width = 0.8
|
||||
external_perimeter_speed = 30
|
||||
external_perimeters_first = 0
|
||||
extra_perimeters = 0
|
||||
extrusion_width = 0.8
|
||||
fill_angle = 45
|
||||
fill_density = 20%
|
||||
fill_pattern = grid
|
||||
first_layer_extrusion_width = 0.8
|
||||
first_layer_height = 0.4
|
||||
first_layer_speed = 20
|
||||
first_layer_speed_over_raft = 30
|
||||
gap_fill_enabled = 1
|
||||
gap_fill_speed = 40
|
||||
infill_extrusion_width = 0.8
|
||||
infill_first = 0
|
||||
infill_overlap = 25%
|
||||
infill_speed = 60
|
||||
layer_height = 0.4
|
||||
max_print_speed = 60
|
||||
max_volumetric_speed = 0
|
||||
only_retract_when_crossing_perimeters = 1
|
||||
overhangs = 1
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0.8
|
||||
perimeter_speed = 45
|
||||
perimeters = 2
|
||||
raft_contact_distance = 0.1
|
||||
raft_expansion = 1.5
|
||||
raft_first_layer_density = 90%
|
||||
raft_first_layer_expansion = 3
|
||||
raft_layers = 0
|
||||
skirt_distance = 10
|
||||
skirt_height = 2
|
||||
skirts = 1
|
||||
small_perimeter_speed = 20
|
||||
solid_infill_below_area = 70
|
||||
solid_infill_every_layers = 0
|
||||
solid_infill_extruder = 1
|
||||
solid_infill_extrusion_width = 0.8
|
||||
solid_infill_speed = 60
|
||||
support_material = 0
|
||||
support_material_angle = 30
|
||||
support_material_auto = 1
|
||||
support_material_bottom_contact_distance = 0
|
||||
support_material_bottom_interface_layers = -1
|
||||
support_material_buildplate_only = 0
|
||||
support_material_closing_radius = 2
|
||||
support_material_contact_distance = 0.1
|
||||
support_material_enforce_layers = 0
|
||||
support_material_extruder = 0
|
||||
support_material_extrusion_width = 0.8
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_interface_extruder = 0
|
||||
support_material_interface_layers = 4
|
||||
support_material_interface_pattern = auto
|
||||
support_material_interface_spacing = 0.4
|
||||
support_material_interface_speed = 100%
|
||||
support_material_pattern = rectilinear
|
||||
support_material_spacing = 2
|
||||
support_material_speed = 50
|
||||
support_material_style = grid
|
||||
support_material_synchronize_layers = 0
|
||||
support_material_threshold = 40
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 0.6
|
||||
thick_bridges = 1
|
||||
thin_walls = 0
|
||||
threads = 12
|
||||
top_fill_pattern = monotonic
|
||||
top_infill_extrusion_width = 0.8
|
||||
top_solid_infill_speed = 40
|
||||
top_solid_layers = 5
|
||||
top_solid_min_thickness = 0.7
|
||||
travel_speed = 200
|
||||
travel_speed_z = 0
|
||||
|
||||
[print:AzteQ Industrial 0.40mm Vase @0.8 nozzle]
|
||||
inherits = AzteQ Industrial 0.40mm Normal @0.8 nozzle
|
||||
bottom_solid_layers = 4
|
||||
perimeters = 1
|
||||
top_solid_layers = 0
|
||||
fill_density = 0
|
||||
support_material = 0
|
||||
spiral_vase = 1
|
||||
ensure_vertical_shell_thickness = 1
|
||||
thin_walls = 0
|
||||
|
||||
# DeltiQ filaments #
|
||||
|
||||
[filament:*DeltiQ common*]
|
||||
@ -586,6 +686,8 @@ filament_soluble = 0
|
||||
filament_toolchange_delay = 0
|
||||
start_filament_gcode = "; FILAMENT_START_GCODE"
|
||||
end_filament_gcode = "; FILAMENT_END_GCODE"
|
||||
filament_cost = 0
|
||||
filament_spool_weight = 250
|
||||
filament_vendor = Generic
|
||||
|
||||
# DeltiQ PLA filaments #
|
||||
@ -597,7 +699,6 @@ bridge_fan_speed = 100
|
||||
cooling = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 100
|
||||
filament_cost = 750
|
||||
filament_density = 1.24
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_retract_before_travel = 2
|
||||
@ -618,7 +719,8 @@ temperature = 215
|
||||
|
||||
[filament:DeltiQ - PLA - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ - PLA - Generic
|
||||
filament_cost = 750
|
||||
filament_cost = 24.27
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.24
|
||||
filament_vendor = Fillamentum
|
||||
|
||||
@ -652,6 +754,10 @@ filament_retract_speed = 28
|
||||
|
||||
[filament:DeltiQ FP - PLA - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ FP - PLA - Generic
|
||||
filament_cost = 24.27
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.24
|
||||
filament_vendor = Fillamentum
|
||||
|
||||
[filament:DeltiQ FP2 - PLA - Generic]
|
||||
inherits = DeltiQ FP - PLA - Generic
|
||||
@ -661,6 +767,10 @@ filament_retract_speed = 28
|
||||
|
||||
[filament:DeltiQ FP2 - PLA - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ FP2 - PLA - Generic
|
||||
filament_cost = 24.27
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.24
|
||||
filament_vendor = Fillamentum
|
||||
|
||||
# DeltiQ PETG filaments #
|
||||
|
||||
@ -671,7 +781,6 @@ bridge_fan_speed = 50
|
||||
cooling = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 480
|
||||
filament_density = 1.27
|
||||
filament_deretract_speed = 25
|
||||
filament_max_volumetric_speed = 8
|
||||
@ -693,7 +802,8 @@ temperature = 245
|
||||
|
||||
[filament:DeltiQ - PETG (Devil Design)]
|
||||
inherits = DeltiQ - PETG - Generic
|
||||
filament_cost = 480
|
||||
filament_cost = 16.53
|
||||
filament_spool_weight = 247
|
||||
filament_density = 1.27
|
||||
filament_vendor = DevilDesign
|
||||
|
||||
@ -733,6 +843,10 @@ filament_retract_speed = 25
|
||||
|
||||
[filament:DeltiQ FP - PETG (Devil Design)]
|
||||
inherits = DeltiQ FP - PETG - Generic
|
||||
filament_cost = 16.53
|
||||
filament_spool_weight = 247
|
||||
filament_density = 1.27
|
||||
filament_vendor = DevilDesign
|
||||
|
||||
[filament:DeltiQ FP2 - PETG - Generic]
|
||||
inherits = DeltiQ FP - PETG - Generic
|
||||
@ -743,6 +857,10 @@ filament_retract_before_wipe = 0%
|
||||
|
||||
[filament:DeltiQ FP2 - PETG (Devil Design)]
|
||||
inherits = DeltiQ FP2 - PETG - Generic
|
||||
filament_cost = 16.53
|
||||
filament_spool_weight = 247
|
||||
filament_density = 1.27
|
||||
filament_vendor = DevilDesign
|
||||
|
||||
# DeltiQ ABS filaments #
|
||||
|
||||
@ -753,7 +871,6 @@ bridge_fan_speed = 25
|
||||
cooling = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 639
|
||||
filament_density = 1.04
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_retract_before_travel = 3
|
||||
@ -774,7 +891,8 @@ temperature = 255
|
||||
|
||||
[filament:DeltiQ - ABS - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ - ABS - Generic
|
||||
filament_cost = 639
|
||||
filament_cost = 24.27
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.04
|
||||
filament_vendor = Fillamentum
|
||||
|
||||
@ -791,6 +909,10 @@ filament_retract_speed = 25
|
||||
|
||||
[filament:DeltiQ FP - ABS - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ FP - ABS - Generic
|
||||
filament_cost = 24.27
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.04
|
||||
filament_vendor = Fillamentum
|
||||
|
||||
[filament:DeltiQ FP2 - ABS - Generic]
|
||||
inherits = DeltiQ FP - ABS - Generic
|
||||
@ -800,12 +922,18 @@ filament_retract_speed = 25
|
||||
|
||||
[filament:DeltiQ FP2 - ABS - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ FP2 - ABS - Generic
|
||||
filament_cost = 24.27
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.04
|
||||
filament_vendor = Fillamentum
|
||||
|
||||
|
||||
# DeltiQ ASA filaments #
|
||||
|
||||
[filament:DeltiQ - ASA - ExtraFill (Fillamentum)]
|
||||
inherits = DeltiQ - ABS - Generic
|
||||
filament_cost = 739
|
||||
filament_cost = 29.53
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.07
|
||||
filament_type = ASA
|
||||
filament_vendor = Fillamentum
|
||||
@ -827,6 +955,7 @@ filament_retract_speed = 25
|
||||
inherits = DeltiQ FP - ASA - ExtraFill (Fillamentum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and printer_notes=~/.*FLEXPRINT2.*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
|
||||
[filament:DeltiQ - ASA - ASA 275 (Spectrum)]
|
||||
inherits = *DeltiQ common*
|
||||
bed_temperature = 55
|
||||
@ -835,7 +964,7 @@ cooling = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_vendor = Spectrum
|
||||
filament_cost = 587
|
||||
filament_cost = 29.86
|
||||
filament_density = 1.07
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_retract_before_travel = 3
|
||||
@ -859,6 +988,7 @@ inherits = DeltiQ - ASA - ASA 275 (Spectrum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
|
||||
# DeltiQ CPE filaments #
|
||||
|
||||
[filament:DeltiQ - CPE - HG100 (Fillamentum)]
|
||||
@ -869,7 +999,8 @@ cooling = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 1003
|
||||
filament_cost = 39.07
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.25
|
||||
filament_deretract_speed = 25
|
||||
filament_max_volumetric_speed = 8
|
||||
@ -910,6 +1041,7 @@ filament_retract_speed = 35
|
||||
filament_deretract_speed = 0
|
||||
filament_retract_before_wipe = 0%
|
||||
|
||||
|
||||
# DeltiQ FLEX filaments #
|
||||
|
||||
[filament:DeltiQ FP - FLEX - Generic]
|
||||
@ -922,8 +1054,6 @@ disable_fan_first_layers = 1
|
||||
extrusion_multiplier = 1.07
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_vendor = Generic
|
||||
filament_cost = 1870
|
||||
filament_density = 1.22
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 3.0
|
||||
@ -954,8 +1084,6 @@ disable_fan_first_layers = 1
|
||||
extrusion_multiplier = 1.07
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 1870
|
||||
filament_density = 1.22
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 3.0
|
||||
@ -986,7 +1114,8 @@ extrusion_multiplier = 1.10
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 1870
|
||||
filament_cost = 58.33
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.22
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 3.0
|
||||
@ -1010,7 +1139,8 @@ temperature = 230
|
||||
[filament:DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum)]
|
||||
inherits = DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum)
|
||||
extrusion_multiplier = 1.10
|
||||
filament_cost = 1870
|
||||
filament_cost = 58.33
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.23
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 3.0
|
||||
@ -1029,7 +1159,8 @@ extrusion_multiplier = 1.00
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 10
|
||||
filament_vendor = Smartfil
|
||||
filament_cost = 1209
|
||||
filament_cost = 38.21
|
||||
filament_spool_weight = 250
|
||||
filament_density = 1.21
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 2.5
|
||||
@ -1053,7 +1184,8 @@ temperature = 235
|
||||
[filament:DeltiQ FP2 - PEBA 90A - FlexFill (Fillamentum)]
|
||||
inherits = DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum)
|
||||
extrusion_multiplier = 1.1
|
||||
filament_cost = 3578
|
||||
filament_cost = 139.67
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.00
|
||||
filament_max_volumetric_speed = 2.9
|
||||
filament_retract_length = 0.0
|
||||
@ -1070,7 +1202,8 @@ temperature = 245
|
||||
[filament:DeltiQ - PA - Nylon PA12 (Fiberlogy)]
|
||||
inherits = DeltiQ - ABS - Generic
|
||||
bed_temperature = 100
|
||||
filament_cost = 1213
|
||||
filament_cost = 45.11
|
||||
filament_spool_weight = 230
|
||||
filament_density = 1.02
|
||||
filament_retract_length = 4.1
|
||||
filament_type = NYLON
|
||||
@ -1083,8 +1216,9 @@ temperature = 255
|
||||
[filament:DeltiQ - PA - Nylon CF15 Carbon (Fillamentum)]
|
||||
inherits = DeltiQ - ABS - Generic
|
||||
bed_temperature = 100
|
||||
filament_cost = 2287
|
||||
filament_cost = 88.17
|
||||
filament_density = 1.08
|
||||
filament_spool_weight = 229
|
||||
filament_retract_length = 2.0
|
||||
filament_type = NYLON
|
||||
first_layer_bed_temperature = 100
|
||||
@ -1097,7 +1231,8 @@ extrusion_multiplier = 0.95
|
||||
[filament:DeltiQ - MoldLay (Wax-Alike)]
|
||||
inherits = DeltiQ - PLA - Generic
|
||||
bed_temperature = 50
|
||||
filament_cost = 1951
|
||||
filament_cost = 79.07
|
||||
filament_spool_weight = 230
|
||||
filament_retract_length = 2.0
|
||||
filament_type = PLA
|
||||
first_layer_bed_temperature = 50
|
||||
@ -1107,6 +1242,7 @@ min_fan_speed = 70
|
||||
temperature = 175
|
||||
filament_vendor = Wax-Alike
|
||||
|
||||
|
||||
# AzteQ filaments #
|
||||
|
||||
[filament:*AzteQ common*]
|
||||
@ -1124,7 +1260,6 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 750
|
||||
filament_density = 1.24
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 8
|
||||
@ -1161,8 +1296,9 @@ filament_max_volumetric_speed = 15
|
||||
[filament:AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum)]
|
||||
inherits = AzteQ Industrial (Door Opened) - PLA - Generic
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 750
|
||||
filament_cost = 24.27
|
||||
filament_density = 1.24
|
||||
filament_spool_weight = 229
|
||||
|
||||
[filament:AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum) @0.6 nozzle]
|
||||
inherits = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum)
|
||||
@ -1178,8 +1314,9 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 750
|
||||
filament_cost = 24.27
|
||||
filament_density = 1.24
|
||||
filament_spool_weight = 229
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_retract_before_travel = 3
|
||||
@ -1192,7 +1329,6 @@ filament_retract_lift_below = nil
|
||||
filament_retract_restart_extra = nil
|
||||
filament_retract_speed = 25
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = PLA
|
||||
filament_vendor = Fillamentum
|
||||
@ -1221,7 +1357,6 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 639
|
||||
filament_density = 1.04
|
||||
filament_deretract_speed = nil
|
||||
filament_load_time = 0
|
||||
@ -1240,7 +1375,6 @@ filament_retract_speed = 25
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_type = ABS
|
||||
filament_vendor = Generic
|
||||
filament_wipe = 1
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 255
|
||||
@ -1257,22 +1391,39 @@ inherits = AzteQ Industrial - ABS - Generic
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:AzteQ Industrial - ABS - Generic @0.8 nozzle]
|
||||
inherits = AzteQ Industrial - ABS - Generic
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
|
||||
first_layer_temperature = 255
|
||||
first_layer_bed_temperature = 100
|
||||
temperature = 255
|
||||
bed_temperature = 100
|
||||
max_fan_speed = 80
|
||||
min_fan_speed = 50
|
||||
filament_retract_length = 6.1
|
||||
filament_max_volumetric_speed = 0
|
||||
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature"
|
||||
|
||||
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum)]
|
||||
inherits = AzteQ Industrial - ABS - Generic
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 639
|
||||
filament_cost = 24.27
|
||||
filament_density = 1.04
|
||||
filament_spool_weight = 229
|
||||
|
||||
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle]
|
||||
inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle]
|
||||
inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum)
|
||||
extrusion_multiplier = 0.95
|
||||
|
||||
[filament:AzteQ Industrial - PC/ABS - (Fillamentum)]
|
||||
inherits = AzteQ Industrial - ABS - Generic
|
||||
filament_vendor = Fillamentum
|
||||
filament_type = PCABS
|
||||
filament_cost = 1324
|
||||
filament_cost = 53.71
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.07
|
||||
bed_temperature = 100
|
||||
filament_retract_length = 4.0
|
||||
@ -1292,7 +1443,8 @@ filament_max_volumetric_speed = 15
|
||||
[filament:AzteQ Industrial - PC - PolyMax (Polymaker)]
|
||||
inherits = AzteQ Industrial - ABS - Generic
|
||||
filament_vendor = Polymaker
|
||||
filament_cost = 1290
|
||||
filament_spool_weight = 230
|
||||
filament_cost = 52.40
|
||||
filament_density = 1.21
|
||||
bed_temperature = 100
|
||||
filament_retract_length = 4.0
|
||||
@ -1318,7 +1470,6 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 739
|
||||
filament_density = 1.07
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 8
|
||||
@ -1334,7 +1485,6 @@ filament_retract_speed = 25
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_type = ASA
|
||||
filament_vendor = Generic
|
||||
filament_wipe = 1
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 265
|
||||
@ -1358,17 +1508,34 @@ first_layer_temperature = 255
|
||||
temperature = 255
|
||||
max_fan_speed = 80
|
||||
min_fan_speed = 60
|
||||
filament_spool_weight = 229
|
||||
filament_cost = 29.53
|
||||
filament_density = 1.07
|
||||
|
||||
[filament:AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.6 nozzle]
|
||||
inherits = AzteQ Industrial - ASA - ExtraFill (Fillamentum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle]
|
||||
inherits = AzteQ Industrial - ASA - ExtraFill (Fillamentum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
|
||||
first_layer_bed_temperature = 100
|
||||
bed_temperature = 100
|
||||
first_layer_temperature = 250
|
||||
temperature = 250
|
||||
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S50 ; Set and wait - chamber temperature"
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 80
|
||||
filament_retract_length = 6.1
|
||||
filament_max_volumetric_speed = 0
|
||||
|
||||
|
||||
[filament:AzteQ Industrial - ASA - Prusament (Prusa)]
|
||||
inherits = AzteQ Industrial - ASA - Generic
|
||||
filament_cost = 680
|
||||
filament_cost = 29.16
|
||||
filament_density = 1.07
|
||||
filament_spool_weight = 0
|
||||
filament_spool_weight = 201
|
||||
filament_vendor = Prusa
|
||||
first_layer_temperature = 260
|
||||
max_fan_speed = 70
|
||||
@ -1381,6 +1548,20 @@ inherits = AzteQ Industrial - ASA - Prusament (Prusa)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:AzteQ Industrial - ASA - Prusament (Prusa) @0.8 nozzle]
|
||||
inherits = AzteQ Industrial - ASA - Prusament (Prusa)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
|
||||
first_layer_bed_temperature = 100
|
||||
bed_temperature = 100
|
||||
first_layer_temperature = 250
|
||||
temperature = 250
|
||||
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature"
|
||||
max_fan_speed = 80
|
||||
min_fan_speed = 50
|
||||
filament_retract_length = 4.1
|
||||
filament_max_volumetric_speed = 0
|
||||
|
||||
|
||||
[filament:AzteQ Industrial - PA - Nylon PA12 (Fiberlogy)]
|
||||
inherits = *AzteQ common*
|
||||
bed_temperature = 100
|
||||
@ -1390,7 +1571,8 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 1212
|
||||
filament_cost = 45.11
|
||||
filament_spool_weight = 230
|
||||
filament_density = 1.02
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 8
|
||||
@ -1404,7 +1586,6 @@ filament_retract_lift_below = nil
|
||||
filament_retract_restart_extra = nil
|
||||
filament_retract_speed = 25
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = NYLON
|
||||
filament_unload_time = 0
|
||||
@ -1436,7 +1617,8 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 1565
|
||||
filament_cost = 57.32
|
||||
filament_spool_weight = 229
|
||||
filament_density = 1.01
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 8
|
||||
@ -1450,7 +1632,6 @@ filament_retract_lift_below = nil
|
||||
filament_retract_restart_extra = nil
|
||||
filament_retract_speed = 25
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = NYLON
|
||||
filament_unload_time = 0
|
||||
@ -1482,8 +1663,9 @@ disable_fan_first_layers = 3
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_cost = 1156
|
||||
filament_cost = 61.98
|
||||
filament_density = 1.22
|
||||
filament_spool_weight = 201
|
||||
filament_deretract_speed = nil
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_retract_before_travel = 3
|
||||
@ -1496,7 +1678,6 @@ filament_retract_lift_below = nil
|
||||
filament_retract_restart_extra = nil
|
||||
filament_retract_speed = 25
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_type = PC
|
||||
filament_vendor = Prusa
|
||||
filament_wipe = 1
|
||||
@ -1516,6 +1697,18 @@ inherits = AzteQ Industrial - PC Blend - Prusament (Prusa)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:AzteQ Industrial - PC Blend - Prusament (Prusa) @0.8 nozzle]
|
||||
inherits = AzteQ Industrial - PC Blend - Prusament (Prusa)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
|
||||
first_layer_bed_temperature = 100
|
||||
bed_temperature = 100
|
||||
first_layer_temperature = 275
|
||||
temperature = 275
|
||||
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature"
|
||||
max_fan_speed = 60
|
||||
min_fan_speed = 60
|
||||
filament_retract_length = 7.1
|
||||
filament_max_volumetric_speed = 0
|
||||
|
||||
|
||||
# DeltiQ Printer #
|
||||
@ -1752,6 +1945,15 @@ nozzle_diameter = 0.6
|
||||
default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle"
|
||||
default_print_profile = AzteQ Industrial 0.30mm Normal @0.6 nozzle
|
||||
|
||||
[printer:AzteQ Industrial - 0.8 nozzle]
|
||||
inherits = AzteQ Industrial
|
||||
printer_variant = 0.8
|
||||
max_layer_height = 0.6
|
||||
min_layer_height = 0.2
|
||||
nozzle_diameter = 0.8
|
||||
default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle"
|
||||
default_print_profile = AzteQ Industrial 0.40mm Normal @0.8 nozzle
|
||||
|
||||
[presets]
|
||||
print = DeltiQ 0.20mm Normal
|
||||
printer = DeltiQ 2
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
BIN
resources/shapes/PLA_recycling_symbol.png
Normal file
BIN
resources/shapes/PLA_recycling_symbol.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
resources/shapes/PLA_recycling_symbol.stl
Normal file
BIN
resources/shapes/PLA_recycling_symbol.stl
Normal file
Binary file not shown.
@ -9,7 +9,7 @@
|
||||
|
||||
bool write_to_pot(boost::filesystem::path path, const std::vector<std::pair<std::string, std::string>>& data)
|
||||
{
|
||||
boost::filesystem::ofstream file(std::move(path), std::ios_base::app);
|
||||
boost::nowide::ofstream file(path.string(), std::ios_base::app);
|
||||
for (const auto& element : data)
|
||||
{
|
||||
//Example of .pot element
|
||||
|
@ -709,10 +709,15 @@ inline bool intersect_ray_all_hits(
|
||||
origin, dir, VectorType(dir.cwiseInverse()),
|
||||
eps }
|
||||
};
|
||||
if (! tree.empty()) {
|
||||
if (tree.empty()) {
|
||||
hits.clear();
|
||||
} else {
|
||||
// Reusing the output memory if there is some memory already pre-allocated.
|
||||
ray_intersector.hits = std::move(hits);
|
||||
ray_intersector.hits.clear();
|
||||
ray_intersector.hits.reserve(8);
|
||||
detail::intersect_ray_recursive_all_hits(ray_intersector, 0);
|
||||
std::swap(hits, ray_intersector.hits);
|
||||
hits = std::move(ray_intersector.hits);
|
||||
std::sort(hits.begin(), hits.end(), [](const auto &l, const auto &r) { return l.t < r.t; });
|
||||
}
|
||||
return ! hits.empty();
|
||||
@ -759,8 +764,8 @@ inline bool is_any_triangle_in_radius(
|
||||
const TreeType &tree,
|
||||
// Point to which the closest point on the indexed triangle set is searched for.
|
||||
const VectorType &point,
|
||||
// Maximum distance in which triangle is search for
|
||||
typename VectorType::Scalar &max_distance)
|
||||
//Square of maximum distance in which triangle is searched for
|
||||
typename VectorType::Scalar &max_distance_squared)
|
||||
{
|
||||
using Scalar = typename VectorType::Scalar;
|
||||
auto distancer = detail::IndexedTriangleSetDistancer<VertexType, IndexedFaceType, TreeType, VectorType>
|
||||
@ -774,7 +779,7 @@ inline bool is_any_triangle_in_radius(
|
||||
return false;
|
||||
}
|
||||
|
||||
detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), max_distance, hit_idx, hit_point);
|
||||
detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), max_distance_squared, hit_idx, hit_point);
|
||||
|
||||
return hit_point.allFinite();
|
||||
}
|
||||
|
@ -98,8 +98,12 @@ set(SLIC3R_SOURCES
|
||||
Format/objparser.hpp
|
||||
Format/STL.cpp
|
||||
Format/STL.hpp
|
||||
Format/SLAArchive.hpp
|
||||
Format/SLAArchive.cpp
|
||||
Format/SLAArchiveWriter.hpp
|
||||
Format/SLAArchiveWriter.cpp
|
||||
Format/SLAArchiveReader.hpp
|
||||
Format/SLAArchiveReader.cpp
|
||||
Format/ZipperArchiveImport.hpp
|
||||
Format/ZipperArchiveImport.cpp
|
||||
Format/SL1.hpp
|
||||
Format/SL1.cpp
|
||||
Format/SL1_SVG.hpp
|
||||
@ -142,10 +146,12 @@ set(SLIC3R_SOURCES
|
||||
GCodeWriter.hpp
|
||||
Geometry.cpp
|
||||
Geometry.hpp
|
||||
Geometry/Bicubic.hpp
|
||||
Geometry/Circle.cpp
|
||||
Geometry/Circle.hpp
|
||||
Geometry/ConvexHull.cpp
|
||||
Geometry/ConvexHull.hpp
|
||||
Geometry/Curves.hpp
|
||||
Geometry/MedialAxis.cpp
|
||||
Geometry/MedialAxis.hpp
|
||||
Geometry/Voronoi.hpp
|
||||
@ -232,6 +238,8 @@ set(SLIC3R_SOURCES
|
||||
SlicesToTriangleMesh.cpp
|
||||
SlicingAdaptive.cpp
|
||||
SlicingAdaptive.hpp
|
||||
Subdivide.cpp
|
||||
Subdivide.hpp
|
||||
SupportMaterial.cpp
|
||||
SupportMaterial.hpp
|
||||
Surface.cpp
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Point.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ColorRGB
|
||||
@ -133,41 +135,57 @@ public:
|
||||
static const ColorRGBA Z() { return { 0.0f, 0.0f, 0.75f, 1.0f }; }
|
||||
};
|
||||
|
||||
extern ColorRGB operator * (float value, const ColorRGB& other);
|
||||
extern ColorRGBA operator * (float value, const ColorRGBA& other);
|
||||
ColorRGB operator * (float value, const ColorRGB& other);
|
||||
ColorRGBA operator * (float value, const ColorRGBA& other);
|
||||
|
||||
extern ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t);
|
||||
extern ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t);
|
||||
ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t);
|
||||
ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t);
|
||||
|
||||
extern ColorRGB complementary(const ColorRGB& color);
|
||||
extern ColorRGBA complementary(const ColorRGBA& color);
|
||||
ColorRGB complementary(const ColorRGB& color);
|
||||
ColorRGBA complementary(const ColorRGBA& color);
|
||||
|
||||
extern ColorRGB saturate(const ColorRGB& color, float factor);
|
||||
extern ColorRGBA saturate(const ColorRGBA& color, float factor);
|
||||
ColorRGB saturate(const ColorRGB& color, float factor);
|
||||
ColorRGBA saturate(const ColorRGBA& color, float factor);
|
||||
|
||||
extern ColorRGB opposite(const ColorRGB& color);
|
||||
extern ColorRGB opposite(const ColorRGB& a, const ColorRGB& b);
|
||||
ColorRGB opposite(const ColorRGB& color);
|
||||
ColorRGB opposite(const ColorRGB& a, const ColorRGB& b);
|
||||
|
||||
extern bool can_decode_color(const std::string& color);
|
||||
bool can_decode_color(const std::string& color);
|
||||
|
||||
extern bool decode_color(const std::string& color_in, ColorRGB& color_out);
|
||||
extern bool decode_color(const std::string& color_in, ColorRGBA& color_out);
|
||||
bool decode_color(const std::string& color_in, ColorRGB& color_out);
|
||||
bool decode_color(const std::string& color_in, ColorRGBA& color_out);
|
||||
|
||||
extern bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGB>& colors_out);
|
||||
extern bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGBA>& colors_out);
|
||||
bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGB>& colors_out);
|
||||
bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGBA>& colors_out);
|
||||
|
||||
extern std::string encode_color(const ColorRGB& color);
|
||||
extern std::string encode_color(const ColorRGBA& color);
|
||||
std::string encode_color(const ColorRGB& color);
|
||||
std::string encode_color(const ColorRGBA& color);
|
||||
|
||||
extern ColorRGB to_rgb(const ColorRGBA& other_rgba);
|
||||
extern ColorRGBA to_rgba(const ColorRGB& other_rgb);
|
||||
extern ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha);
|
||||
ColorRGB to_rgb(const ColorRGBA& other_rgba);
|
||||
ColorRGBA to_rgba(const ColorRGB& other_rgb);
|
||||
ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha);
|
||||
|
||||
extern ColorRGBA picking_decode(unsigned int id);
|
||||
extern unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b);
|
||||
// Color mapping of a value into RGB false colors.
|
||||
inline Vec3f value_to_rgbf(float minimum, float maximum, float value)
|
||||
{
|
||||
float ratio = 2.0f * (value - minimum) / (maximum - minimum);
|
||||
float b = std::max(0.0f, (1.0f - ratio));
|
||||
float r = std::max(0.0f, (ratio - 1.0f));
|
||||
float g = 1.0f - b - r;
|
||||
return Vec3f { r, g, b };
|
||||
}
|
||||
|
||||
// Color mapping of a value into RGB false colors.
|
||||
inline Vec3i value_to_rgbi(float minimum, float maximum, float value)
|
||||
{
|
||||
return (value_to_rgbf(minimum, maximum, value) * 255).cast<int>();
|
||||
}
|
||||
|
||||
ColorRGBA picking_decode(unsigned int id);
|
||||
unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b);
|
||||
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
|
||||
// were not interpolated by alpha blending or multi sampling.
|
||||
extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
|
||||
unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -824,6 +824,7 @@ public:
|
||||
m_ifs.seekg(m_file_pos, m_ifs.beg);
|
||||
if (! m_ifs.read(m_block.data(), m_block_len))
|
||||
return false;
|
||||
assert(m_block_len == m_ifs.gcount());
|
||||
}
|
||||
|
||||
assert(m_block_len > 0);
|
||||
@ -866,7 +867,7 @@ private:
|
||||
ConfigSubstitutions ConfigBase::load_from_gcode_file(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
{
|
||||
// Read a 64k block from the end of the G-code.
|
||||
boost::nowide::ifstream ifs(file);
|
||||
boost::nowide::ifstream ifs(file, std::ifstream::binary);
|
||||
// Look for Slic3r or PrusaSlicer header.
|
||||
// Look for the header across the whole file as the G-code may have been extended at the start by a post-processing script or the user.
|
||||
bool has_delimiters = false;
|
||||
|
@ -194,7 +194,8 @@ enum ConfigOptionType {
|
||||
enum ConfigOptionMode {
|
||||
comSimple = 0,
|
||||
comAdvanced,
|
||||
comExpert
|
||||
comExpert,
|
||||
comUndef
|
||||
};
|
||||
|
||||
enum PrinterTechnology : unsigned char
|
||||
|
@ -375,8 +375,9 @@ void Node::convertToPolylines(size_t long_line_idx, Polygons& output) const
|
||||
void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_width) const
|
||||
{
|
||||
const coord_t reduction = line_width / 2; // TODO make configurable?
|
||||
for (auto poly_it = result_lines.begin(); poly_it != result_lines.end(); ) {
|
||||
Polygon &polyline = *poly_it;
|
||||
size_t res_line_idx = 0;
|
||||
while (res_line_idx < result_lines.size()) {
|
||||
Polygon &polyline = result_lines[res_line_idx];
|
||||
if (polyline.size() <= 1) {
|
||||
polyline = std::move(result_lines.back());
|
||||
result_lines.pop_back();
|
||||
@ -403,7 +404,7 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt
|
||||
polyline = std::move(result_lines.back());
|
||||
result_lines.pop_back();
|
||||
} else
|
||||
++ poly_it;
|
||||
++ res_line_idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,359 +1,37 @@
|
||||
#include "SL1.hpp"
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
#include "libslic3r/Time.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "libslic3r/Zipper.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "libslic3r/Time.hpp"
|
||||
#include "libslic3r/Zipper.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Exception.hpp"
|
||||
#include "libslic3r/SlicesToTriangleMesh.hpp"
|
||||
#include "libslic3r/MarchingSquares.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/MTUtils.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/SLA/RasterBase.hpp"
|
||||
|
||||
#include "libslic3r/miniz_extension.hpp"
|
||||
#include "libslic3r/PNGReadWrite.hpp"
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||
|
||||
#include "SLAArchiveReader.hpp"
|
||||
#include "ZipperArchiveImport.hpp"
|
||||
|
||||
#include "libslic3r/MarchingSquares.hpp"
|
||||
#include "libslic3r/PNGReadWrite.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Execution/ExecutionTBB.hpp"
|
||||
|
||||
#include "libslic3r/SLA/RasterBase.hpp"
|
||||
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <miniz.h>
|
||||
|
||||
namespace marchsq {
|
||||
|
||||
template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> {
|
||||
using Rst = Slic3r::png::ImageGreyscale;
|
||||
|
||||
// The type of pixel cell in the raster
|
||||
using ValueType = uint8_t;
|
||||
|
||||
// Value at a given position
|
||||
static uint8_t get(const Rst &rst, size_t row, size_t col)
|
||||
{
|
||||
return rst.get(row, col);
|
||||
}
|
||||
|
||||
// Number of rows and cols of the raster
|
||||
static size_t rows(const Rst &rst) { return rst.rows; }
|
||||
static size_t cols(const Rst &rst) { return rst.cols; }
|
||||
};
|
||||
|
||||
} // namespace marchsq
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
struct PNGBuffer { std::vector<uint8_t> buf; std::string fname; };
|
||||
struct ArchiveData {
|
||||
boost::property_tree::ptree profile, config;
|
||||
std::vector<PNGBuffer> images;
|
||||
};
|
||||
|
||||
static const constexpr char *CONFIG_FNAME = "config.ini";
|
||||
static const constexpr char *PROFILE_FNAME = "prusaslicer.ini";
|
||||
|
||||
boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
|
||||
MZ_Archive & zip)
|
||||
{
|
||||
std::string buf(size_t(entry.m_uncomp_size), '\0');
|
||||
|
||||
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
|
||||
buf.data(), buf.size(), 0))
|
||||
throw Slic3r::FileIOError(zip.get_errorstr());
|
||||
|
||||
boost::property_tree::ptree tree;
|
||||
std::stringstream ss(buf);
|
||||
boost::property_tree::read_ini(ss, tree);
|
||||
return tree;
|
||||
}
|
||||
|
||||
PNGBuffer read_png(const mz_zip_archive_file_stat &entry,
|
||||
MZ_Archive & zip,
|
||||
const std::string & name)
|
||||
{
|
||||
std::vector<uint8_t> buf(entry.m_uncomp_size);
|
||||
|
||||
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
|
||||
buf.data(), buf.size(), 0))
|
||||
throw Slic3r::FileIOError(zip.get_errorstr());
|
||||
|
||||
return {std::move(buf), (name.empty() ? entry.m_filename : name)};
|
||||
}
|
||||
|
||||
ArchiveData extract_sla_archive(const std::string &zipfname,
|
||||
const std::string &exclude)
|
||||
{
|
||||
ArchiveData arch;
|
||||
|
||||
// Little RAII
|
||||
struct Arch: public MZ_Archive {
|
||||
Arch(const std::string &fname) {
|
||||
if (!open_zip_reader(&arch, fname))
|
||||
throw Slic3r::FileIOError(get_errorstr());
|
||||
}
|
||||
|
||||
~Arch() { close_zip_reader(&arch); }
|
||||
} zip (zipfname);
|
||||
|
||||
mz_uint num_entries = mz_zip_reader_get_num_files(&zip.arch);
|
||||
|
||||
for (mz_uint i = 0; i < num_entries; ++i)
|
||||
{
|
||||
mz_zip_archive_file_stat entry;
|
||||
|
||||
if (mz_zip_reader_file_stat(&zip.arch, i, &entry))
|
||||
{
|
||||
std::string name = entry.m_filename;
|
||||
boost::algorithm::to_lower(name);
|
||||
|
||||
if (boost::algorithm::contains(name, exclude)) continue;
|
||||
|
||||
if (name == CONFIG_FNAME) arch.config = read_ini(entry, zip);
|
||||
if (name == PROFILE_FNAME) arch.profile = read_ini(entry, zip);
|
||||
|
||||
if (boost::filesystem::path(name).extension().string() == ".png") {
|
||||
auto it = std::lower_bound(
|
||||
arch.images.begin(), arch.images.end(), PNGBuffer{{}, name},
|
||||
[](const PNGBuffer &r1, const PNGBuffer &r2) {
|
||||
return std::less<std::string>()(r1.fname, r2.fname);
|
||||
});
|
||||
|
||||
arch.images.insert(it, read_png(entry, zip, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
||||
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
|
||||
double px_w, double px_h)
|
||||
{
|
||||
auto polys = reserve_vector<ExPolygon>(rings.size());
|
||||
|
||||
for (const marchsq::Ring &ring : rings) {
|
||||
Polygon poly; Points &pts = poly.points;
|
||||
pts.reserve(ring.size());
|
||||
|
||||
for (const marchsq::Coord &crd : ring)
|
||||
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
|
||||
|
||||
polys.emplace_back(poly);
|
||||
}
|
||||
|
||||
// TODO: Is a union necessary?
|
||||
return union_ex(polys);
|
||||
}
|
||||
|
||||
template<class Fn> void foreach_vertex(ExPolygon &poly, Fn &&fn)
|
||||
{
|
||||
for (auto &p : poly.contour.points) fn(p);
|
||||
for (auto &h : poly.holes)
|
||||
for (auto &p : h.points) fn(p);
|
||||
}
|
||||
|
||||
void invert_raster_trafo(ExPolygons & expolys,
|
||||
const sla::RasterBase::Trafo &trafo,
|
||||
coord_t width,
|
||||
coord_t height)
|
||||
{
|
||||
if (trafo.flipXY) std::swap(height, width);
|
||||
|
||||
for (auto &expoly : expolys) {
|
||||
if (trafo.mirror_y)
|
||||
foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); });
|
||||
|
||||
if (trafo.mirror_x)
|
||||
foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); });
|
||||
|
||||
expoly.translate(-trafo.center_x, -trafo.center_y);
|
||||
|
||||
if (trafo.flipXY)
|
||||
foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); });
|
||||
|
||||
if ((trafo.mirror_x + trafo.mirror_y + trafo.flipXY) % 2) {
|
||||
expoly.contour.reverse();
|
||||
for (auto &h : expoly.holes) h.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RasterParams {
|
||||
sla::RasterBase::Trafo trafo; // Raster transformations
|
||||
coord_t width, height; // scaled raster dimensions (not resolution)
|
||||
double px_h, px_w; // pixel dimesions
|
||||
marchsq::Coord win; // marching squares window size
|
||||
};
|
||||
|
||||
RasterParams get_raster_params(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
auto *opt_disp_cols = cfg.option<ConfigOptionInt>("display_pixels_x");
|
||||
auto *opt_disp_rows = cfg.option<ConfigOptionInt>("display_pixels_y");
|
||||
auto *opt_disp_w = cfg.option<ConfigOptionFloat>("display_width");
|
||||
auto *opt_disp_h = cfg.option<ConfigOptionFloat>("display_height");
|
||||
auto *opt_mirror_x = cfg.option<ConfigOptionBool>("display_mirror_x");
|
||||
auto *opt_mirror_y = cfg.option<ConfigOptionBool>("display_mirror_y");
|
||||
auto *opt_orient = cfg.option<ConfigOptionEnum<SLADisplayOrientation>>("display_orientation");
|
||||
|
||||
if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h ||
|
||||
!opt_mirror_x || !opt_mirror_y || !opt_orient)
|
||||
throw MissingProfileError("Invalid SL1 / SL1S file");
|
||||
|
||||
RasterParams rstp;
|
||||
|
||||
rstp.px_w = opt_disp_w->value / (opt_disp_cols->value - 1);
|
||||
rstp.px_h = opt_disp_h->value / (opt_disp_rows->value - 1);
|
||||
|
||||
rstp.trafo = sla::RasterBase::Trafo{opt_orient->value == sladoLandscape ?
|
||||
sla::RasterBase::roLandscape :
|
||||
sla::RasterBase::roPortrait,
|
||||
{opt_mirror_x->value, opt_mirror_y->value}};
|
||||
|
||||
rstp.height = scaled(opt_disp_h->value);
|
||||
rstp.width = scaled(opt_disp_w->value);
|
||||
|
||||
return rstp;
|
||||
}
|
||||
|
||||
struct SliceParams { double layerh = 0., initial_layerh = 0.; };
|
||||
|
||||
SliceParams get_slice_params(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
auto *opt_layerh = cfg.option<ConfigOptionFloat>("layer_height");
|
||||
auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("initial_layer_height");
|
||||
|
||||
if (!opt_layerh || !opt_init_layerh)
|
||||
throw MissingProfileError("Invalid SL1 / SL1S file");
|
||||
|
||||
return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()};
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> extract_slices_from_sla_archive(
|
||||
ArchiveData & arch,
|
||||
const RasterParams & rstp,
|
||||
std::function<bool(int)> progr)
|
||||
{
|
||||
auto jobdir = arch.config.get<std::string>("jobDir");
|
||||
for (auto &c : jobdir) c = std::tolower(c);
|
||||
|
||||
std::vector<ExPolygons> slices(arch.images.size());
|
||||
|
||||
struct Status
|
||||
{
|
||||
double incr, val, prev;
|
||||
bool stop = false;
|
||||
tbb::spin_mutex mutex = {};
|
||||
} st {100. / slices.size(), 0., 0.};
|
||||
|
||||
tbb::parallel_for(size_t(0), arch.images.size(),
|
||||
[&arch, &slices, &st, &rstp, progr](size_t i) {
|
||||
// Status indication guarded with the spinlock
|
||||
{
|
||||
std::lock_guard<tbb::spin_mutex> lck(st.mutex);
|
||||
if (st.stop) return;
|
||||
|
||||
st.val += st.incr;
|
||||
double curr = std::round(st.val);
|
||||
if (curr > st.prev) {
|
||||
st.prev = curr;
|
||||
st.stop = !progr(int(curr));
|
||||
}
|
||||
}
|
||||
|
||||
png::ImageGreyscale img;
|
||||
png::ReadBuf rb{arch.images[i].buf.data(), arch.images[i].buf.size()};
|
||||
if (!png::decode_png(rb, img)) return;
|
||||
|
||||
uint8_t isoval = 128;
|
||||
auto rings = marchsq::execute(img, isoval, rstp.win);
|
||||
ExPolygons expolys = rings_to_expolygons(rings, rstp.px_w, rstp.px_h);
|
||||
|
||||
// Invert the raster transformations indicated in the profile metadata
|
||||
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
|
||||
|
||||
slices[i] = std::move(expolys);
|
||||
});
|
||||
|
||||
if (st.stop) slices = {};
|
||||
|
||||
return slices;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out)
|
||||
{
|
||||
ArchiveData arch = extract_sla_archive(zipfname, "png");
|
||||
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
|
||||
}
|
||||
|
||||
// If the profile is missing from the archive (older PS versions did not have
|
||||
// it), profile_out's initial value will be used as fallback. profile_out will be empty on
|
||||
// function return if the archive did not contain any profile.
|
||||
ConfigSubstitutions import_sla_archive(
|
||||
const std::string & zipfname,
|
||||
Vec2i windowsize,
|
||||
indexed_triangle_set & out,
|
||||
DynamicPrintConfig & profile_out,
|
||||
std::function<bool(int)> progr)
|
||||
{
|
||||
// Ensure minimum window size for marching squares
|
||||
windowsize.x() = std::max(2, windowsize.x());
|
||||
windowsize.y() = std::max(2, windowsize.y());
|
||||
|
||||
std::string exclude_entries{"thumbnail"};
|
||||
ArchiveData arch = extract_sla_archive(zipfname, exclude_entries);
|
||||
DynamicPrintConfig profile_in, profile_use;
|
||||
ConfigSubstitutions config_substitutions =
|
||||
profile_in.load(arch.profile,
|
||||
ForwardCompatibilitySubstitutionRule::Enable);
|
||||
|
||||
if (profile_in.empty()) { // missing profile... do guess work
|
||||
// try to recover the layer height from the config.ini which was
|
||||
// present in all versions of sl1 files.
|
||||
if (auto lh_opt = arch.config.find("layerHeight");
|
||||
lh_opt != arch.config.not_found())
|
||||
{
|
||||
auto lh_str = lh_opt->second.data();
|
||||
|
||||
size_t pos;
|
||||
double lh = string_to_double_decimal_point(lh_str, &pos);
|
||||
if (pos) { // TODO: verify that pos is 0 when parsing fails
|
||||
profile_out.set("layer_height", lh);
|
||||
profile_out.set("initial_layer_height", lh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the archive contains an empty profile, use the one that was passed as output argument
|
||||
// then replace it with the readed profile to report that it was empty.
|
||||
profile_use = profile_in.empty() ? profile_out : profile_in;
|
||||
profile_out = profile_in;
|
||||
|
||||
RasterParams rstp = get_raster_params(profile_use);
|
||||
rstp.win = {windowsize.y(), windowsize.x()};
|
||||
|
||||
SliceParams slicp = get_slice_params(profile_use);
|
||||
|
||||
std::vector<ExPolygons> slices =
|
||||
extract_slices_from_sla_archive(arch, rstp, progr);
|
||||
|
||||
if (!slices.empty())
|
||||
out = slices_to_mesh(slices, 0, slicp.layerh, slicp.initial_layerh);
|
||||
|
||||
return config_substitutions;
|
||||
}
|
||||
|
||||
using ConfMap = std::map<std::string, std::string>;
|
||||
|
||||
namespace {
|
||||
@ -558,3 +236,207 @@ void SL1Archive::export_print(const std::string fname,
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Reader implementation
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace marchsq {
|
||||
|
||||
template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> {
|
||||
using Rst = Slic3r::png::ImageGreyscale;
|
||||
|
||||
// The type of pixel cell in the raster
|
||||
using ValueType = uint8_t;
|
||||
|
||||
// Value at a given position
|
||||
static uint8_t get(const Rst &rst, size_t row, size_t col)
|
||||
{
|
||||
return rst.get(row, col);
|
||||
}
|
||||
|
||||
// Number of rows and cols of the raster
|
||||
static size_t rows(const Rst &rst) { return rst.rows; }
|
||||
static size_t cols(const Rst &rst) { return rst.cols; }
|
||||
};
|
||||
|
||||
} // namespace marchsq
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
template<class Fn> static void foreach_vertex(ExPolygon &poly, Fn &&fn)
|
||||
{
|
||||
for (auto &p : poly.contour.points) fn(p);
|
||||
for (auto &h : poly.holes)
|
||||
for (auto &p : h.points) fn(p);
|
||||
}
|
||||
|
||||
void invert_raster_trafo(ExPolygons & expolys,
|
||||
const sla::RasterBase::Trafo &trafo,
|
||||
coord_t width,
|
||||
coord_t height)
|
||||
{
|
||||
if (trafo.flipXY) std::swap(height, width);
|
||||
|
||||
for (auto &expoly : expolys) {
|
||||
if (trafo.mirror_y)
|
||||
foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); });
|
||||
|
||||
if (trafo.mirror_x)
|
||||
foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); });
|
||||
|
||||
expoly.translate(-trafo.center_x, -trafo.center_y);
|
||||
|
||||
if (trafo.flipXY)
|
||||
foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); });
|
||||
|
||||
if ((trafo.mirror_x + trafo.mirror_y + trafo.flipXY) % 2) {
|
||||
expoly.contour.reverse();
|
||||
for (auto &h : expoly.holes) h.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RasterParams get_raster_params(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
auto *opt_disp_cols = cfg.option<ConfigOptionInt>("display_pixels_x");
|
||||
auto *opt_disp_rows = cfg.option<ConfigOptionInt>("display_pixels_y");
|
||||
auto *opt_disp_w = cfg.option<ConfigOptionFloat>("display_width");
|
||||
auto *opt_disp_h = cfg.option<ConfigOptionFloat>("display_height");
|
||||
auto *opt_mirror_x = cfg.option<ConfigOptionBool>("display_mirror_x");
|
||||
auto *opt_mirror_y = cfg.option<ConfigOptionBool>("display_mirror_y");
|
||||
auto *opt_orient = cfg.option<ConfigOptionEnum<SLADisplayOrientation>>("display_orientation");
|
||||
|
||||
if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h ||
|
||||
!opt_mirror_x || !opt_mirror_y || !opt_orient)
|
||||
throw MissingProfileError("Invalid SL1 / SL1S file");
|
||||
|
||||
RasterParams rstp;
|
||||
|
||||
rstp.px_w = opt_disp_w->value / (opt_disp_cols->value - 1);
|
||||
rstp.px_h = opt_disp_h->value / (opt_disp_rows->value - 1);
|
||||
|
||||
rstp.trafo = sla::RasterBase::Trafo{opt_orient->value == sladoLandscape ?
|
||||
sla::RasterBase::roLandscape :
|
||||
sla::RasterBase::roPortrait,
|
||||
{opt_mirror_x->value, opt_mirror_y->value}};
|
||||
|
||||
rstp.height = scaled(opt_disp_h->value);
|
||||
rstp.width = scaled(opt_disp_w->value);
|
||||
|
||||
return rstp;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
|
||||
double px_w, double px_h)
|
||||
{
|
||||
auto polys = reserve_vector<ExPolygon>(rings.size());
|
||||
|
||||
for (const marchsq::Ring &ring : rings) {
|
||||
Polygon poly; Points &pts = poly.points;
|
||||
pts.reserve(ring.size());
|
||||
|
||||
for (const marchsq::Coord &crd : ring)
|
||||
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
|
||||
|
||||
polys.emplace_back(poly);
|
||||
}
|
||||
|
||||
// TODO: Is a union necessary?
|
||||
return union_ex(polys);
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> extract_slices_from_sla_archive(
|
||||
ZipperArchive &arch,
|
||||
const RasterParams &rstp,
|
||||
const marchsq::Coord &win,
|
||||
std::function<bool(int)> progr)
|
||||
{
|
||||
std::vector<ExPolygons> slices(arch.entries.size());
|
||||
|
||||
struct Status
|
||||
{
|
||||
double incr, val, prev;
|
||||
bool stop = false;
|
||||
execution::SpinningMutex<ExecutionTBB> mutex = {};
|
||||
} st{100. / slices.size(), 0., 0.};
|
||||
|
||||
execution::for_each(
|
||||
ex_tbb, size_t(0), arch.entries.size(),
|
||||
[&arch, &slices, &st, &rstp, &win, progr](size_t i) {
|
||||
// Status indication guarded with the spinlock
|
||||
{
|
||||
std::lock_guard lck(st.mutex);
|
||||
if (st.stop) return;
|
||||
|
||||
st.val += st.incr;
|
||||
double curr = std::round(st.val);
|
||||
if (curr > st.prev) {
|
||||
st.prev = curr;
|
||||
st.stop = !progr(int(curr));
|
||||
}
|
||||
}
|
||||
|
||||
png::ImageGreyscale img;
|
||||
png::ReadBuf rb{arch.entries[i].buf.data(),
|
||||
arch.entries[i].buf.size()};
|
||||
if (!png::decode_png(rb, img)) return;
|
||||
|
||||
constexpr uint8_t isoval = 128;
|
||||
auto rings = marchsq::execute(img, isoval, win);
|
||||
ExPolygons expolys = rings_to_expolygons(rings, rstp.px_w,
|
||||
rstp.px_h);
|
||||
|
||||
// Invert the raster transformations indicated in the profile metadata
|
||||
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
|
||||
|
||||
slices[i] = std::move(expolys);
|
||||
},
|
||||
execution::max_concurrency(ex_tbb));
|
||||
|
||||
if (st.stop) slices = {};
|
||||
|
||||
return slices;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConfigSubstitutions SL1Reader::read(std::vector<ExPolygons> &slices,
|
||||
DynamicPrintConfig &profile_out)
|
||||
{
|
||||
Vec2i windowsize;
|
||||
|
||||
switch(m_quality)
|
||||
{
|
||||
case SLAImportQuality::Fast: windowsize = {8, 8}; break;
|
||||
case SLAImportQuality::Balanced: windowsize = {4, 4}; break;
|
||||
default:
|
||||
case SLAImportQuality::Accurate:
|
||||
windowsize = {2, 2}; break;
|
||||
};
|
||||
|
||||
// Ensure minimum window size for marching squares
|
||||
windowsize.x() = std::max(2, windowsize.x());
|
||||
windowsize.y() = std::max(2, windowsize.y());
|
||||
|
||||
std::vector<std::string> includes = { "ini", "png"};
|
||||
std::vector<std::string> excludes = { "thumbnail" };
|
||||
ZipperArchive arch = read_zipper_archive(m_fname, includes, excludes);
|
||||
auto [profile_use, config_substitutions] = extract_profile(arch, profile_out);
|
||||
|
||||
RasterParams rstp = get_raster_params(profile_use);
|
||||
marchsq::Coord win = {windowsize.y(), windowsize.x()};
|
||||
slices = extract_slices_from_sla_archive(arch, rstp, win, m_progr);
|
||||
|
||||
return std::move(config_substitutions);
|
||||
}
|
||||
|
||||
ConfigSubstitutions SL1Reader::read(DynamicPrintConfig &out)
|
||||
{
|
||||
ZipperArchive arch = read_zipper_archive(m_fname, {}, {"png"});
|
||||
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -3,16 +3,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SLAArchive.hpp"
|
||||
#include "SLAArchiveWriter.hpp"
|
||||
#include "SLAArchiveReader.hpp"
|
||||
|
||||
#include "libslic3r/Zipper.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
struct indexed_triangle_set;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class SL1Archive: public SLAArchive {
|
||||
class SL1Archive: public SLAArchiveWriter {
|
||||
SLAPrinterConfig m_cfg;
|
||||
|
||||
protected:
|
||||
@ -38,27 +37,41 @@ public:
|
||||
const ThumbnailsList &thumbnails,
|
||||
const std::string &projectname = "") override;
|
||||
};
|
||||
|
||||
ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out);
|
||||
|
||||
ConfigSubstitutions import_sla_archive(
|
||||
const std::string & zipfname,
|
||||
Vec2i windowsize,
|
||||
indexed_triangle_set & out,
|
||||
DynamicPrintConfig & profile,
|
||||
std::function<bool(int)> progr = [](int) { return true; });
|
||||
class SL1Reader: public SLAArchiveReader {
|
||||
SLAImportQuality m_quality = SLAImportQuality::Balanced;
|
||||
std::function<bool(int)> m_progr;
|
||||
std::string m_fname;
|
||||
|
||||
inline ConfigSubstitutions import_sla_archive(
|
||||
const std::string & zipfname,
|
||||
Vec2i windowsize,
|
||||
indexed_triangle_set & out,
|
||||
std::function<bool(int)> progr = [](int) { return true; })
|
||||
{
|
||||
DynamicPrintConfig profile;
|
||||
return import_sla_archive(zipfname, windowsize, out, profile, progr);
|
||||
}
|
||||
public:
|
||||
// If the profile is missing from the archive (older PS versions did not have
|
||||
// it), profile_out's initial value will be used as fallback. profile_out will be empty on
|
||||
// function return if the archive did not contain any profile.
|
||||
ConfigSubstitutions read(std::vector<ExPolygons> &slices,
|
||||
DynamicPrintConfig &profile_out) override;
|
||||
|
||||
class MissingProfileError : public RuntimeError { using RuntimeError::RuntimeError; };
|
||||
ConfigSubstitutions read(DynamicPrintConfig &profile) override;
|
||||
|
||||
SL1Reader() = default;
|
||||
SL1Reader(const std::string &fname,
|
||||
SLAImportQuality quality,
|
||||
std::function<bool(int)> progr)
|
||||
: m_quality(quality), m_progr(progr), m_fname(fname)
|
||||
{}
|
||||
};
|
||||
|
||||
struct RasterParams {
|
||||
sla::RasterBase::Trafo trafo; // Raster transformations
|
||||
coord_t width, height; // scaled raster dimensions (not resolution)
|
||||
double px_h, px_w; // pixel dimesions
|
||||
};
|
||||
|
||||
RasterParams get_raster_params(const DynamicPrintConfig &cfg);
|
||||
|
||||
void invert_raster_trafo(ExPolygons & expolys,
|
||||
const sla::RasterBase::Trafo &trafo,
|
||||
coord_t width,
|
||||
coord_t height);
|
||||
|
||||
} // namespace Slic3r::sla
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "libslic3r/Format/ZipperArchiveImport.hpp"
|
||||
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
#include "nanosvg/nanosvg.h"
|
||||
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
@ -16,6 +20,7 @@ namespace {
|
||||
|
||||
size_t constexpr coord_t_bufsize = 40;
|
||||
|
||||
// A fast and locale independent implementation of int=>str
|
||||
char const* decimal_from(coord_t snumber, char* buffer)
|
||||
{
|
||||
std::make_unsigned_t<coord_t> number = 0;
|
||||
@ -50,6 +55,7 @@ inline std::string coord2str(coord_t crd)
|
||||
return decimal_from(crd, buf);
|
||||
}
|
||||
|
||||
// Apply the sla::RasterBase::Trafo onto an ExPolygon
|
||||
void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBox &bb)
|
||||
{
|
||||
if (tr.flipXY) {
|
||||
@ -71,12 +77,13 @@ void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBo
|
||||
}
|
||||
}
|
||||
|
||||
// Append the svg string representation of a Polygon to the input 'buf'
|
||||
void append_svg(std::string &buf, const Polygon &poly)
|
||||
{
|
||||
if (poly.points.empty())
|
||||
return;
|
||||
|
||||
auto c = poly.points.front();
|
||||
Point c = poly.points.front();
|
||||
|
||||
char intbuf[coord_t_bufsize];
|
||||
|
||||
@ -84,15 +91,16 @@ void append_svg(std::string &buf, const Polygon &poly)
|
||||
buf += decimal_from(c.x(), intbuf);
|
||||
buf += " "sv;
|
||||
buf += decimal_from(c.y(), intbuf);
|
||||
buf += " m"sv;
|
||||
buf += " l "sv;
|
||||
|
||||
for (auto &p : poly) {
|
||||
auto d = p - c;
|
||||
if (d.squaredNorm() == 0) continue;
|
||||
for (const Point &p : poly) {
|
||||
Point d = p - c;
|
||||
if (d.x() == 0 && d.y() == 0)
|
||||
continue;
|
||||
buf += " "sv;
|
||||
buf += decimal_from(p.x() - c.x(), intbuf);
|
||||
buf += decimal_from(d.x(), intbuf);
|
||||
buf += " "sv;
|
||||
buf += decimal_from(p.y() - c.y(), intbuf);
|
||||
buf += decimal_from(d.y(), intbuf);
|
||||
c = p;
|
||||
}
|
||||
buf += " z\""sv; // mark path as closed
|
||||
@ -138,9 +146,6 @@ public:
|
||||
"<svg height=\"" + hf + "mm" + "\" width=\"" + wf + "mm" + "\" viewBox=\"0 0 " + w + " " + h +
|
||||
"\" style=\"fill: white; stroke: none; fill-rule: nonzero\" "
|
||||
"xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
||||
|
||||
// Add black background;
|
||||
m_svg += "<rect fill='black' stroke='none' x='0' y='0' width='" + w + "' height='" + h + "'/>\n";
|
||||
}
|
||||
|
||||
void draw(const ExPolygon& poly) override
|
||||
@ -170,6 +175,8 @@ public:
|
||||
|
||||
Trafo trafo() const override { return m_trafo; }
|
||||
|
||||
// The encoder is ignored here, the svg text does not need any further
|
||||
// encoding.
|
||||
sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
@ -189,13 +196,11 @@ std::unique_ptr<sla::RasterBase> SL1_SVGArchive::create_raster() const
|
||||
auto w = cfg().display_width.getFloat();
|
||||
auto h = cfg().display_height.getFloat();
|
||||
|
||||
// auto res_x = size_t(cfg().display_pixels_x.getInt());
|
||||
// auto res_y = size_t(cfg().display_pixels_y.getInt());
|
||||
float precision_nm = scaled<float>(cfg().sla_output_precision.getFloat());
|
||||
size_t res_x = std::round(scaled(w) / precision_nm);
|
||||
size_t res_y = std::round(scaled(h) / precision_nm);
|
||||
auto res_x = size_t(std::round(scaled(w) / precision_nm));
|
||||
auto res_y = size_t(std::round(scaled(h) / precision_nm));
|
||||
|
||||
std::array<bool, 2> mirror;
|
||||
std::array<bool, 2> mirror;
|
||||
|
||||
mirror[X] = cfg().display_mirror_x.getBool();
|
||||
mirror[Y] = cfg().display_mirror_y.getBool();
|
||||
@ -219,6 +224,7 @@ std::unique_ptr<sla::RasterBase> SL1_SVGArchive::create_raster() const
|
||||
return std::make_unique<SVGRaster>(svgarea, sla::Resolution{res_x, res_y}, tr);
|
||||
}
|
||||
|
||||
// SVG does not need additional binary encoding.
|
||||
sla::RasterEncoder SL1_SVGArchive::get_encoder() const
|
||||
{
|
||||
return nullptr;
|
||||
@ -229,9 +235,83 @@ void SL1_SVGArchive::export_print(const std::string fname,
|
||||
const ThumbnailsList &thumbnails,
|
||||
const std::string &projectname)
|
||||
{
|
||||
// Export code is completely identical to SL1, only the compression level
|
||||
// is elevated, as the SL1 has already compressed PNGs with deflate,
|
||||
// but the svg is just text.
|
||||
Zipper zipper{fname, Zipper::TIGHT_COMPRESSION};
|
||||
|
||||
SL1Archive::export_print(zipper, print, thumbnails, projectname);
|
||||
}
|
||||
|
||||
struct NanoSVGParser {
|
||||
NSVGimage *image;
|
||||
static constexpr const char *Units = "mm"; // Denotes user coordinate system
|
||||
static constexpr float Dpi = 1.f; // Not needed
|
||||
explicit NanoSVGParser(char* input): image{nsvgParse(input, Units, Dpi)} {}
|
||||
~NanoSVGParser() { nsvgDelete(image); }
|
||||
};
|
||||
|
||||
ConfigSubstitutions SL1_SVGReader::read(std::vector<ExPolygons> &slices,
|
||||
DynamicPrintConfig &profile_out)
|
||||
{
|
||||
std::vector<std::string> includes = { CONFIG_FNAME, PROFILE_FNAME, "svg"};
|
||||
ZipperArchive arch = read_zipper_archive(m_fname, includes, {});
|
||||
auto [profile_use, config_substitutions] = extract_profile(arch, profile_out);
|
||||
|
||||
RasterParams rstp = get_raster_params(profile_use);
|
||||
|
||||
struct Status
|
||||
{
|
||||
double incr, val, prev;
|
||||
bool stop = false;
|
||||
} st{100. / arch.entries.size(), 0., 0.};
|
||||
|
||||
for (const EntryBuffer &entry : arch.entries) {
|
||||
if (st.stop) break;
|
||||
|
||||
st.val += st.incr;
|
||||
double curr = std::round(st.val);
|
||||
if (curr > st.prev) {
|
||||
st.prev = curr;
|
||||
st.stop = !m_progr(int(curr));
|
||||
}
|
||||
|
||||
// Don't want to use dirty casts for the buffer to be usable in
|
||||
// the NanoSVGParser until performance is not a bottleneck here.
|
||||
auto svgtxt = reserve_vector<char>(entry.buf.size() + 1);
|
||||
std::copy(entry.buf.begin(), entry.buf.end(), std::back_inserter(svgtxt));
|
||||
svgtxt.emplace_back('\0');
|
||||
NanoSVGParser svgp(svgtxt.data());
|
||||
|
||||
Polygons polys;
|
||||
for (NSVGshape *shape = svgp.image->shapes; shape != nullptr; shape = shape->next) {
|
||||
for (NSVGpath *path = shape->paths; path != nullptr; path = path->next) {
|
||||
Polygon p;
|
||||
for (int i = 0; i < path->npts; ++i) {
|
||||
size_t c = 2 * i;
|
||||
p.points.emplace_back(scaled(Vec2f(path->pts[c], path->pts[c + 1])));
|
||||
}
|
||||
polys.emplace_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the slice from the read polygons. Here, the fill rule has to
|
||||
// be the same as stated in the svg file which is `nonzero` when exported
|
||||
// using SL1_SVGArchive. Would be better to parse it from the svg file,
|
||||
// but if it's different, the file is probably corrupted anyways.
|
||||
ExPolygons expolys = union_ex(polys, ClipperLib::pftNonZero);
|
||||
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
|
||||
slices.emplace_back(expolys);
|
||||
}
|
||||
|
||||
// Compile error without the move
|
||||
return std::move(config_substitutions);
|
||||
}
|
||||
|
||||
ConfigSubstitutions SL1_SVGReader::read(DynamicPrintConfig &out)
|
||||
{
|
||||
ZipperArchive arch = read_zipper_archive(m_fname, {"prusaslicer.ini"}, {});
|
||||
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -22,6 +22,27 @@ public:
|
||||
using SL1Archive::SL1Archive;
|
||||
};
|
||||
|
||||
class SL1_SVGReader: public SLAArchiveReader {
|
||||
std::function<bool(int)> m_progr;
|
||||
std::string m_fname;
|
||||
|
||||
public:
|
||||
// If the profile is missing from the archive (older PS versions did not have
|
||||
// it), profile_out's initial value will be used as fallback. profile_out will be empty on
|
||||
// function return if the archive did not contain any profile.
|
||||
ConfigSubstitutions read(std::vector<ExPolygons> &slices,
|
||||
DynamicPrintConfig &profile_out) override;
|
||||
|
||||
ConfigSubstitutions read(DynamicPrintConfig &profile) override;
|
||||
|
||||
SL1_SVGReader() = default;
|
||||
SL1_SVGReader(const std::string &fname,
|
||||
SLAImportQuality /*quality*/,
|
||||
const ProgrFn & progr)
|
||||
: m_progr(progr), m_fname(fname)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // SL1_SVG_HPP
|
||||
|
179
src/libslic3r/Format/SLAArchiveReader.cpp
Normal file
179
src/libslic3r/Format/SLAArchiveReader.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
#include "SLAArchiveReader.hpp"
|
||||
#include "SL1.hpp"
|
||||
#include "SL1_SVG.hpp"
|
||||
|
||||
#include "libslic3r/SlicesToTriangleMesh.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
constexpr const char * L(const char * str) { return str; }
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
// Factory function that returns an implementation of SLAArchiveReader.
|
||||
using ArchiveFactory = std::function<
|
||||
std::unique_ptr<SLAArchiveReader>(const std::string &fname,
|
||||
SLAImportQuality quality,
|
||||
const ProgrFn & progr)>;
|
||||
|
||||
// Entry in the global registry of readable archive formats.
|
||||
struct ArchiveEntry {
|
||||
const char *descr;
|
||||
std::vector<const char *> extensions;
|
||||
ArchiveFactory factoryfn;
|
||||
};
|
||||
|
||||
// This is where the readable archive formats are registered.
|
||||
static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
|
||||
{
|
||||
"SL1",
|
||||
{ L("SL1 / SL1S archive files"), {"sl1", "sl1s", "zip"},
|
||||
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1Reader>(fname, quality, progr); } }
|
||||
},
|
||||
{
|
||||
"SL2",
|
||||
{ L("SL2 archive files"), {"sl2", "sl1_svg"/*, "zip"*/}, // also a zip but unnecessary hassle to implement single extension for multiple archives
|
||||
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1_SVGReader>(fname, quality, progr); }}
|
||||
},
|
||||
// TODO: pwmx and future others.
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<SLAArchiveReader> SLAArchiveReader::create(
|
||||
const std::string &fname,
|
||||
const std::string &format_id,
|
||||
SLAImportQuality quality,
|
||||
const ProgrFn & progr)
|
||||
{
|
||||
// Create an instance of SLAArchiveReader using the registered archive
|
||||
// reader implementations.
|
||||
// If format_id is specified and valid, that archive format will be
|
||||
// preferred. When format_id is emtpy, the file extension is compared
|
||||
// with the advertised extensions of registered readers and the first
|
||||
// match will be used.
|
||||
|
||||
std::string ext = boost::filesystem::path(fname).extension().string();
|
||||
boost::algorithm::to_lower(ext);
|
||||
|
||||
std::unique_ptr<SLAArchiveReader> ret;
|
||||
|
||||
auto arch_from = REGISTERED_ARCHIVES.begin();
|
||||
auto arch_to = REGISTERED_ARCHIVES.end();
|
||||
|
||||
auto arch_it = REGISTERED_ARCHIVES.find(format_id);
|
||||
if (arch_it != REGISTERED_ARCHIVES.end()) {
|
||||
arch_from = arch_it;
|
||||
arch_to = arch_it;
|
||||
}
|
||||
|
||||
if (!ext.empty()) {
|
||||
if (ext.front() == '.')
|
||||
ext.erase(ext.begin());
|
||||
|
||||
auto extcmp = [&ext](const auto &e) { return e == ext; };
|
||||
|
||||
for (auto it = arch_from; it != arch_to; ++it) {
|
||||
const auto &[format_id, entry] = *it;
|
||||
if (std::any_of(entry.extensions.begin(), entry.extensions.end(), extcmp))
|
||||
ret = entry.factoryfn(fname, quality, progr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::vector<const char *> &SLAArchiveReader::registered_archives()
|
||||
{
|
||||
static std::vector<const char*> archnames;
|
||||
|
||||
if (archnames.empty()) {
|
||||
archnames.reserve(REGISTERED_ARCHIVES.size());
|
||||
|
||||
for (auto &[name, _] : REGISTERED_ARCHIVES)
|
||||
archnames.emplace_back(name.c_str());
|
||||
}
|
||||
|
||||
return archnames;
|
||||
}
|
||||
|
||||
std::vector<const char *> SLAArchiveReader::get_extensions(const char *archtype)
|
||||
{
|
||||
auto it = REGISTERED_ARCHIVES.find(archtype);
|
||||
|
||||
if (it != REGISTERED_ARCHIVES.end())
|
||||
return it->second.extensions;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
const char *SLAArchiveReader::get_description(const char *archtype)
|
||||
{
|
||||
auto it = REGISTERED_ARCHIVES.find(archtype);
|
||||
|
||||
if (it != REGISTERED_ARCHIVES.end())
|
||||
return it->second.descr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct SliceParams { double layerh = 0., initial_layerh = 0.; };
|
||||
|
||||
static SliceParams get_slice_params(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
auto *opt_layerh = cfg.option<ConfigOptionFloat>("layer_height");
|
||||
auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("initial_layer_height");
|
||||
|
||||
if (!opt_layerh || !opt_init_layerh)
|
||||
throw MissingProfileError("Invalid SL1 / SL1S file");
|
||||
|
||||
return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()};
|
||||
}
|
||||
|
||||
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
|
||||
const std::string &format_id,
|
||||
indexed_triangle_set &out,
|
||||
DynamicPrintConfig &profile,
|
||||
SLAImportQuality quality,
|
||||
const ProgrFn & progr)
|
||||
{
|
||||
ConfigSubstitutions ret;
|
||||
|
||||
if (auto reader = SLAArchiveReader::create(zipfname, format_id, quality, progr)) {
|
||||
std::vector<ExPolygons> slices;
|
||||
ret = reader->read(slices, profile);
|
||||
|
||||
SliceParams slicp = get_slice_params(profile);
|
||||
|
||||
if (!slices.empty())
|
||||
out = slices_to_mesh(slices, 0, slicp.layerh, slicp.initial_layerh);
|
||||
|
||||
} else {
|
||||
throw ReaderUnimplementedError("Reader unimplemented");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
|
||||
const std::string &format_id,
|
||||
DynamicPrintConfig &out)
|
||||
{
|
||||
ConfigSubstitutions ret;
|
||||
|
||||
if (auto reader = SLAArchiveReader::create(zipfname, format_id)) {
|
||||
ret = reader->read(out);
|
||||
} else {
|
||||
throw ReaderUnimplementedError("Reader unimplemented");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
85
src/libslic3r/Format/SLAArchiveReader.hpp
Normal file
85
src/libslic3r/Format/SLAArchiveReader.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef SLAARCHIVEREADER_HPP
|
||||
#define SLAARCHIVEREADER_HPP
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/ExPolygon.hpp"
|
||||
|
||||
struct indexed_triangle_set;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// A generic indicator for the quality of an imported model. Obviously, the
|
||||
// original cannot be fully reconstructed.
|
||||
enum class SLAImportQuality { Accurate, Balanced, Fast };
|
||||
|
||||
// Raised when the needed metadata cannot be retrieved or guessed from an archive
|
||||
class MissingProfileError : public RuntimeError
|
||||
{
|
||||
using RuntimeError::RuntimeError;
|
||||
};
|
||||
|
||||
// A shortname for status indication function.
|
||||
// The argument is the status (from <0, 100>)
|
||||
// Returns false if cancel was requested.
|
||||
using ProgrFn = std::function<bool(int)>;
|
||||
|
||||
// Abstract interface for an archive reader. This needs to be implemented for
|
||||
// every supported archive format.
|
||||
class SLAArchiveReader {
|
||||
public:
|
||||
|
||||
virtual ~SLAArchiveReader() = default;
|
||||
|
||||
// Read the profile and reconstruct the slices
|
||||
virtual ConfigSubstitutions read(std::vector<ExPolygons> &slices,
|
||||
DynamicPrintConfig &profile) = 0;
|
||||
|
||||
// Overload for reading only the profile contained in the archive (if present)
|
||||
virtual ConfigSubstitutions read(DynamicPrintConfig &profile) = 0;
|
||||
|
||||
// Creates a reader instance based on the provided file path.
|
||||
// format_id can be one of the archive type identifiers returned by
|
||||
// registered_archives(). If left empty, only the file extension will
|
||||
// be considered. If more archive types have the same extension (like *.zip)
|
||||
// The first match is used.
|
||||
static std::unique_ptr<SLAArchiveReader> create(
|
||||
const std::string &fname,
|
||||
const std::string &format_id,
|
||||
SLAImportQuality quality = SLAImportQuality::Balanced,
|
||||
const ProgrFn &progr = [](int) { return false; });
|
||||
|
||||
// Get the names of currently known archive reader implementations
|
||||
static const std::vector<const char *> & registered_archives();
|
||||
|
||||
// Get the understood file extensions belonging to an archive format
|
||||
static std::vector<const char *> get_extensions(const char *archtype);
|
||||
|
||||
// Generic description (usable in GUI) about an archive format
|
||||
static const char * get_description(const char *archtype);
|
||||
};
|
||||
|
||||
// Raised in import_sla_archive when a nullptr reader is returned by
|
||||
// SLAArchiveReader::create()
|
||||
class ReaderUnimplementedError : public RuntimeError
|
||||
{
|
||||
using RuntimeError::RuntimeError;
|
||||
};
|
||||
|
||||
// Helper free functions to import an archive using the above interface.
|
||||
// Can throw ReaderUnimplementedError or MissingProfileError
|
||||
ConfigSubstitutions import_sla_archive(
|
||||
const std::string &zipfname,
|
||||
const std::string &format_id,
|
||||
indexed_triangle_set &out,
|
||||
DynamicPrintConfig &profile,
|
||||
SLAImportQuality quality = SLAImportQuality::Balanced,
|
||||
const ProgrFn &progr = [](int) { return true; });
|
||||
|
||||
// Only reads the profile, doesn't reconstruct the model.
|
||||
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
|
||||
const std::string &format_id,
|
||||
DynamicPrintConfig &out);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // SLAARCHIVEREADER_HPP
|
@ -1,4 +1,4 @@
|
||||
#include "SLAArchive.hpp"
|
||||
#include "SLAArchiveWriter.hpp"
|
||||
|
||||
#include "SL1.hpp"
|
||||
#include "SL1_SVG.hpp"
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using ArchiveFactory = std::function<std::unique_ptr<SLAArchive>(const SLAPrinterConfig&)>;
|
||||
using ArchiveFactory = std::function<std::unique_ptr<SLAArchiveWriter>(const SLAPrinterConfig&)>;
|
||||
|
||||
struct ArchiveEntry {
|
||||
const char *ext;
|
||||
@ -35,8 +35,8 @@ static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<SLAArchive>
|
||||
SLAArchive::create(const std::string &archtype, const SLAPrinterConfig &cfg)
|
||||
std::unique_ptr<SLAArchiveWriter>
|
||||
SLAArchiveWriter::create(const std::string &archtype, const SLAPrinterConfig &cfg)
|
||||
{
|
||||
auto entry = REGISTERED_ARCHIVES.find(archtype);
|
||||
|
||||
@ -46,7 +46,7 @@ SLAArchive::create(const std::string &archtype, const SLAPrinterConfig &cfg)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::vector<const char*>& SLAArchive::registered_archives()
|
||||
const std::vector<const char*>& SLAArchiveWriter::registered_archives()
|
||||
{
|
||||
static std::vector<const char*> archnames;
|
||||
|
||||
@ -60,9 +60,9 @@ const std::vector<const char*>& SLAArchive::registered_archives()
|
||||
return archnames;
|
||||
}
|
||||
|
||||
const char *SLAArchive::get_extension(const char *archtype)
|
||||
const char *SLAArchiveWriter::get_extension(const char *archtype)
|
||||
{
|
||||
static const char* DEFAULT_EXT = "zip";
|
||||
constexpr const char* DEFAULT_EXT = "zip";
|
||||
|
||||
auto entry = REGISTERED_ARCHIVES.find(archtype);
|
||||
if (entry != REGISTERED_ARCHIVES.end())
|
@ -12,7 +12,7 @@ namespace Slic3r {
|
||||
class SLAPrint;
|
||||
class SLAPrinterConfig;
|
||||
|
||||
class SLAArchive {
|
||||
class SLAArchiveWriter {
|
||||
protected:
|
||||
std::vector<sla::EncodedRaster> m_layers;
|
||||
|
||||
@ -20,7 +20,7 @@ protected:
|
||||
virtual sla::RasterEncoder get_encoder() const = 0;
|
||||
|
||||
public:
|
||||
virtual ~SLAArchive() = default;
|
||||
virtual ~SLAArchiveWriter() = default;
|
||||
|
||||
// Fn have to be thread safe: void(sla::RasterBase& raster, size_t lyrid);
|
||||
template<class Fn, class CancelFn, class EP = ExecutionTBB>
|
||||
@ -44,14 +44,15 @@ public:
|
||||
execution::max_concurrency(ep));
|
||||
}
|
||||
|
||||
// Export the print into an archive using the provided filename.
|
||||
// Export the print into an archive using the provided filename.
|
||||
virtual void export_print(const std::string fname,
|
||||
const SLAPrint &print,
|
||||
const ThumbnailsList &thumbnails,
|
||||
const std::string &projectname = "") = 0;
|
||||
|
||||
// Factory method to create an archiver instance
|
||||
static std::unique_ptr<SLAArchive> create(const std::string &archtype, const SLAPrinterConfig&);
|
||||
static std::unique_ptr<SLAArchiveWriter> create(
|
||||
const std::string &archtype, const SLAPrinterConfig &);
|
||||
|
||||
// Get the names of currently known archiver implementations
|
||||
static const std::vector<const char *> & registered_archives();
|
136
src/libslic3r/Format/ZipperArchiveImport.cpp
Normal file
136
src/libslic3r/Format/ZipperArchiveImport.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
#include "ZipperArchiveImport.hpp"
|
||||
|
||||
#include "libslic3r/miniz_extension.hpp"
|
||||
#include "libslic3r/Exception.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
// Read an ini file into boost property tree
|
||||
boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
|
||||
MZ_Archive &zip)
|
||||
{
|
||||
std::string buf(size_t(entry.m_uncomp_size), '\0');
|
||||
|
||||
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
|
||||
buf.data(), buf.size(), 0))
|
||||
throw Slic3r::FileIOError(zip.get_errorstr());
|
||||
|
||||
boost::property_tree::ptree tree;
|
||||
std::stringstream ss(buf);
|
||||
boost::property_tree::read_ini(ss, tree);
|
||||
return tree;
|
||||
}
|
||||
|
||||
// Read an arbitrary file into EntryBuffer
|
||||
EntryBuffer read_entry(const mz_zip_archive_file_stat &entry,
|
||||
MZ_Archive &zip,
|
||||
const std::string &name)
|
||||
{
|
||||
std::vector<uint8_t> buf(entry.m_uncomp_size);
|
||||
|
||||
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
|
||||
buf.data(), buf.size(), 0))
|
||||
throw Slic3r::FileIOError(zip.get_errorstr());
|
||||
|
||||
return {std::move(buf), (name.empty() ? entry.m_filename : name)};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ZipperArchive read_zipper_archive(const std::string &zipfname,
|
||||
const std::vector<std::string> &includes,
|
||||
const std::vector<std::string> &excludes)
|
||||
{
|
||||
ZipperArchive arch;
|
||||
|
||||
// Little RAII
|
||||
struct Arch : public MZ_Archive
|
||||
{
|
||||
Arch(const std::string &fname)
|
||||
{
|
||||
if (!open_zip_reader(&arch, fname))
|
||||
throw Slic3r::FileIOError(get_errorstr());
|
||||
}
|
||||
|
||||
~Arch() { close_zip_reader(&arch); }
|
||||
} zip(zipfname);
|
||||
|
||||
mz_uint num_entries = mz_zip_reader_get_num_files(&zip.arch);
|
||||
|
||||
for (mz_uint i = 0; i < num_entries; ++i) {
|
||||
mz_zip_archive_file_stat entry;
|
||||
|
||||
if (mz_zip_reader_file_stat(&zip.arch, i, &entry)) {
|
||||
std::string name = entry.m_filename;
|
||||
boost::algorithm::to_lower(name);
|
||||
|
||||
if (!std::any_of(includes.begin(), includes.end(),
|
||||
[&name](const std::string &incl) {
|
||||
return boost::algorithm::contains(name, incl);
|
||||
}))
|
||||
continue;
|
||||
|
||||
if (std::any_of(excludes.begin(), excludes.end(),
|
||||
[&name](const std::string &excl) {
|
||||
return boost::algorithm::contains(name, excl);
|
||||
}))
|
||||
continue;
|
||||
|
||||
if (name == CONFIG_FNAME) { arch.config = read_ini(entry, zip); continue; }
|
||||
if (name == PROFILE_FNAME) { arch.profile = read_ini(entry, zip); continue; }
|
||||
|
||||
auto it = std::lower_bound(
|
||||
arch.entries.begin(), arch.entries.end(),
|
||||
EntryBuffer{{}, name},
|
||||
[](const EntryBuffer &r1, const EntryBuffer &r2) {
|
||||
return std::less<std::string>()(r1.fname, r2.fname);
|
||||
});
|
||||
|
||||
arch.entries.insert(it, read_entry(entry, zip, name));
|
||||
}
|
||||
}
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
||||
std::pair<DynamicPrintConfig, ConfigSubstitutions> extract_profile(
|
||||
const ZipperArchive &arch, DynamicPrintConfig &profile_out)
|
||||
{
|
||||
DynamicPrintConfig profile_in, profile_use;
|
||||
ConfigSubstitutions config_substitutions =
|
||||
profile_in.load(arch.profile,
|
||||
ForwardCompatibilitySubstitutionRule::Enable);
|
||||
|
||||
if (profile_in.empty()) { // missing profile... do guess work
|
||||
// try to recover the layer height from the config.ini which was
|
||||
// present in all versions of sl1 files.
|
||||
if (auto lh_opt = arch.config.find("layerHeight");
|
||||
lh_opt != arch.config.not_found()) {
|
||||
auto lh_str = lh_opt->second.data();
|
||||
|
||||
size_t pos = 0;
|
||||
double lh = string_to_double_decimal_point(lh_str, &pos);
|
||||
if (pos) { // TODO: verify that pos is 0 when parsing fails
|
||||
profile_out.set("layer_height", lh);
|
||||
profile_out.set("initial_layer_height", lh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the archive contains an empty profile, use the one that was passed
|
||||
// as output argument then replace it with the readed profile to report
|
||||
// that it was empty.
|
||||
profile_use = profile_in.empty() ? profile_out : profile_in;
|
||||
profile_out = profile_in;
|
||||
|
||||
return {profile_use, std::move(config_substitutions)};
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
54
src/libslic3r/Format/ZipperArchiveImport.hpp
Normal file
54
src/libslic3r/Format/ZipperArchiveImport.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef ZIPPERARCHIVEIMPORT_HPP
|
||||
#define ZIPPERARCHIVEIMPORT_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Buffer for arbitraryfiles inside a zipper archive.
|
||||
struct EntryBuffer
|
||||
{
|
||||
std::vector<uint8_t> buf;
|
||||
std::string fname;
|
||||
};
|
||||
|
||||
// Structure holding the data read from a zipper archive.
|
||||
struct ZipperArchive
|
||||
{
|
||||
boost::property_tree::ptree profile, config;
|
||||
std::vector<EntryBuffer> entries;
|
||||
};
|
||||
|
||||
// Names of the files containing metadata inside the archive.
|
||||
const constexpr char *CONFIG_FNAME = "config.ini";
|
||||
const constexpr char *PROFILE_FNAME = "prusaslicer.ini";
|
||||
|
||||
// Read an archive that was written using the Zipper class.
|
||||
// The includes parameter is a set of file name substrings that the entries
|
||||
// must contain to be included in ZipperArchive.
|
||||
// The excludes parameter may contain substrings that filenames must not
|
||||
// contain.
|
||||
// Every file in the archive is read into ZipperArchive::entries
|
||||
// except the files CONFIG_FNAME, and PROFILE_FNAME which are read into
|
||||
// ZipperArchive::config and ZipperArchive::profile structures.
|
||||
ZipperArchive read_zipper_archive(const std::string &zipfname,
|
||||
const std::vector<std::string> &includes,
|
||||
const std::vector<std::string> &excludes);
|
||||
|
||||
// Extract the print profile form the archive into 'out'.
|
||||
// Returns a profile that has correct parameters to use for model reconstruction
|
||||
// even if the needed parameters were not fully found in the archive's metadata.
|
||||
// The inout argument shall be a usable fallback profile if the archive
|
||||
// has totally corrupted metadata.
|
||||
std::pair<DynamicPrintConfig, ConfigSubstitutions> extract_profile(
|
||||
const ZipperArchive &arch, DynamicPrintConfig &inout);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ZIPPERARCHIVEIMPORT_HPP
|
@ -3,13 +3,13 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SLAArchive.hpp"
|
||||
#include "SLAArchiveWriter.hpp"
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class PwmxArchive: public SLAArchive {
|
||||
class PwmxArchive: public SLAArchiveWriter {
|
||||
SLAPrinterConfig m_cfg;
|
||||
|
||||
protected:
|
||||
|
@ -2312,7 +2312,6 @@ GCode::LayerResult GCode::process_layer(
|
||||
} // for objects
|
||||
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
std::vector<std::unique_ptr<EdgeGrid::Grid>> lower_layer_edge_grids(layers.size());
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
|
||||
@ -2337,7 +2336,7 @@ GCode::LayerResult GCode::process_layer(
|
||||
path.mm3_per_mm = mm3_per_mm;
|
||||
}
|
||||
//FIXME using the support_material_speed of the 1st object printed.
|
||||
gcode += this->extrude_loop(loop, "skirt", m_config.support_material_speed.value);
|
||||
gcode += this->extrude_loop(loop, "skirt"sv, m_config.support_material_speed.value);
|
||||
}
|
||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||
// Allow a straight travel move to the first object point if this is the first layer (but don't in next layers).
|
||||
@ -2350,7 +2349,7 @@ GCode::LayerResult GCode::process_layer(
|
||||
this->set_origin(0., 0.);
|
||||
m_avoid_crossing_perimeters.use_external_mp();
|
||||
for (const ExtrusionEntity *ee : print.brim().entities) {
|
||||
gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value);
|
||||
gcode += this->extrude_entity(*ee, "brim"sv, m_config.support_material_speed.value);
|
||||
}
|
||||
m_brim_done = true;
|
||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||
@ -2406,9 +2405,9 @@ GCode::LayerResult GCode::process_layer(
|
||||
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
|
||||
if (print.config().infill_first) {
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
} else {
|
||||
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
}
|
||||
// ironing
|
||||
@ -2543,51 +2542,28 @@ std::string GCode::change_layer(coordf_t print_z)
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static std::unique_ptr<EdgeGrid::Grid> calculate_layer_edge_grid(const Layer& layer)
|
||||
{
|
||||
auto out = make_unique<EdgeGrid::Grid>();
|
||||
|
||||
// Create the distance field for a layer below.
|
||||
const coord_t distance_field_resolution = coord_t(scale_(1.) + 0.5);
|
||||
out->create(layer.lslices, distance_field_resolution);
|
||||
out->calculate_sdf();
|
||||
#if 0
|
||||
{
|
||||
static int iRun = 0;
|
||||
BoundingBox bbox = (*lower_layer_edge_grid)->bbox();
|
||||
bbox.min(0) -= scale_(5.f);
|
||||
bbox.min(1) -= scale_(5.f);
|
||||
bbox.max(0) += scale_(5.f);
|
||||
bbox.max(1) += scale_(5.f);
|
||||
EdgeGrid::save_png(*(*lower_layer_edge_grid), bbox, scale_(0.1f), debug_out_path("GCode_extrude_loop_edge_grid-%d.png", iRun++));
|
||||
}
|
||||
#endif
|
||||
return out;
|
||||
static const auto comment_perimeter = "perimeter"sv;
|
||||
// Comparing string_view pointer & length for speed.
|
||||
static inline bool comment_is_perimeter(const std::string_view comment) {
|
||||
return comment.data() == comment_perimeter.data() && comment.size() == comment_perimeter.size();
|
||||
}
|
||||
|
||||
|
||||
std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, double speed, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
|
||||
std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view description, double speed)
|
||||
{
|
||||
// get a copy; don't modify the orientation of the original loop object otherwise
|
||||
// next copies (if any) would not detect the correct orientation
|
||||
|
||||
if (m_layer->lower_layer && lower_layer_edge_grid != nullptr && ! *lower_layer_edge_grid)
|
||||
*lower_layer_edge_grid = calculate_layer_edge_grid(*m_layer->lower_layer);
|
||||
|
||||
// extrude all loops ccw
|
||||
bool was_clockwise = loop.make_counter_clockwise();
|
||||
|
||||
// find the point of the loop that is closest to the current extruder position
|
||||
// or randomize if requested
|
||||
Point last_pos = this->last_pos();
|
||||
if (m_config.spiral_vase) {
|
||||
if (! m_config.spiral_vase && comment_is_perimeter(description)) {
|
||||
assert(m_layer != nullptr);
|
||||
m_seam_placer.place_seam(m_layer, loop, m_config.external_perimeters_first, this->last_pos());
|
||||
} else
|
||||
loop.split_at(last_pos, false);
|
||||
}
|
||||
else
|
||||
m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first,
|
||||
EXTRUDER_CONFIG(nozzle_diameter), lower_layer_edge_grid ? lower_layer_edge_grid->get() : nullptr);
|
||||
|
||||
// clip the path to avoid the extruder to get exactly on the first point of the loop;
|
||||
// if polyline was shorter than the clipping distance we'd get a null polyline, so
|
||||
@ -2607,11 +2583,9 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
|
||||
// extrude along the path
|
||||
std::string gcode;
|
||||
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
|
||||
// description += ExtrusionLoop::role_to_string(loop.loop_role());
|
||||
// description += ExtrusionEntity::role_to_string(path->role);
|
||||
path->simplify(m_scaled_resolution);
|
||||
gcode += this->_extrude(*path, description, speed);
|
||||
for (ExtrusionPath &path : paths) {
|
||||
path.simplify(m_scaled_resolution);
|
||||
gcode += this->_extrude(path, description, speed);
|
||||
}
|
||||
|
||||
// reset acceleration
|
||||
@ -2626,18 +2600,19 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
// the side depends on the original winding order of the polygon (left for contours, right for holes)
|
||||
//FIXME improve the algorithm in case the loop is tiny.
|
||||
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
|
||||
Point a = paths.front().polyline.points[1]; // second point
|
||||
Point b = *(paths.back().polyline.points.end()-3); // second to last point
|
||||
// Angle from the 2nd point to the last point.
|
||||
double angle_inside = angle(paths.front().polyline.points[1] - paths.front().first_point(),
|
||||
*(paths.back().polyline.points.end()-3) - paths.front().first_point());
|
||||
assert(angle_inside >= -M_PI && angle_inside <= M_PI);
|
||||
// 3rd of this angle will be taken, thus make the angle monotonic before interpolation.
|
||||
if (was_clockwise) {
|
||||
// swap points
|
||||
Point c = a; a = b; b = c;
|
||||
if (angle_inside > 0)
|
||||
angle_inside -= 2.0 * M_PI;
|
||||
} else {
|
||||
if (angle_inside < 0)
|
||||
angle_inside += 2.0 * M_PI;
|
||||
}
|
||||
|
||||
double angle = paths.front().first_point().ccw_angle(a, b) / 3;
|
||||
|
||||
// turn left if contour, turn right if hole
|
||||
if (was_clockwise) angle *= -1;
|
||||
|
||||
// create the destination point along the first segment and rotate it
|
||||
// we make sure we don't exceed the segment length because we don't know
|
||||
// the rotation of the second segment so we might cross the object boundary
|
||||
@ -2649,7 +2624,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
// Shift by no more than a nozzle diameter.
|
||||
//FIXME Hiding the seams will not work nicely for very densely discretized contours!
|
||||
Point pt = ((nd * nd >= l2) ? p2 : (p1 + v * (nd / sqrt(l2)))).cast<coord_t>();
|
||||
pt.rotate(angle, paths.front().polyline.points.front());
|
||||
// Rotate pt inside around the seam point.
|
||||
pt.rotate(angle_inside / 3., paths.front().polyline.points.front());
|
||||
// generate the travel move
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), "move inwards before travel");
|
||||
}
|
||||
@ -2657,13 +2633,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string description, double speed)
|
||||
std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, const std::string_view description, double speed)
|
||||
{
|
||||
// extrude along the path
|
||||
std::string gcode;
|
||||
for (ExtrusionPath path : multipath.paths) {
|
||||
// description += ExtrusionLoop::role_to_string(loop.loop_role());
|
||||
// description += ExtrusionEntity::role_to_string(path->role);
|
||||
path.simplify(m_scaled_resolution);
|
||||
gcode += this->_extrude(path, description, speed);
|
||||
}
|
||||
@ -2676,22 +2650,21 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string description, double speed, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
|
||||
std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::string_view description, double speed)
|
||||
{
|
||||
if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(&entity))
|
||||
return this->extrude_path(*path, description, speed);
|
||||
else if (const ExtrusionMultiPath* multipath = dynamic_cast<const ExtrusionMultiPath*>(&entity))
|
||||
return this->extrude_multi_path(*multipath, description, speed);
|
||||
else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity))
|
||||
return this->extrude_loop(*loop, description, speed, lower_layer_edge_grid);
|
||||
return this->extrude_loop(*loop, description, speed);
|
||||
else
|
||||
throw Slic3r::InvalidArgument("Invalid argument supplied to extrude()");
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed)
|
||||
std::string GCode::extrude_path(ExtrusionPath path, std::string_view description, double speed)
|
||||
{
|
||||
// description += ExtrusionEntity::role_to_string(path.role());
|
||||
path.simplify(m_scaled_resolution);
|
||||
std::string gcode = this->_extrude(path, description, speed);
|
||||
if (m_wipe.enable) {
|
||||
@ -2704,24 +2677,15 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string description, dou
|
||||
}
|
||||
|
||||
// Extrude perimeters: Decide where to put seams (hide or align seams).
|
||||
std::string GCode::extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid)
|
||||
std::string GCode::extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region)
|
||||
{
|
||||
std::string gcode;
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
||||
if (! region.perimeters.empty()) {
|
||||
m_config.apply(print.get_print_region(®ion - &by_region.front()).config());
|
||||
|
||||
// plan_perimeters tries to place seams, it needs to have the lower_layer_edge_grid calculated already.
|
||||
if (m_layer->lower_layer && ! lower_layer_edge_grid)
|
||||
lower_layer_edge_grid = calculate_layer_edge_grid(*m_layer->lower_layer);
|
||||
|
||||
m_seam_placer.plan_perimeters(std::vector<const ExtrusionEntity*>(region.perimeters.begin(), region.perimeters.end()),
|
||||
*m_layer, m_config.seam_position, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter),
|
||||
(m_layer == NULL ? nullptr : m_layer->object()),
|
||||
(lower_layer_edge_grid ? lower_layer_edge_grid.get() : nullptr));
|
||||
|
||||
for (const ExtrusionEntity* ee : region.perimeters)
|
||||
gcode += this->extrude_entity(*ee, "perimeter", -1., &lower_layer_edge_grid);
|
||||
gcode += this->extrude_entity(*ee, comment_perimeter, -1.);
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
@ -2731,7 +2695,7 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
||||
{
|
||||
std::string gcode;
|
||||
ExtrusionEntitiesPtr extrusions;
|
||||
const char* extrusion_name = ironing ? "ironing" : "infill";
|
||||
const auto extrusion_name = ironing ? "ironing"sv : "infill"sv;
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
||||
if (! region.infills.empty()) {
|
||||
extrusions.clear();
|
||||
@ -2757,8 +2721,8 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
||||
|
||||
std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills)
|
||||
{
|
||||
static constexpr const char *support_label = "support material";
|
||||
static constexpr const char *support_interface_label = "support material interface";
|
||||
static constexpr const auto support_label = "support material"sv;
|
||||
static constexpr const auto support_interface_label = "support material interface"sv;
|
||||
|
||||
std::string gcode;
|
||||
if (! support_fills.entities.empty()) {
|
||||
@ -2767,7 +2731,7 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
||||
for (const ExtrusionEntity *ee : support_fills.entities) {
|
||||
ExtrusionRole role = ee->role();
|
||||
assert(role == erSupportMaterial || role == erSupportMaterialInterface);
|
||||
const char *label = (role == erSupportMaterial) ? support_label : support_interface_label;
|
||||
const auto label = (role == erSupportMaterial) ? support_label : support_interface_label;
|
||||
const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed;
|
||||
const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ee);
|
||||
if (path)
|
||||
@ -2855,20 +2819,18 @@ void GCode::GCodeOutputStream::write_format(const char* format, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed)
|
||||
std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view description, double speed)
|
||||
{
|
||||
std::string gcode;
|
||||
|
||||
if (is_bridge(path.role()))
|
||||
description += " (bridge)";
|
||||
const std::string_view description_bridge = is_bridge(path.role()) ? " (bridge)"sv : ""sv;
|
||||
|
||||
// go to first point of extrusion path
|
||||
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
|
||||
gcode += this->travel_to(
|
||||
path.first_point(),
|
||||
path.role(),
|
||||
"move to first " + description + " point"
|
||||
);
|
||||
std::string comment = "move to first ";
|
||||
comment += description;
|
||||
comment += description_bridge;
|
||||
comment += " point";
|
||||
gcode += this->travel_to(path.first_point(), path.role(), comment);
|
||||
}
|
||||
|
||||
// compensate retraction
|
||||
@ -3006,7 +2968,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
gcode += m_writer.set_speed(F, "", comment);
|
||||
double path_length = 0.;
|
||||
{
|
||||
std::string comment = m_config.gcode_comments ? description : "";
|
||||
std::string comment;
|
||||
if (m_config.gcode_comments) {
|
||||
comment = description;
|
||||
comment += description_bridge;
|
||||
}
|
||||
Vec2d prev = this->point_to_gcode_quantized(path.polyline.points.front());
|
||||
auto it = path.polyline.points.begin();
|
||||
auto end = path.polyline.points.end();
|
||||
|
@ -274,10 +274,10 @@ private:
|
||||
void set_extruders(const std::vector<unsigned int> &extruder_ids);
|
||||
std::string preamble();
|
||||
std::string change_layer(coordf_t print_z);
|
||||
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1., std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid = nullptr);
|
||||
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1., std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid = nullptr);
|
||||
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
|
||||
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);
|
||||
std::string extrude_entity(const ExtrusionEntity &entity, const std::string_view description, double speed = -1.);
|
||||
std::string extrude_loop(ExtrusionLoop loop, const std::string_view description, double speed = -1.);
|
||||
std::string extrude_multi_path(ExtrusionMultiPath multipath, const std::string_view description, double speed = -1.);
|
||||
std::string extrude_path(ExtrusionPath path, const std::string_view description, double speed = -1.);
|
||||
|
||||
// Extruding multiple objects with soluble / non-soluble / combined supports
|
||||
// on a multi-material printer, trying to minimize tool switches.
|
||||
@ -342,7 +342,7 @@ private:
|
||||
// For sequential print, the instance of the object to be printing has to be defined.
|
||||
const size_t single_object_instance_idx);
|
||||
|
||||
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid);
|
||||
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
|
||||
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing);
|
||||
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
|
||||
|
||||
@ -428,7 +428,7 @@ private:
|
||||
// Processor
|
||||
GCodeProcessor m_processor;
|
||||
|
||||
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
|
||||
std::string _extrude(const ExtrusionPath &path, const std::string_view description, double speed = -1);
|
||||
void print_machine_envelope(GCodeOutputStream &file, Print &print);
|
||||
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,12 +3,16 @@
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||
#include "libslic3r/KDTreeIndirect.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -16,119 +20,148 @@ class PrintObject;
|
||||
class ExtrusionLoop;
|
||||
class Print;
|
||||
class Layer;
|
||||
namespace EdgeGrid { class Grid; }
|
||||
|
||||
namespace EdgeGrid {
|
||||
class Grid;
|
||||
}
|
||||
|
||||
class SeamHistory {
|
||||
public:
|
||||
SeamHistory() { clear(); }
|
||||
std::optional<Point> get_last_seam(const PrintObject* po, size_t layer_id, const BoundingBox& island_bb);
|
||||
void add_seam(const PrintObject* po, const Point& pos, const BoundingBox& island_bb);
|
||||
void clear();
|
||||
namespace SeamPlacerImpl {
|
||||
|
||||
private:
|
||||
struct SeamPoint {
|
||||
Point m_pos;
|
||||
BoundingBox m_island_bb;
|
||||
};
|
||||
struct GlobalModelInfo;
|
||||
struct SeamComparator;
|
||||
|
||||
std::map<const PrintObject*, std::vector<SeamPoint>> m_data_last_layer;
|
||||
std::map<const PrintObject*, std::vector<SeamPoint>> m_data_this_layer;
|
||||
size_t m_layer_id;
|
||||
enum class EnforcedBlockedSeamPoint {
|
||||
Blocked = 0,
|
||||
Neutral = 1,
|
||||
Enforced = 2,
|
||||
};
|
||||
|
||||
// struct representing single perimeter loop
|
||||
struct Perimeter {
|
||||
size_t start_index;
|
||||
size_t end_index; //inclusive!
|
||||
size_t seam_index;
|
||||
float flow_width;
|
||||
|
||||
// During alignment, a final position may be stored here. In that case, finalized is set to true.
|
||||
// Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
|
||||
// Random position also uses this flexibility to set final seam point position
|
||||
bool finalized = false;
|
||||
Vec3f final_seam_position;
|
||||
};
|
||||
|
||||
//Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
|
||||
// then all the needed attributes are computed and finally, for each perimeter one point is chosen as seam.
|
||||
// This seam position can be then further aligned
|
||||
struct SeamCandidate {
|
||||
SeamCandidate(const Vec3f &pos, Perimeter &perimeter,
|
||||
float local_ccw_angle,
|
||||
EnforcedBlockedSeamPoint type) :
|
||||
position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(
|
||||
local_ccw_angle), type(type), central_enforcer(false) {
|
||||
}
|
||||
const Vec3f position;
|
||||
// pointer to Perimeter loop of this point. It is shared across all points of the loop
|
||||
Perimeter &perimeter;
|
||||
float visibility;
|
||||
float overhang;
|
||||
// distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
|
||||
// Negative sign means inside the print, comes from EdgeGrid structure
|
||||
float embedded_distance;
|
||||
float local_ccw_angle;
|
||||
EnforcedBlockedSeamPoint type;
|
||||
bool central_enforcer; //marks this candidate as central point of enforced segment on the perimeter - important for alignment
|
||||
};
|
||||
|
||||
struct FaceVisibilityInfo {
|
||||
float visibility;
|
||||
};
|
||||
|
||||
struct SeamCandidateCoordinateFunctor {
|
||||
SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) :
|
||||
seam_candidates(seam_candidates) {
|
||||
}
|
||||
const std::vector<SeamCandidate> &seam_candidates;
|
||||
float operator()(size_t index, size_t dim) const {
|
||||
return seam_candidates[index].position[dim];
|
||||
}
|
||||
};
|
||||
} // namespace SeamPlacerImpl
|
||||
|
||||
struct PrintObjectSeamData
|
||||
{
|
||||
using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>;
|
||||
|
||||
struct LayerSeams
|
||||
{
|
||||
Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters;
|
||||
std::vector<SeamPlacerImpl::SeamCandidate> points;
|
||||
std::unique_ptr<SeamCandidatesTree> points_tree;
|
||||
};
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
|
||||
std::vector<LayerSeams> layers;
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
|
||||
// tree of all points of the given layer
|
||||
|
||||
void clear()
|
||||
{
|
||||
layers.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class SeamPlacer {
|
||||
public:
|
||||
void init(const Print& print);
|
||||
static constexpr size_t raycasting_decimation_target_triangle_count = 10000;
|
||||
static constexpr float raycasting_subdivision_target_length = 2.0f;
|
||||
//square of number of rays per triangle
|
||||
static constexpr size_t sqr_rays_per_triangle = 7;
|
||||
|
||||
// When perimeters are printed, first call this function with the respective
|
||||
// external perimeter. SeamPlacer will find a location for its seam and remember it.
|
||||
// Subsequent calls to get_seam will return this position.
|
||||
// arm length used during angles computation
|
||||
static constexpr float polygon_local_angles_arm_distance = 0.5f;
|
||||
|
||||
// increases angle importance at the cost of deacreasing visibility info importance. must be > 0
|
||||
static constexpr float additional_angle_importance = 0.6f;
|
||||
|
||||
void plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
|
||||
const Layer& layer, SeamPosition seam_position,
|
||||
Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid);
|
||||
// If enforcer or blocker is closer to the seam candidate than this limit, the seam candidate is set to Blocker or Enforcer
|
||||
static constexpr float enforcer_blocker_distance_tolerance = 0.35f;
|
||||
// For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
|
||||
static constexpr float enforcer_oversampling_distance = 0.2f;
|
||||
|
||||
void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid);
|
||||
|
||||
// When searching for seam clusters for alignment:
|
||||
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
|
||||
static constexpr float seam_align_score_tolerance = 0.5f;
|
||||
// seam_align_tolerable_dist - if next layer closes point is too far away, break string
|
||||
static constexpr float seam_align_tolerable_dist = 1.0f;
|
||||
// if the seam of the current layer is too far away, and the closest seam candidate is not very good, layer is skipped.
|
||||
// this param limits the number of allowed skips
|
||||
static constexpr size_t seam_align_tolerable_skips = 4;
|
||||
// minimum number of seams needed in cluster to make alignment happen
|
||||
static constexpr size_t seam_align_minimum_string_seams = 6;
|
||||
// points covered by spline; determines number of splines for the given string
|
||||
static constexpr size_t seam_align_seams_per_segment = 8;
|
||||
|
||||
using TreeType = AABBTreeIndirect::Tree<2, coord_t>;
|
||||
using AlignedBoxType = Eigen::AlignedBox<TreeType::CoordType, TreeType::NumDimensions>;
|
||||
//The following data structures hold all perimeter points for all PrintObject.
|
||||
std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object;
|
||||
|
||||
void init(const Print &print);
|
||||
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||
|
||||
private:
|
||||
|
||||
// When given an external perimeter (!), returns the seam.
|
||||
Point calculate_seam(const Layer& layer, const SeamPosition seam_position,
|
||||
const ExtrusionLoop& loop, coordf_t nozzle_dmr, const PrintObject* po,
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos, bool prefer_nearest);
|
||||
|
||||
struct CustomTrianglesPerLayer {
|
||||
Polygons polys;
|
||||
TreeType tree;
|
||||
};
|
||||
|
||||
// Just a cache to save some lookups.
|
||||
const Layer* m_last_layer_po = nullptr;
|
||||
coordf_t m_last_print_z = -1.;
|
||||
const PrintObject* m_last_po = nullptr;
|
||||
|
||||
struct SeamPoint {
|
||||
Point pt;
|
||||
bool precalculated = false;
|
||||
bool external = false;
|
||||
const Layer* layer = nullptr;
|
||||
SeamPosition seam_position;
|
||||
const PrintObject* po = nullptr;
|
||||
};
|
||||
std::vector<SeamPoint> m_plan;
|
||||
size_t m_plan_idx;
|
||||
|
||||
std::vector<std::vector<CustomTrianglesPerLayer>> m_enforcers;
|
||||
std::vector<std::vector<CustomTrianglesPerLayer>> m_blockers;
|
||||
std::vector<const PrintObject*> m_po_list;
|
||||
|
||||
//std::map<const PrintObject*, Point> m_last_seam_position;
|
||||
SeamHistory m_seam_history;
|
||||
|
||||
// Get indices of points inside enforcers and blockers.
|
||||
void get_enforcers_and_blockers(size_t layer_id,
|
||||
const Polygon& polygon,
|
||||
size_t po_id,
|
||||
std::vector<size_t>& enforcers_idxs,
|
||||
std::vector<size_t>& blockers_idxs) const;
|
||||
|
||||
// Apply penalties to points inside enforcers/blockers.
|
||||
void apply_custom_seam(const Polygon& polygon, size_t po_id,
|
||||
std::vector<float>& penalties,
|
||||
const std::vector<float>& lengths,
|
||||
int layer_id, SeamPosition seam_position) const;
|
||||
|
||||
// Return random point of a polygon. The distribution will be uniform
|
||||
// along the contour and account for enforcers and blockers.
|
||||
Point get_random_seam(size_t layer_idx, const Polygon& polygon, size_t po_id,
|
||||
bool* saw_custom = nullptr) const;
|
||||
|
||||
// Is there any enforcer/blocker on this layer?
|
||||
bool is_custom_seam_on_layer(size_t layer_id, size_t po_idx) const {
|
||||
return is_custom_enforcer_on_layer(layer_id, po_idx)
|
||||
|| is_custom_blocker_on_layer(layer_id, po_idx);
|
||||
}
|
||||
|
||||
bool is_custom_enforcer_on_layer(size_t layer_id, size_t po_idx) const {
|
||||
return (! m_enforcers.at(po_idx).empty() && ! m_enforcers.at(po_idx)[layer_id].polys.empty());
|
||||
}
|
||||
|
||||
bool is_custom_blocker_on_layer(size_t layer_id, size_t po_idx) const {
|
||||
return (! m_blockers.at(po_idx).empty() && ! m_blockers.at(po_idx)[layer_id].polys.empty());
|
||||
}
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info,
|
||||
const SeamPosition configured_seam_preference);
|
||||
void calculate_candidates_visibility(const PrintObject *po,
|
||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
||||
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
|
||||
bool find_next_seam_in_layer(
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
std::pair<size_t, size_t> &last_point_indexes,
|
||||
const size_t layer_idx, const float slice_z,
|
||||
const SeamPlacerImpl::SeamComparator &comparator,
|
||||
std::vector<std::pair<size_t, size_t>> &seam_string) const;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // libslic3r_SeamPlacer_hpp_
|
||||
|
@ -153,8 +153,8 @@ public:
|
||||
float layer_height,
|
||||
// Maximum number of tool changes on this layer or the layers below.
|
||||
size_t max_tool_changes,
|
||||
// Is this the first layer of the print? In that case print the brim first.
|
||||
bool is_first_layer,
|
||||
// Is this the first layer of the print? In that case print the brim first. (OBSOLETE)
|
||||
bool /*is_first_layer*/,
|
||||
// Is this the last layer of the waste tower?
|
||||
bool is_last_layer)
|
||||
{
|
||||
@ -162,8 +162,14 @@ public:
|
||||
m_layer_height = layer_height;
|
||||
m_depth_traversed = 0.f;
|
||||
m_current_layer_finished = false;
|
||||
m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
|
||||
if (is_first_layer) {
|
||||
|
||||
|
||||
// Advance m_layer_info iterator, making sure we got it right
|
||||
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end())
|
||||
++m_layer_info;
|
||||
|
||||
m_current_shape = (! this->is_first_layer() && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
|
||||
if (this->is_first_layer()) {
|
||||
m_num_layer_changes = 0;
|
||||
m_num_tool_changes = 0;
|
||||
} else
|
||||
@ -171,10 +177,6 @@ public:
|
||||
|
||||
// Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height:
|
||||
m_extrusion_flow = extrusion_flow(layer_height);
|
||||
|
||||
// Advance m_layer_info iterator, making sure we got it right
|
||||
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end())
|
||||
++m_layer_info;
|
||||
}
|
||||
|
||||
// Return the wipe tower position.
|
||||
|
@ -36,9 +36,9 @@ enum Orientation
|
||||
static inline Orientation orient(const Point &a, const Point &b, const Point &c)
|
||||
{
|
||||
static_assert(sizeof(coord_t) * 2 == sizeof(int64_t), "orient works with 32 bit coordinates");
|
||||
int64_t u = int64_t(b(0)) * int64_t(c(1)) - int64_t(b(1)) * int64_t(c(0));
|
||||
int64_t v = int64_t(a(0)) * int64_t(c(1)) - int64_t(a(1)) * int64_t(c(0));
|
||||
int64_t w = int64_t(a(0)) * int64_t(b(1)) - int64_t(a(1)) * int64_t(b(0));
|
||||
int64_t u = int64_t(b.x()) * int64_t(c.y()) - int64_t(b.y()) * int64_t(c.x());
|
||||
int64_t v = int64_t(a.x()) * int64_t(c.y()) - int64_t(a.y()) * int64_t(c.x());
|
||||
int64_t w = int64_t(a.x()) * int64_t(b.y()) - int64_t(a.y()) * int64_t(b.x());
|
||||
int64_t d = u - v + w;
|
||||
return (d > 0) ? ORIENTATION_CCW : ((d == 0) ? ORIENTATION_COLINEAR : ORIENTATION_CW);
|
||||
}
|
||||
|
291
src/libslic3r/Geometry/Bicubic.hpp
Normal file
291
src/libslic3r/Geometry/Bicubic.hpp
Normal file
@ -0,0 +1,291 @@
|
||||
#ifndef BICUBIC_HPP
|
||||
#define BICUBIC_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace Geometry {
|
||||
|
||||
namespace BicubicInternal {
|
||||
// Linear kernel, to be able to test cubic methods with hat kernels.
|
||||
template<typename T>
|
||||
struct LinearKernel
|
||||
{
|
||||
typedef T FloatType;
|
||||
|
||||
static T a00() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a01() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a02() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a03() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a10() {
|
||||
return T(1.);
|
||||
}
|
||||
static T a11() {
|
||||
return T(-1.);
|
||||
}
|
||||
static T a12() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a13() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a20() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a21() {
|
||||
return T(1.);
|
||||
}
|
||||
static T a22() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a23() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a30() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a31() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a32() {
|
||||
return T(0.);
|
||||
}
|
||||
static T a33() {
|
||||
return T(0.);
|
||||
}
|
||||
};
|
||||
|
||||
// Interpolation kernel aka Catmul-Rom aka Keyes kernel.
|
||||
template<typename T>
|
||||
struct CubicCatmulRomKernel
|
||||
{
|
||||
typedef T FloatType;
|
||||
|
||||
static T a00() {
|
||||
return 0;
|
||||
}
|
||||
static T a01() {
|
||||
return T( -0.5);
|
||||
}
|
||||
static T a02() {
|
||||
return T( 1.);
|
||||
}
|
||||
static T a03() {
|
||||
return T( -0.5);
|
||||
}
|
||||
static T a10() {
|
||||
return T( 1.);
|
||||
}
|
||||
static T a11() {
|
||||
return 0;
|
||||
}
|
||||
static T a12() {
|
||||
return T( -5. / 2.);
|
||||
}
|
||||
static T a13() {
|
||||
return T( 3. / 2.);
|
||||
}
|
||||
static T a20() {
|
||||
return 0;
|
||||
}
|
||||
static T a21() {
|
||||
return T( 0.5);
|
||||
}
|
||||
static T a22() {
|
||||
return T( 2.);
|
||||
}
|
||||
static T a23() {
|
||||
return T( -3. / 2.);
|
||||
}
|
||||
static T a30() {
|
||||
return 0;
|
||||
}
|
||||
static T a31() {
|
||||
return 0;
|
||||
}
|
||||
static T a32() {
|
||||
return T( -0.5);
|
||||
}
|
||||
static T a33() {
|
||||
return T( 0.5);
|
||||
}
|
||||
};
|
||||
|
||||
// B-spline kernel
|
||||
template<typename T>
|
||||
struct CubicBSplineKernel
|
||||
{
|
||||
typedef T FloatType;
|
||||
|
||||
static T a00() {
|
||||
return T( 1. / 6.);
|
||||
}
|
||||
static T a01() {
|
||||
return T( -3. / 6.);
|
||||
}
|
||||
static T a02() {
|
||||
return T( 3. / 6.);
|
||||
}
|
||||
static T a03() {
|
||||
return T( -1. / 6.);
|
||||
}
|
||||
static T a10() {
|
||||
return T( 4. / 6.);
|
||||
}
|
||||
static T a11() {
|
||||
return 0;
|
||||
}
|
||||
static T a12() {
|
||||
return T( -6. / 6.);
|
||||
}
|
||||
static T a13() {
|
||||
return T( 3. / 6.);
|
||||
}
|
||||
static T a20() {
|
||||
return T( 1. / 6.);
|
||||
}
|
||||
static T a21() {
|
||||
return T( 3. / 6.);
|
||||
}
|
||||
static T a22() {
|
||||
return T( 3. / 6.);
|
||||
}
|
||||
static T a23() {
|
||||
return T( -3. / 6.);
|
||||
}
|
||||
static T a30() {
|
||||
return 0;
|
||||
}
|
||||
static T a31() {
|
||||
return 0;
|
||||
}
|
||||
static T a32() {
|
||||
return 0;
|
||||
}
|
||||
static T a33() {
|
||||
return T( 1. / 6.);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline T clamp(T a, T lower, T upper)
|
||||
{
|
||||
return (a < lower) ? lower :
|
||||
(a > upper) ? upper : a;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Kernel>
|
||||
struct CubicKernelWrapper
|
||||
{
|
||||
typedef typename Kernel::FloatType FloatType;
|
||||
|
||||
static constexpr size_t kernel_span = 4;
|
||||
|
||||
static FloatType kernel(FloatType x)
|
||||
{
|
||||
x = fabs(x);
|
||||
if (x >= (FloatType) 2.)
|
||||
return 0.0f;
|
||||
if (x <= (FloatType) 1.) {
|
||||
FloatType x2 = x * x;
|
||||
FloatType x3 = x2 * x;
|
||||
return Kernel::a10() + Kernel::a11() * x + Kernel::a12() * x2 + Kernel::a13() * x3;
|
||||
}
|
||||
assert(x > (FloatType )1. && x < (FloatType )2.);
|
||||
x -= (FloatType) 1.;
|
||||
FloatType x2 = x * x;
|
||||
FloatType x3 = x2 * x;
|
||||
return Kernel::a00() + Kernel::a01() * x + Kernel::a02() * x2 + Kernel::a03() * x3;
|
||||
}
|
||||
|
||||
static FloatType interpolate(FloatType f0, FloatType f1, FloatType f2, FloatType f3, FloatType x)
|
||||
{
|
||||
const FloatType x2 = x * x;
|
||||
const FloatType x3 = x * x * x;
|
||||
return f0 * (Kernel::a00() + Kernel::a01() * x + Kernel::a02() * x2 + Kernel::a03() * x3) +
|
||||
f1 * (Kernel::a10() + Kernel::a11() * x + Kernel::a12() * x2 + Kernel::a13() * x3) +
|
||||
f2 * (Kernel::a20() + Kernel::a21() * x + Kernel::a22() * x2 + Kernel::a23() * x3) +
|
||||
f3 * (Kernel::a30() + Kernel::a31() * x + Kernel::a32() * x2 + Kernel::a33() * x3);
|
||||
}
|
||||
};
|
||||
|
||||
// Linear splines
|
||||
template<typename NumberType>
|
||||
using LinearKernel = CubicKernelWrapper<BicubicInternal::LinearKernel<NumberType>>;
|
||||
|
||||
// Catmul-Rom splines
|
||||
template<typename NumberType>
|
||||
using CubicCatmulRomKernel = CubicKernelWrapper<BicubicInternal::CubicCatmulRomKernel<NumberType>>;
|
||||
|
||||
// Cubic B-splines
|
||||
template<typename NumberType>
|
||||
using CubicBSplineKernel = CubicKernelWrapper<BicubicInternal::CubicBSplineKernel<NumberType>>;
|
||||
|
||||
template<typename KernelWrapper>
|
||||
static typename KernelWrapper::FloatType cubic_interpolate(const Eigen::ArrayBase<typename KernelWrapper::FloatType> &F,
|
||||
const typename KernelWrapper::FloatType pt) {
|
||||
typedef typename KernelWrapper::FloatType T;
|
||||
const int w = int(F.size());
|
||||
const int ix = (int) floor(pt);
|
||||
const T s = pt - T( ix);
|
||||
|
||||
if (ix > 1 && ix + 2 < w) {
|
||||
// Inside the fully interpolated region.
|
||||
return KernelWrapper::interpolate(F[ix - 1], F[ix], F[ix + 1], F[ix + 2], s);
|
||||
}
|
||||
// Transition region. Extend with a constant function.
|
||||
auto f = [&F, w](T x) {
|
||||
return F[BicubicInternal::clamp(x, 0, w - 1)];
|
||||
};
|
||||
return KernelWrapper::interpolate(f(ix - 1), f(ix), f(ix + 1), f(ix + 2), s);
|
||||
}
|
||||
|
||||
template<typename Kernel, typename Derived>
|
||||
static float bicubic_interpolate(const Eigen::MatrixBase<Derived> &F,
|
||||
const Eigen::Matrix<typename Kernel::FloatType, 2, 1, Eigen::DontAlign> &pt) {
|
||||
typedef typename Kernel::FloatType T;
|
||||
const int w = F.cols();
|
||||
const int h = F.rows();
|
||||
const int ix = (int) floor(pt[0]);
|
||||
const int iy = (int) floor(pt[1]);
|
||||
const T s = pt[0] - T( ix);
|
||||
const T t = pt[1] - T( iy);
|
||||
|
||||
if (ix > 1 && ix + 2 < w && iy > 1 && iy + 2 < h) {
|
||||
// Inside the fully interpolated region.
|
||||
return Kernel::interpolate(
|
||||
Kernel::interpolate(F(ix - 1, iy - 1), F(ix, iy - 1), F(ix + 1, iy - 1), F(ix + 2, iy - 1), s),
|
||||
Kernel::interpolate(F(ix - 1, iy), F(ix, iy), F(ix + 1, iy), F(ix + 2, iy), s),
|
||||
Kernel::interpolate(F(ix - 1, iy + 1), F(ix, iy + 1), F(ix + 1, iy + 1), F(ix + 2, iy + 1), s),
|
||||
Kernel::interpolate(F(ix - 1, iy + 2), F(ix, iy + 2), F(ix + 1, iy + 2), F(ix + 2, iy + 2), s), t);
|
||||
}
|
||||
// Transition region. Extend with a constant function.
|
||||
auto f = [&F, w, h](int x, int y) {
|
||||
return F(BicubicInternal::clamp(x, 0, w - 1), BicubicInternal::clamp(y, 0, h - 1));
|
||||
};
|
||||
return Kernel::interpolate(
|
||||
Kernel::interpolate(f(ix - 1, iy - 1), f(ix, iy - 1), f(ix + 1, iy - 1), f(ix + 2, iy - 1), s),
|
||||
Kernel::interpolate(f(ix - 1, iy), f(ix, iy), f(ix + 1, iy), f(ix + 2, iy), s),
|
||||
Kernel::interpolate(f(ix - 1, iy + 1), f(ix, iy + 1), f(ix + 1, iy + 1), f(ix + 2, iy + 1), s),
|
||||
Kernel::interpolate(f(ix - 1, iy + 2), f(ix, iy + 2), f(ix + 1, iy + 2), f(ix + 2, iy + 2), s), t);
|
||||
}
|
||||
|
||||
} //namespace Geometry
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* BICUBIC_HPP */
|
@ -1,6 +1,7 @@
|
||||
#include "libslic3r.h"
|
||||
#include "ConvexHull.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "../Geometry.hpp"
|
||||
|
||||
#include <boost/multiprecision/integer.hpp>
|
||||
|
||||
@ -19,13 +20,13 @@ Polygon convex_hull(Points pts)
|
||||
hull.points.resize(2 * n);
|
||||
// Build lower hull
|
||||
for (int i = 0; i < n; ++ i) {
|
||||
while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0)
|
||||
while (k >= 2 && Geometry::orient(pts[i], hull[k-2], hull[k-1]) != Geometry::ORIENTATION_CCW)
|
||||
-- k;
|
||||
hull[k ++] = pts[i];
|
||||
}
|
||||
// Build upper hull
|
||||
for (int i = n-2, t = k+1; i >= 0; i--) {
|
||||
while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0)
|
||||
while (k >= t && Geometry::orient(pts[i], hull[k-2], hull[k-1]) != Geometry::ORIENTATION_CCW)
|
||||
-- k;
|
||||
hull[k ++] = pts[i];
|
||||
}
|
||||
@ -58,7 +59,7 @@ Pointf3s convex_hull(Pointf3s points)
|
||||
Point k1 = Point::new_scale(hull[k - 1](0), hull[k - 1](1));
|
||||
Point k2 = Point::new_scale(hull[k - 2](0), hull[k - 2](1));
|
||||
|
||||
if (p.ccw(k2, k1) <= 0)
|
||||
if (Geometry::orient(p, k2, k1) != Geometry::ORIENTATION_CCW)
|
||||
--k;
|
||||
else
|
||||
break;
|
||||
@ -76,7 +77,7 @@ Pointf3s convex_hull(Pointf3s points)
|
||||
Point k1 = Point::new_scale(hull[k - 1](0), hull[k - 1](1));
|
||||
Point k2 = Point::new_scale(hull[k - 2](0), hull[k - 2](1));
|
||||
|
||||
if (p.ccw(k2, k1) <= 0)
|
||||
if (Geometry::orient(p, k2, k1) != Geometry::ORIENTATION_CCW)
|
||||
--k;
|
||||
else
|
||||
break;
|
||||
|
205
src/libslic3r/Geometry/Curves.hpp
Normal file
205
src/libslic3r/Geometry/Curves.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
#ifndef SRC_LIBSLIC3R_GEOMETRY_CURVES_HPP_
|
||||
#define SRC_LIBSLIC3R_GEOMETRY_CURVES_HPP_
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "Bicubic.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//#define LSQR_DEBUG
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Geometry {
|
||||
|
||||
template<int Dimension, typename NumberType>
|
||||
struct PolynomialCurve {
|
||||
Eigen::MatrixXf coefficients;
|
||||
|
||||
Vec3f get_fitted_value(const NumberType value) const {
|
||||
auto result = Vec<Dimension, NumberType>::Zero();
|
||||
size_t order = this->coefficients.rows() - 1;
|
||||
auto x = NumberType(1.);
|
||||
for (size_t index = 0; index < order + 1; ++index, x *= value)
|
||||
result += x * this->coefficients.col(index);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//https://towardsdatascience.com/least-square-polynomial-CURVES-using-c-eigen-package-c0673728bd01
|
||||
template<int Dimension, typename NumberType>
|
||||
PolynomialCurve<Dimension, NumberType> fit_polynomial(const std::vector<Vec<Dimension, NumberType>> &observations,
|
||||
const std::vector<NumberType> &observation_points,
|
||||
const std::vector<NumberType> &weights, size_t order) {
|
||||
// check to make sure inputs are correct
|
||||
size_t cols = order + 1;
|
||||
assert(observation_points.size() >= cols);
|
||||
assert(observation_points.size() == weights.size());
|
||||
assert(observations.size() == weights.size());
|
||||
|
||||
Eigen::MatrixXf data_points(Dimension, observations.size());
|
||||
Eigen::MatrixXf T(observations.size(), cols);
|
||||
for (size_t i = 0; i < weights.size(); ++i) {
|
||||
auto squared_weight = sqrt(weights[i]);
|
||||
data_points.col(i) = observations[i] * squared_weight;
|
||||
// Populate the matrix
|
||||
auto x = squared_weight;
|
||||
auto c = observation_points[i];
|
||||
for (size_t j = 0; j < cols; ++j, x *= c)
|
||||
T(i, j) = x;
|
||||
}
|
||||
|
||||
const auto QR = T.householderQr();
|
||||
Eigen::MatrixXf coefficients(Dimension, cols);
|
||||
// Solve for linear least square fit
|
||||
for (size_t dim = 0; dim < Dimension; ++dim) {
|
||||
coefficients.row(dim) = QR.solve(data_points.row(dim).transpose());
|
||||
}
|
||||
|
||||
return {std::move(coefficients)};
|
||||
}
|
||||
|
||||
template<size_t Dimension, typename NumberType, typename KernelType>
|
||||
struct PiecewiseFittedCurve {
|
||||
using Kernel = KernelType;
|
||||
|
||||
Eigen::MatrixXf coefficients;
|
||||
NumberType start;
|
||||
NumberType segment_size;
|
||||
size_t endpoints_level_of_freedom;
|
||||
|
||||
Vec<Dimension, NumberType> get_fitted_value(const NumberType &observation_point) const {
|
||||
Vec<Dimension, NumberType> result = Vec<Dimension, NumberType>::Zero();
|
||||
|
||||
//find corresponding segment index; expects kernels to be centered
|
||||
int middle_right_segment_index = floor((observation_point - start) / segment_size);
|
||||
//find index of first segment that is affected by the point i; this can be deduced from kernel_span
|
||||
int start_segment_idx = middle_right_segment_index - Kernel::kernel_span / 2 + 1;
|
||||
for (int segment_index = start_segment_idx; segment_index < int(start_segment_idx + Kernel::kernel_span);
|
||||
segment_index++) {
|
||||
NumberType segment_start = start + segment_index * segment_size;
|
||||
NumberType normalized_segment_distance = (segment_start - observation_point) / segment_size;
|
||||
|
||||
int parameter_index = segment_index + endpoints_level_of_freedom;
|
||||
parameter_index = std::clamp(parameter_index, 0, int(coefficients.cols()) - 1);
|
||||
result += Kernel::kernel(normalized_segment_distance) * coefficients.col(parameter_index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// observations: data to be fitted by the curve
|
||||
// observation points: growing sequence of points where the observations were made.
|
||||
// In other words, for function f(x) = y, observations are y0...yn, and observation points are x0...xn
|
||||
// weights: how important the observation is
|
||||
// segments_count: number of segments inside the valid length of the curve
|
||||
// endpoints_level_of_freedom: number of additional parameters at each end; reasonable values depend on the kernel span
|
||||
template<typename Kernel, int Dimension, typename NumberType>
|
||||
PiecewiseFittedCurve<Dimension, NumberType, Kernel> fit_curve(
|
||||
const std::vector<Vec<Dimension, NumberType>> &observations,
|
||||
const std::vector<NumberType> &observation_points,
|
||||
const std::vector<NumberType> &weights,
|
||||
size_t segments_count,
|
||||
size_t endpoints_level_of_freedom) {
|
||||
|
||||
// check to make sure inputs are correct
|
||||
assert(segments_count > 0);
|
||||
assert(observations.size() > 0);
|
||||
assert(observation_points.size() == observations.size());
|
||||
assert(observation_points.size() == weights.size());
|
||||
assert(segments_count <= observations.size());
|
||||
|
||||
//prepare sqrt of weights, which will then be applied to both matrix T and observed data: https://en.wikipedia.org/wiki/Weighted_least_squares
|
||||
std::vector<NumberType> sqrt_weights(weights.size());
|
||||
for (size_t index = 0; index < weights.size(); ++index) {
|
||||
assert(weights[index] > 0);
|
||||
sqrt_weights[index] = sqrt(weights[index]);
|
||||
}
|
||||
|
||||
// prepare result and compute metadata
|
||||
PiecewiseFittedCurve<Dimension, NumberType, Kernel> result { };
|
||||
|
||||
NumberType valid_length = observation_points.back() - observation_points.front();
|
||||
NumberType segment_size = valid_length / NumberType(segments_count);
|
||||
result.start = observation_points.front();
|
||||
result.segment_size = segment_size;
|
||||
result.endpoints_level_of_freedom = endpoints_level_of_freedom;
|
||||
|
||||
// prepare observed data
|
||||
// Eigen defaults to column major memory layout.
|
||||
Eigen::MatrixXf data_points(Dimension, observations.size());
|
||||
for (size_t index = 0; index < observations.size(); ++index) {
|
||||
data_points.col(index) = observations[index] * sqrt_weights[index];
|
||||
}
|
||||
// parameters count is always increased by one to make the parametric space of the curve symmetric.
|
||||
// without this fix, the end of the curve is less flexible than the beginning
|
||||
size_t parameters_count = segments_count + 1 + 2 * endpoints_level_of_freedom;
|
||||
//Create weight matrix T for each point and each segment;
|
||||
Eigen::MatrixXf T(observation_points.size(), parameters_count);
|
||||
T.setZero();
|
||||
//Fill the weight matrix
|
||||
for (size_t i = 0; i < observation_points.size(); ++i) {
|
||||
NumberType observation_point = observation_points[i];
|
||||
//find corresponding segment index; expects kernels to be centered
|
||||
int middle_right_segment_index = floor((observation_point - result.start) / result.segment_size);
|
||||
//find index of first segment that is affected by the point i; this can be deduced from kernel_span
|
||||
int start_segment_idx = middle_right_segment_index - Kernel::kernel_span / 2 + 1;
|
||||
for (int segment_index = start_segment_idx; segment_index < int(start_segment_idx + Kernel::kernel_span);
|
||||
segment_index++) {
|
||||
NumberType segment_start = result.start + segment_index * result.segment_size;
|
||||
NumberType normalized_segment_distance = (segment_start - observation_point) / result.segment_size;
|
||||
|
||||
int parameter_index = segment_index + endpoints_level_of_freedom;
|
||||
parameter_index = std::clamp(parameter_index, 0, int(parameters_count) - 1);
|
||||
T(i, parameter_index) += Kernel::kernel(normalized_segment_distance) * sqrt_weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LSQR_DEBUG
|
||||
std::cout << "weight matrix: " << std::endl;
|
||||
for (int obs = 0; obs < observation_points.size(); ++obs) {
|
||||
std::cout << std::endl;
|
||||
for (int segment = 0; segment < parameters_count; ++segment) {
|
||||
std::cout << T(obs, segment) << " ";
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
|
||||
// Solve for linear least square fit
|
||||
result.coefficients.resize(Dimension, parameters_count);
|
||||
const auto QR = T.fullPivHouseholderQr();
|
||||
for (size_t dim = 0; dim < Dimension; ++dim) {
|
||||
result.coefficients.row(dim) = QR.solve(data_points.row(dim).transpose());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<int Dimension, typename NumberType>
|
||||
PiecewiseFittedCurve<Dimension, NumberType, CubicBSplineKernel<NumberType>>
|
||||
fit_cubic_bspline(
|
||||
const std::vector<Vec<Dimension, NumberType>> &observations,
|
||||
std::vector<NumberType> observation_points,
|
||||
std::vector<NumberType> weights,
|
||||
size_t segments_count,
|
||||
size_t endpoints_level_of_freedom = 0) {
|
||||
return fit_curve<CubicBSplineKernel<NumberType>>(observations, observation_points, weights, segments_count,
|
||||
endpoints_level_of_freedom);
|
||||
}
|
||||
|
||||
template<int Dimension, typename NumberType>
|
||||
PiecewiseFittedCurve<Dimension, NumberType, CubicCatmulRomKernel<NumberType>>
|
||||
fit_catmul_rom_spline(
|
||||
const std::vector<Vec<Dimension, NumberType>> &observations,
|
||||
std::vector<NumberType> observation_points,
|
||||
std::vector<NumberType> weights,
|
||||
size_t segments_count,
|
||||
size_t endpoints_level_of_freedom = 0) {
|
||||
return fit_curve<CubicCatmulRomKernel<NumberType>>(observations, observation_points, weights, segments_count,
|
||||
endpoints_level_of_freedom);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SRC_LIBSLIC3R_GEOMETRY_CURVES_HPP_ */
|
@ -59,7 +59,7 @@ public:
|
||||
CONTINUE_RIGHT = 2,
|
||||
STOP = 4,
|
||||
};
|
||||
template<typename CoordType>
|
||||
template<typename CoordType>
|
||||
unsigned int descent_mask(const CoordType &point_coord, const CoordType &search_radius, size_t idx, size_t dimension) const
|
||||
{
|
||||
CoordType dist = point_coord - this->coordinate(idx, dimension);
|
||||
@ -110,8 +110,8 @@ private:
|
||||
|
||||
// Partition the input m_nodes <left, right> at "k" and "dimension" using the QuickSelect method:
|
||||
// https://en.wikipedia.org/wiki/Quickselect
|
||||
// Items left of the k'th item are lower than the k'th item in the "dimension",
|
||||
// items right of the k'th item are higher than the k'th item in the "dimension",
|
||||
// Items left of the k'th item are lower than the k'th item in the "dimension",
|
||||
// items right of the k'th item are higher than the k'th item in the "dimension",
|
||||
void partition_input(std::vector<size_t> &input, const size_t dimension, size_t left, size_t right, const size_t k) const
|
||||
{
|
||||
while (left < right) {
|
||||
@ -231,6 +231,53 @@ size_t find_closest_point(const KDTreeIndirectType& kdtree, const PointType& poi
|
||||
return find_closest_point(kdtree, point, [](size_t) { return true; });
|
||||
}
|
||||
|
||||
// Find nearby points (spherical neighbourhood) using Euclidian metrics.
|
||||
template<typename KDTreeIndirectType, typename PointType, typename FilterFn>
|
||||
std::vector<size_t> find_nearby_points(const KDTreeIndirectType &kdtree, const PointType ¢er,
|
||||
const typename KDTreeIndirectType::CoordType& max_distance, FilterFn filter)
|
||||
{
|
||||
using CoordType = typename KDTreeIndirectType::CoordType;
|
||||
|
||||
struct Visitor {
|
||||
const KDTreeIndirectType &kdtree;
|
||||
const PointType center;
|
||||
const CoordType max_distance_squared;
|
||||
const FilterFn filter;
|
||||
std::vector<size_t> result;
|
||||
|
||||
Visitor(const KDTreeIndirectType &kdtree, const PointType& center, const CoordType &max_distance,
|
||||
FilterFn filter) :
|
||||
kdtree(kdtree), center(center), max_distance_squared(max_distance*max_distance), filter(filter) {
|
||||
}
|
||||
unsigned int operator()(size_t idx, size_t dimension) {
|
||||
if (this->filter(idx)) {
|
||||
auto dist = CoordType(0);
|
||||
for (size_t i = 0; i < KDTreeIndirectType::NumDimensions; ++i) {
|
||||
CoordType d = center[i] - kdtree.coordinate(idx, i);
|
||||
dist += d * d;
|
||||
}
|
||||
if (dist < max_distance_squared) {
|
||||
result.push_back(idx);
|
||||
}
|
||||
}
|
||||
return kdtree.descent_mask(center[dimension], max_distance_squared, idx, dimension);
|
||||
}
|
||||
} visitor(kdtree, center, max_distance, filter);
|
||||
|
||||
kdtree.visit(visitor);
|
||||
return visitor.result;
|
||||
}
|
||||
|
||||
template<typename KDTreeIndirectType, typename PointType>
|
||||
std::vector<size_t> find_nearby_points(const KDTreeIndirectType &kdtree, const PointType ¢er,
|
||||
const typename KDTreeIndirectType::CoordType& max_distance)
|
||||
{
|
||||
return find_nearby_points(kdtree, center, max_distance, [](size_t) {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_KDTreeIndirect_hpp_ */
|
||||
|
@ -113,7 +113,6 @@ public:
|
||||
Vector vector() const { return this->b - this->a; }
|
||||
Vector normal() const { return Vector((this->b(1) - this->a(1)), -(this->b(0) - this->a(0))); }
|
||||
bool intersection(const Line& line, Point* intersection) const;
|
||||
double ccw(const Point& point) const { return point.ccw(*this); }
|
||||
// Clip a line with a bounding box. Returns false if the line is completely outside of the bounding box.
|
||||
bool clip_with_bbox(const BoundingBox &bbox);
|
||||
// Extend the line from both sides by an offset.
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <openvdb/tools/VolumeToMesh.h>
|
||||
#include <openvdb/tools/Composite.h>
|
||||
#include <openvdb/tools/LevelSetRebuild.h>
|
||||
#include <openvdb/tools/FastSweeping.h>
|
||||
|
||||
//#include "MTUtils.hpp"
|
||||
|
||||
@ -42,16 +43,13 @@ public:
|
||||
: its{m}, voxel_scale{voxel_sc} {};
|
||||
};
|
||||
|
||||
// TODO: Do I need to call initialize? Seems to work without it as well but the
|
||||
// docs say it should be called ones. It does a mutex lock-unlock sequence all
|
||||
// even if was called previously.
|
||||
openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh,
|
||||
const openvdb::math::Transform &tr,
|
||||
float voxel_scale,
|
||||
float exteriorBandWidth,
|
||||
float interiorBandWidth,
|
||||
int flags)
|
||||
float interiorBandWidth)
|
||||
{
|
||||
// Might not be needed but this is now proven to be working
|
||||
openvdb::initialize();
|
||||
|
||||
std::vector<indexed_triangle_set> meshparts = its_split(mesh);
|
||||
@ -64,23 +62,35 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh,
|
||||
openvdb::FloatGrid::Ptr grid;
|
||||
for (auto &m : meshparts) {
|
||||
auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||
TriangleMeshDataAdapter{m, voxel_scale}, tr, exteriorBandWidth,
|
||||
interiorBandWidth, flags);
|
||||
TriangleMeshDataAdapter{m, voxel_scale}, tr, 1.f, 1.f);
|
||||
|
||||
if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
|
||||
else if (subgrid) grid = std::move(subgrid);
|
||||
}
|
||||
|
||||
if (grid) {
|
||||
grid = openvdb::tools::levelSetRebuild(*grid, 0., exteriorBandWidth,
|
||||
interiorBandWidth);
|
||||
} else if(meshparts.empty()) {
|
||||
if (meshparts.size() > 1) {
|
||||
// This is needed to avoid various artefacts on multipart meshes.
|
||||
// TODO: replace with something faster
|
||||
grid = openvdb::tools::levelSetRebuild(*grid, 0., 1.f, 1.f);
|
||||
}
|
||||
if(meshparts.empty()) {
|
||||
// Splitting failed, fall back to hollow the original mesh
|
||||
grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||
TriangleMeshDataAdapter{mesh}, tr, exteriorBandWidth,
|
||||
interiorBandWidth, flags);
|
||||
TriangleMeshDataAdapter{mesh}, tr, 1.f, 1.f);
|
||||
}
|
||||
|
||||
constexpr int DilateIterations = 1;
|
||||
|
||||
grid = openvdb::tools::dilateSdf(
|
||||
*grid, interiorBandWidth, openvdb::tools::NN_FACE_EDGE,
|
||||
DilateIterations,
|
||||
openvdb::tools::FastSweepingDomain::SWEEP_LESS_THAN_ISOVALUE);
|
||||
|
||||
grid = openvdb::tools::dilateSdf(
|
||||
*grid, exteriorBandWidth, openvdb::tools::NN_FACE_EDGE,
|
||||
DilateIterations,
|
||||
openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE);
|
||||
|
||||
grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale));
|
||||
|
||||
return grid;
|
||||
@ -133,4 +143,15 @@ openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
return new_grid;
|
||||
}
|
||||
|
||||
openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
double iso)
|
||||
{
|
||||
auto new_grid = openvdb::tools::levelSetRebuild(grid, float(iso));
|
||||
|
||||
// Copies voxel_scale metadata, if it exists.
|
||||
new_grid->insertMeta(*grid.deepCopyMeta());
|
||||
|
||||
return new_grid;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -30,18 +30,20 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh,
|
||||
const openvdb::math::Transform &tr = {},
|
||||
float voxel_scale = 1.f,
|
||||
float exteriorBandWidth = 3.0f,
|
||||
float interiorBandWidth = 3.0f,
|
||||
int flags = 0);
|
||||
float interiorBandWidth = 3.0f);
|
||||
|
||||
indexed_triangle_set grid_to_mesh(const openvdb::FloatGrid &grid,
|
||||
double isovalue = 0.0,
|
||||
double adaptivity = 0.0,
|
||||
bool relaxDisorientedTriangles = true);
|
||||
|
||||
openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
double iso);
|
||||
|
||||
openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
double iso,
|
||||
double ext_range = 3.,
|
||||
double int_range = 3.);
|
||||
double ext_range,
|
||||
double int_range);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -108,36 +108,6 @@ bool Point::nearest_point(const Points &points, Point* point) const
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Three points are a counter-clockwise turn if ccw > 0, clockwise if
|
||||
* ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
|
||||
* gives the signed area of the triangle formed by p1, p2 and this point.
|
||||
* In other words it is the 2D cross product of p1-p2 and p1-this, i.e.
|
||||
* z-component of their 3D cross product.
|
||||
* We return double because it must be big enough to hold 2*max(|coordinate|)^2
|
||||
*/
|
||||
double Point::ccw(const Point &p1, const Point &p2) const
|
||||
{
|
||||
static_assert(sizeof(coord_t) == 4, "Point::ccw() requires a 32 bit coord_t");
|
||||
return cross2((p2 - p1).cast<int64_t>(), (*this - p1).cast<int64_t>());
|
||||
// return cross2((p2 - p1).cast<double>(), (*this - p1).cast<double>());
|
||||
}
|
||||
|
||||
double Point::ccw(const Line &line) const
|
||||
{
|
||||
return this->ccw(line.a, line.b);
|
||||
}
|
||||
|
||||
// returns the CCW angle between this-p1 and this-p2
|
||||
// i.e. this assumes a CCW rotation from p1 to p2 around this
|
||||
double Point::ccw_angle(const Point &p1, const Point &p2) const
|
||||
{
|
||||
//FIXME this calculates an atan2 twice! Project one vector into the other!
|
||||
double angle = atan2(p1.x() - (*this).x(), p1.y() - (*this).y())
|
||||
- atan2(p2.x() - (*this).x(), p2.y() - (*this).y());
|
||||
// we only want to return only positive angles
|
||||
return angle <= 0 ? angle + 2*PI : angle;
|
||||
}
|
||||
|
||||
Point Point::projection_onto(const MultiPoint &poly) const
|
||||
{
|
||||
Point running_projection = poly.first_point();
|
||||
|
@ -28,6 +28,9 @@ using Mat = Eigen::Matrix<T, N, M, Eigen::DontAlign, N, M>;
|
||||
|
||||
template<int N, class T> using Vec = Mat<N, 1, T>;
|
||||
|
||||
template<typename NumberType>
|
||||
using DynVec = Eigen::Matrix<NumberType, Eigen::Dynamic, 1>;
|
||||
|
||||
// Eigen types, to replace the Slic3r's own types in the future.
|
||||
// Vector types with a fixed point coordinate base type.
|
||||
using Vec2crd = Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign>;
|
||||
@ -76,24 +79,35 @@ inline const auto &identity3d = identity<3, double>;
|
||||
|
||||
inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs.x() < rhs.x() || (lhs.x() == rhs.x() && lhs.y() < rhs.y()); }
|
||||
|
||||
template<int Options>
|
||||
int32_t cross2(const Eigen::MatrixBase<Eigen::Matrix<int32_t, 2, 1, Options>> &v1, const Eigen::MatrixBase<Eigen::Matrix<int32_t, 2, 1, Options>> &v2) = delete;
|
||||
|
||||
template<typename T, int Options>
|
||||
inline T cross2(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v1, const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v2)
|
||||
{
|
||||
return v1.x() * v2.y() - v1.y() * v2.x();
|
||||
}
|
||||
|
||||
// Cross product of two 2D vectors.
|
||||
// None of the vectors may be of int32_t type as the result would overflow.
|
||||
template<typename Derived, typename Derived2>
|
||||
inline typename Derived::Scalar cross2(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2)
|
||||
{
|
||||
static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "cross2(): first parameter is not a 2D vector");
|
||||
static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "cross2(): first parameter is not a 2D vector");
|
||||
static_assert(! std::is_same<typename Derived::Scalar, int32_t>::value, "cross2(): Scalar type must not be int32_t, otherwise the cross product would overflow.");
|
||||
static_assert(std::is_same<typename Derived::Scalar, typename Derived2::Scalar>::value, "cross2(): Scalar types of 1st and 2nd operand must be equal.");
|
||||
return v1.x() * v2.y() - v1.y() * v2.x();
|
||||
}
|
||||
|
||||
template<typename T, int Options>
|
||||
inline Eigen::Matrix<T, 2, 1, Eigen::DontAlign> perp(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v) { return Eigen::Matrix<T, 2, 1, Eigen::DontAlign>(- v.y(), v.x()); }
|
||||
// 2D vector perpendicular to the argument.
|
||||
template<typename Derived>
|
||||
inline Eigen::Matrix<typename Derived::Scalar, 2, 1, Eigen::DontAlign> perp(const Eigen::MatrixBase<Derived> &v)
|
||||
{
|
||||
static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "perp(): parameter is not a 2D vector");
|
||||
return { - v.y(), v.x() };
|
||||
}
|
||||
|
||||
// Angle from v1 to v2, returning double atan2(y, x) normalized to <-PI, PI>.
|
||||
template<typename Derived, typename Derived2>
|
||||
inline double angle(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2) {
|
||||
static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "angle(): first parameter is not a 2D vector");
|
||||
static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "angle(): second parameter is not a 2D vector");
|
||||
auto v1d = v1.template cast<double>();
|
||||
auto v2d = v2.template cast<double>();
|
||||
return atan2(cross2(v1d, v2d), v1d.dot(v2d));
|
||||
}
|
||||
|
||||
template<class T, int N, int Options>
|
||||
Eigen::Matrix<T, 2, 1, Eigen::DontAlign> to_2d(const Eigen::MatrixBase<Eigen::Matrix<T, N, 1, Options>> &ptN) { return { ptN.x(), ptN.y() }; }
|
||||
@ -165,9 +179,6 @@ public:
|
||||
int nearest_point_index(const PointConstPtrs &points) const;
|
||||
int nearest_point_index(const PointPtrs &points) const;
|
||||
bool nearest_point(const Points &points, Point* point) const;
|
||||
double ccw(const Point &p1, const Point &p2) const;
|
||||
double ccw(const Line &line) const;
|
||||
double ccw_angle(const Point &p1, const Point &p2) const;
|
||||
Point projection_onto(const MultiPoint &poly) const;
|
||||
Point projection_onto(const Line &line) const;
|
||||
};
|
||||
|
@ -171,50 +171,56 @@ Point Polygon::centroid() const
|
||||
return Point(Vec2d(c / (3. * area_sum)));
|
||||
}
|
||||
|
||||
// find all concave vertices (i.e. having an internal angle greater than the supplied angle)
|
||||
// (external = right side, thus we consider ccw orientation)
|
||||
Points Polygon::concave_points(double angle) const
|
||||
// Filter points from poly to the output with the help of FilterFn.
|
||||
// filter function receives two vectors:
|
||||
// v1: this_point - previous_point
|
||||
// v2: next_point - this_point
|
||||
// and returns true if the point is to be copied to the output.
|
||||
template<typename FilterFn>
|
||||
Points filter_points_by_vectors(const Points &poly, FilterFn filter)
|
||||
{
|
||||
Points points;
|
||||
angle = 2. * PI - angle + EPSILON;
|
||||
|
||||
// check whether first point forms a concave angle
|
||||
if (this->points.front().ccw_angle(this->points.back(), *(this->points.begin()+1)) <= angle)
|
||||
points.push_back(this->points.front());
|
||||
|
||||
// check whether points 1..(n-1) form concave angles
|
||||
for (Points::const_iterator p = this->points.begin()+1; p != this->points.end()-1; ++ p)
|
||||
if (p->ccw_angle(*(p-1), *(p+1)) <= angle)
|
||||
points.push_back(*p);
|
||||
|
||||
// check whether last point forms a concave angle
|
||||
if (this->points.back().ccw_angle(*(this->points.end()-2), this->points.front()) <= angle)
|
||||
points.push_back(this->points.back());
|
||||
|
||||
return points;
|
||||
}
|
||||
// Last point is the first point visited.
|
||||
Point p1 = poly.back();
|
||||
// Previous vector to p1.
|
||||
Vec2d v1 = (p1 - *(poly.end() - 2)).cast<double>();
|
||||
|
||||
// find all convex vertices (i.e. having an internal angle smaller than the supplied angle)
|
||||
// (external = right side, thus we consider ccw orientation)
|
||||
Points Polygon::convex_points(double angle) const
|
||||
{
|
||||
Points points;
|
||||
angle = 2*PI - angle - EPSILON;
|
||||
|
||||
// check whether first point forms a convex angle
|
||||
if (this->points.front().ccw_angle(this->points.back(), *(this->points.begin()+1)) >= angle)
|
||||
points.push_back(this->points.front());
|
||||
|
||||
// check whether points 1..(n-1) form convex angles
|
||||
for (Points::const_iterator p = this->points.begin()+1; p != this->points.end()-1; ++p) {
|
||||
if (p->ccw_angle(*(p-1), *(p+1)) >= angle) points.push_back(*p);
|
||||
Points out;
|
||||
for (Point p2 : poly) {
|
||||
// p2 is next point to the currently visited point p1.
|
||||
Vec2d v2 = (p2 - p1).cast<double>();
|
||||
if (filter(v1, v2))
|
||||
out.emplace_back(p2);
|
||||
v1 = v2;
|
||||
p1 = p2;
|
||||
}
|
||||
|
||||
// check whether last point forms a convex angle
|
||||
if (this->points.back().ccw_angle(*(this->points.end()-2), this->points.front()) >= angle)
|
||||
points.push_back(this->points.back());
|
||||
|
||||
return points;
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename ConvexConcaveFilterFn>
|
||||
Points filter_convex_concave_points_by_angle_threshold(const Points &poly, double angle_threshold, ConvexConcaveFilterFn convex_concave_filter)
|
||||
{
|
||||
assert(angle_threshold >= 0.);
|
||||
if (angle_threshold < EPSILON) {
|
||||
double cos_angle = cos(angle_threshold);
|
||||
return filter_points_by_vectors(poly, [convex_concave_filter, cos_angle](const Vec2d &v1, const Vec2d &v2){
|
||||
return convex_concave_filter(v1, v2) && v1.normalized().dot(v2.normalized()) < cos_angle;
|
||||
});
|
||||
} else {
|
||||
return filter_points_by_vectors(poly, [convex_concave_filter](const Vec2d &v1, const Vec2d &v2){
|
||||
return convex_concave_filter(v1, v2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Points Polygon::convex_points(double angle_threshold) const
|
||||
{
|
||||
return filter_convex_concave_points_by_angle_threshold(this->points, angle_threshold, [](const Vec2d &v1, const Vec2d &v2){ return cross2(v1, v2) > 0.; });
|
||||
}
|
||||
|
||||
Points Polygon::concave_points(double angle_threshold) const
|
||||
{
|
||||
return filter_convex_concave_points_by_angle_threshold(this->points, angle_threshold, [](const Vec2d &v1, const Vec2d &v2){ return cross2(v1, v2) < 0.; });
|
||||
}
|
||||
|
||||
// Projection of a point onto the polygon.
|
||||
|
@ -65,8 +65,11 @@ public:
|
||||
void densify(float min_length, std::vector<float>* lengths = nullptr);
|
||||
void triangulate_convex(Polygons* polygons) const;
|
||||
Point centroid() const;
|
||||
Points concave_points(double angle = PI) const;
|
||||
Points convex_points(double angle = PI) const;
|
||||
// Considering CCW orientation of this polygon, find all convex resp. concave points
|
||||
// with the angle at the vertex larger than a threshold.
|
||||
// Zero angle_threshold means to accept all convex resp. concave points.
|
||||
Points convex_points(double angle_threshold = 0.) const;
|
||||
Points concave_points(double angle_threshold = 0.) const;
|
||||
// Projection of a point onto the polygon.
|
||||
Point point_projection(const Point &point) const;
|
||||
std::vector<float> parameter_by_length() const;
|
||||
|
@ -84,7 +84,7 @@ ConfigFileType guess_config_file_type(const ptree &tree)
|
||||
VendorProfile VendorProfile::from_ini(const boost::filesystem::path &path, bool load_all)
|
||||
{
|
||||
ptree tree;
|
||||
boost::filesystem::ifstream ifs(path);
|
||||
boost::nowide::ifstream ifs(path.string());
|
||||
boost::property_tree::read_ini(ifs, tree);
|
||||
return VendorProfile::from_ini(tree, path, load_all);
|
||||
}
|
||||
|
@ -538,8 +538,21 @@ std::string Print::validate(std::string* warning) const
|
||||
for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
|
||||
if (idx_object == tallest_object_idx)
|
||||
continue;
|
||||
if (layer_height_profiles[idx_object] != layer_height_profiles[tallest_object_idx])
|
||||
return L("The Wipe tower is only supported if all objects have the same variable layer height");
|
||||
// Check that the layer height profiles are equal. This will happen when one object is
|
||||
// a copy of another, or when a layer height modifier is used the same way on both objects.
|
||||
// The latter case might create a floating point inaccuracy mismatch, so compare
|
||||
// element-wise using an epsilon check.
|
||||
size_t i = 0;
|
||||
const coordf_t eps = 0.5 * EPSILON; // layers closer than EPSILON will be merged later. Let's make
|
||||
// this check a bit more sensitive to make sure we never consider two different layers as one.
|
||||
while (i < layer_height_profiles[idx_object].size()
|
||||
&& i < layer_height_profiles[tallest_object_idx].size()) {
|
||||
if (i%2 == 0 && layer_height_profiles[tallest_object_idx][i] > layer_height_profiles[idx_object][layer_height_profiles[idx_object].size() - 2 ])
|
||||
break;
|
||||
if (std::abs(layer_height_profiles[idx_object][i] - layer_height_profiles[tallest_object_idx][i]) > eps)
|
||||
return L("The Wipe tower is only supported if all objects have the same variable layer height");
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <openvdb/tools/FastSweeping.h>
|
||||
|
||||
#include <libslic3r/MTUtils.hpp>
|
||||
#include <libslic3r/I18N.hpp>
|
||||
|
||||
@ -27,12 +29,10 @@ struct Interior {
|
||||
openvdb::FloatGrid::Ptr gridptr;
|
||||
mutable std::optional<openvdb::FloatGrid::ConstAccessor> accessor;
|
||||
|
||||
double closing_distance = 0.;
|
||||
double iso_surface = 0.;
|
||||
double thickness = 0.;
|
||||
double voxel_scale = 1.;
|
||||
double nb_in = 3.; // narrow band width inwards
|
||||
double nb_out = 3.; // narrow band width outwards
|
||||
// Full narrow band is the sum of the two above values.
|
||||
double full_narrowb = 2.;
|
||||
|
||||
void reset_accessor() const // This resets the accessor and its cache
|
||||
// Not a thread safe call!
|
||||
@ -63,10 +63,11 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
|
||||
double voxel_scale,
|
||||
double closing_dist)
|
||||
{
|
||||
double offset = voxel_scale * min_thickness;
|
||||
double D = voxel_scale * closing_dist;
|
||||
float out_range = 0.1f * float(offset);
|
||||
double offset = voxel_scale * min_thickness;
|
||||
double D = voxel_scale * closing_dist;
|
||||
float in_range = 1.1f * float(offset + D);
|
||||
auto narrowb = 1.;
|
||||
float out_range = narrowb;
|
||||
|
||||
if (ctl.stopcondition()) return {};
|
||||
else ctl.statuscb(0, L("Hollowing"));
|
||||
@ -84,8 +85,21 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
|
||||
else ctl.statuscb(30, L("Hollowing"));
|
||||
|
||||
double iso_surface = D;
|
||||
auto narrowb = double(in_range);
|
||||
gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, narrowb);
|
||||
if (D > EPSILON) {
|
||||
in_range = narrowb;
|
||||
gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, in_range);
|
||||
|
||||
constexpr int DilateIterations = 1;
|
||||
|
||||
gridptr = openvdb::tools::dilateSdf(
|
||||
*gridptr, std::ceil(iso_surface),
|
||||
openvdb::tools::NN_FACE_EDGE_VERTEX, DilateIterations,
|
||||
openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE);
|
||||
|
||||
out_range = iso_surface;
|
||||
} else {
|
||||
iso_surface = -offset;
|
||||
}
|
||||
|
||||
if (ctl.stopcondition()) return {};
|
||||
else ctl.statuscb(70, L("Hollowing"));
|
||||
@ -99,11 +113,10 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
|
||||
if (ctl.stopcondition()) return {};
|
||||
else ctl.statuscb(100, L("Hollowing"));
|
||||
|
||||
interior->closing_distance = D;
|
||||
interior->thickness = offset;
|
||||
interior->iso_surface = iso_surface;
|
||||
interior->thickness = offset;
|
||||
interior->voxel_scale = voxel_scale;
|
||||
interior->nb_in = narrowb;
|
||||
interior->nb_out = narrowb;
|
||||
interior->full_narrowb = out_range + in_range;
|
||||
|
||||
return interior;
|
||||
}
|
||||
@ -112,8 +125,9 @@ InteriorPtr generate_interior(const TriangleMesh & mesh,
|
||||
const HollowingConfig &hc,
|
||||
const JobController & ctl)
|
||||
{
|
||||
static const double MIN_OVERSAMPL = 3.5;
|
||||
static const double MAX_OVERSAMPL = 8.;
|
||||
static constexpr double MIN_SAMPLES_IN_WALL = 3.5;
|
||||
static constexpr double MAX_OVERSAMPL = 8.;
|
||||
static constexpr double UNIT_VOLUME = 500000; // empiric
|
||||
|
||||
// I can't figure out how to increase the grid resolution through openvdb
|
||||
// API so the model will be scaled up before conversion and the result
|
||||
@ -121,12 +135,25 @@ InteriorPtr generate_interior(const TriangleMesh & mesh,
|
||||
// scales the whole geometry down, and doesn't increase the number of
|
||||
// voxels.
|
||||
//
|
||||
// max 8x upscale, min is native voxel size
|
||||
auto voxel_scale = MIN_OVERSAMPL + (MAX_OVERSAMPL - MIN_OVERSAMPL) * hc.quality;
|
||||
// First an allowed range for voxel scale is determined from an initial
|
||||
// range of <MIN_SAMPLES_IN_WALL, MAX_OVERSAMPL>. The final voxel scale is
|
||||
// then chosen from this range using the 'quality:<0, 1>' parameter.
|
||||
// The minimum can be lowered if the wall thickness is great enough and
|
||||
// the maximum is lowered if the model volume very big.
|
||||
double mesh_vol = its_volume(mesh.its);
|
||||
double sc_divider = std::max(1.0, (mesh_vol / UNIT_VOLUME));
|
||||
double min_oversampl = std::max(MIN_SAMPLES_IN_WALL / hc.min_thickness, 1.);
|
||||
double max_oversampl_scaled = std::max(min_oversampl, MAX_OVERSAMPL / sc_divider);
|
||||
auto voxel_scale = min_oversampl + (max_oversampl_scaled - min_oversampl) * hc.quality;
|
||||
|
||||
InteriorPtr interior =
|
||||
generate_interior_verbose(mesh, ctl, hc.min_thickness, voxel_scale,
|
||||
hc.closing_distance);
|
||||
BOOST_LOG_TRIVIAL(debug) << "Hollowing: max oversampl will be: " << max_oversampl_scaled;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Hollowing: voxel scale will be: " << voxel_scale;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Hollowing: mesh volume is: " << mesh_vol;
|
||||
|
||||
InteriorPtr interior = generate_interior_verbose(mesh, ctl,
|
||||
hc.min_thickness,
|
||||
voxel_scale,
|
||||
hc.closing_distance);
|
||||
|
||||
if (interior && !interior->mesh.empty()) {
|
||||
|
||||
@ -342,22 +369,18 @@ struct TriangleBubble { Vec3f center; double R; };
|
||||
static double get_distance(const TriangleBubble &b, const Interior &interior)
|
||||
{
|
||||
double R = b.R * interior.voxel_scale;
|
||||
double D = get_distance_raw(b.center, interior);
|
||||
double D = 2. * R;
|
||||
double Dst = get_distance_raw(b.center, interior);
|
||||
|
||||
return (D > 0. && R >= interior.nb_out) ||
|
||||
(D < 0. && R >= interior.nb_in) ||
|
||||
((D - R) < 0. && 2 * R > interior.thickness) ?
|
||||
return D > interior.full_narrowb ||
|
||||
((Dst - R) < 0. && 2 * R > interior.thickness) ?
|
||||
std::nan("") :
|
||||
// FIXME: Adding interior.voxel_scale is a compromise supposed
|
||||
// to prevent the deletion of the triangles forming the interior
|
||||
// itself. This has a side effect that a small portion of the
|
||||
// bad triangles will still be visible.
|
||||
D - interior.closing_distance /*+ 2 * interior.voxel_scale*/;
|
||||
Dst - interior.iso_surface;
|
||||
}
|
||||
|
||||
double get_distance(const Vec3f &p, const Interior &interior)
|
||||
{
|
||||
double d = get_distance_raw(p, interior) - interior.closing_distance;
|
||||
double d = get_distance_raw(p, interior) - interior.iso_surface;
|
||||
return d / interior.voxel_scale;
|
||||
}
|
||||
|
||||
@ -494,7 +517,7 @@ void remove_inside_triangles(TriangleMesh &mesh, const Interior &interior,
|
||||
if (f.parent != NEW_FACE) // Top parent needs to be removed as well
|
||||
mesh_mods.to_remove[f.parent] = true;
|
||||
|
||||
// If the outside part is between the interior end the exterior
|
||||
// If the outside part is between the interior and the exterior
|
||||
// (inside the wall being invisible), no further division is needed.
|
||||
if ((R + D) < interior.thickness)
|
||||
return false;
|
||||
|
@ -1,186 +0,0 @@
|
||||
#ifndef BICUBIC_HPP
|
||||
#define BICUBIC_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace BicubicInternal {
|
||||
// Linear kernel, to be able to test cubic methods with hat kernels.
|
||||
template<typename T>
|
||||
struct LinearKernel
|
||||
{
|
||||
typedef T FloatType;
|
||||
|
||||
static T a00() { return T(0.); }
|
||||
static T a01() { return T(0.); }
|
||||
static T a02() { return T(0.); }
|
||||
static T a03() { return T(0.); }
|
||||
static T a10() { return T(1.); }
|
||||
static T a11() { return T(-1.); }
|
||||
static T a12() { return T(0.); }
|
||||
static T a13() { return T(0.); }
|
||||
static T a20() { return T(0.); }
|
||||
static T a21() { return T(1.); }
|
||||
static T a22() { return T(0.); }
|
||||
static T a23() { return T(0.); }
|
||||
static T a30() { return T(0.); }
|
||||
static T a31() { return T(0.); }
|
||||
static T a32() { return T(0.); }
|
||||
static T a33() { return T(0.); }
|
||||
};
|
||||
|
||||
// Interpolation kernel aka Catmul-Rom aka Keyes kernel.
|
||||
template<typename T>
|
||||
struct CubicCatmulRomKernel
|
||||
{
|
||||
typedef T FloatType;
|
||||
|
||||
static T a00() { return 0; }
|
||||
static T a01() { return (T)-0.5; }
|
||||
static T a02() { return (T) 1.; }
|
||||
static T a03() { return (T)-0.5; }
|
||||
static T a10() { return (T) 1.; }
|
||||
static T a11() { return 0; }
|
||||
static T a12() { return (T)-5./2.; }
|
||||
static T a13() { return (T) 3./2.; }
|
||||
static T a20() { return 0; }
|
||||
static T a21() { return (T) 0.5; }
|
||||
static T a22() { return (T) 2.; }
|
||||
static T a23() { return (T)-3./2.; }
|
||||
static T a30() { return 0; }
|
||||
static T a31() { return 0; }
|
||||
static T a32() { return (T)-0.5; }
|
||||
static T a33() { return (T) 0.5; }
|
||||
};
|
||||
|
||||
// B-spline kernel
|
||||
template<typename T>
|
||||
struct CubicBSplineKernel
|
||||
{
|
||||
typedef T FloatType;
|
||||
|
||||
static T a00() { return (T) 1./6.; }
|
||||
static T a01() { return (T) -3./6.; }
|
||||
static T a02() { return (T) 3./6.; }
|
||||
static T a03() { return (T) -1./6.; }
|
||||
static T a10() { return (T) 4./6.; }
|
||||
static T a11() { return 0; }
|
||||
static T a12() { return (T) -6./6.; }
|
||||
static T a13() { return (T) 3./6.; }
|
||||
static T a20() { return (T) 1./6.; }
|
||||
static T a21() { return (T) 3./6.; }
|
||||
static T a22() { return (T) 3./6.; }
|
||||
static T a23() { return (T)- 3./6.; }
|
||||
static T a30() { return 0; }
|
||||
static T a31() { return 0; }
|
||||
static T a32() { return 0; }
|
||||
static T a33() { return (T) 1./6.; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline T clamp(T a, T lower, T upper)
|
||||
{
|
||||
return (a < lower) ? lower :
|
||||
(a > upper) ? upper : a;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename KERNEL>
|
||||
struct CubicKernel
|
||||
{
|
||||
typedef typename KERNEL KernelInternal;
|
||||
typedef typename KERNEL::FloatType FloatType;
|
||||
|
||||
static FloatType kernel(FloatType x)
|
||||
{
|
||||
x = fabs(x);
|
||||
if (x >= (FloatType)2.)
|
||||
return 0.0f;
|
||||
if (x <= (FloatType)1.) {
|
||||
FloatType x2 = x * x;
|
||||
FloatType x3 = x2 * x;
|
||||
return KERNEL::a10() + KERNEL::a11() * x + KERNEL::a12() * x2 + KERNEL::a13() * x3;
|
||||
}
|
||||
assert(x > (FloatType)1. && x < (FloatType)2.);
|
||||
x -= (FloatType)1.;
|
||||
FloatType x2 = x * x;
|
||||
FloatType x3 = x2 * x;
|
||||
return KERNEL::a00() + KERNEL::a01() * x + KERNEL::a02() * x2 + KERNEL::a03() * x3;
|
||||
}
|
||||
|
||||
static FloatType interpolate(FloatType f0, FloatType f1, FloatType f2, FloatType f3, FloatType x)
|
||||
{
|
||||
const FloatType x2 = x*x;
|
||||
const FloatType x3 = x*x*x;
|
||||
return f0*(KERNEL::a00() + KERNEL::a01() * x + KERNEL::a02() * x2 + KERNEL::a03() * x3) +
|
||||
f1*(KERNEL::a10() + KERNEL::a11() * x + KERNEL::a12() * x2 + KERNEL::a13() * x3) +
|
||||
f2*(KERNEL::a20() + KERNEL::a21() * x + KERNEL::a22() * x2 + KERNEL::a23() * x3) +
|
||||
f3*(KERNEL::a30() + KERNEL::a31() * x + KERNEL::a32() * x2 + KERNEL::a33() * x3);
|
||||
}
|
||||
};
|
||||
|
||||
// Linear splines
|
||||
typedef CubicKernel<BicubicInternal::LinearKernel<float>> LinearKernelf;
|
||||
typedef CubicKernel<BicubicInternal::LinearKernel<double>> LinearKerneld;
|
||||
// Catmul-Rom splines
|
||||
typedef CubicKernel<BicubicInternal::CubicCatmulRomKernel<float>> CubicCatmulRomKernelf;
|
||||
typedef CubicKernel<BicubicInternal::CubicCatmulRomKernel<double>> CubicCatmulRomKerneld;
|
||||
typedef CubicKernel<BicubicInternal::CubicCatmulRomKernel<float>> CubicInterpolationKernelf;
|
||||
typedef CubicKernel<BicubicInternal::CubicCatmulRomKernel<double>> CubicInterpolationKerneld;
|
||||
// Cubic B-splines
|
||||
typedef CubicKernel<BicubicInternal::CubicBSplineKernel<float>> CubicBSplineKernelf;
|
||||
typedef CubicKernel<BicubicInternal::CubicBSplineKernel<double>> CubicBSplineKerneld;
|
||||
|
||||
template<typename KERNEL, typename Derived>
|
||||
static float cubic_interpolate(const Eigen::ArrayBase<Derived> &F, const typename KERNEL::FloatType pt, const typename KERNEL::FloatType dx)
|
||||
{
|
||||
typedef typename KERNEL::FloatType T;
|
||||
const int w = int(F.size());
|
||||
const int ix = (int)floor(pt);
|
||||
const T s = pt - (T)ix;
|
||||
|
||||
if (ix > 1 && ix + 2 < w) {
|
||||
// Inside the fully interpolated region.
|
||||
return KERNEL::interpolate(F[ix - 1], F[ix], F[ix + 1], F[ix + 2], s);
|
||||
}
|
||||
// Transition region. Extend with a constant function.
|
||||
auto f = [&F, w](x) { return F[BicubicInternal::clamp(x, 0, w - 1)]; }
|
||||
return KERNEL::interpolate(f(ix - 1), f(ix), f(ix + 1), f(ix + 2), s);
|
||||
}
|
||||
|
||||
template<typename KERNEL, typename Derived>
|
||||
static float bicubic_interpolate(const Eigen::MatrixBase<Derived> &F, const Eigen::Matrix<typename KERNEL::FloatType, 2, 1, Eigen::DontAlign> &pt, const typename KERNEL::FloatType dx)
|
||||
{
|
||||
typedef typename KERNEL::FloatType T;
|
||||
const int w = F.cols();
|
||||
const int h = F.rows();
|
||||
const int ix = (int)floor(pt[0]);
|
||||
const int iy = (int)floor(pt[1]);
|
||||
const T s = pt[0] - (T)ix;
|
||||
const T t = pt[1] - (T)iy;
|
||||
|
||||
if (ix > 1 && ix + 2 < w && iy > 1 && iy + 2 < h) {
|
||||
// Inside the fully interpolated region.
|
||||
return KERNEL::interpolate(
|
||||
KERNEL::interpolate(F(ix-1,iy-1),F(ix ,iy-1),F(ix+1,iy-1),F(ix+2,iy-1),s),
|
||||
KERNEL::interpolate(F(ix-1,iy ),F(ix ,iy ),F(ix+1,iy ),F(ix+2,iy ),s),
|
||||
KERNEL::interpolate(F(ix-1,iy+1),F(ix ,iy+1),F(ix+1,iy+1),F(ix+2,iy+1),s),
|
||||
KERNEL::interpolate(F(ix-1,iy+2),F(ix ,iy+2),F(ix+1,iy+2),F(ix+2,iy+2),s),t);
|
||||
}
|
||||
// Transition region. Extend with a constant function.
|
||||
auto f = [&f, w, h](int x, int y) { return F(BicubicInternal::clamp(x,0,w-1),BicubicInternal::clamp(y,0,h-1)); }
|
||||
return KERNEL::interpolate(
|
||||
KERNEL::interpolate(f(ix-1,iy-1),f(ix ,iy-1),f(ix+1,iy-1),f(ix+2,iy-1),s),
|
||||
KERNEL::interpolate(f(ix-1,iy ),f(ix ,iy ),f(ix+1,iy ),f(ix+2,iy ),s),
|
||||
KERNEL::interpolate(f(ix-1,iy+1),f(ix ,iy+1),f(ix+1,iy+1),f(ix+2,iy+1),s),
|
||||
KERNEL::interpolate(f(ix-1,iy+2),f(ix ,iy+2),f(ix+1,iy+2),f(ix+2,iy+2),s),t);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* BICUBIC_HPP */
|
@ -246,7 +246,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
||||
m_default_object_config.apply_only(config, object_diff, true);
|
||||
|
||||
if (!m_archiver || !printer_diff.empty())
|
||||
m_archiver = SLAArchive::create(m_printer_config.sla_archive_format.value.c_str(), m_printer_config);
|
||||
m_archiver = SLAArchiveWriter::create(m_printer_config.sla_archive_format.value.c_str(), m_printer_config);
|
||||
|
||||
struct ModelObjectStatus {
|
||||
enum Status {
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "Point.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
#include "Zipper.hpp"
|
||||
#include "Format/SLAArchive.hpp"
|
||||
#include "Format/SLAArchiveWriter.hpp"
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
|
||||
#include "libslic3r/Execution/ExecutionTBB.hpp"
|
||||
@ -524,7 +524,7 @@ private:
|
||||
std::vector<PrintLayer> m_printer_input;
|
||||
|
||||
// The archive object which collects the raster images after slicing
|
||||
std::unique_ptr<SLAArchive> m_archiver;
|
||||
std::unique_ptr<SLAArchiveWriter> m_archiver;
|
||||
|
||||
// Estimated print time, material consumed.
|
||||
SLAPrintStatistics m_print_statistics;
|
||||
|
@ -215,6 +215,22 @@ struct FaceHash {
|
||||
}
|
||||
};
|
||||
|
||||
static void exclude_neighbors(const Vec3i &face,
|
||||
std::vector<bool> &mask,
|
||||
const indexed_triangle_set &its,
|
||||
const VertexFaceIndex &index,
|
||||
size_t recursions)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const auto &neighbors_range = index[face(i)];
|
||||
for (size_t fi_n : neighbors_range) {
|
||||
mask[fi_n] = true;
|
||||
if (recursions > 0)
|
||||
exclude_neighbors(its.indices[fi_n], mask, its, index, recursions - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create exclude mask for triangle removal inside hollowed interiors.
|
||||
// This is necessary when the interior is already part of the mesh which was
|
||||
// drilled using CGAL mesh boolean operation. Excluded will be the triangles
|
||||
@ -231,15 +247,6 @@ static std::vector<bool> create_exclude_mask(
|
||||
|
||||
VertexFaceIndex neighbor_index{its};
|
||||
|
||||
auto exclude_neighbors = [&neighbor_index, &exclude_mask](const Vec3i &face)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const auto &neighbors_range = neighbor_index[face(i)];
|
||||
for (size_t fi_n : neighbors_range)
|
||||
exclude_mask[fi_n] = true;
|
||||
}
|
||||
};
|
||||
|
||||
for (size_t fi = 0; fi < its.indices.size(); ++fi) {
|
||||
auto &face = its.indices[fi];
|
||||
|
||||
@ -249,7 +256,7 @@ static std::vector<bool> create_exclude_mask(
|
||||
}
|
||||
|
||||
if (exclude_mask[fi]) {
|
||||
exclude_neighbors(face);
|
||||
exclude_neighbors(face, exclude_mask, its, neighbor_index, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -294,7 +301,7 @@ static std::vector<bool> create_exclude_mask(
|
||||
|
||||
if (D_hole < D_tol && std::abs(dot) < normal_angle_tol) {
|
||||
exclude_mask[fi] = true;
|
||||
exclude_neighbors(face);
|
||||
exclude_neighbors(face, exclude_mask, its, neighbor_index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
218
src/libslic3r/Subdivide.cpp
Normal file
218
src/libslic3r/Subdivide.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
#include "Subdivide.hpp"
|
||||
#include "Point.hpp"
|
||||
|
||||
namespace Slic3r{
|
||||
|
||||
indexed_triangle_set its_subdivide(
|
||||
const indexed_triangle_set &its, float max_length)
|
||||
{
|
||||
// same order as key order in Edge Divides
|
||||
struct VerticesSequence
|
||||
{
|
||||
size_t start_index;
|
||||
bool positive_order;
|
||||
VerticesSequence(size_t start_index, bool positive_order = true)
|
||||
: start_index(start_index), positive_order(positive_order){}
|
||||
};
|
||||
// vertex index small, big vertex index from key.first to key.second
|
||||
using EdgeDivides = std::map<std::pair<size_t, size_t>, VerticesSequence>;
|
||||
struct Edges
|
||||
{
|
||||
Vec3f data[3];
|
||||
Vec3f lengths;
|
||||
Edges(const Vec3crd &indices, const std::vector<Vec3f> &vertices)
|
||||
: lengths(-1.f,-1.f,-1.f)
|
||||
{
|
||||
const Vec3f &v0 = vertices[indices[0]];
|
||||
const Vec3f &v1 = vertices[indices[1]];
|
||||
const Vec3f &v2 = vertices[indices[2]];
|
||||
data[0] = v0 - v1;
|
||||
data[1] = v1 - v2;
|
||||
data[2] = v2 - v0;
|
||||
}
|
||||
float abs_sum(const Vec3f &v)
|
||||
{
|
||||
return abs(v[0]) + abs(v[1]) + abs(v[2]);
|
||||
}
|
||||
bool is_dividable(const float& max_length) {
|
||||
Vec3f sum(abs_sum(data[0]), abs_sum(data[1]), abs_sum(data[2]));
|
||||
Vec3i biggest_index = (sum[0] > sum[1]) ?
|
||||
((sum[0] > sum[2]) ?
|
||||
((sum[2] > sum[1]) ?
|
||||
Vec3i(0, 2, 1) :
|
||||
Vec3i(0, 1, 2)) :
|
||||
Vec3i(2, 0, 1)) :
|
||||
((sum[1] > sum[2]) ?
|
||||
((sum[2] > sum[0]) ?
|
||||
Vec3i(1, 2, 0) :
|
||||
Vec3i(1, 0, 2)) :
|
||||
Vec3i(2, 1, 0));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int index = biggest_index[i];
|
||||
if (sum[index] <= max_length) return false;
|
||||
lengths[index] = data[index].norm();
|
||||
if (lengths[index] <= max_length) continue;
|
||||
|
||||
// calculate rest of lengths
|
||||
for (int j = i + 1; j < 3; j++) {
|
||||
index = biggest_index[j];
|
||||
lengths[index] = data[index].norm();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
struct TriangleLengths
|
||||
{
|
||||
Vec3crd indices;
|
||||
Vec3f l; // lengths
|
||||
TriangleLengths(const Vec3crd &indices, const Vec3f &lengths)
|
||||
: indices(indices), l(lengths)
|
||||
{}
|
||||
|
||||
int get_divide_index(float max_length) {
|
||||
if (l[0] > l[1] && l[0] > l[2]) {
|
||||
if (l[0] > max_length) return 0;
|
||||
} else if (l[1] > l[2]) {
|
||||
if (l[1] > max_length) return 1;
|
||||
} else {
|
||||
if (l[2] > max_length) return 2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// divide triangle add new vertex to vertices
|
||||
std::pair<TriangleLengths, TriangleLengths> divide(
|
||||
int divide_index, float max_length,
|
||||
std::vector<Vec3f> &vertices,
|
||||
EdgeDivides &edge_divides)
|
||||
{
|
||||
// index to lengths and indices
|
||||
size_t i0 = divide_index;
|
||||
size_t i1 = (divide_index + 1) % 3;
|
||||
size_t vi0 = indices[i0];
|
||||
size_t vi1 = indices[i1];
|
||||
std::pair<size_t, size_t> key(vi0, vi1);
|
||||
bool key_swap = false;
|
||||
if (key.first > key.second) {
|
||||
std::swap(key.first, key.second);
|
||||
key_swap = true;
|
||||
}
|
||||
|
||||
float length = l[divide_index];
|
||||
size_t count_edge_vertices = static_cast<size_t>(floor(length / max_length));
|
||||
float count_edge_segments = static_cast<float>(count_edge_vertices + 1);
|
||||
|
||||
auto it = edge_divides.find(key);
|
||||
if (it == edge_divides.end()) {
|
||||
// Create new vertices
|
||||
VerticesSequence new_vs(vertices.size());
|
||||
Vec3f vf = vertices[key.first]; // copy
|
||||
const Vec3f &vs = vertices[key.second];
|
||||
Vec3f dir = vs - vf;
|
||||
for (size_t i = 1; i <= count_edge_vertices; ++i) {
|
||||
float ratio = i / count_edge_segments;
|
||||
vertices.push_back(vf + dir * ratio);
|
||||
}
|
||||
bool success;
|
||||
std::tie(it,success) = edge_divides.insert({key, new_vs});
|
||||
assert(success);
|
||||
}
|
||||
const VerticesSequence &vs = it->second;
|
||||
|
||||
int index_offset = count_edge_vertices/2;
|
||||
size_t i2 = (divide_index + 2) % 3;
|
||||
if (count_edge_vertices % 2 == 0 && key_swap == (l[i1] < l[i2])) {
|
||||
--index_offset;
|
||||
}
|
||||
int sign = (vs.positive_order) ? 1 : -1;
|
||||
size_t new_index = vs.start_index + sign*index_offset;
|
||||
|
||||
size_t vi2 = indices[i2];
|
||||
const Vec3f &v2 = vertices[vi2];
|
||||
Vec3f new_edge = v2 - vertices[new_index];
|
||||
float new_len = new_edge.norm();
|
||||
|
||||
float ratio = (1 + index_offset) / count_edge_segments;
|
||||
float len1 = l[i0] * ratio;
|
||||
float len2 = l[i0] - len1;
|
||||
if (key_swap) std::swap(len1, len2);
|
||||
|
||||
Vec3crd indices1(vi0, new_index, vi2);
|
||||
Vec3f lengths1(len1, new_len, l[i2]);
|
||||
|
||||
Vec3crd indices2(new_index, vi1, vi2);
|
||||
Vec3f lengths2(len2, l[i1], new_len);
|
||||
|
||||
// append key for divided edge when neccesary
|
||||
if (index_offset > 0) {
|
||||
std::pair<size_t, size_t> new_key(key.first, new_index);
|
||||
bool new_key_swap = false;
|
||||
if (new_key.first > new_key.second) {
|
||||
std::swap(new_key.first, new_key.second);
|
||||
new_key_swap = true;
|
||||
}
|
||||
if (edge_divides.find(new_key) == edge_divides.end()) {
|
||||
// insert new
|
||||
edge_divides.insert({new_key, (new_key_swap) ?
|
||||
VerticesSequence(new_index - sign, !vs.positive_order)
|
||||
: vs});
|
||||
}
|
||||
}
|
||||
|
||||
if (index_offset < int(count_edge_vertices)-1) {
|
||||
std::pair<size_t, size_t> new_key(new_index, key.second);
|
||||
bool new_key_swap = false;
|
||||
if (new_key.first > new_key.second) {
|
||||
std::swap(new_key.first, new_key.second);
|
||||
new_key_swap = true;
|
||||
}
|
||||
// bad order
|
||||
if (edge_divides.find(new_key) == edge_divides.end()) {
|
||||
edge_divides.insert({new_key, (new_key_swap) ?
|
||||
VerticesSequence(vs.start_index + sign*(count_edge_vertices-1), !vs.positive_order)
|
||||
: VerticesSequence(new_index + sign, vs.positive_order)});
|
||||
}
|
||||
}
|
||||
|
||||
return {TriangleLengths(indices1, lengths1),
|
||||
TriangleLengths(indices2, lengths2)};
|
||||
}
|
||||
};
|
||||
indexed_triangle_set result;
|
||||
result.indices.reserve(its.indices.size());
|
||||
const std::vector<Vec3f> &vertices = its.vertices;
|
||||
result.vertices = vertices; // copy
|
||||
std::queue<TriangleLengths> tls;
|
||||
|
||||
EdgeDivides edge_divides;
|
||||
for (const Vec3crd &indices : its.indices) {
|
||||
Edges edges(indices, vertices);
|
||||
// speed up only sum not sqrt is apply
|
||||
if (!edges.is_dividable(max_length)) {
|
||||
// small triangle
|
||||
result.indices.push_back(indices);
|
||||
continue;
|
||||
}
|
||||
TriangleLengths tl(indices, edges.lengths);
|
||||
do {
|
||||
int divide_index = tl.get_divide_index(max_length);
|
||||
if (divide_index < 0) {
|
||||
// no dividing
|
||||
result.indices.push_back(tl.indices);
|
||||
if (tls.empty()) break;
|
||||
tl = tls.front(); // copy
|
||||
tls.pop();
|
||||
} else {
|
||||
auto [tl1, tl2] = tl.divide(divide_index, max_length,
|
||||
result.vertices, edge_divides);
|
||||
tl = tl1;
|
||||
tls.push(tl2);
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
12
src/libslic3r/Subdivide.hpp
Normal file
12
src/libslic3r/Subdivide.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef libslic3r_Subdivide_hpp_
|
||||
#define libslic3r_Subdivide_hpp_
|
||||
|
||||
#include "TriangleMesh.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
indexed_triangle_set its_subdivide(const indexed_triangle_set &its, float max_length);
|
||||
|
||||
}
|
||||
|
||||
#endif //libslic3r_Subdivide_hpp_
|
@ -24,6 +24,13 @@
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
|
||||
#ifdef _WIN32
|
||||
// On MSVC, std::deque degenerates to a list of pointers, which defeats its purpose of reducing allocator load and memory fragmentation.
|
||||
// https://github.com/microsoft/STL/issues/147#issuecomment-1090148740
|
||||
// Thus it is recommended to use boost::container::deque instead.
|
||||
#include <boost/container/deque.hpp>
|
||||
#endif // _WIN32
|
||||
|
||||
#include "Technologies.hpp"
|
||||
#include "Semver.hpp"
|
||||
|
||||
@ -74,6 +81,16 @@ namespace Slic3r {
|
||||
|
||||
extern Semver SEMVER;
|
||||
|
||||
// On MSVC, std::deque degenerates to a list of pointers, which defeats its purpose of reducing allocator load and memory fragmentation.
|
||||
template<class T, class Allocator = std::allocator<T>>
|
||||
using deque =
|
||||
#ifdef _WIN32
|
||||
// Use boost implementation, which allocates blocks of 512 bytes instead of blocks of 8 bytes.
|
||||
boost::container::deque<T, Allocator>;
|
||||
#else // _WIN32
|
||||
std::deque<T, Allocator>;
|
||||
#endif // _WIN32
|
||||
|
||||
template<typename T, typename Q>
|
||||
inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
|
||||
|
||||
|
@ -64,6 +64,12 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/warning_disable.hpp>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#ifdef _WIN32
|
||||
// On MSVC, std::deque degenerates to a list of pointers, which defeats its purpose of reducing allocator load and memory fragmentation.
|
||||
// https://github.com/microsoft/STL/issues/147#issuecomment-1090148740
|
||||
// Thus it is recommended to use boost::container::deque instead.
|
||||
#include <boost/container/deque.hpp>
|
||||
#endif // _WIN32
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#ifdef __WXGTK2__
|
||||
// Broken alpha workaround
|
||||
@ -13,7 +15,7 @@
|
||||
#include <wx/rawbmp.h>
|
||||
#endif /* __WXGTK2__ */
|
||||
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
//#define NANOSVG_IMPLEMENTATION
|
||||
#include "nanosvg/nanosvg.h"
|
||||
#define NANOSVGRAST_IMPLEMENTATION
|
||||
#include "nanosvg/nanosvgrast.h"
|
||||
|
@ -2176,7 +2176,8 @@ void Control::auto_color_change()
|
||||
|
||||
const Print& print = GUI::wxGetApp().plater()->fff_print();
|
||||
for (auto object : print.objects()) {
|
||||
if (object->layer_count() == 0)
|
||||
// An object should to have at least 2 layers to apply an auto color change
|
||||
if (object->layer_count() < 2)
|
||||
continue;
|
||||
|
||||
check_color_change(object, 1, object->layers().size(), false, [this, extruders_cnt](Layer* layer)
|
||||
|
@ -4483,23 +4483,25 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
ImGui::SameLine();
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
if (!wxGetApp().is_gcode_viewer()) {
|
||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
image_icon(window, pos, size, ImGui::LegendShells);
|
||||
toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
image_icon(window, pos, size, ImGui::LegendShells);
|
||||
#else
|
||||
toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
const ImU32 color = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
const float margin = 3.0f;
|
||||
const float proj = 0.25f * size;
|
||||
window.DrawList->AddRect({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin - proj, pos.y + margin + proj }, color);
|
||||
window.DrawList->AddLine({ pos.x + margin, pos.y + margin + proj }, { pos.x + margin + proj, pos.y + margin }, color);
|
||||
window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + margin + proj }, { pos.x + size - margin, pos.y + margin }, color);
|
||||
window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + size - margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color);
|
||||
window.DrawList->AddLine({ pos.x + margin + proj, pos.y + margin }, { pos.x + size - margin, pos.y + margin }, color);
|
||||
window.DrawList->AddLine({ pos.x + size - margin, pos.y + margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color);
|
||||
toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
const ImU32 color = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
const float margin = 3.0f;
|
||||
const float proj = 0.25f * size;
|
||||
window.DrawList->AddRect({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin - proj, pos.y + margin + proj }, color);
|
||||
window.DrawList->AddLine({ pos.x + margin, pos.y + margin + proj }, { pos.x + margin + proj, pos.y + margin }, color);
|
||||
window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + margin + proj }, { pos.x + size - margin, pos.y + margin }, color);
|
||||
window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + size - margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color);
|
||||
window.DrawList->AddLine({ pos.x + margin + proj, pos.y + margin }, { pos.x + size - margin, pos.y + margin }, color);
|
||||
window.DrawList->AddLine({ pos.x + size - margin, pos.y + margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color);
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
});
|
||||
ImGui::SameLine();
|
||||
});
|
||||
ImGui::SameLine();
|
||||
}
|
||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
toggle_button(Preview::OptionType::ToolMarker, _u8L("Tool marker"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
image_icon(window, pos, size, ImGui::LegendToolMarker);
|
||||
|
@ -1051,8 +1051,6 @@ bool GUI_App::OnInit()
|
||||
}
|
||||
}
|
||||
|
||||
static bool update_gui_after_init = true;
|
||||
|
||||
bool GUI_App::on_init_inner()
|
||||
{
|
||||
// Set initialization of image handlers before any UI actions - See GH issue #7469
|
||||
@ -1328,18 +1326,18 @@ bool GUI_App::on_init_inner()
|
||||
// An ugly solution to GH #5537 in which GUI_App::init_opengl (normally called from events wxEVT_PAINT
|
||||
// and wxEVT_SET_FOCUS before GUI_App::post_init is called) wasn't called before GUI_App::post_init and OpenGL wasn't initialized.
|
||||
#ifdef __linux__
|
||||
if (update_gui_after_init && m_opengl_initialized) {
|
||||
if (! m_post_initialized && m_opengl_initialized) {
|
||||
#else
|
||||
if (update_gui_after_init) {
|
||||
if (! m_post_initialized) {
|
||||
#endif
|
||||
update_gui_after_init = false;
|
||||
m_post_initialized = true;
|
||||
#ifdef WIN32
|
||||
this->mainframe->register_win32_callbacks();
|
||||
#endif
|
||||
this->post_init();
|
||||
}
|
||||
|
||||
if (! update_gui_after_init && app_config->dirty() && app_config->get("autosave") == "1")
|
||||
if (m_post_initialized && app_config->dirty() && app_config->get("autosave") == "1")
|
||||
app_config->save();
|
||||
});
|
||||
|
||||
@ -2727,17 +2725,25 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
|
||||
// Running in G-code viewer.
|
||||
// Load the first G-code into the G-code viewer.
|
||||
// Or if no G-codes, send other files to slicer.
|
||||
if (! gcode_files.empty())
|
||||
this->plater()->load_gcode(gcode_files.front());
|
||||
if (! gcode_files.empty()) {
|
||||
if (m_post_initialized)
|
||||
this->plater()->load_gcode(gcode_files.front());
|
||||
else
|
||||
this->init_params->input_files = { into_u8(gcode_files.front()) };
|
||||
}
|
||||
if (!non_gcode_files.empty())
|
||||
start_new_slicer(non_gcode_files, true);
|
||||
} else {
|
||||
if (! files.empty()) {
|
||||
wxArrayString input_files;
|
||||
for (size_t i = 0; i < non_gcode_files.size(); ++i) {
|
||||
input_files.push_back(non_gcode_files[i]);
|
||||
if (m_post_initialized) {
|
||||
wxArrayString input_files;
|
||||
for (size_t i = 0; i < non_gcode_files.size(); ++i)
|
||||
input_files.push_back(non_gcode_files[i]);
|
||||
this->plater()->load_files(input_files);
|
||||
} else {
|
||||
for (const auto &f : non_gcode_files)
|
||||
this->init_params->input_files.emplace_back(into_u8(f));
|
||||
}
|
||||
this->plater()->load_files(input_files);
|
||||
}
|
||||
for (const wxString &filename : gcode_files)
|
||||
start_new_gcodeviewer(&filename);
|
||||
|
@ -117,6 +117,7 @@ public:
|
||||
|
||||
private:
|
||||
bool m_initialized { false };
|
||||
bool m_post_initialized { false };
|
||||
bool m_app_conf_exists{ false };
|
||||
EAppMode m_app_mode{ EAppMode::Editor };
|
||||
bool m_is_recreating_gui{ false };
|
||||
|
@ -14,12 +14,14 @@
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <map>
|
||||
|
||||
#include <cereal/archives/binary.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
@ -65,7 +67,7 @@ inline void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, f
|
||||
|
||||
void write_used_binary(const std::vector<std::string>& ids)
|
||||
{
|
||||
boost::filesystem::ofstream file((boost::filesystem::path(data_dir()) / "cache" / "hints.cereal"), std::ios::binary);
|
||||
boost::nowide::ofstream file((boost::filesystem::path(data_dir()) / "cache" / "hints.cereal").string(), std::ios::binary);
|
||||
cereal::BinaryOutputArchive archive(file);
|
||||
HintsCerealData cd { ids };
|
||||
try
|
||||
@ -84,7 +86,7 @@ void read_used_binary(std::vector<std::string>& ids)
|
||||
BOOST_LOG_TRIVIAL(warning) << "Failed to load to hints.cereal. File does not exists. " << path.string();
|
||||
return;
|
||||
}
|
||||
boost::filesystem::ifstream file(path);
|
||||
boost::nowide::ifstream file(path.string());
|
||||
cereal::BinaryInputArchive archive(file);
|
||||
HintsCerealData cd;
|
||||
try
|
||||
|
@ -1554,6 +1554,15 @@ void ImGuiWrapper::init_font(bool compress)
|
||||
ImVector<ImWchar> ranges;
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
builder.AddRanges(m_glyph_ranges);
|
||||
|
||||
if (m_font_cjk) {
|
||||
// This is a temporary fix of https://github.com/prusa3d/PrusaSlicer/issues/8171. The translation
|
||||
// contains characters not in the ImGui ranges for simplified Chinese. For now, just add them manually.
|
||||
// In future, it might be worth to parse the dictionary and add all the necessary characters.
|
||||
builder.AddChar(ImWchar(0x5ED3));
|
||||
builder.AddChar(ImWchar(0x8F91));
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (m_font_cjk)
|
||||
// Apple keyboard shortcuts are only contained in the CJK fonts.
|
||||
|
@ -10,17 +10,67 @@
|
||||
#include <wx/filepicker.h>
|
||||
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "libslic3r/Format/SLAArchiveReader.hpp"
|
||||
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
//#include "libslic3r/Model.hpp"
|
||||
//#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
std::string get_readers_wildcard()
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
for (const char *archtype : SLAArchiveReader::registered_archives()) {
|
||||
ret += _utf8(SLAArchiveReader::get_description(archtype));
|
||||
ret += " (";
|
||||
auto extensions = SLAArchiveReader::get_extensions(archtype);
|
||||
for (const char * ext : extensions) {
|
||||
ret += "*.";
|
||||
ret += ext;
|
||||
ret += ", ";
|
||||
}
|
||||
// remove last ", "
|
||||
if (!extensions.empty()) {
|
||||
ret.pop_back();
|
||||
ret.pop_back();
|
||||
}
|
||||
|
||||
ret += ")|";
|
||||
|
||||
for (std::string ext : extensions) {
|
||||
boost::algorithm::to_lower(ext);
|
||||
ret += "*.";
|
||||
ret += ext;
|
||||
ret += ";";
|
||||
|
||||
boost::algorithm::to_upper(ext);
|
||||
ret += "*.";
|
||||
ret += ext;
|
||||
ret += ";";
|
||||
}
|
||||
|
||||
// remove last ';'
|
||||
if (!extensions.empty())
|
||||
ret.pop_back();
|
||||
|
||||
ret += "|";
|
||||
}
|
||||
|
||||
if (ret.back() == '|')
|
||||
ret.pop_back();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
class SLAImportDialog: public wxDialog, public SLAImportJobView {
|
||||
wxFilePickerCtrl *m_filepicker;
|
||||
wxComboBox *m_import_dropdown, *m_quality_dropdown;
|
||||
@ -34,7 +84,7 @@ public:
|
||||
|
||||
m_filepicker = new wxFilePickerCtrl(this, wxID_ANY,
|
||||
from_u8(wxGetApp().app_config->get_last_dir()), _(L("Choose SLA archive:")),
|
||||
"SL1 / SL1S archive files (*.sl1, *.sl1s, *.zip)|*.sl1;*.SL1;*.sl1s;*.SL1S;*.zip;*.ZIP",
|
||||
get_readers_wildcard(),
|
||||
wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE | wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
|
||||
szfilepck->Add(new wxStaticText(this, wxID_ANY, _L("Import file") + ": "), 0, wxALIGN_CENTER);
|
||||
@ -64,7 +114,7 @@ public:
|
||||
};
|
||||
|
||||
m_quality_dropdown = new wxComboBox(
|
||||
this, wxID_ANY, qual_choices[0], wxDefaultPosition, wxDefaultSize,
|
||||
this, wxID_ANY, qual_choices[1], wxDefaultPosition, wxDefaultSize,
|
||||
qual_choices.size(), qual_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
|
||||
szchoices->Add(m_quality_dropdown, 1);
|
||||
|
||||
@ -96,17 +146,15 @@ public:
|
||||
return Sel(std::min(int(Sel::modelOnly), std::max(0, sel)));
|
||||
}
|
||||
|
||||
Vec2i get_marchsq_windowsize() const override
|
||||
SLAImportQuality get_quality() const override
|
||||
{
|
||||
enum { Accurate, Balanced, Fast};
|
||||
|
||||
switch(m_quality_dropdown->GetSelection())
|
||||
{
|
||||
case Fast: return {8, 8};
|
||||
case Balanced: return {4, 4};
|
||||
case 2: return SLAImportQuality::Fast;
|
||||
case 1: return SLAImportQuality::Balanced;
|
||||
case 0: return SLAImportQuality::Accurate;
|
||||
default:
|
||||
case Accurate:
|
||||
return {2, 2};
|
||||
return SLAImportQuality::Balanced;
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,6 +162,14 @@ public:
|
||||
{
|
||||
return m_filepicker->GetPath().ToUTF8().data();
|
||||
}
|
||||
|
||||
std::string get_archive_format() const override
|
||||
{
|
||||
// TODO: the choosen format is inside the file dialog which is not
|
||||
// accessible from the file picker object. The file picker could be
|
||||
// changed to a custom file dialog.
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "libslic3r/Format/SLAArchiveReader.hpp"
|
||||
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
@ -24,7 +25,7 @@ public:
|
||||
indexed_triangle_set mesh;
|
||||
DynamicPrintConfig profile;
|
||||
wxString path;
|
||||
Vec2i win = {2, 2};
|
||||
Quality quality = Quality::Balanced;
|
||||
std::string err;
|
||||
ConfigSubstitutions config_substitutions;
|
||||
|
||||
@ -43,6 +44,8 @@ SLAImportJob::~SLAImportJob() = default;
|
||||
|
||||
void SLAImportJob::process(Ctl &ctl)
|
||||
{
|
||||
if (p->path.empty() || ! p->err.empty()) return;
|
||||
|
||||
auto statustxt = _u8L("Importing SLA archive");
|
||||
ctl.update_status(0, statustxt);
|
||||
|
||||
@ -52,23 +55,31 @@ void SLAImportJob::process(Ctl &ctl)
|
||||
return !ctl.was_canceled();
|
||||
};
|
||||
|
||||
if (p->path.empty()) return;
|
||||
|
||||
std::string path = p->path.ToUTF8().data();
|
||||
std::string format_id = p->import_dlg->get_archive_format();
|
||||
|
||||
try {
|
||||
switch (p->sel) {
|
||||
case Sel::modelAndProfile:
|
||||
case Sel::modelOnly:
|
||||
p->config_substitutions = import_sla_archive(path, p->win, p->mesh, p->profile, progr);
|
||||
p->config_substitutions = import_sla_archive(path,
|
||||
format_id,
|
||||
p->mesh,
|
||||
p->profile,
|
||||
p->quality, progr);
|
||||
break;
|
||||
case Sel::profileOnly:
|
||||
p->config_substitutions = import_sla_archive(path, p->profile);
|
||||
p->config_substitutions = import_sla_archive(path, format_id,
|
||||
p->profile);
|
||||
break;
|
||||
}
|
||||
} catch (MissingProfileError &) {
|
||||
p->err = _L("The SLA archive doesn't contain any presets. "
|
||||
"Please activate some SLA printer preset first before importing that SLA archive.").ToStdString();
|
||||
} catch (std::exception &ex) {
|
||||
p->err = _u8L("The SLA archive doesn't contain any presets. "
|
||||
"Please activate some SLA printer preset first before "
|
||||
"importing that SLA archive.");
|
||||
} catch (ReaderUnimplementedError &) {
|
||||
p->err = _u8L("Import is unavailable for this archive format.");
|
||||
}catch (std::exception &ex) {
|
||||
p->err = ex.what();
|
||||
}
|
||||
|
||||
@ -81,19 +92,25 @@ void SLAImportJob::reset()
|
||||
p->sel = Sel::modelAndProfile;
|
||||
p->mesh = {};
|
||||
p->profile = p->plater->sla_print().full_print_config();
|
||||
p->win = {2, 2};
|
||||
p->quality = SLAImportQuality::Balanced;
|
||||
p->path.Clear();
|
||||
p->err = "";
|
||||
}
|
||||
|
||||
void SLAImportJob::prepare()
|
||||
{
|
||||
reset();
|
||||
|
||||
auto path = p->import_dlg->get_path();
|
||||
auto nm = wxFileName(path);
|
||||
p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : nm.GetFullPath();
|
||||
p->sel = p->import_dlg->get_selection();
|
||||
p->win = p->import_dlg->get_marchsq_windowsize();
|
||||
auto path = p->import_dlg->get_path();
|
||||
auto nm = wxFileName(path);
|
||||
p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : nm.GetFullPath();
|
||||
if (p->path.empty()) {
|
||||
p->err = _u8L("The file does not exist.");
|
||||
return;
|
||||
}
|
||||
p->sel = p->import_dlg->get_selection();
|
||||
p->quality = p->import_dlg->get_quality();
|
||||
|
||||
p->config_substitutions.clear();
|
||||
}
|
||||
|
||||
@ -115,8 +132,8 @@ void SLAImportJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||
p->plater->get_notification_manager()->push_notification(
|
||||
NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||
_L("The imported SLA archive did not contain any presets. "
|
||||
"The current SLA presets were used as fallback.").ToStdString());
|
||||
_u8L("The imported SLA archive did not contain any presets. "
|
||||
"The current SLA presets were used as fallback."));
|
||||
}
|
||||
|
||||
if (p->sel != Sel::modelOnly) {
|
||||
@ -138,15 +155,27 @@ void SLAImportJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||
config.apply(SLAFullPrintConfig::defaults());
|
||||
config += std::move(p->profile);
|
||||
|
||||
wxGetApp().preset_bundle->load_config_model(name, std::move(config));
|
||||
p->plater->check_selected_presets_visibility(ptSLA);
|
||||
wxGetApp().load_current_presets();
|
||||
if (Preset::printer_technology(config) == ptSLA) {
|
||||
wxGetApp().preset_bundle->load_config_model(name, std::move(config));
|
||||
p->plater->check_selected_presets_visibility(ptSLA);
|
||||
wxGetApp().load_current_presets();
|
||||
} else {
|
||||
p->plater->get_notification_manager()->push_notification(
|
||||
NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||
_u8L("The profile in the imported archive is corrupt and will not be loaded."));
|
||||
}
|
||||
}
|
||||
|
||||
if (!p->mesh.empty()) {
|
||||
bool is_centered = false;
|
||||
p->plater->sidebar().obj_list()->load_mesh_object(TriangleMesh{std::move(p->mesh)},
|
||||
name, is_centered);
|
||||
} else if (p->sel == Sel::modelOnly || p->sel == Sel::modelAndProfile) {
|
||||
p->plater->get_notification_manager()->push_notification(
|
||||
NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||
_u8L("No object could be retrieved from the archive. The slices might be corrupted or missing."));
|
||||
}
|
||||
|
||||
if (! p->config_substitutions.empty())
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "Job.hpp"
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/Format/SLAArchiveReader.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@ -14,8 +14,9 @@ public:
|
||||
virtual ~SLAImportJobView() = default;
|
||||
|
||||
virtual Sel get_selection() const = 0;
|
||||
virtual Vec2i get_marchsq_windowsize() const = 0;
|
||||
virtual SLAImportQuality get_quality() const = 0;
|
||||
virtual std::string get_path() const = 0;
|
||||
virtual std::string get_archive_format() const { return ""; }
|
||||
};
|
||||
|
||||
class Plater;
|
||||
@ -25,6 +26,7 @@ class SLAImportJob : public Job {
|
||||
|
||||
std::unique_ptr<priv> p;
|
||||
using Sel = SLAImportJobView::Sel;
|
||||
using Quality = SLAImportQuality;
|
||||
|
||||
public:
|
||||
void prepare();
|
||||
|
@ -1212,7 +1212,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(true); }, "import_plater", nullptr,
|
||||
[this](){return m_plater != nullptr; }, this);
|
||||
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import SL1 / SL1S Archive") + dots, _L("Load an SL1 / Sl1S archive"),
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import SLA Archive") + dots, _L("Load an SLA archive"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr,
|
||||
[this](){return m_plater != nullptr && m_plater->get_ui_job_worker().is_idle(); }, this);
|
||||
|
||||
|
@ -1494,22 +1494,18 @@ bool Sidebar::is_multifilament()
|
||||
return p->combos_filament.size() > 1;
|
||||
}
|
||||
|
||||
static std::vector<Search::InputInfo> get_search_inputs(ConfigOptionMode mode)
|
||||
void Sidebar::check_and_update_searcher(bool respect_mode /*= false*/)
|
||||
{
|
||||
std::vector<Search::InputInfo> ret {};
|
||||
std::vector<Search::InputInfo> search_inputs{};
|
||||
|
||||
auto& tabs_list = wxGetApp().tabs_list;
|
||||
auto print_tech = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology();
|
||||
for (auto tab : tabs_list)
|
||||
if (tab->supports_printer_technology(print_tech))
|
||||
ret.emplace_back(Search::InputInfo {tab->get_config(), tab->type(), mode});
|
||||
search_inputs.emplace_back(Search::InputInfo{ tab->get_config(), tab->type() });
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Sidebar::update_searcher()
|
||||
{
|
||||
p->searcher.init(get_search_inputs(m_mode));
|
||||
p->searcher.check_and_update(wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology(),
|
||||
respect_mode ? m_mode : comExpert, search_inputs);
|
||||
}
|
||||
|
||||
void Sidebar::update_mode()
|
||||
@ -1518,7 +1514,6 @@ void Sidebar::update_mode()
|
||||
|
||||
update_reslice_btn_tooltip();
|
||||
update_mode_sizer();
|
||||
update_searcher();
|
||||
|
||||
wxWindowUpdateLocker noUpdates(this);
|
||||
|
||||
@ -1581,6 +1576,8 @@ Search::OptionsSearcher& Sidebar::get_searcher()
|
||||
|
||||
std::string& Sidebar::get_search_line()
|
||||
{
|
||||
// update searcher before show imGui search dialog on the plater, if printer technology or mode was changed
|
||||
check_and_update_searcher(true);
|
||||
return p->searcher.search_string();
|
||||
}
|
||||
|
||||
@ -1724,8 +1721,11 @@ struct Plater::priv
|
||||
res = (act == "1") ? wxID_YES : wxID_NO;
|
||||
|
||||
if (res == wxID_YES)
|
||||
if (!mainframe->save_project_as(project_name))
|
||||
res = wxID_CANCEL;
|
||||
if (!mainframe->save_project_as(project_name)) {
|
||||
// Return Cancel only, when we don't remember a choice for closing the application.
|
||||
// Elsewhere it can causes an impossibility to close the application at all.
|
||||
res = act.empty() ? wxID_CANCEL : wxID_NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@ -2407,7 +2407,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
|
||||
const auto loading = _L("Loading") + dots;
|
||||
wxProgressDialog progress_dlg(loading, "", 100, find_toplevel_parent(q), wxPD_AUTO_HIDE);
|
||||
|
||||
// Create wxProgressDialog on heap, see the linux ifdef below.
|
||||
auto progress_dlg = new wxProgressDialog(loading, "", 100, find_toplevel_parent(q), wxPD_AUTO_HIDE);
|
||||
Slic3r::ScopeGuard([&progress_dlg](){ if (progress_dlg) progress_dlg->Destroy(); progress_dlg = nullptr; });
|
||||
|
||||
wxBusyCursor busy;
|
||||
|
||||
auto *new_model = (!load_model || one_by_one) ? nullptr : new Slic3r::Model();
|
||||
@ -2427,8 +2431,10 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
const auto &path = input_files[i];
|
||||
#endif // _WIN32
|
||||
const auto filename = path.filename();
|
||||
progress_dlg.Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())), _L("Loading file") + ": " + from_path(filename));
|
||||
progress_dlg.Fit();
|
||||
if (progress_dlg) {
|
||||
progress_dlg->Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())), _L("Loading file") + ": " + from_path(filename));
|
||||
progress_dlg->Fit();
|
||||
}
|
||||
|
||||
const bool type_3mf = std::regex_match(path.string(), pattern_3mf);
|
||||
const bool type_zip_amf = !type_3mf && std::regex_match(path.string(), pattern_zip_amf);
|
||||
@ -2446,8 +2452,10 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
// then related SLA Print and Materials Settings or FFF Print and Filaments Settings will be unparent from the wxNoteBook
|
||||
// and that is why they will never be enabled after destruction of the ProgressDialog.
|
||||
// So, distroy progress_gialog if we are loading project file
|
||||
if (input_files_size == 1)
|
||||
progress_dlg.Destroy();
|
||||
if (input_files_size == 1 && progress_dlg) {
|
||||
progress_dlg->Destroy();
|
||||
progress_dlg = nullptr;
|
||||
}
|
||||
#endif
|
||||
DynamicPrintConfig config;
|
||||
PrinterTechnology loaded_printer_technology {ptFFF};
|
||||
@ -5428,7 +5436,7 @@ void Plater::load_gcode(const wxString& filename)
|
||||
if (p->preview->get_canvas3d()->get_gcode_layers_zs().empty()) {
|
||||
//wxMessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."),
|
||||
MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."),
|
||||
wxString(GCODEVIEWER_APP_NAME) + " - " + _L("Error while loading .gcode file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal();
|
||||
wxString(GCODEVIEWER_APP_NAME) + " - " + _L("Error while loading .gcode file"), wxOK | wxICON_WARNING | wxCENTRE).ShowModal();
|
||||
set_project_filename(wxEmptyString);
|
||||
}
|
||||
else
|
||||
@ -5840,6 +5848,10 @@ void Plater::convert_unit(ConversionType conv_type)
|
||||
if (obj_idxs.empty() && volume_idxs.empty())
|
||||
return;
|
||||
|
||||
// We will remove object indexes after convertion
|
||||
// So, resort object indexes descending to avoid the crash after remove
|
||||
std::sort(obj_idxs.begin(), obj_idxs.end(), std::greater<int>());
|
||||
|
||||
TakeSnapshot snapshot(this, conv_type == ConversionType::CONV_FROM_INCH ? _L("Convert from imperial units") :
|
||||
conv_type == ConversionType::CONV_TO_INCH ? _L("Revert conversion from imperial units") :
|
||||
conv_type == ConversionType::CONV_FROM_METER ? _L("Convert from meters") : _L("Revert conversion from meters"));
|
||||
@ -6515,8 +6527,6 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
||||
p->config->set_key_value(opt_key, config.option(opt_key)->clone());
|
||||
if (opt_key == "printer_technology") {
|
||||
this->set_printer_technology(config.opt_enum<PrinterTechnology>(opt_key));
|
||||
// print technology is changed, so we should to update a search list
|
||||
p->sidebar->update_searcher();
|
||||
p->sidebar->show_sliced_info_sizer(false);
|
||||
p->reset_gcode_toolpaths();
|
||||
p->view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
@ -6765,8 +6775,6 @@ bool Plater::set_printer_technology(PrinterTechnology printer_technology)
|
||||
|
||||
p->update_main_toolbar_tooltips();
|
||||
|
||||
p->sidebar->get_searcher().set_printer_technology(printer_technology);
|
||||
|
||||
p->notification_manager->set_fff(printer_technology == ptFFF);
|
||||
p->notification_manager->set_slicing_progress_hidden();
|
||||
|
||||
@ -6930,8 +6938,10 @@ void Plater::search(bool plater_is_active)
|
||||
evt.SetControlDown(true);
|
||||
canvas3D()->on_char(evt);
|
||||
}
|
||||
else
|
||||
else {
|
||||
p->sidebar->check_and_update_searcher(true);
|
||||
p->sidebar->get_searcher().show_dialog();
|
||||
}
|
||||
}
|
||||
|
||||
void Plater::msw_rescale()
|
||||
|
@ -113,7 +113,7 @@ public:
|
||||
void update_mode();
|
||||
bool is_collapsed();
|
||||
void collapse(bool collapse);
|
||||
void update_searcher();
|
||||
void check_and_update_searcher(bool respect_mode = false);
|
||||
void update_ui_from_settings();
|
||||
|
||||
#ifdef _MSW_DARK_MODE
|
||||
|
@ -78,7 +78,7 @@ static std::string get_key(const std::string& opt_key, Preset::Type type)
|
||||
return std::to_string(int(type)) + ";" + opt_key;
|
||||
}
|
||||
|
||||
void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode)
|
||||
void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type type)
|
||||
{
|
||||
auto emplace = [this, type](const std::string key, const wxString& label)
|
||||
{
|
||||
@ -299,30 +299,18 @@ OptionsSearcher::~OptionsSearcher()
|
||||
{
|
||||
}
|
||||
|
||||
void OptionsSearcher::init(std::vector<InputInfo> input_values)
|
||||
void OptionsSearcher::check_and_update(PrinterTechnology pt_in, ConfigOptionMode mode_in, std::vector<InputInfo> input_values)
|
||||
{
|
||||
options.clear();
|
||||
for (auto i : input_values)
|
||||
append_options(i.config, i.type, i.mode);
|
||||
|
||||
options.insert(options.end(), preferences_options.begin(), preferences_options.end());
|
||||
|
||||
sort_options();
|
||||
|
||||
search(search_line, true);
|
||||
}
|
||||
|
||||
void OptionsSearcher::apply(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode)
|
||||
{
|
||||
if (options.empty())
|
||||
if (printer_technology == pt_in && mode == mode_in)
|
||||
return;
|
||||
|
||||
options.erase(std::remove_if(options.begin(), options.end(), [type](Option opt) {
|
||||
return opt.type == type;
|
||||
}), options.end());
|
||||
options.clear();
|
||||
|
||||
append_options(config, type, mode);
|
||||
printer_technology = pt_in;
|
||||
mode = mode_in;
|
||||
|
||||
for (auto i : input_values)
|
||||
append_options(i.config, i.type);
|
||||
sort_options();
|
||||
|
||||
search(search_line, true);
|
||||
|
@ -33,7 +33,6 @@ struct InputInfo
|
||||
{
|
||||
DynamicPrintConfig* config {nullptr};
|
||||
Preset::Type type {Preset::TYPE_INVALID};
|
||||
ConfigOptionMode mode {comSimple};
|
||||
};
|
||||
|
||||
struct GroupAndCategory {
|
||||
@ -83,13 +82,14 @@ class OptionsSearcher
|
||||
{
|
||||
std::string search_line;
|
||||
std::map<std::string, GroupAndCategory> groups_and_categories;
|
||||
PrinterTechnology printer_technology;
|
||||
PrinterTechnology printer_technology {ptAny};
|
||||
ConfigOptionMode mode{ comUndef };
|
||||
|
||||
std::vector<Option> options {};
|
||||
std::vector<Option> preferences_options {};
|
||||
std::vector<FoundOption> found {};
|
||||
|
||||
void append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode);
|
||||
void append_options(DynamicPrintConfig* config, Preset::Type type);
|
||||
|
||||
void sort_options() {
|
||||
std::sort(options.begin(), options.end(), [](const Option& o1, const Option& o2) {
|
||||
@ -111,12 +111,11 @@ public:
|
||||
OptionsSearcher();
|
||||
~OptionsSearcher();
|
||||
|
||||
void init(std::vector<InputInfo> input_values);
|
||||
void apply(DynamicPrintConfig *config,
|
||||
Preset::Type type,
|
||||
ConfigOptionMode mode);
|
||||
void append_preferences_option(const GUI::Line& opt_line);
|
||||
void append_preferences_options(const std::vector<GUI::Line>& opt_lines);
|
||||
void check_and_update( PrinterTechnology pt_in,
|
||||
ConfigOptionMode mode_in,
|
||||
std::vector<InputInfo> input_values);
|
||||
bool search();
|
||||
bool search(const std::string& search, bool force = false);
|
||||
|
||||
@ -133,8 +132,6 @@ public:
|
||||
const GroupAndCategory& get_group_and_category (const std::string& opt_key) { return groups_and_categories[opt_key]; }
|
||||
std::string& search_string() { return search_line; }
|
||||
|
||||
void set_printer_technology(PrinterTechnology pt) { printer_technology = pt; }
|
||||
|
||||
void sort_options_by_key() {
|
||||
std::sort(options.begin(), options.end(), [](const Option& o1, const Option& o2) {
|
||||
return o1.key < o2.key; });
|
||||
|
@ -1191,11 +1191,6 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category)
|
||||
m_highlighter.init(get_custom_ctrl_with_blinking_ptr(opt_key));
|
||||
}
|
||||
|
||||
void Tab::apply_searcher()
|
||||
{
|
||||
wxGetApp().sidebar().get_searcher().apply(m_config, m_type, m_mode);
|
||||
}
|
||||
|
||||
void Tab::cache_config_diff(const std::vector<std::string>& selected_options)
|
||||
{
|
||||
m_cache_config.apply_only(m_presets->get_edited_preset().config, selected_options);
|
||||
@ -2836,9 +2831,6 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
|
||||
|
||||
// Reload preset pages with current configuration values
|
||||
reload_config();
|
||||
|
||||
// apply searcher with current configuration
|
||||
apply_searcher();
|
||||
}
|
||||
|
||||
// this gets executed after preset is loaded and before GUI fields are updated
|
||||
|
@ -377,7 +377,6 @@ public:
|
||||
|
||||
void update_wiping_button_visibility();
|
||||
void activate_option(const std::string& opt_key, const wxString& category);
|
||||
void apply_searcher();
|
||||
void cache_config_diff(const std::vector<std::string>& selected_options);
|
||||
void apply_config_from_cache();
|
||||
|
||||
|
@ -1243,6 +1243,8 @@ void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent
|
||||
|
||||
void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* presets_)
|
||||
{
|
||||
// update searcher befofre update of tree
|
||||
wxGetApp().sidebar().check_and_update_searcher();
|
||||
Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher();
|
||||
searcher.sort_options_by_key();
|
||||
|
||||
@ -1298,9 +1300,6 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres
|
||||
get_string_value(opt_key, old_config), get_string_value(opt_key, new_config), category_icon_map.at(option.category));
|
||||
}
|
||||
}
|
||||
|
||||
// Revert sort of searcher back
|
||||
searcher.sort_options_by_label();
|
||||
}
|
||||
|
||||
void UnsavedChangesDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
@ -1606,6 +1605,8 @@ void DiffPresetDialog::update_presets(Preset::Type type)
|
||||
|
||||
void DiffPresetDialog::update_tree()
|
||||
{
|
||||
// update searcher befofre update of tree
|
||||
wxGetApp().sidebar().check_and_update_searcher();
|
||||
Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher();
|
||||
searcher.sort_options_by_key();
|
||||
|
||||
@ -1708,9 +1709,6 @@ void DiffPresetDialog::update_tree()
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
// Revert sort of searcher back
|
||||
searcher.sort_options_by_label();
|
||||
}
|
||||
|
||||
void DiffPresetDialog::on_dpi_changed(const wxRect&)
|
||||
|
59
t/geometry.t
59
t/geometry.t
@ -2,7 +2,7 @@ use Test::More;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 42;
|
||||
plan tests => 30;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
@ -189,63 +189,6 @@ my $polygons = [
|
||||
is +Slic3r::Point->new(10, 0)->distance_to_line($line), 0, 'distance_to';
|
||||
}
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $square = Slic3r::Polygon->new_scale(
|
||||
[100,100],
|
||||
[200,100],
|
||||
[200,200],
|
||||
[100,200],
|
||||
);
|
||||
is scalar(@{$square->concave_points(PI*4/3)}), 0, 'no concave vertices detected in ccw square';
|
||||
is scalar(@{$square->convex_points(PI*2/3)}), 4, 'four convex vertices detected in ccw square';
|
||||
|
||||
$square->make_clockwise;
|
||||
is scalar(@{$square->concave_points(PI*4/3)}), 4, 'fuor concave vertices detected in cw square';
|
||||
is scalar(@{$square->convex_points(PI*2/3)}), 0, 'no convex vertices detected in cw square';
|
||||
}
|
||||
|
||||
{
|
||||
my $square = Slic3r::Polygon->new_scale(
|
||||
[150,100],
|
||||
[200,100],
|
||||
[200,200],
|
||||
[100,200],
|
||||
[100,100],
|
||||
);
|
||||
is scalar(@{$square->concave_points(PI*4/3)}), 0, 'no concave vertices detected in convex polygon';
|
||||
is scalar(@{$square->convex_points(PI*2/3)}), 4, 'four convex vertices detected in square';
|
||||
}
|
||||
|
||||
{
|
||||
my $square = Slic3r::Polygon->new_scale(
|
||||
[200,200],
|
||||
[100,200],
|
||||
[100,100],
|
||||
[150,100],
|
||||
[200,100],
|
||||
);
|
||||
is scalar(@{$square->concave_points(PI*4/3)}), 0, 'no concave vertices detected in convex polygon';
|
||||
is scalar(@{$square->convex_points(PI*2/3)}), 4, 'four convex vertices detected in square';
|
||||
}
|
||||
|
||||
{
|
||||
my $triangle = Slic3r::Polygon->new(
|
||||
[16000170,26257364], [714223,461012], [31286371,461008],
|
||||
);
|
||||
is scalar(@{$triangle->concave_points(PI*4/3)}), 0, 'no concave vertices detected in triangle';
|
||||
is scalar(@{$triangle->convex_points(PI*2/3)}), 3, 'three convex vertices detected in triangle';
|
||||
}
|
||||
|
||||
{
|
||||
my $triangle = Slic3r::Polygon->new(
|
||||
[16000170,26257364], [714223,461012], [20000000,461012], [31286371,461012],
|
||||
);
|
||||
is scalar(@{$triangle->concave_points(PI*4/3)}), 0, 'no concave vertices detected in triangle having collinear point';
|
||||
is scalar(@{$triangle->convex_points(PI*2/3)}), 3, 'three convex vertices detected in triangle having collinear point';
|
||||
}
|
||||
|
||||
{
|
||||
my $triangle = Slic3r::Polygon->new(
|
||||
[16000170,26257364], [714223,461012], [31286371,461008],
|
||||
|
@ -223,7 +223,7 @@ use Slic3r::Test;
|
||||
|
||||
if ($model eq 'cube_with_concave_hole') {
|
||||
# check that loop starts at a concave vertex
|
||||
my $ccw_angle = $loop->first_point->ccw_angle(@$loop[-2,1]);
|
||||
my $ccw_angle = $loop->[-2]->ccw($loop->first_point, $loop->[1]);
|
||||
my $convex = ($ccw_angle > PI); # whether the angle on the *right* side is convex
|
||||
$starts_on_convex_point = 1
|
||||
if ($convex && $is_contour) || (!$convex && $is_hole);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <libslic3r/ModelArrange.hpp>
|
||||
|
||||
@ -286,7 +287,7 @@ std::string gcode(Print & print)
|
||||
print.set_status_silent();
|
||||
print.process();
|
||||
print.export_gcode(temp.string(), nullptr, nullptr);
|
||||
std::ifstream t(temp.string());
|
||||
boost::nowide::ifstream t(temp.string());
|
||||
std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
boost::nowide::remove(temp.string().c_str());
|
||||
return str;
|
||||
|
@ -8,6 +8,7 @@ add_executable(${_TEST_NAME}_tests
|
||||
test_clipper_utils.cpp
|
||||
test_color.cpp
|
||||
test_config.cpp
|
||||
test_curve_fitting.cpp
|
||||
test_elephant_foot_compensation.cpp
|
||||
test_geometry.cpp
|
||||
test_placeholder_parser.cpp
|
||||
|
118
tests/libslic3r/test_curve_fitting.cpp
Normal file
118
tests/libslic3r/test_curve_fitting.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <test_utils.hpp>
|
||||
|
||||
#include <libslic3r/Geometry/Curves.hpp>
|
||||
#include <libslic3r/Utils.hpp>
|
||||
#include <libslic3r/SVG.hpp>
|
||||
|
||||
TEST_CASE("Curves: cubic b spline fit test", "[Curves]") {
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Geometry;
|
||||
|
||||
auto fx = [&](size_t index) {
|
||||
return float(index) / 200.0f;
|
||||
};
|
||||
|
||||
auto fy = [&](size_t index) {
|
||||
return 1.0f;
|
||||
};
|
||||
|
||||
std::vector<Vec<1, float>> observations { };
|
||||
std::vector<float> observation_points { };
|
||||
std::vector<float> weights { };
|
||||
for (size_t index = 0; index < 200; ++index) {
|
||||
observations.push_back(Vec<1, float> { fy(index) });
|
||||
observation_points.push_back(fx(index));
|
||||
weights.push_back(1);
|
||||
}
|
||||
|
||||
Vec2f fmin { fx(0), fy(0) };
|
||||
Vec2f fmax { fx(200), fy(200) };
|
||||
|
||||
auto bspline = fit_cubic_bspline(observations, observation_points, weights, 1);
|
||||
|
||||
Approx ap(1.0f);
|
||||
ap.epsilon(0.1f);
|
||||
|
||||
for (int p = 0; p < 200; ++p) {
|
||||
float fitted_val = bspline.get_fitted_value(fx(p))(0);
|
||||
float expected = fy(p);
|
||||
|
||||
REQUIRE(fitted_val == ap(expected));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Curves: quadratic f cubic b spline fit test", "[Curves]") {
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Geometry;
|
||||
|
||||
auto fx = [&](size_t index) {
|
||||
return float(index) / 100.0f;
|
||||
};
|
||||
|
||||
auto fy = [&](size_t index) {
|
||||
return (fx(index) - 1) * (fx(index) - 1);
|
||||
};
|
||||
|
||||
std::vector<Vec<1, float>> observations { };
|
||||
std::vector<float> observation_points { };
|
||||
std::vector<float> weights { };
|
||||
for (size_t index = 0; index < 200; ++index) {
|
||||
observations.push_back(Vec<1, float> { fy(index) });
|
||||
observation_points.push_back(fx(index));
|
||||
weights.push_back(1);
|
||||
}
|
||||
|
||||
Vec2f fmin { fx(0), fy(0) };
|
||||
Vec2f fmax { fx(200), fy(200) };
|
||||
|
||||
auto bspline = fit_cubic_bspline(observations, observation_points, weights, 10);
|
||||
|
||||
for (int p = 0; p < 200; ++p) {
|
||||
float fitted_val = bspline.get_fitted_value(fx(p))(0);
|
||||
float expected = fy(p);
|
||||
|
||||
auto check = [](float a, float b) {
|
||||
return abs(a - b) < 0.2f;
|
||||
};
|
||||
//Note: checking is problematic, splines will not perfectly align
|
||||
REQUIRE(check(fitted_val, expected));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Curves: polynomial fit test", "[Curves]") {
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Geometry;
|
||||
|
||||
auto fx = [&](size_t index) {
|
||||
return float(index) / 100.0f;
|
||||
};
|
||||
|
||||
auto fy = [&](size_t index) {
|
||||
return (fx(index) - 1) * (fx(index) - 1);
|
||||
};
|
||||
|
||||
std::vector<Vec<1, float>> observations { };
|
||||
std::vector<float> observation_points { };
|
||||
std::vector<float> weights { };
|
||||
for (size_t index = 0; index < 200; ++index) {
|
||||
observations.push_back(Vec<1, float> { fy(index) });
|
||||
observation_points.push_back(fx(index));
|
||||
weights.push_back(1);
|
||||
}
|
||||
|
||||
Vec2f fmin { fx(0), fy(0) };
|
||||
Vec2f fmax { fx(200), fy(200) };
|
||||
|
||||
Approx ap(1.0f);
|
||||
ap.epsilon(0.1f);
|
||||
|
||||
auto poly = fit_polynomial(observations, observation_points, weights, 2);
|
||||
|
||||
REQUIRE(poly.coefficients(0, 0) == ap(1));
|
||||
REQUIRE(poly.coefficients(0, 1) == ap(-2));
|
||||
REQUIRE(poly.coefficients(0, 2) == ap(1));
|
||||
}
|
||||
|
@ -373,7 +373,43 @@ SCENARIO("Line distances", "[Geometry]"){
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Calculating angles", "[Geometry]")
|
||||
{
|
||||
GIVEN(("Vectors 30 degrees apart"))
|
||||
{
|
||||
std::vector<std::pair<Point, Point>> pts {
|
||||
{ {1000, 0}, { 866, 500 } },
|
||||
{ { 866, 500 }, { 500, 866 } },
|
||||
{ { 500, 866 }, { 0, 1000 } },
|
||||
{ { -500, 866 }, { -866, 500 } }
|
||||
};
|
||||
|
||||
THEN("Angle detected is 30 degrees")
|
||||
{
|
||||
for (auto &p : pts)
|
||||
REQUIRE(is_approx(angle(p.first, p.second), M_PI / 6.));
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN(("Vectors 30 degrees apart"))
|
||||
{
|
||||
std::vector<std::pair<Point, Point>> pts {
|
||||
{ { 866, 500 }, {1000, 0} },
|
||||
{ { 500, 866 }, { 866, 500 } },
|
||||
{ { 0, 1000 }, { 500, 866 } },
|
||||
{ { -866, 500 }, { -500, 866 } }
|
||||
};
|
||||
|
||||
THEN("Angle detected is -30 degrees")
|
||||
{
|
||||
for (auto &p : pts)
|
||||
REQUIRE(is_approx(angle(p.first, p.second), - M_PI / 6.));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
static constexpr const double angle_threshold = M_PI / 3.;
|
||||
GIVEN(("A Square with dimension 100")){
|
||||
auto square = Slic3r::Polygon /*new_scale*/(std::vector<Point>({
|
||||
Point(100,100),
|
||||
@ -381,13 +417,13 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
Point(200,200),
|
||||
Point(100,200)}));
|
||||
THEN("It has 4 convex points counterclockwise"){
|
||||
REQUIRE(square.concave_points(PI*4/3).size() == 0);
|
||||
REQUIRE(square.convex_points(PI*2/3).size() == 4);
|
||||
REQUIRE(square.concave_points(angle_threshold).size() == 0);
|
||||
REQUIRE(square.convex_points(angle_threshold).size() == 4);
|
||||
}
|
||||
THEN("It has 4 concave points clockwise"){
|
||||
square.make_clockwise();
|
||||
REQUIRE(square.concave_points(PI*4/3).size() == 4);
|
||||
REQUIRE(square.convex_points(PI*2/3).size() == 0);
|
||||
REQUIRE(square.concave_points(angle_threshold).size() == 4);
|
||||
REQUIRE(square.convex_points(angle_threshold).size() == 0);
|
||||
}
|
||||
}
|
||||
GIVEN("A Square with an extra colinearvertex"){
|
||||
@ -398,8 +434,8 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
Point(100,200),
|
||||
Point(100,100)}));
|
||||
THEN("It has 4 convex points counterclockwise"){
|
||||
REQUIRE(square.concave_points(PI*4/3).size() == 0);
|
||||
REQUIRE(square.convex_points(PI*2/3).size() == 4);
|
||||
REQUIRE(square.concave_points(angle_threshold).size() == 0);
|
||||
REQUIRE(square.convex_points(angle_threshold).size() == 4);
|
||||
}
|
||||
}
|
||||
GIVEN("A Square with an extra collinear vertex in different order"){
|
||||
@ -410,8 +446,8 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
Point(150,100),
|
||||
Point(200,100)}));
|
||||
THEN("It has 4 convex points counterclockwise"){
|
||||
REQUIRE(square.concave_points(PI*4/3).size() == 0);
|
||||
REQUIRE(square.convex_points(PI*2/3).size() == 4);
|
||||
REQUIRE(square.concave_points(angle_threshold).size() == 0);
|
||||
REQUIRE(square.convex_points(angle_threshold).size() == 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,8 +458,8 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
Point(31286371,461008)
|
||||
}));
|
||||
THEN("it has three convex vertices"){
|
||||
REQUIRE(triangle.concave_points(PI*4/3).size() == 0);
|
||||
REQUIRE(triangle.convex_points(PI*2/3).size() == 3);
|
||||
REQUIRE(triangle.concave_points(angle_threshold).size() == 0);
|
||||
REQUIRE(triangle.convex_points(angle_threshold).size() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,8 +471,8 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
Point(31286371,461012)
|
||||
}));
|
||||
THEN("it has three convex vertices"){
|
||||
REQUIRE(triangle.concave_points(PI*4/3).size() == 0);
|
||||
REQUIRE(triangle.convex_points(PI*2/3).size() == 3);
|
||||
REQUIRE(triangle.concave_points(angle_threshold).size() == 0);
|
||||
REQUIRE(triangle.convex_points(angle_threshold).size() == 3);
|
||||
}
|
||||
}
|
||||
GIVEN("A polygon with concave vertices with angles of specifically 4/3pi"){
|
||||
@ -453,8 +489,8 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){
|
||||
Point(38092663,692699),Point(52100125,692699)
|
||||
}));
|
||||
THEN("the correct number of points are detected"){
|
||||
REQUIRE(polygon.concave_points(PI*4/3).size() == 6);
|
||||
REQUIRE(polygon.convex_points(PI*2/3).size() == 10);
|
||||
REQUIRE(polygon.concave_points(angle_threshold).size() == 6);
|
||||
REQUIRE(polygon.convex_points(angle_threshold).size() == 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp
|
||||
sla_test_utils.hpp sla_test_utils.cpp
|
||||
sla_supptgen_tests.cpp
|
||||
sla_raycast_tests.cpp
|
||||
sla_archive_export_tests.cpp)
|
||||
sla_archive_readwrite_tests.cpp)
|
||||
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
||||
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <test_utils.hpp>
|
||||
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Format/SLAArchive.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
TEST_CASE("Archive export test", "[sla_archives]") {
|
||||
constexpr const char *PNAME = "20mm_cube";
|
||||
|
||||
for (auto &archname : SLAArchive::registered_archives()) {
|
||||
INFO(std::string("Testing archive type: ") + archname);
|
||||
SLAPrint print;
|
||||
SLAFullPrintConfig fullcfg;
|
||||
|
||||
auto m = Model::read_from_file(TEST_DATA_DIR PATH_SEPARATOR + std::string(PNAME) + ".obj", nullptr);
|
||||
|
||||
fullcfg.set("sla_archive_format", archname);
|
||||
fullcfg.set("supports_enable", false);
|
||||
fullcfg.set("pad_enable", false);
|
||||
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.apply(fullcfg);
|
||||
|
||||
print.set_status_callback([](const PrintBase::SlicingStatus&) {});
|
||||
print.apply(m, cfg);
|
||||
print.process();
|
||||
|
||||
ThumbnailsList thumbnails;
|
||||
auto outputfname = std::string("output.") + SLAArchive::get_extension(archname);
|
||||
|
||||
print.export_print(outputfname, thumbnails, PNAME);
|
||||
|
||||
// Not much can be checked about the archives...
|
||||
REQUIRE(boost::filesystem::exists(outputfname));
|
||||
}
|
||||
}
|
71
tests/sla_print/sla_archive_readwrite_tests.cpp
Normal file
71
tests/sla_print/sla_archive_readwrite_tests.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <test_utils.hpp>
|
||||
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/Format/SLAArchiveWriter.hpp"
|
||||
#include "libslic3r/Format/SLAArchiveReader.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
TEST_CASE("Archive export test", "[sla_archives]") {
|
||||
for (const char * pname : {"20mm_cube", "extruder_idler"})
|
||||
for (auto &archname : SLAArchiveWriter::registered_archives()) {
|
||||
INFO(std::string("Testing archive type: ") + archname + " -- writing...");
|
||||
SLAPrint print;
|
||||
SLAFullPrintConfig fullcfg;
|
||||
|
||||
auto m = Model::read_from_file(TEST_DATA_DIR PATH_SEPARATOR + std::string(pname) + ".obj", nullptr);
|
||||
|
||||
fullcfg.printer_technology.setInt(ptSLA); // FIXME this should be ensured
|
||||
fullcfg.set("sla_archive_format", archname);
|
||||
fullcfg.set("supports_enable", false);
|
||||
fullcfg.set("pad_enable", false);
|
||||
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.apply(fullcfg);
|
||||
|
||||
print.set_status_callback([](const PrintBase::SlicingStatus&) {});
|
||||
print.apply(m, cfg);
|
||||
print.process();
|
||||
|
||||
ThumbnailsList thumbnails;
|
||||
auto outputfname = std::string("output_") + pname + "." + SLAArchiveWriter::get_extension(archname);
|
||||
|
||||
print.export_print(outputfname, thumbnails, pname);
|
||||
|
||||
// Not much can be checked about the archives...
|
||||
REQUIRE(boost::filesystem::exists(outputfname));
|
||||
|
||||
double vol_written = m.mesh().volume();
|
||||
|
||||
auto readable_formats = SLAArchiveReader::registered_archives();
|
||||
if (std::any_of(readable_formats.begin(), readable_formats.end(),
|
||||
[&archname](const std::string &a) { return a == archname; })) {
|
||||
|
||||
INFO(std::string("Testing archive type: ") + archname + " -- reading back...");
|
||||
|
||||
indexed_triangle_set its;
|
||||
DynamicPrintConfig cfg;
|
||||
|
||||
try {
|
||||
// Leave format_id deliberetaly empty, guessing should always
|
||||
// work here.
|
||||
import_sla_archive(outputfname, "", its, cfg);
|
||||
} catch (...) {
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
// its_write_obj(its, (outputfname + ".obj").c_str());
|
||||
|
||||
REQUIRE(!cfg.empty());
|
||||
REQUIRE(!its.empty());
|
||||
|
||||
double vol_read = its_volume(its);
|
||||
double rel_err = std::abs(vol_written - vol_read) / vol_written;
|
||||
REQUIRE(rel_err < 0.1);
|
||||
}
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@
|
||||
Clone<Point> normal();
|
||||
Clone<Point> vector();
|
||||
double ccw(Point* point)
|
||||
%code{% RETVAL = THIS->ccw(*point); %};
|
||||
%code{% RETVAL = cross2((THIS->a - *point).cast<double>(), (THIS->b - THIS->a).cast<double>()); %};
|
||||
%{
|
||||
|
||||
Line*
|
||||
|
@ -39,13 +39,7 @@
|
||||
double perp_distance_to_line(Line* line)
|
||||
%code{% RETVAL = line->perp_distance_to(*THIS); %};
|
||||
double ccw(Point* p1, Point* p2)
|
||||
%code{% RETVAL = THIS->ccw(*p1, *p2); %};
|
||||
double ccw_angle(Point* p1, Point* p2)
|
||||
%code{% RETVAL = THIS->ccw_angle(*p1, *p2); %};
|
||||
Point* projection_onto_polygon(Polygon* polygon)
|
||||
%code{% RETVAL = new Point(THIS->projection_onto(*polygon)); %};
|
||||
Point* projection_onto_polyline(Polyline* polyline)
|
||||
%code{% RETVAL = new Point(THIS->projection_onto(*polyline)); %};
|
||||
%code{% RETVAL = cross2((*p1 - *THIS).cast<double>(), (*p2 - *p1).cast<double>()); %};
|
||||
Point* projection_onto_line(Line* line)
|
||||
%code{% RETVAL = new Point(THIS->projection_onto(*line)); %};
|
||||
Point* negative()
|
||||
|
@ -39,8 +39,6 @@
|
||||
%code{% THIS->triangulate_convex(&RETVAL); %};
|
||||
Clone<Point> centroid();
|
||||
Clone<BoundingBox> bounding_box();
|
||||
Points concave_points(double angle);
|
||||
Points convex_points(double angle);
|
||||
Clone<Point> point_projection(Point* point)
|
||||
%code{% RETVAL = THIS->point_projection(*point); %};
|
||||
Clone<Point> intersection(Line* line)
|
||||
|
Loading…
Reference in New Issue
Block a user