Merge branch 'master' into fs_emboss

# Conflicts:
#	src/slic3r/GUI/GLCanvas3D.cpp
#	src/slic3r/GUI/Selection.cpp
This commit is contained in:
Filip Sykala - NTB T15p 2022-09-14 11:28:36 +02:00
commit ed6a1b18f3
115 changed files with 19036 additions and 16206 deletions

View file

@ -46,7 +46,7 @@ BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 78
ColumnLimit: 140
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true

4
resources/icons/edit.svg Normal file
View file

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.2923 1.34808L38.2441 1.30417C37.3235 0.463194 36.1301 0 34.8837 0C33.4864 0 32.1449 0.591489 31.2029 1.62267L13.3916 21.1224C13.2293 21.3002 13.1061 21.5099 13.03 21.7381L10.9357 28.0167C10.6935 28.7426 10.815 29.5453 11.2607 30.164C11.7099 30.7875 12.4336 31.1598 13.1967 31.1598H13.1968C13.5269 31.1598 13.8495 31.0919 14.1555 30.958L20.2195 28.3052C20.44 28.2087 20.6377 28.0671 20.8 27.8894L38.6114 8.38977C40.4648 6.36078 40.3219 3.20211 38.2923 1.34808ZM14.9484 26.8569L16.1773 23.1726L16.281 23.0591L18.6102 25.1866L18.5066 25.3001L14.9484 26.8569ZM36.0718 6.07002L20.93 22.6472L18.6007 20.5197L33.7426 3.94242C34.0387 3.61819 34.444 3.43956 34.8838 3.43956C35.2696 3.43956 35.6391 3.5831 35.9251 3.84428L35.9731 3.88819C36.6019 4.46248 36.6461 5.44127 36.0718 6.07002V6.07002Z" fill="#ED6B21"/>
<path d="M34.8369 15.8664C33.8871 15.8664 33.1171 16.6364 33.1171 17.5862V32.1868C33.1171 34.5984 31.155 36.5604 28.7435 36.5604H7.89985C5.48815 36.5604 3.52623 34.5984 3.52623 32.1868V11.5125C3.52623 9.10094 5.48826 7.1389 7.89985 7.1389H22.9865C23.9363 7.1389 24.7063 6.3689 24.7063 5.41912C24.7063 4.46934 23.9363 3.69934 22.9865 3.69934H7.89985C3.59158 3.69934 0.0866699 7.20437 0.0866699 11.5125V32.1867C0.0866699 36.4949 3.59169 39.9999 7.89985 39.9999H28.7433C33.0515 39.9999 36.5565 36.4949 36.5565 32.1867V17.5862C36.5566 16.6364 35.7866 15.8664 34.8369 15.8664V15.8664Z" fill="#808080"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2135,8 +2135,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "Vyberte jeden nebo více souborů (STL, OBJ):"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "Vyberte jeden nebo více souborů (STL/OBJ/AMF/3MF/PRUSA):"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "Vyberte jeden nebo více souborů (STL/3MF/STEP/OBJ/AMF/PRUSA):"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -6044,12 +6044,13 @@ msgid "Import STL (Imperial Units)"
msgstr "Importovat STL (imperiální jednotky)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "Importovat STL/OBJ/AM&F/3MF"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "Importovat STL/3MF/STEP/OBJ/AM&F"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgstr "Importovat STL/OBJ/AMF/3MF bez konfigurace, zachová stávající podložku"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr ""
"Importovat STL/3MF/STEP/OBJ/AMF bez konfigurace, zachová stávající podložku"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8227,9 +8228,8 @@ msgid "Open new instance"
msgstr "Otevřít novou instanci"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr ""
"Otevřít projekt STL/OBJ/AMF/3MF s konfigurací, odstranit modely na podložce"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "Otevřít projekt AMF/3MF s konfigurací, odstranit modely na podložce"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

View file

@ -2130,8 +2130,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "Wählen Sie eine oder mehrere Dateien (STL, OBJ):"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "Wählen Sie eine oder mehrere Dateien (STL/OBJ/AMF/3MF/PRUSA):"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "Wählen Sie eine oder mehrere Dateien (STL/3MF/STEP/OBJ/AMF/PRUSA):"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -6141,13 +6141,13 @@ msgid "Import STL (Imperial Units)"
msgstr "STL importieren (imperiale Einheiten)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "Importiere STL/OBJ/AM&F/3MF"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "Importiere STL/3MF/STEP/OBJ/AM&F"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr ""
"Importiere STL/OBJ/AMF/3MF mit Konfigurationsdaten, Druckplatte beibehalten"
"Importiere STL/3MF/STEP/OBJ/AMF mit Konfigurationsdaten, Druckplatte beibehalten"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8357,8 +8357,8 @@ msgid "Open new instance"
msgstr "Neue Instanz öffnen"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr "Öffne Projekt STL/OBJ/AMF/3MF mit Konfiguration, Druckplatte leeren"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "Öffne Projekt AMF/3MF mit Konfiguration, Druckplatte leeren"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

File diff suppressed because it is too large Load diff

View file

@ -2115,8 +2115,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "Elije uno o varios archivos (STL, OBJ):"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "Escoje uno o más archivos (STL/OBJ/AMF/3MF/PRUSA):"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "Escoje uno o más archivos (STL/3MF/STEP/OBJ/AMF/PRUSA):"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -6096,12 +6096,12 @@ msgid "Import STL (Imperial Units)"
msgstr "Importar STL (Unidades Imperiales)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "Importar STL/OBJ/AM&F/3MF"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "Importar STL/3MF/STEP/OBJ/AM&F"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgstr "Importar STL/OBJ/AMF/3MF sin configuración, mantener la base"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr "Importar STL/3MF/STEP/OBJ/AMF sin configuración, mantener la base"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8302,8 +8302,8 @@ msgid "Open new instance"
msgstr "Abrir instancia nueva"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr "Abrir proyecto STL/OBJ/AMF/3MF con configuración, limpiar plataforma"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "Abrir proyecto AMF/3MF con configuración, limpiar plataforma"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

View file

@ -2139,8 +2139,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "Choisissez un ou plusieurs fichiers (STL, OBJ) :"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "Choisir un ou plusieurs fichiers (STL/OBJ/AMF/3MF/PRUSA) :"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "Choisir un ou plusieurs fichiers (STL/3MF/STEP/OBJ/AMF/PRUSA) :"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -6155,12 +6155,12 @@ msgid "Import STL (Imperial Units)"
msgstr "Importer le STL (unités impériales)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "Importer STL/OBJ/AM&F/3MF"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "Importer STL/3MF/STEP/OBJ/AM&F"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgstr "Importer un STL/OBJ/AMF/3MF sans configuration, conserver le plateau"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr "Importer un STL/3MF/STEP/OBJ/AMF sans configuration, conserver le plateau"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8375,9 +8375,8 @@ msgid "Open new instance"
msgstr "Ouvrir une nouvelle instance"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr ""
"Ouvrir un projet STL/OBJ/AMF/3MF avec configuration, libérer le plateau"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "Ouvrir un projet AMF/3MF avec configuration, libérer le plateau"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

File diff suppressed because it is too large Load diff

View file

@ -2119,8 +2119,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "Scegli uno o più file (STL, OBJ):"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "Seleziona uno o più file (STL/OBJ/AMF/3MF/PRUSA):"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "Seleziona uno o più file (STL/3MF/STEP/OBJ/AMF/PRUSA):"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -6091,12 +6091,12 @@ msgid "Import STL (Imperial Units)"
msgstr "Importa STL (unità imperiali)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "Importa STL/OBJ/AM&F/3MF"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "Importa STL/3MF/STEP/OBJ/AM&F"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgstr "Importa STL/OBJ/AMF/3MF senza configurazione, mantieni piano"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr "Importa STL/3MF/STEP/OBJ/AMF senza configurazione, mantieni piano"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8294,8 +8294,8 @@ msgid "Open new instance"
msgstr "Apri una nuova istanza"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr "Apri progetto STL/OBJ/AMF/3MF con configurazione, pulisci piano"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "Apri progetto AMF/3MF con configurazione, pulisci piano"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

View file

@ -2081,8 +2081,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "1つ以上のファイル(STL, OBJ)を選択します:"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "1つ以上のファイルの選択(STL/OBJ/AMF/3MF/PRUSA):"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "1つ以上のファイルの選択(STL/3MF/STEP/OBJ/AMF/PRUSA):"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -5963,12 +5963,12 @@ msgid "Import STL (Imperial Units)"
msgstr "STLのインポート(インチ)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "STL/OBJ/AMF/3MFのインポート(&F)"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "STL/3MF/STEP/OBJ/AMFのインポート(&F)"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgstr "既存のプレートを保持しながらSTL/OBJ/AMF/3MFを設定なしでインポート"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr "既存のプレートを保持しながらSTL/3MF/STEP/OBJ/AMFを設定なしでインポート"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8124,8 +8124,8 @@ msgid "Open new instance"
msgstr "新しいインスタンスを開く"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr "プロジェクトSTL/OBJ/AMF/3MFを設定を含めて開き、プレートをクリアします"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "プロジェクトAMF/3MFを設定を含めて開き、プレートをクリアします"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2145,8 +2145,8 @@ msgid "Choose one or more files (STL, OBJ):"
msgstr "Wybierz jeden lub więcej plików (STL, OBJ):"
#: src/slic3r/GUI/GUI_App.cpp:1870
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
msgstr "Wybierz jeden lub więcej plików (STL/OBJ/AMF/3MF/PRUSA):"
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
msgstr "Wybierz jeden lub więcej plików (STL/3MF/STEP/OBJ/AMF/PRUSA):"
#: src/slic3r/GUI/ConfigWizard.cpp:1361
msgid "Choose the type of firmware used by your printer."
@ -6080,12 +6080,12 @@ msgid "Import STL (Imperial Units)"
msgstr "Import STL (jednostki imperialne)"
#: src/slic3r/GUI/MainFrame.cpp:1208
msgid "Import STL/OBJ/AM&F/3MF"
msgstr "Import STL/OBJ/AM&F/3MF"
msgid "Import STL/3MF/STEP/OBJ/AM&F"
msgstr "Import STL/3MF/STEP/OBJ/AM&F"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
msgstr "Otwórz STL/OBJ/AMF/3MF bez konfiguracji, zachowaj zawartość stołu"
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
msgstr "Otwórz STL/3MF/STEP/OBJ/AMF bez konfiguracji, zachowaj zawartość stołu"
#: src/slic3r/GUI/Plater.cpp:5293
msgid "Import config only"
@ -8279,8 +8279,8 @@ msgid "Open new instance"
msgstr "Otwórz nową instancję"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
msgstr "Otwórz projekt STL/OBJ/AMF/3MF z konfiguracją, wyczyść stół"
msgid "Open project AMF/3MF with config, clear plater"
msgstr "Otwórz projekt AMF/3MF z konfiguracją, wyczyść stół"
#: src/slic3r/GUI/MainFrame.cpp:1082
#, c-format, boost-format

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1,3 @@
min_slic3r_version = 2.6.0-alpha0
1.0.0 Initial Rigid3D bundle

View file

@ -0,0 +1,469 @@
# Print profiles for the Rigid3D printers.
[vendor]
# Vendor name will be shown by the Config Wizard.
name = Rigid3D
# 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.0.0
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Rigid3D/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
# The printer models will be shown by the Configuration Wizard in this order,
# also the first model installed & the first nozzle installed will be activated after install.
# Printer model name will be shown by the installation wizard.
[printer_model:Zero2]
name = Rigid3D Zero2
variants = 0.4
technology = FFF
family = Zero
bed_model = zero_bed.stl
bed_texture = zero2_bed.png
default_materials = Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
[printer_model:Zero3]
name = Rigid3D Zero3
variants = 0.4
technology = FFF
family = Zero
bed_model = zero_bed.stl
bed_texture = zero3_bed.png
default_materials =Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
[printer_model:Mucit]
name = Rigid3D Mucit
variants = 0.4
technology = FFF
family = Mucit
bed_model = mucit_bed.stl
bed_texture = mucit_bed.png
default_materials = Generic PLA @Rigid3D; Rigid3D PLA @Rigid3D
[printer_model:Mucit2]
name = Rigid3D Mucit2
variants = 0.4
technology = FFF
family = Mucit
bed_model = mucit2_bed.stl
bed_texture = mucit2_bed.png
default_materials = Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
# All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface.
# Common print preset
[print:*common*]
avoid_crossing_perimeters = 0
avoid_crossing_perimeters_max_detour = 0
bottom_fill_pattern = monotonic
bottom_solid_min_thickness = 0.8
bridge_acceleration = 0
bridge_angle = 0
bridge_flow_ratio = 1
bridge_speed = 60
brim_separation = 0
brim_type = no_brim
brim_width = 0
clip_multipart_objects = 1
compatible_printers =
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/
complete_objects = 0
default_acceleration = 0
dont_support_bridges = 1
draft_shield = disabled
elefant_foot_compensation = 0
ensure_vertical_shell_thickness = 0
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 50%
external_perimeters_first = 1
extra_perimeters = 1
extruder_clearance_height = 20
extruder_clearance_radius = 20
extrusion_width = 0.45
fill_angle = 45
fill_density = 10%
fill_pattern = line
first_layer_acceleration = 0
first_layer_acceleration_over_raft = 0
first_layer_extrusion_width = 0.42
first_layer_height = 0.2
first_layer_speed = 50%
first_layer_speed_over_raft = 30
fuzzy_skin = none
fuzzy_skin_point_dist = 0.8
fuzzy_skin_thickness = 0.3
gap_fill_enabled = 1
gap_fill_speed = 20
gcode_comments = 0
gcode_label_objects = 0
gcode_resolution = 0.0125
gcode_substitutions =
infill_acceleration = 0
infill_anchor = 2.5
infill_anchor_max = 12
infill_every_layers = 1
infill_extruder = 1
infill_extrusion_width = 0.45
infill_first = 1
infill_only_where_needed = 0
infill_overlap = 25%
infill_speed = 60
inherits =
interface_shells = 0
ironing = 0
ironing_flowrate = 15%
ironing_spacing = 0.1
ironing_speed = 15
ironing_type = top
max_print_speed = 80
max_volumetric_speed = 0
min_skirt_length = 0
mmu_segmented_region_max_width = 0
notes =
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
output_filename_format = {input_filename_base}_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode
overhangs = 1
perimeter_acceleration = 0
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
perimeter_speed = 60
perimeters = 2
post_process =
print_settings_id =
raft_contact_distance = 0.1
raft_expansion = 1.5
raft_first_layer_density = 90%
raft_first_layer_expansion = 3
raft_layers = 0
resolution = 0
seam_position = rear
single_extruder_multi_material_priming = 1
skirt_distance = 6
skirt_height = 1
skirts = 0
slice_closing_radius = 0.049
slicing_mode = regular
small_perimeter_speed = 15
solid_infill_below_area = 70
solid_infill_every_layers = 0
solid_infill_extruder = 1
solid_infill_extrusion_width = 0.45
solid_infill_speed = 100%
spiral_vase = 0
standby_temperature_delta = -5
support_material = 0
support_material_angle = 0
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.2
support_material_enforce_layers = 0
support_material_extruder = 1
support_material_extrusion_width = 0.35
support_material_interface_contact_loops = 0
support_material_interface_extruder = 1
support_material_interface_layers = 3
support_material_interface_pattern = rectilinear
support_material_interface_spacing = 0
support_material_interface_speed = 100%
support_material_pattern = rectilinear
support_material_spacing = 2.5
support_material_speed = 60
support_material_style = grid
support_material_synchronize_layers = 0
support_material_threshold = 0
support_material_with_sheath = 1
support_material_xy_spacing = 50%
thick_bridges = 0
thin_walls = 1
top_fill_pattern = monotonic
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 100%
top_solid_min_thickness = 0.8
travel_speed = 80
travel_speed_z = 0
wipe_tower = 0
wipe_tower_bridging = 10
wipe_tower_brim_width = 2
wipe_tower_no_sparse_layers = 0
wipe_tower_rotation_angle = 0
wipe_tower_width = 60
wipe_tower_x = 180
wipe_tower_y = 140
xy_size_compensation = 0
[print:0.06mm - Ultra @Rigid3D]
inherits = *common*
layer_height = 0.06
bottom_solid_layers = 10
top_solid_layers = 14
[print:0.12mm - Super @Rigid3D]
inherits = *common*
layer_height = 0.12
bottom_solid_layers = 7
top_solid_layers = 7
[print:0.16mm - Good @Rigid3D]
inherits = *common*
layer_height = 0.16
bottom_solid_layers = 5
top_solid_layers = 5
[print:0.20mm - Standard @Rigid3D]
inherits = *common*
layer_height = 0.20
bottom_solid_layers = 4
top_solid_layers = 4
[print:0.24mm - Draft @Rigid3D]
inherits = *common*
layer_height = 0.24
bottom_solid_layers = 3
top_solid_layers = 4
[print:0.28mm - Low @Rigid3D]
inherits = *common*
layer_height = 0.28
bottom_solid_layers = 3
top_solid_layers = 4
[filament:*common*]
disable_fan_first_layers = 3
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
extrusion_multiplier = 1
fan_below_layer_time = 60
filament_cooling_final_speed = 3.4
filament_cooling_initial_speed = 2.2
filament_cooling_moves = 4
filament_cost = 0
filament_deretract_speed = nil
filament_diameter = 1.75
filament_minimal_purge_on_wipe_tower = 15
filament_notes = ""
filament_retract_before_travel = nil
filament_retract_before_wipe = nil
filament_retract_layer_change = nil
filament_retract_length = nil
filament_retract_lift = nil
filament_retract_lift_above = nil
filament_retract_lift_below = nil
filament_retract_restart_extra = nil
filament_retract_speed = nil
filament_settings_id = ""
filament_soluble = 0
filament_spool_weight = 0
filament_wipe = nil
min_print_speed = 10
slowdown_below_layer_time = 10
start_filament_gcode = "; Filament gcode\n"
[filament:*PLA*]
inherits = *common*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/
bridge_fan_speed = 100
cooling = 1
fan_always_on = 1
filament_type = PLA
full_fan_speed_layer = 4
max_fan_speed = 100
min_fan_speed = 100
[filament:*ABS*]
inherits = *common*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
cooling = 1
fan_always_on = 0
filament_type = ABS
max_fan_speed = 0
min_fan_speed = 0
[filament:*PETG*]
inherits = *common*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
cooling = 1
fan_always_on = 0
filament_type = PETG
max_fan_speed = 50
min_fan_speed = 30
[filament:*FLEX*]
inherits = *common*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
bridge_fan_speed = 100
cooling = 1
fan_always_on = 1
filament_type = FLEX
full_fan_speed_layer = 4
max_fan_speed = 100
min_fan_speed = 100
[filament:*NYLON*]
inherits = *common*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
cooling = 1
fan_always_on = 0
filament_type = NYLON
max_fan_speed = 0
min_fan_speed = 0
[filament:Generic PLA @Rigid3D]
inherits = *PLA*
bed_temperature = 55
filament_colour = #FFFF00
filament_density = 1.24
filament_max_volumetric_speed = 12
first_layer_temperature = 215
temperature = 215
first_layer_bed_temperature = 60
[filament:Rigid3D PLA @Rigid3D]
inherits = *PLA*
filament_colour = #FFFF00
filament_density = 1.24
first_layer_temperature = 210
temperature = 205
first_layer_bed_temperature = 60
bed_temperature = 55
filament_max_volumetric_speed = 12
[filament:Generic ABS @Rigid3D]
inherits = *ABS*
filament_colour = #49B928
filament_density = 1.04
first_layer_temperature = 235
temperature = 235
first_layer_bed_temperature = 100
bed_temperature = 100
filament_max_volumetric_speed = 8
[filament:Generic PETG @Rigid3D]
inherits = *PETG*
filament_colour = #FF8000
filament_density = 1.27
first_layer_temperature = 240
temperature = 240
first_layer_bed_temperature = 70
bed_temperature = 70
filament_max_volumetric_speed = 8
[filament:Generic FLEX @Rigid3D]
inherits = *FLEX*
filament_colour = #C80000
filament_density = 1.21
first_layer_temperature = 225
temperature = 225
first_layer_bed_temperature = 70
bed_temperature = 70
filament_max_volumetric_speed = 2.5
[filament:Generic Nylon @Rigid3D]
inherits = *NYLON*
filament_colour = #0AF1CE
filament_density = 1.12
first_layer_temperature = 250
temperature = 250
first_layer_bed_temperature = 100
bed_temperature = 100
filament_max_volumetric_speed = 8
# Common printer preset
[printer:*common*]
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
between_objects_gcode =
color_change_gcode = M600
default_filament_profile = "Rigid3D PLA @Rigid3D"
default_print_profile = "0.20mm - Standard @Rigid3D"
deretract_speed = 0
extruder_offset = 0x0
gcode_flavor = marlin2
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]\n\n
machine_limits_usage = time_estimate_only
machine_max_acceleration_e = 1000
machine_max_acceleration_extruding = 500
machine_max_acceleration_retracting = 1000
machine_max_acceleration_travel = 1000
machine_max_acceleration_x = 500
machine_max_acceleration_y = 500
machine_max_acceleration_z = 100
machine_max_feedrate_e = 25
machine_max_feedrate_x = 120
machine_max_feedrate_y = 120
machine_max_feedrate_z = 20
machine_max_jerk_e = 5
machine_max_jerk_x = 10
machine_max_jerk_y = 10
machine_max_jerk_z = 0.3
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
max_layer_height = 0.32
min_layer_height = 0.05
nozzle_diameter = 0.4
pause_print_gcode = M0
printer_settings_id =
printer_technology = FFF
printer_variant = 0.4
remaining_times = 1
retract_before_travel = 2
retract_before_wipe = 0%
retract_layer_change = 0
retract_length = 1
retract_length_toolchange = 10
retract_lift = 0
retract_lift_above = 0
retract_lift_below = 0
retract_restart_extra = 0
retract_restart_extra_toolchange = 0
retract_speed = 25
silent_mode = 0
single_extruder_multi_material = 0
template_custom_gcode =
thumbnails =
toolchange_gcode =
use_firmware_retraction = 0
use_relative_e_distances = 0
use_volumetric_e = 0
variable_layer_height = 1
wipe = 0
z_offset = 0
[printer:Rigid3D Zero2]
inherits = *common*
bed_shape = 0x0,200x0,200x200,0x200
max_print_height = 190
printer_model = Zero2
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_RIGID3D\nPRINTER_MODEL_ZERO2\nPRINTER_HAS_HEATEDBED\n
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X190.0 Y0.1 Z0.3 F1500.0 E15\nG1 X190 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E30\nG1 Z2.0 F1500.0\nG92 E0\n
end_gcode = G1 X0 Y180\nM107\nG91\nG0 Z20\nT0\nG1 E-1\nM104 T0 S0\nG90\nG92 E0\nM140 S0\nM84\nM300 S2093 P150\nM300 S2637 P150\nM300 S3135 P150\nM300 S4186 P150\nM300 S3135 P150\nM300 S2637 P150\nM300 S2793 P150\nM300 S2349 P150\nM300 S1975 P150\nM300 S2093 P450\n
[printer:Rigid3D Zero3]
inherits = *common*
bed_shape = 0x0,200x0,200x200,0x200
max_print_height = 200
printer_model = Zero3
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_RIGID3D\nPRINTER_MODEL_ZERO3\nPRINTER_HAS_HEATEDBED\n
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X190.0 Y0.1 Z0.3 F1500.0 E15\nG1 X190 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E30\nG1 Z2.0 F1500.0\nG92 E0\n
end_gcode = G92 E0\nT0\nG1 F1800 E-2\nG27 P2\nM107\nM104 T0 S0\nM140 S0\nG90\nG92 E0\nM18\n
[printer:Rigid3D Mucit]
inherits = *common*
bed_shape = 0x0,150x0,150x150,0x150
max_print_height = 150
printer_model = Mucit
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_RIGID3D\nPRINTER_MODEL_MUCIT\n
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X140.0 Y0.1 Z0.3 F1500.0 E10\nG1 X140 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E20\nG1 Z2.0 F1500.0\nG92 E0\n
end_gcode = G1 X0 Y140\nM107\nG91\nG0 Z20\nT0\nG1 E-2\nM104 T0 S0\nG90\nG92 E0\nM140 S0\nM84\nM300 S2093 P150\nM300 S2637 P150\nM300 S3135 P150\nM300 S4186 P150\nM300 S3135 P150\nM300 S2637 P150\nM300 S2793 P150\nM300 S2349 P150\nM300 S1975 P150\nM300 S2093 P450\n
[printer:Rigid3D Mucit2]
inherits = *common*
bed_shape = 0x0,150x0,150x150,0x150
max_print_height = 150
printer_model = Mucit2
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_RIGID3D\nPRINTER_MODEL_MUCIT2\nPRINTER_HAS_HEATEDBED\n
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X140.0 Y0.1 Z0.3 F1500.0 E10\nG1 X140 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E20\nG1 Z2.0 F1500.0\nG92 E0\n
end_gcode = G92 E0\nT0\nG1 F1800 E-2\nG27 P2\nM107\nM104 T0 S0\nM140 S0\nG90\nG92 E0\nM18\n

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

View file

@ -1,8 +1,6 @@
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
#include "libslic3r/Point.hpp"
#include "libslic3r/EdgeGrid.hpp"
#include "libslic3r/AABBTreeIndirect.hpp"
#include "libslic3r/Line.hpp"

View file

@ -250,6 +250,8 @@ set(SLIC3R_SOURCES
SlicingAdaptive.hpp
Subdivide.cpp
Subdivide.hpp
SupportSpotsGenerator.cpp
SupportSpotsGenerator.hpp
SupportMaterial.cpp
SupportMaterial.hpp
Surface.cpp
@ -283,6 +285,8 @@ set(SLIC3R_SOURCES
TriangleSelector.hpp
TriangleSetSampling.cpp
TriangleSetSampling.hpp
TriangleSelectorWrapper.cpp
TriangleSelectorWrapper.hpp
MTUtils.hpp
Zipper.hpp
Zipper.cpp

View file

@ -5,6 +5,7 @@
#include "libslic3r/format.hpp"
#include "GCodeProcessor.hpp"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/log/trivial.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
@ -777,8 +778,7 @@ void GCodeProcessorResult::reset() {
max_print_height = 0.0f;
settings_ids.reset();
extruders_count = 0;
extruder_colors = DEFAULT_EXTRUDER_COLORS;
assert(extruder_colors.size() == MIN_EXTRUDERS_COUNT);
extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
#if ENABLE_USED_FILAMENT_POST_PROCESS
@ -870,6 +870,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
{
m_parser.apply_config(config);
m_producer = EProducer::PrusaSlicer;
m_flavor = config.gcode_flavor;
size_t extruders_count = config.nozzle_diameter.values.size();
@ -1093,6 +1094,20 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
}
}
// With MM setups like Prusa MMU2, the filaments may be expected to be parked at the beginning.
// Remember the parking position so the initial load is not included in filament estimate.
const ConfigOptionBool* single_extruder_multi_material = config.option<ConfigOptionBool>("single_extruder_multi_material");
const ConfigOptionBool* wipe_tower = config.option<ConfigOptionBool>("wipe_tower");
const ConfigOptionFloat* parking_pos_retraction = config.option<ConfigOptionFloat>("parking_pos_retraction");
const ConfigOptionFloat* extra_loading_move = config.option<ConfigOptionFloat>("extra_loading_move");
if (single_extruder_multi_material != nullptr && wipe_tower != nullptr && parking_pos_retraction != nullptr && extra_loading_move != nullptr) {
if (single_extruder_multi_material->value && m_result.extruders_count > 1 && wipe_tower->value) {
m_parking_position = float(parking_pos_retraction->value);
m_extra_loading_move = float(extra_loading_move->value);
}
}
bool use_machine_limits = false;
const ConfigOptionEnum<MachineLimitsUsage>* machine_limits_usage = config.option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
if (machine_limits_usage != nullptr)
@ -1289,6 +1304,7 @@ void GCodeProcessor::reset()
m_options_z_corrector.reset();
m_spiral_vase_active = false;
m_kissslicer_toolchange_time_correction = 0.0f;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
m_mm3_per_mm_compare.reset();
@ -1343,10 +1359,16 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
apply_config(config);
}
else if (m_producer == EProducer::Simplify3D)
apply_config_simplify3d(filename);
else if (m_producer == EProducer::SuperSlicer)
apply_config_superslicer(filename);
else {
m_result.extruder_colors = DEFAULT_EXTRUDER_COLORS;
if (m_producer == EProducer::Simplify3D)
apply_config_simplify3d(filename);
else if (m_producer == EProducer::SuperSlicer)
apply_config_superslicer(filename);
else if (m_producer == EProducer::KissSlicer)
apply_config_kissslicer(filename);
}
}
// process gcode
@ -1529,6 +1551,82 @@ void GCodeProcessor::apply_config_superslicer(const std::string& filename)
apply_config(config);
}
void GCodeProcessor::apply_config_kissslicer(const std::string& filename)
{
size_t found_counter = 0;
m_parser.parse_file_raw(filename, [this, &found_counter](GCodeReader& reader, const char* begin, const char* end) {
auto detect_flavor = [this](const std::string_view comment) {
static const std::string search_str = "firmware_type";
const size_t pos = comment.find(search_str);
if (pos != comment.npos) {
std::vector<std::string> elements;
boost::split(elements, comment, boost::is_any_of("="));
if (elements.size() == 2) {
try
{
switch (std::stoi(elements[1]))
{
default: { break; }
case 1:
case 2:
case 3: { m_flavor = gcfMarlinLegacy; break; }
}
return true;
}
catch (...)
{
// invalid data, do nothing
}
}
}
return false;
};
auto detect_printer = [this](const std::string_view comment) {
static const std::string search_str = "printer_name";
const size_t pos = comment.find(search_str);
if (pos != comment.npos) {
std::vector<std::string> elements;
boost::split(elements, comment, boost::is_any_of("="));
if (elements.size() == 2) {
elements[1] = boost::to_upper_copy(elements[1]);
if (boost::contains(elements[1], "MK2.5") || boost::contains(elements[1], "MK3"))
m_kissslicer_toolchange_time_correction = 18.0f; // MMU2
else if (boost::contains(elements[1], "MK2"))
m_kissslicer_toolchange_time_correction = 5.0f; // MMU
}
return true;
}
return false;
};
begin = skip_whitespaces(begin, end);
if (begin != end) {
if (*begin == ';') {
// Comment.
begin = skip_whitespaces(++begin, end);
end = remove_eols(begin, end);
if (begin != end) {
const std::string_view comment(begin, end - begin);
if (detect_flavor(comment) || detect_printer(comment))
++found_counter;
}
// we got the data,
// force early exit to avoid parsing the entire file
if (found_counter == 2)
m_parser.quit_parsing();
}
else if (*begin == 'M' || *begin == 'G')
// the header has been fully parsed, quit search
m_parser.quit_parsing();
}
}
);
m_parser.reset();
}
std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
{
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ?
@ -2559,7 +2657,7 @@ bool GCodeProcessor::process_bambustudio_tags(const std::string_view comment)
bool GCodeProcessor::detect_producer(const std::string_view comment)
{
for (const auto& [id, search_string] : Producers) {
size_t pos = comment.find(search_string);
const size_t pos = comment.find(search_string);
if (pos != comment.npos) {
m_producer = id;
BOOST_LOG_TRIVIAL(info) << "Detected gcode producer: " << search_string;
@ -3615,10 +3713,12 @@ void GCodeProcessor::process_T(const std::string_view command)
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
} else {
}
else {
unsigned char id = static_cast<unsigned char>(eid);
if (m_extruder_id != id) {
if (id >= m_result.extruder_colors.size())
if (((m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) && id >= m_result.extruders_count) ||
((m_producer != EProducer::PrusaSlicer && m_producer != EProducer::Slic3rPE && m_producer != EProducer::Slic3r) && id >= m_result.extruder_colors.size()))
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode.";
else {
unsigned char old_extruder_id = m_extruder_id;
@ -3631,6 +3731,8 @@ void GCodeProcessor::process_T(const std::string_view command)
float extra_time = get_filament_unload_time(static_cast<size_t>(old_extruder_id));
m_time_processor.extruder_unloaded = false;
extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
if (m_producer == EProducer::KissSlicer && m_flavor == gcfMarlinLegacy)
extra_time += m_kissslicer_toolchange_time_correction;
simulate_st_synchronize(extra_time);
m_result.extruders_count = std::max<size_t>(m_result.extruders_count, m_extruder_id + 1);

View file

@ -575,6 +575,7 @@ namespace Slic3r {
OptionsZCorrector m_options_z_corrector;
size_t m_last_default_color_id;
bool m_spiral_vase_active;
float m_kissslicer_toolchange_time_correction;
#if ENABLE_GCODE_VIEWER_STATISTICS
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -648,6 +649,7 @@ namespace Slic3r {
void apply_config(const DynamicPrintConfig& config);
void apply_config_simplify3d(const std::string& filename);
void apply_config_superslicer(const std::string& filename);
void apply_config_kissslicer(const std::string& filename);
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
// Process tags embedded into comments

View file

@ -395,8 +395,7 @@ struct GlobalModelInfo {
;
//Extract perimeter polygons of the given layer
Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition configured_seam_preference,
std::vector<const LayerRegion*> &corresponding_regions_out) {
Polygons extract_perimeter_polygons(const Layer *layer, std::vector<const LayerRegion*> &corresponding_regions_out) {
Polygons polygons;
for (const LayerRegion *layer_region : layer->regions()) {
for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) {
@ -411,9 +410,7 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi
}
}
if (role == ExtrusionRole::erExternalPerimeter
|| (is_perimeter(role)
&& configured_seam_preference == spRandom)) { //for random seam alignment, extract all perimeters
if (role == ExtrusionRole::erExternalPerimeter) {
Points p;
perimeter->collect_points(p);
polygons.emplace_back(std::move(p));
@ -1044,14 +1041,13 @@ public:
// Parallel process and extract each perimeter polygon of the given print object.
// Gather SeamCandidates of each layer into vector and build KDtree over them
// Store results in the SeamPlacer variables m_seam_per_object
void SeamPlacer::gather_seam_candidates(const PrintObject *po,
const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference) {
void SeamPlacer::gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info) {
using namespace SeamPlacerImpl;
PrintObjectSeamData &seam_data = m_seam_per_object.emplace(po, PrintObjectSeamData { }).first->second;
seam_data.layers.resize(po->layer_count());
tbb::parallel_for(tbb::blocked_range<size_t>(0, po->layers().size()),
[po, configured_seam_preference, &global_model_info, &seam_data]
[po, &global_model_info, &seam_data]
(tbb::blocked_range<size_t> r) {
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) {
PrintObjectSeamData::LayerSeams &layer_seams = seam_data.layers[layer_idx];
@ -1059,7 +1055,7 @@ void SeamPlacer::gather_seam_candidates(const PrintObject *po,
auto unscaled_z = layer->slice_z;
std::vector<const LayerRegion*> regions;
//NOTE corresponding region ptr may be null, if the layer has zero perimeters
Polygons polygons = extract_perimeter_polygons(layer, configured_seam_preference, regions);
Polygons polygons = extract_perimeter_polygons(layer, regions);
for (size_t poly_index = 0; poly_index < polygons.size(); ++poly_index) {
process_perimeter_polygon(polygons[poly_index], unscaled_z,
regions[poly_index], global_model_info, layer_seams);
@ -1468,7 +1464,7 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
throw_if_canceled_func();
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: gather_seam_candidates: start";
gather_seam_candidates(po, global_model_info, configured_seam_preference);
gather_seam_candidates(po, global_model_info);
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: gather_seam_candidates: end";
throw_if_canceled_func();
@ -1533,7 +1529,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
const size_t layer_index = layer->id() - po->slicing_parameters().raft_layers();
const double unscaled_z = layer->slice_z;
auto get_next_loop_point = [&loop](ExtrusionLoop::ClosestPathPoint current) {
auto get_next_loop_point = [loop](ExtrusionLoop::ClosestPathPoint current) {
current.segment_idx += 1;
if (current.segment_idx >= loop.paths[current.path_idx].polyline.points.size()) {
current.path_idx = next_idx_modulo(current.path_idx, loop.paths.size());
@ -1556,7 +1552,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
size_t points_count = std::accumulate(loop.paths.begin(), loop.paths.end(), 0, [](size_t acc,const ExtrusionPath& p) {
return acc + p.polyline.points.size();
});
for (size_t _ = 0; _ < points_count; ++_) {
for (size_t i = 0; i < points_count; ++i) {
Vec2f unscaled_p = unscaled<float>(closest_point.foot_pt);
closest_perimeter_point_index = find_closest_point(*layer_perimeters.points_tree.get(),
to_3d(unscaled_p, float(unscaled_z)));
@ -1586,13 +1582,12 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
Point seam_point = Point::new_scale(seam_position.x(), seam_position.y());
if (const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
(po->config().seam_position == spNearest || po->config().seam_position == spAligned) &&
loop.role() == ExtrusionRole::erPerimeter && //Hopefully internal perimeter
(seam_position - perimeter_point.position).squaredNorm() < 4.0f && // seam is on perimeter point
perimeter_point.local_ccw_angle < -EPSILON // In concave angles
) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align
// the internal seam into the concave corner, and not on the perpendicular projection on the closest edge (which is what the split_at function does)
if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter
const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false);
// determine depth of the seam point.
float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm();
float beta_angle = cos(perimeter_point.local_ccw_angle / 2.0f);
size_t index_of_prev =
seam_index == perimeter_point.perimeter.start_index ?
perimeter_point.perimeter.end_index - 1 :
@ -1602,18 +1597,46 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
perimeter_point.perimeter.start_index :
seam_index + 1;
Vec2f dir_to_middle =
((perimeter_point.position - layer_perimeters.points[index_of_prev].position).head<2>().normalized()
+ (perimeter_point.position - layer_perimeters.points[index_of_next].position).head<2>().normalized())
* 0.5;
if ((seam_position - perimeter_point.position).squaredNorm() < depth && // seam is on perimeter point
perimeter_point.local_ccw_angle < -EPSILON // In concave angles
) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align
// the internal seam into the concave corner, and not on the perpendicular projection on the closest edge (which is what the split_at function does)
Vec2f dir_to_middle =
((perimeter_point.position - layer_perimeters.points[index_of_prev].position).head<2>().normalized()
+ (perimeter_point.position - layer_perimeters.points[index_of_next].position).head<2>().normalized())
* 0.5;
depth = 1.4142 * depth / beta_angle;
// There are some nice geometric identities in determination of the correct depth of new seam point.
//overshoot the target depth, in concave angles it will correctly snap to the corner; TODO: find out why such big overshoot is needed.
Vec2f final_pos = perimeter_point.position.head<2>() + depth * dir_to_middle;
projected_point = loop.get_closest_path_and_point(Point::new_scale(final_pos.x(), final_pos.y()), false);
} else { // not concave angle, in that case the nearest point is the good candidate
// but for staggering, we also need to recompute depth of the inner perimter, because in convex corners, the distance is larger than layer width
// we want the perpendicular depth, not distance to nearest point
depth = depth * beta_angle / 1.4142;
}
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, true);
//get closest projected point, determine depth of the seam point.
float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm();
float angle_factor = cos(-perimeter_point.local_ccw_angle / 2.0f); // There are some nice geometric identities in determination of the correct depth of new seam point.
//overshoot the target depth, in concave angles it will correctly snap to the corner; TODO: find out why such big overshoot is needed.
Vec2f final_pos = perimeter_point.position.head<2>() + (1.4142 * depth / angle_factor) * dir_to_middle;
seam_point = Point::new_scale(final_pos.x(), final_pos.y());
seam_point = projected_point.foot_pt;
//lastly, for internal perimeters, do the staggering if requested
if (po->config().staggered_inner_seams && loop.length() > 0.0) {
//fix depth, it is sometimes strongly underestimated
depth = std::max(loop.paths[projected_point.path_idx].width, depth);
while (depth > 0.0f) {
auto next_point = get_next_loop_point(projected_point);
Vec2f a = unscale(projected_point.foot_pt).cast<float>();
Vec2f b = unscale(next_point.foot_pt).cast<float>();
float dist = (a - b).norm();
if (dist > depth) {
Vec2f final_pos = a + (b - a) * depth / dist;
next_point.foot_pt = Point::new_scale(final_pos.x(), final_pos.y());
}
depth -= dist;
projected_point = next_point;
}
seam_point = projected_point.foot_pt;
}
}
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,

View file

@ -143,8 +143,7 @@ public:
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
private:
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info,
const SeamPosition configured_seam_preference);
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
void calculate_candidates_visibility(const PrintObject *po,
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
void calculate_overhangs_and_layer_embedding(const PrintObject *po);

View file

@ -550,12 +550,16 @@ void Transformation::set_rotation(Axis axis, double rotation)
Vec3d Transformation::get_scaling_factor() const
{
const Transform3d scale = extract_scale(m_matrix);
return { scale(0, 0), scale(1, 1), scale(2, 2) };
return { std::abs(scale(0, 0)), std::abs(scale(1, 1)), std::abs(scale(2, 2)) };
}
Transform3d Transformation::get_scaling_factor_matrix() const
{
return extract_scale(m_matrix);
Transform3d scale = extract_scale(m_matrix);
scale(0, 0) = std::abs(scale(0, 0));
scale(1, 1) = std::abs(scale(1, 1));
scale(2, 2) = std::abs(scale(2, 2));
return scale;
}
#endif // ENABLE_WORLD_COORDINATE
@ -577,6 +581,8 @@ void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
{
#if ENABLE_WORLD_COORDINATE
assert(scaling_factor > 0.0);
auto [rotation, scale] = extract_rotation_scale(m_matrix);
scale(axis, axis) = scaling_factor;
@ -600,8 +606,11 @@ Vec3d Transformation::get_mirror() const
Transform3d Transformation::get_mirror_matrix() const
{
const Vec3d scale = get_scaling_factor();
return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) });
Transform3d scale = extract_scale(m_matrix);
scale(0, 0) = scale(0, 0) / std::abs(scale(0, 0));
scale(1, 1) = scale(1, 1) / std::abs(scale(1, 1));
scale(2, 2) = scale(2, 2) / std::abs(scale(2, 2));
return scale;
}
#endif // ENABLE_WORLD_COORDINATE
@ -617,13 +626,17 @@ void Transformation::set_mirror(const Vec3d& mirror)
copy(i) /= abs_mirror(i);
}
const Vec3d curr_scale = get_scaling_factor();
const Vec3d signs = curr_scale.cwiseProduct(copy);
set_scaling_factor({
signs.x() < 0.0 ? std::abs(curr_scale.x()) * copy.x() : curr_scale.x(),
signs.y() < 0.0 ? std::abs(curr_scale.y()) * copy.y() : curr_scale.y(),
signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z()
});
auto [rotation, scale] = extract_rotation_scale(m_matrix);
const Vec3d curr_scales = { scale(0, 0), scale(1, 1), scale(2, 2) };
const Vec3d signs = curr_scales.cwiseProduct(copy);
if (signs[0] < 0.0) scale(0, 0) = -scale(0, 0);
if (signs[1] < 0.0) scale(1, 1) = -scale(1, 1);
if (signs[2] < 0.0) scale(2, 2) = -scale(2, 2);
const Vec3d offset = get_offset();
m_matrix = rotation * scale;
m_matrix.translation() = offset;
#else
set_mirror(X, mirror.x());
set_mirror(Y, mirror.y());
@ -640,9 +653,15 @@ void Transformation::set_mirror(Axis axis, double mirror)
mirror /= abs_mirror;
#if ENABLE_WORLD_COORDINATE
const double curr_scale = get_scaling_factor(axis);
auto [rotation, scale] = extract_rotation_scale(m_matrix);
const double curr_scale = scale(axis, axis);
const double sign = curr_scale * mirror;
set_scaling_factor(axis, sign < 0.0 ? std::abs(curr_scale) * mirror : curr_scale);
if (sign < 0.0) scale(axis, axis) = -scale(axis, axis);
const Vec3d offset = get_offset();
m_matrix = rotation * scale;
m_matrix.translation() = offset;
#else
if (m_mirror(axis) != mirror) {
m_mirror(axis) = mirror;
@ -746,7 +765,6 @@ Transform3d Transformation::get_matrix_no_scaling_factor() const
{
Transformation copy(*this);
copy.reset_scaling_factor();
copy.reset_mirror();
return copy.get_matrix();
}
#else

View file

@ -235,7 +235,7 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
}
if (ext_lines.back().p == ext_lines.front().p) // Connect endpoints.
out.back().p = out.front().p;
out.front().p = out.back().p;
if (out.size() >= 3)
ext_lines.junctions = std::move(out);

View file

@ -528,4 +528,23 @@ bool contains(const Polygons &polygons, const Point &p, bool border_result)
return (poly_count_inside % 2) == 1;
}
Polygon make_circle(double radius, double error)
{
double angle = 2. * acos(1. - error / radius);
size_t num_segments = size_t(ceil(2. * M_PI / angle));
return make_circle_num_segments(radius, num_segments);
}
Polygon make_circle_num_segments(double radius, size_t num_segments)
{
Polygon out;
out.points.reserve(num_segments);
double angle_inc = 2.0 * M_PI / num_segments;
for (size_t i = 0; i < num_segments; ++ i) {
const double angle = angle_inc * i;
out.points.emplace_back(coord_t(cos(angle) * radius), coord_t(sin(angle) * radius));
}
return out;
}
}

View file

@ -253,6 +253,9 @@ inline Polygons to_polygons(std::vector<Points> &&paths)
// Returns true if inside. Returns border_result if on boundary.
bool contains(const Polygons& polygons, const Point& p, bool border_result = true);
Polygon make_circle(double radius, double error);
Polygon make_circle_num_segments(double radius, size_t num_segments);
} // Slic3r
// start Boost

View file

@ -421,7 +421,7 @@ static std::vector<std::string> s_Preset_print_options {
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode",
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
"seam_position","staggered_inner_seams", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
"infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle",
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",
"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing",
@ -1055,12 +1055,12 @@ const std::string& PresetCollection::get_suffix_modified() {
// Return a preset by its name. If the preset is active, a temporary copy is returned.
// If a preset is not found by its name, null is returned.
Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found)
Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found, bool respect_active_preset /*= true*/)
{
Preset key(m_type, name, false);
auto it = this->find_preset_internal(name);
// Ensure that a temporary copy is returned if the preset found is currently selected.
return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin()) :
return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin(), respect_active_preset) :
first_visible_if_not_found ? &this->first_visible() : nullptr;
}
@ -1876,13 +1876,23 @@ bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string&
return true;
}
void PhysicalPrinterCollection::rename_preset_in_printers(const std::string& old_preset_name, const std::string& new_preset_name)
{
for (PhysicalPrinter& printer : m_printers)
if (printer.delete_preset(old_preset_name)) {
printer.add_preset(new_preset_name);
printer.update_preset_names_in_config();
printer.save();
}
}
// Get list of printers which have more than one preset and "preset_names" preset is one of them
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name)
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name, bool respect_only_preset /*= true*/)
{
std::vector<std::string> printers;
for (auto printer : m_printers) {
if (printer.preset_names.size() == 1)
if (!respect_only_preset && printer.preset_names.size() == 1)
continue;
if (printer.preset_names.find(preset_name) != printer.preset_names.end())
printers.emplace_back(printer.name);

View file

@ -392,8 +392,8 @@ public:
const Preset& default_preset(size_t idx = 0) const { assert(idx < m_num_default_presets); return m_presets[idx]; }
virtual const Preset& default_preset_for(const DynamicPrintConfig & /* config */) const { return this->default_preset(); }
// Return a preset by an index. If the preset is active, a temporary copy is returned.
Preset& preset(size_t idx) { return (idx == m_idx_selected) ? m_edited_preset : m_presets[idx]; }
const Preset& preset(size_t idx) const { return const_cast<PresetCollection*>(this)->preset(idx); }
Preset& preset(size_t idx, bool respect_active_preset = true) { return (idx == m_idx_selected && respect_active_preset) ? m_edited_preset : m_presets[idx]; }
const Preset& preset(size_t idx, bool respect_active_preset = true) const { return const_cast<PresetCollection*>(this)->preset(idx); }
void discard_current_changes() {
m_presets[m_idx_selected].reset_dirty();
m_edited_preset = m_presets[m_idx_selected];
@ -403,9 +403,9 @@ public:
// Return a preset by its name. If the preset is active, a temporary copy is returned.
// If a preset is not found by its name, null is returned.
Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false);
const Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false) const
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found); }
Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false, bool respect_active_preset = true);
const Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false, bool respect_active_preset = true) const
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found, respect_active_preset); }
size_t first_visible_idx() const;
// Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible.
@ -734,9 +734,9 @@ public:
// If there is last preset for the printer and first_check== false, then delete this printer
// returns true if all presets were deleted successfully.
bool delete_preset_from_printers(const std::string& preset_name);
void rename_preset_in_printers(const std::string& old_name, const std::string& new_name);
// Get list of printers which have more than one preset and "preset_names" preset is one of them
std::vector<std::string> get_printers_with_preset( const std::string &preset_name);
std::vector<std::string> get_printers_with_preset( const std::string &preset_name, bool respect_only_preset = true);
// Get list of printers which has only "preset_names" preset
std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name);

View file

@ -825,6 +825,8 @@ void Print::process()
obj->infill();
for (PrintObject *obj : m_objects)
obj->ironing();
for (PrintObject *obj : m_objects)
obj->generate_support_spots();
for (PrintObject *obj : m_objects)
obj->generate_support_material();
if (this->set_started(psWipeTower)) {

View file

@ -61,7 +61,7 @@ enum PrintStep : unsigned int {
enum PrintObjectStep : unsigned int {
posSlice, posPerimeters, posPrepareInfill,
posInfill, posIroning, posSupportMaterial, posCount,
posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posCount,
};
// A PrintRegion object represents a group of volumes to print
@ -381,6 +381,7 @@ private:
void prepare_infill();
void infill();
void ironing();
void generate_support_spots();
void generate_support_material();
void slice_volumes();

View file

@ -1195,8 +1195,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
update_apply_status(false);
}
// Invalidate just the supports step.
for (const PrintObjectStatus &print_object_status : print_objects_range)
for (const PrintObjectStatus &print_object_status : print_objects_range) {
update_apply_status(print_object_status.print_object->invalidate_step(posSupportSpotsSearch));
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
}
if (supports_differ) {
// Copy just the support volumes.
model_volume_list_update_supports(model_object, model_object_new);

View file

@ -2253,6 +2253,12 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned));
def = this->add("staggered_inner_seams", coBool);
def->label = L("Staggered inner seams");
def->tooltip = L("This option causes the inner seams to be shifted backwards based on their depth, forming a zigzag pattern.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
#if 0
def = this->add("seam_preferred_direction", coFloat);
// def->gui_type = ConfigOptionDef::GUIType::slider;

View file

@ -503,6 +503,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, raft_first_layer_expansion))
((ConfigOptionInt, raft_layers))
((ConfigOptionEnum<SeamPosition>, seam_position))
((ConfigOptionBool, staggered_inner_seams))
// ((ConfigOptionFloat, seam_preferred_direction))
// ((ConfigOptionFloat, seam_preferred_direction_jitter))
((ConfigOptionFloat, slice_closing_radius))

View file

@ -17,6 +17,9 @@
#include "Fill/FillAdaptive.hpp"
#include "Fill/FillLightning.hpp"
#include "Format/STL.hpp"
#include "SupportSpotsGenerator.hpp"
#include "TriangleSelectorWrapper.hpp"
#include "format.hpp"
#include <float.h>
#include <string_view>
@ -394,6 +397,65 @@ void PrintObject::ironing()
}
}
/*
std::vector<size_t> problematic_layers = SupportSpotsGenerator::quick_search(this);
if (!problematic_layers.empty()) {
std::cout << "Object needs supports" << std::endl;
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
L("Supportable issues found. Consider enabling supports for this object"));
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
L("Supportable issues found. Consider enabling supports for this object"));
for (size_t index = 0; index < std::min(problematic_layers.size(), size_t(4)); ++index) {
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
format(L("Layer with issues: %1%"), problematic_layers[index] + 1));
}
}
*/
void PrintObject::generate_support_spots()
{
if (this->set_started(posSupportSpotsSearch)) {
BOOST_LOG_TRIVIAL(debug)
<< "Searching support spots - start";
m_print->set_status(75, L("Searching support spots"));
if (this->m_config.support_material && !this->m_config.support_material_auto &&
std::all_of(this->model_object()->volumes.begin(), this->model_object()->volumes.end(),
[](const ModelVolume* mv){return mv->supported_facets.empty();})
) {
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values};
SupportSpotsGenerator::Issues issues = SupportSpotsGenerator::full_search(this, params);
auto obj_transform = this->trafo_centered();
for (ModelVolume *model_volume : this->model_object()->volumes) {
if (model_volume->is_model_part()) {
Transform3d mesh_transformation = obj_transform * model_volume->get_matrix();
Transform3d inv_transform = mesh_transformation.inverse();
TriangleSelectorWrapper selector { model_volume->mesh(), mesh_transformation};
for (const SupportSpotsGenerator::SupportPoint &support_point : issues.support_points) {
Vec3f point = Vec3f(inv_transform.cast<float>() * support_point.position);
Vec3f origin = Vec3f(
inv_transform.cast<float>() * Vec3f(support_point.position.x(), support_point.position.y(), 0.0f));
selector.enforce_spot(point, origin, support_point.spot_radius);
}
model_volume->supported_facets.set(selector.selector);
#if 0 //DEBUG export
indexed_triangle_set copy = model_volume->mesh().its;
its_transform(copy, obj_transform * model_transformation);
its_write_obj(copy,
debug_out_path(("model"+std::to_string(model_volume->id().id)+".obj").c_str()).c_str());
#endif
}
}
}
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug)
<< "Searching support spots - end";
this->set_done(posSupportSpotsSearch);
}
}
void PrintObject::generate_support_material()
{
if (this->set_started(posSupportMaterial)) {

View file

@ -43,6 +43,9 @@
#include "SVG.hpp"
#endif
#pragma message ("TODO: Wrap svg usages in DEBUG ifdef and remove the following include")
#include "SVG.hpp"
// #undef NDEBUG
#include <cassert>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,82 @@
#ifndef SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
#define SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
#include "libslic3r/Print.hpp"
#include <boost/log/trivial.hpp>
namespace Slic3r {
namespace SupportSpotsGenerator {
struct Params {
Params(const std::vector<std::string> &filament_types) {
if (filament_types.size() > 1) {
BOOST_LOG_TRIVIAL(warning)
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
}
if (filament_types.empty() || filament_types[0].empty()) {
BOOST_LOG_TRIVIAL(error)
<< "SupportSpotsGenerator error: empty filament_type";
filament_type = std::string("PLA");
} else {
filament_type = filament_types[0];
}
}
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
const float bridge_distance = 12.0f; //mm
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
const float overhang_angle_deg = 80.0f;
const std::pair<float,float> malformation_angle_span_deg = std::pair<float, float> { 45.0f, 80.0f };
const float min_distance_between_support_points = 3.0f; //mm
const float support_points_interface_radius = 1.5f; // mm
const float connections_min_considerable_area = 1.5f; //mm^2
const float small_parts_threshold = 5.0f; //mm^3
const float small_parts_support_points_interface_radius = 3.0f; // mm
std::string filament_type;
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important
const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials.
const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... );
const float malformations_additive_conflict_extruder_force = 300.0f * gravity_constant; // for areas with possible high layered curled filaments
// MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface
double get_bed_adhesion_yield_strength() const {
if (filament_type == "PLA") {
return 0.018 * 1e6;
} else if (filament_type == "PET" || filament_type == "PETG") {
return 0.3 * 1e6;
} else { //PLA default value - defensive approach, PLA has quite low adhesion
return 0.018 * 1e6;
}
}
//just return PLA adhesion value as value for supports
double get_support_spots_adhesion_strength() const {
return 0.018f * 1e6;
}
};
struct SupportPoint {
SupportPoint(const Vec3f &position, float force, float spot_radius, const Vec3f &direction);
Vec3f position;
float force;
float spot_radius;
Vec3f direction;
};
struct Issues {
std::vector<SupportPoint> support_points;
};
// std::vector<size_t> quick_search(const PrintObject *po, const Params &params);
Issues full_search(const PrintObject *po, const Params &params);
}
}
#endif /* SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_ */

View file

@ -63,7 +63,6 @@ TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &pr
config.support_material_interface_layers.value) * this->layer_height :
0;
this->support_material_buildplate_only = config.support_material_buildplate_only;
// this->support_xy_overrides_z =
this->support_xy_distance = scaled<coord_t>(config.support_material_xy_spacing.get_abs_value(external_perimeter_width));
// Separation of interfaces, it is likely smaller than support_xy_distance.
this->support_xy_distance_overhang = std::min(this->support_xy_distance, scaled<coord_t>(0.5 * external_perimeter_width));
@ -163,15 +162,9 @@ TreeModelVolumes::TreeModelVolumes(
}
const TreeSupport::TreeSupportSettings config{ m_layer_outlines[m_current_outline_idx].first };
if (! config.support_xy_overrides_z) {
m_current_min_xy_dist = config.xy_min_distance;
if (TreeSupport::TreeSupportSettings::has_to_rely_on_min_xy_dist_only)
m_current_min_xy_dist = std::max(m_current_min_xy_dist, coord_t(100));
m_current_min_xy_dist_delta = std::max(config.xy_distance - m_current_min_xy_dist, coord_t(0));
} else {
m_current_min_xy_dist = config.xy_distance;
m_current_min_xy_dist_delta = 0;
}
m_current_min_xy_dist = config.xy_min_distance;
m_current_min_xy_dist_delta = config.xy_distance - m_current_min_xy_dist;
assert(m_current_min_xy_dist_delta >= 0);
m_increase_until_radius = config.increase_radius_until_radius;
m_radius_0 = config.getRadius(0);
@ -436,12 +429,14 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
const int z_distance_top_layers = round_up_divide<int>(settings.support_top_distance, layer_height);
const LayerIndex max_required_layer = std::min<LayerIndex>(outlines.size(), max_layer_idx + std::max(coord_t(1), z_distance_top_layers));
const LayerIndex min_layer_bottom = std::max<LayerIndex>(0, min_layer_last - int(z_distance_bottom_layers));
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
// not currently processing meshes as this delta will be added at request time.
// avoiding this would require saving each collision for each outline_idx separately.
// and later for each avoidance... But avoidance calculation has to be for the whole scene and can NOT be done for each outline_idx separately and combined later.
// so avoiding this inaccuracy seems infeasible as it would require 2x the avoidance calculations => 0.5x the performance.
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist : settings.support_xy_distance;
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist :
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
// not currently processing meshes as this delta will be added at request time.
// avoiding this would require saving each collision for each outline_idx separately.
// and later for each avoidance... But avoidance calculation has to be for the whole scene and can NOT be done for each outline_idx separately and combined later.
// so avoiding this inaccuracy seems infeasible as it would require 2x the avoidance calculations => 0.5x the performance.
//FIXME support_xy_distance is not corrected for "soluble" flag, see TreeSupportSettings constructor.
settings.support_xy_distance;
// 1) Calculate offsets of collision areas in parallel.
std::vector<Polygons> collision_areas_offsetted(max_required_layer + 1 - min_layer_bottom);

View file

@ -64,10 +64,6 @@ struct TreeSupportMeshGroupSettings {
// The thickness of the support floors. This controls the number of dense layers that are printed on top of places of a model on which support rests.
coord_t support_bottom_height { scaled<coord_t>(1.) };
bool support_material_buildplate_only { false };
// Support Distance Priority
// Whether the Support X/Y Distance overrides the Support Z Distance or vice versa. When X/Y overrides Z the X/Y distance can push away
// the support from the model, influencing the actual Z distance to the overhang. We can disable this by not applying the X/Y distance around overhangs.
bool support_xy_overrides_z { false };
// Support X/Y Distance
// Distance of the support structure from the print in the X/Y directions.
// minimum: 0, maximum warning: 1.5 * machine_nozzle_tip_outer_diameter
@ -75,7 +71,6 @@ struct TreeSupportMeshGroupSettings {
// Minimum Support X/Y Distance
// Distance of the support structure from the overhang in the X/Y directions.
// minimum_value: 0, minimum warning": support_xy_distance - support_line_width * 2, maximum warning: support_xy_distance
// Used if ! support_xy_overrides_z.
coord_t support_xy_distance_overhang { scaled<coord_t>(0.2) };
// Support Top Distance
// Distance from the top of the support to the print.
@ -91,7 +86,7 @@ struct TreeSupportMeshGroupSettings {
// A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end
// of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained
// in square brackets. Default is an empty list which means use the default angle 0 degrees.
std::vector<double> support_infill_angles {};
// std::vector<double> support_infill_angles {};
// Enable Support Roof
// Generate a dense slab of material between the top of support and the model. This will create a skin between the model and support.
bool support_roof_enable { false };

View file

@ -173,11 +173,9 @@ static std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_
for (size_t object_id = 0; object_id < print_object_ids.size(); ++ object_id) {
const PrintObject &print_object = *print.get_object(object_id);
const PrintObjectConfig &object_config = print_object.config();
if (object_config.support_material_interface_layers >= 2)
TreeSupport::TreeSupportSettings::some_model_contains_thick_roof = true;
if (object_config.support_material_contact_distance < EPSILON)
// || min_feature_size < scaled<coord_t>(0.1) that is the minimum line width
TreeSupport::TreeSupportSettings::has_to_rely_on_min_xy_dist_only = true;
TreeSupport::TreeSupportSettings::soluble = true;
}
size_t largest_printed_mesh_idx = 0;
@ -307,7 +305,7 @@ void TreeSupport::showError(std::string message, bool critical)
raw_overhangs_calculated = true;
}
if (! (enforced_layer || blockers_layers.empty() || blockers_layers[layer_id].empty()))
overhangs = diff(overhangs, blockers_layers[layer_id]);
overhangs = diff(overhangs, blockers_layers[layer_id], ApplySafetyOffset::Yes);
}
if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty())
// Has some support enforcers at this layer, apply them to the overhangs, don't apply the support threshold angle.
@ -531,26 +529,27 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
* \param layer_idx[in] The current layer.
* \return All lines of the \p polylines object, with information for each point regarding in which avoidance it is currently valid in.
*/
// Called by TreeSupport::generateInitialAreas()
[[nodiscard]] static LineInformations convertLinesToInternal(
const TreeModelVolumes &volumes, const TreeSupport::TreeSupportSettings &config,
const Polylines &polylines, LayerIndex layer_idx)
{
const bool xy_overrides_z = config.support_xy_overrides_z;
const bool min_xy_dist = config.xy_distance > config.xy_min_distance;
LineInformations result;
// Also checks if the position is valid, if it is NOT, it deletes that point
for (const Polyline &line : polylines) {
LineInformation res_line;
for (Point p : line) {
if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, false, !xy_overrides_z), p))
if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, false, min_xy_dist), p))
res_line.emplace_back(p, LineStatus::TO_BP_SAFE);
else if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, false, !xy_overrides_z), p))
else if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, false, min_xy_dist), p))
res_line.emplace_back(p, LineStatus::TO_BP);
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, true, !xy_overrides_z), p))
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, true, min_xy_dist), p))
res_line.emplace_back(p, LineStatus::TO_MODEL_GRACIOUS_SAFE);
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, true, !xy_overrides_z), p))
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, true, min_xy_dist), p))
res_line.emplace_back(p, LineStatus::TO_MODEL_GRACIOUS);
else if (config.support_rests_on_model && ! contains(volumes.getCollision(config.getRadius(0), layer_idx, !xy_overrides_z), p))
else if (config.support_rests_on_model && ! contains(volumes.getCollision(config.getRadius(0), layer_idx, min_xy_dist), p))
res_line.emplace_back(p, LineStatus::TO_MODEL);
else if (!res_line.empty()) {
result.emplace_back(res_line);
@ -597,13 +596,14 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
size_t current_layer, std::pair<Point, LineStatus> &p)
{
using AvoidanceType = TreeSupport::AvoidanceType;
if (! contains(volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_BP_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, false, !config.support_xy_overrides_z), p.first))
const bool min_xy_dist = config.xy_distance > config.xy_min_distance;
if (! contains(volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_BP_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, false, min_xy_dist), p.first))
return true;
if (config.support_rests_on_model && (p.second != LineStatus::TO_BP && p.second != LineStatus::TO_BP_SAFE))
return ! contains(
p.second == LineStatus::TO_MODEL_GRACIOUS || p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ?
volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, true, !config.support_xy_overrides_z) :
volumes.getCollision(config.getRadius(0), current_layer - 1, !config.support_xy_overrides_z),
volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, true, min_xy_dist) :
volumes.getCollision(config.getRadius(0), current_layer - 1, min_xy_dist),
p.first);
return false;
}
@ -1066,12 +1066,8 @@ void TreeSupport::generateInitialAreas(
SupportGeneratorLayersPtr &top_interface_layers,
SupportGeneratorLayerStorage &layer_storage)
{
Polygon base_circle;
const auto base_radius = scaled<int>(0.01);
for (unsigned int i = 0; i < SUPPORT_TREE_CIRCLE_RESOLUTION; ++ i) {
const double angle = static_cast<double>(i) / SUPPORT_TREE_CIRCLE_RESOLUTION * (2.0 * M_PI);
base_circle.points.emplace_back(coord_t(cos(angle) * base_radius), coord_t(sin(angle) * base_radius));
}
static constexpr const auto base_radius = scaled<int>(0.01);
const Polygon base_circle = make_circle(base_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
TreeSupportMeshGroupSettings mesh_group_settings(print_object);
TreeSupportSettings mesh_config{ mesh_group_settings };
SupportParameters support_params(print_object);
@ -1080,7 +1076,8 @@ void TreeSupport::generateInitialAreas(
const size_t z_distance_delta = mesh_config.z_distance_top_layers + 1; // To ensure z_distance_top_layers are left empty between the overhang (zeroth empty layer), the support has to be added z_distance_top_layers+1 layers below
const bool xy_overrides_z = mesh_config.support_xy_overrides_z;
const bool min_xy_dist = mesh_config.xy_distance > mesh_config.xy_min_distance;
#if 0
if (mesh.overhang_areas.size() <= z_distance_delta)
return;
@ -1096,7 +1093,7 @@ void TreeSupport::generateInitialAreas(
//FIXME Vojtech: This is not sufficient for support enforcers to work.
//FIXME There is no account for the support overhang angle.
//FIXME There is no account for the width of the collision regions.
const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width) + (xy_overrides_z ? 0 : mesh_config.support_line_width / 2)
const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width) + (min_xy_dist ? mesh_config.support_line_width / 2 : 0)
//FIXME this is a heuristic value for support enforcers to work.
// + 10 * mesh_config.support_line_width;
;
@ -1114,9 +1111,9 @@ void TreeSupport::generateInitialAreas(
std::mutex mutex_layer_storage, mutex_movebounds;
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_support_layers - z_distance_delta),
[this, &print_object, &overhangs, &mesh_config, &mesh_group_settings, &support_params,
z_distance_delta, xy_overrides_z, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag,
z_distance_delta, min_xy_dist, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag,
&base_circle, &mutex_layer_storage, &mutex_movebounds, &top_contacts, &layer_storage, &already_inserted,
&move_bounds, &base_radius](const tbb::blocked_range<size_t> &range) {
&move_bounds](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
if (overhangs[layer_idx + z_distance_delta].empty())
continue;
@ -1124,9 +1121,9 @@ void TreeSupport::generateInitialAreas(
Polygons relevant_forbidden;
{
const Polygons &relevant_forbidden_raw = (mesh_config.support_rests_on_model ?
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, true, !xy_overrides_z) :
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx, !xy_overrides_z)) :
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, false, !xy_overrides_z));
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, true, min_xy_dist) :
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx, min_xy_dist)) :
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, false, min_xy_dist));
// prevent rounding errors down the line, points placed directly on the line of the forbidden area may not be added otherwise.
relevant_forbidden = offset(union_ex(relevant_forbidden_raw), scaled<float>(0.005), jtMiter, 1.2);
}
@ -1154,7 +1151,7 @@ void TreeSupport::generateInitialAreas(
if (! already_inserted[insert_layer].count(p.first / ((mesh_config.min_radius + 1) / 10))) {
// normalize the point a bit to also catch points which are so close that inserting it would achieve nothing
already_inserted[insert_layer].emplace(p.first / ((mesh_config.min_radius + 1) / 10));
SupportElement* elem = new SupportElement(dtt, insert_layer, p.first, to_bp, gracious, !xy_overrides_z, dont_move_until, roof, safe_radius, force_tip_to_roof, skip_ovalisation);
SupportElement* elem = new SupportElement(dtt, insert_layer, p.first, to_bp, gracious, min_xy_dist, dont_move_until, roof, safe_radius, force_tip_to_roof, skip_ovalisation);
elem->area = new Polygons();
validate_range(circle);
elem->area->emplace_back(std::move(circle));
@ -1264,8 +1261,7 @@ void TreeSupport::generateInitialAreas(
}
// If the xy distance overrides the z distance, some support needs to be inserted further down.
//=> Analyze which support points do not fit on this layer and check if they will fit a few layers down (while adding them an infinite amount of layers down would technically be closer the the setting description, it would not produce reasonable results. )
if (xy_overrides_z)
{
if (! min_xy_dist) {
LineInformations overhang_lines;
{
//Vojtech: Generate support heads at support_tree_branch_distance spacing by producing a zig-zag infill at support_tree_branch_distance spacing,
@ -1286,10 +1282,9 @@ void TreeSupport::generateInitialAreas(
}
validate_range(overhang_lines);
}
for (size_t lag_ctr = 1; lag_ctr <= max_overhang_insert_lag && !overhang_lines.empty() && layer_idx - coord_t(lag_ctr) >= 1; lag_ctr++) {
// get least restricted avoidance for layer_idx-lag_ctr
const Polygons &relevant_forbidden_below = (mesh_config.support_rests_on_model ? (SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, true, !xy_overrides_z) : m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - lag_ctr, !xy_overrides_z)) : m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, false, !xy_overrides_z));
const Polygons &relevant_forbidden_below = (mesh_config.support_rests_on_model ? (SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, true, min_xy_dist) : m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - lag_ctr, min_xy_dist)) : m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, false, min_xy_dist));
// it is not required to offset the forbidden area here as the points wont change: If points here are not inside the forbidden area neither will they be later when placing these points, as these are the same points.
auto evaluatePoint = [&](std::pair<Point, LineStatus> p) { return contains(relevant_forbidden_below, p.first); };
@ -1310,7 +1305,7 @@ void TreeSupport::generateInitialAreas(
overhang_roofs = safeOffsetInc(overhangs[layer_idx + z_distance_delta], support_roof_offset, relevant_forbidden, mesh_config.min_radius * 2 + mesh_config.xy_min_distance, 0, 1);
if (mesh_group_settings.minimum_support_area > 0)
remove_small(overhang_roofs, mesh_group_settings.minimum_roof_area);
overhang_regular = diff(overhang_regular, overhang_roofs);
overhang_regular = diff(overhang_regular, overhang_roofs, ApplySafetyOffset::Yes);
for (ExPolygon &roof_part : union_ex(overhang_roofs))
overhang_processing.emplace_back(std::move(roof_part), true);
}
@ -1345,9 +1340,9 @@ void TreeSupport::generateInitialAreas(
{
const Polygons &forbidden_next_raw = mesh_config.support_rests_on_model ?
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ?
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, true, !xy_overrides_z) :
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), !xy_overrides_z)) :
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, false, !xy_overrides_z);
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, true, min_xy_dist) :
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), min_xy_dist)) :
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, false, min_xy_dist);
// prevent rounding errors down the line
forbidden_next = offset(union_ex(forbidden_next_raw), scaled<float>(0.005), jtMiter, 1.2);
}
@ -2406,12 +2401,8 @@ void TreeSupport::generateBranchAreas(
constexpr int progress_report_steps = 10;
#endif // SLIC3R_TREESUPPORTS_PROGRESS
Polygon branch_circle; // Pre-generate a circle with correct diameter so that we don't have to recompute those (co)sines every time.
for (unsigned int i = 0; i < SUPPORT_TREE_CIRCLE_RESOLUTION; ++ i) {
const double angle = static_cast<double>(i) / SUPPORT_TREE_CIRCLE_RESOLUTION * (2.0 * M_PI);
branch_circle.points.emplace_back(coord_t(cos(angle) * m_config.branch_radius), coord_t(sin(angle) * m_config.branch_radius));
}
// Pre-generate a circle with correct diameter so that we don't have to recompute those (co)sines every time.
const Polygon branch_circle = make_circle(m_config.branch_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
std::vector<Polygons> linear_inserts(linear_data.size());
#ifdef SLIC3R_TREESUPPORTS_PROGRESS

View file

@ -85,7 +85,6 @@ public:
void generateSupportAreas(Print &print, const BuildVolume &build_volume, const std::vector<size_t>& print_object_ids);
void generateSupportAreas(PrintObject &print_object);
//todo Remove! Only relevant for public BETA!
static bool inline showed_critical=false;
static bool inline showed_performance=false;
@ -375,14 +374,13 @@ public:
increase_radius_until_layer(increase_radius_until_radius <= branch_radius ? tip_layers * (increase_radius_until_radius / branch_radius) : (increase_radius_until_radius - branch_radius) / (branch_radius * diameter_angle_scale_factor)),
support_rests_on_model(! mesh_group_settings.support_material_buildplate_only),
xy_distance(mesh_group_settings.support_xy_distance),
xy_min_distance(std::min(mesh_group_settings.support_xy_distance, mesh_group_settings.support_xy_distance_overhang)),
bp_radius(mesh_group_settings.support_tree_bp_diameter / 2),
diameter_scale_bp_radius(std::min(sin(0.7) * layer_height / branch_radius, 1.0 / (branch_radius / (support_line_width / 2.0)))), // Either 40? or as much as possible so that 2 lines will overlap by at least 50%, whichever is smaller.
support_xy_overrides_z(mesh_group_settings.support_xy_overrides_z),
xy_min_distance(support_xy_overrides_z ? xy_distance : mesh_group_settings.support_xy_distance_overhang),
z_distance_top_layers(round_up_divide(mesh_group_settings.support_top_distance, layer_height)),
z_distance_bottom_layers(round_up_divide(mesh_group_settings.support_bottom_distance, layer_height)),
performance_interface_skip_layers(round_up_divide(mesh_group_settings.support_interface_skip_height, layer_height)),
support_infill_angles(mesh_group_settings.support_infill_angles),
// support_infill_angles(mesh_group_settings.support_infill_angles),
support_roof_angles(mesh_group_settings.support_roof_angles),
roof_pattern(mesh_group_settings.support_roof_pattern),
support_pattern(mesh_group_settings.support_pattern),
@ -399,40 +397,15 @@ public:
{
layer_start_bp_radius = (bp_radius - branch_radius) / (branch_radius * diameter_scale_bp_radius);
// safeOffsetInc can only work in steps of the size xy_min_distance in the worst case => xy_min_distance has to be a bit larger than 0 in this worst case and should be large enough for performance to not suffer extremely
// When for all meshes the z bottom and top distance is more than one layer though the worst case is xy_min_distance + min_feature_size
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
if (has_to_rely_on_min_xy_dist_only)
xy_min_distance = std::max(coord_t(100), xy_min_distance); // If set to low rounding errors WILL cause errors. Best to keep it above 25.
if (TreeSupport::TreeSupportSettings::soluble) {
// safeOffsetInc can only work in steps of the size xy_min_distance in the worst case => xy_min_distance has to be a bit larger than 0 in this worst case and should be large enough for performance to not suffer extremely
// When for all meshes the z bottom and top distance is more than one layer though the worst case is xy_min_distance + min_feature_size
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
xy_min_distance = std::max(xy_min_distance, scaled<coord_t>(0.1));
xy_distance = std::max(xy_distance, xy_min_distance);
}
xy_distance = std::max(xy_distance, xy_min_distance);
// (logic) from getInterfaceAngles in FFFGcodeWriter.
auto getInterfaceAngles = [&](std::vector<double>& angles, SupportMaterialInterfacePattern pattern) {
if (angles.empty())
{
if (pattern == SupportMaterialInterfacePattern::smipConcentric)
angles.push_back(0); // Concentric has no rotation.
/*
else if (pattern == SupportMaterialInterfacePattern::TRIANGLES)
angles.push_back(90); // Triangular support interface shouldn't alternate every layer.
*/
else {
if (TreeSupportSettings::some_model_contains_thick_roof) {
// Some roofs are quite thick.
// Alternate between the two kinds of diagonal: / and \ .
angles.push_back(M_PI / 4.);
angles.push_back(3. * M_PI / 4.);
}
if (angles.empty())
angles.push_back(M_PI / 2.); // Perpendicular to support lines.
}
}
};
//getInterfaceAngles(support_infill_angles, support_pattern);
support_infill_angles = { M_PI / 2. };
getInterfaceAngles(support_roof_angles, roof_pattern);
// const std::unordered_map<std::string, InterfacePreference> interface_map = { { "support_area_overwrite_interface_area", InterfacePreference::SUPPORT_AREA_OVERWRITES_INTERFACE }, { "interface_area_overwrite_support_area", InterfacePreference::INTERFACE_AREA_OVERWRITES_SUPPORT }, { "support_lines_overwrite_interface_area", InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE }, { "interface_lines_overwrite_support_area", InterfacePreference::INTERFACE_LINES_OVERWRITE_SUPPORT }, { "nothing", InterfacePreference::NOTHING } };
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
//FIXME this was the default
@ -448,8 +421,7 @@ public:
public:
// some static variables dependent on other meshes that are not currently processed.
// Has to be static because TreeSupportConfig will be used in TreeModelVolumes as this reduces redundancy.
inline static bool some_model_contains_thick_roof = false;
inline static bool has_to_rely_on_min_xy_dist_only = false;
inline static bool soluble = false;
/*!
* \brief Width of a single line of support.
*/
@ -522,10 +494,6 @@ public:
* \brief Factor by which to increase the branch radius to reach the required bp_radius at layer 0. Note that this radius increase will not happen in the tip, to ensure the tip is structurally sound.
*/
double diameter_scale_bp_radius;
/*!
* \brief Should Z distance override X/Y distance, or the other way around.
*/
bool support_xy_overrides_z;
/*!
* \brief minimum xy_distance. Only relevant when Z overrides XY, otherwise equal to xy_distance-
*/
@ -545,7 +513,7 @@ public:
/*!
* \brief User specified angles for the support infill.
*/
std::vector<double> support_infill_angles;
// std::vector<double> support_infill_angles;
/*!
* \brief User specified angles for the support roof infill.
*/
@ -603,9 +571,11 @@ public:
return branch_radius == other.branch_radius && tip_layers == other.tip_layers && diameter_angle_scale_factor == other.diameter_angle_scale_factor && layer_start_bp_radius == other.layer_start_bp_radius && bp_radius == other.bp_radius && diameter_scale_bp_radius == other.diameter_scale_bp_radius && min_radius == other.min_radius && xy_min_distance == other.xy_min_distance && // as a recalculation of the collision areas is required to set a new min_radius.
xy_distance - xy_min_distance == other.xy_distance - other.xy_min_distance && // if the delta of xy_min_distance and xy_distance is different the collision areas have to be recalculated.
support_rests_on_model == other.support_rests_on_model && increase_radius_until_layer == other.increase_radius_until_layer && min_dtt_to_model == other.min_dtt_to_model && max_to_model_radius_increase == other.max_to_model_radius_increase && maximum_move_distance == other.maximum_move_distance && maximum_move_distance_slow == other.maximum_move_distance_slow && z_distance_bottom_layers == other.z_distance_bottom_layers && support_line_width == other.support_line_width &&
support_xy_overrides_z == other.support_xy_overrides_z && support_line_spacing == other.support_line_spacing && support_roof_line_width == other.support_roof_line_width && // can not be set on a per-mesh basis currently, so code to enable processing different roof line width in the same iteration seems useless.
support_line_spacing == other.support_line_spacing && support_roof_line_width == other.support_roof_line_width && // can not be set on a per-mesh basis currently, so code to enable processing different roof line width in the same iteration seems useless.
support_bottom_offset == other.support_bottom_offset && support_wall_count == other.support_wall_count && support_pattern == other.support_pattern && roof_pattern == other.roof_pattern && // can not be set on a per-mesh basis currently, so code to enable processing different roof patterns in the same iteration seems useless.
support_roof_angles == other.support_roof_angles && support_infill_angles == other.support_infill_angles && increase_radius_until_radius == other.increase_radius_until_radius && support_bottom_layers == other.support_bottom_layers && layer_height == other.layer_height && z_distance_top_layers == other.z_distance_top_layers && resolution == other.resolution && // Infill generation depends on deviation and resolution.
support_roof_angles == other.support_roof_angles &&
//support_infill_angles == other.support_infill_angles &&
increase_radius_until_radius == other.increase_radius_until_radius && support_bottom_layers == other.support_bottom_layers && layer_height == other.layer_height && z_distance_top_layers == other.z_distance_top_layers && resolution == other.resolution && // Infill generation depends on deviation and resolution.
support_roof_line_distance == other.support_roof_line_distance && interface_preference == other.interface_preference
&& min_feature_size == other.min_feature_size // interface_preference should be identical to ensure the tree will correctly interact with the roof.
// The infill class now wants the settings object and reads a lot of settings, and as the infill class is used to calculate support roof lines for interface-preference. Not all of these may be required to be identical, but as I am not sure, better safe than sorry

View file

@ -0,0 +1,46 @@
#include "TriangleSelectorWrapper.hpp"
#include <memory>
namespace Slic3r {
TriangleSelectorWrapper::TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform) :
mesh(mesh), mesh_transform(mesh_transform), selector(mesh), triangles_tree(
AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(mesh.its.vertices, mesh.its.indices)) {
}
void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &origin, float radius) {
std::vector<igl::Hit> hits;
Vec3f dir = (point - origin).normalized();
if (AABBTreeIndirect::intersect_ray_all_hits(mesh.its.vertices, mesh.its.indices, triangles_tree,
Vec3d(origin.cast<double>()),
Vec3d(dir.cast<double>()),
hits)) {
for (int hit_idx = hits.size() - 1; hit_idx >= 0; --hit_idx) {
const igl::Hit &hit = hits[hit_idx];
Vec3f pos = origin + dir * hit.t;
Vec3f face_normal = its_face_normal(mesh.its, hit.id);
if ((point - pos).norm() < radius && face_normal.dot(dir) < 0) {
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
pos, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
selector.select_patch(hit.id, std::move(cursor), EnforcerBlockerType::ENFORCER, Transform3d::Identity(),
true, 0.0f);
break;
}
}
} else {
size_t hit_idx_out;
Vec3f hit_point_out;
float dist = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(mesh.its.vertices, mesh.its.indices,
triangles_tree, point, hit_idx_out, hit_point_out);
if (dist < radius) {
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
point, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
selector.select_patch(hit_idx_out, std::move(cursor), EnforcerBlockerType::ENFORCER,
Transform3d::Identity(),
true, 0.0f);
}
}
}
}

View file

@ -0,0 +1,31 @@
#ifndef SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
#define SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
#include "TriangleSelector.hpp"
#include "Model.hpp"
#include "AABBTreeIndirect.hpp"
namespace Slic3r {
//NOTE: We need to replace the FacetsAnnotation struct for support storage (or extend/add another)
// Problems: Does not support negative volumes, strange usage for supports computed from extrusion -
// expensively converted back to triangles and then sliced again.
// Another problem is weird and very limited interface when painting supports via algorithms
class TriangleSelectorWrapper {
public:
const TriangleMesh &mesh;
const Transform3d& mesh_transform;
TriangleSelector selector;
AABBTreeIndirect::Tree<3, float> triangles_tree;
TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform);
void enforce_spot(const Vec3f &point, const Vec3f& origin, float radius);
};
}
#endif /* SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_ */

View file

@ -738,7 +738,7 @@ void BackgroundSlicingProcess::prepare_upload()
ThumbnailsList thumbnails = this->render_thumbnails(
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.string());
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.filename().string());
}
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());

View file

@ -219,7 +219,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
{
bool have_perimeters = config->opt_int("perimeters") > 0;
for (auto el : { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
"seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width",
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" })
toggle_field(el, have_perimeters);

View file

@ -2564,9 +2564,9 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
if (check_unsaved_preset_changes)
header = _L("All user presets will be deleted.");
int act_btns = UnsavedChangesDialog::ActionButtons::KEEP;
int act_btns = ActionButtons::KEEP;
if (!check_unsaved_preset_changes)
act_btns |= UnsavedChangesDialog::ActionButtons::SAVE;
act_btns |= ActionButtons::SAVE;
// Install bundles from resources if needed:
std::vector<std::string> install_bundles;

View file

@ -33,7 +33,7 @@ wxString double_to_string(double const value, const int max_precision /*= 4*/)
// Style_NoTrailingZeroes does not work on OSX. It also does not work correctly with some locales on Windows.
// return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
wxString s = wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_None);
wxString s = wxNumberFormatter::ToString(value, value < 0.0001 ? 10 : max_precision, wxNumberFormatter::Style_None);
// The following code comes from wxNumberFormatter::RemoveTrailingZeroes(wxString& s)
// with the exception that here one sets the decimal separator explicitely to dot.

View file

@ -3288,6 +3288,7 @@ void GCodeViewer::render_toolpaths()
shader->set_uniform("emission_factor", 0.0f);
}
else {
shader->set_uniform("emission_factor", 0.15f);
#if ENABLE_LEGACY_OPENGL_REMOVAL
const int position_id = shader->get_attrib_location("v_position");
const int normal_id = shader->get_attrib_location("v_normal");
@ -3859,14 +3860,16 @@ void GCodeViewer::render_legend(float& legend_height)
if (m_view_type == EViewType::Tool) {
// calculate used filaments data
used_filaments_m = std::vector<double>(m_extruders_count, 0.0);
used_filaments_g = std::vector<double>(m_extruders_count, 0.0);
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
continue;
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
used_filaments_m.push_back(used_filament_m);
used_filaments_g.push_back(used_filament_g);
used_filaments_m[extruder_id] = used_filament_m;
used_filaments_g[extruder_id] = used_filament_g;
}
std::string longest_used_filament_string;
@ -3999,11 +4002,10 @@ void GCodeViewer::render_legend(float& legend_height)
#endif // ENABLE_PREVIEW_LAYER_TIME
case EViewType::Tool: {
// shows only extruders actually used
size_t i = 0;
for (unsigned char extruder_id : m_extruder_ids) {
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
true, "", 0.0f, 0.0f, offsets, used_filaments_m[i], used_filaments_g[i]);
++i;
if (used_filaments_m[extruder_id] > 0.0 && used_filaments_g[extruder_id] > 0.0)
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
true, "", 0.0f, 0.0f, offsets, used_filaments_m[extruder_id], used_filaments_g[extruder_id]);
}
break;
}

View file

@ -834,14 +834,14 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
imgui.begin(owner.title, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
float win_w = ImGui::GetWindowWidth();
float label_len = imgui.calc_text_size(owner.label).x;
float label_len = ImGui::CalcTextSize(owner.label.c_str()).x;
ImGui::SetCursorPosX(0.5f * (win_w - label_len));
ImGui::AlignTextToFramePadding();
imgui.text(owner.label);
if (!owner.print_order.empty()) {
ImGui::Separator();
float po_len = imgui.calc_text_size(owner.print_order).x;
float po_len = ImGui::CalcTextSize(owner.print_order.c_str()).x;
ImGui::SetCursorPosX(0.5f * (win_w - po_len));
ImGui::AlignTextToFramePadding();
imgui.text(owner.print_order);
@ -4173,7 +4173,7 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc
void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type)
{
std::string field = "layer_" + std::to_string(type) + "_" + std::to_string(range.first) + "_" + std::to_string(range.second);
std::string field = "layer_" + std::to_string(type) + "_" + float_to_string_decimal_point(range.first) + "_" + float_to_string_decimal_point(range.second);
handle_sidebar_focus_event(field, true);
}
@ -5504,28 +5504,41 @@ void GLCanvas3D::_picking_pass()
}
default: { break; }
}
auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) {
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
imgui.text_colored(col_1_color, col_1.c_str());
ImGui::TableSetColumnIndex(1);
imgui.text_colored(col_2_color, col_2.c_str());
};
char buf[1024];
if (hit.type != SceneRaycaster::EType::None) {
sprintf(buf, "Object ID: %d", hit.raycaster_id);
imgui.text(std::string(buf));
sprintf(buf, "Type: %s", object_type.c_str());
imgui.text(std::string(buf));
sprintf(buf, "Position: %.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
imgui.text(std::string(buf));
sprintf(buf, "Normal: %.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
imgui.text(std::string(buf));
if (ImGui::BeginTable("Hit", 2)) {
add_strings_row_to_table("Object ID", ImGuiWrapper::COL_ORANGE_LIGHT, std::to_string(hit.raycaster_id), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_strings_row_to_table("Type", ImGuiWrapper::COL_ORANGE_LIGHT, object_type, ImGui::GetStyleColorVec4(ImGuiCol_Text));
sprintf(buf, "%.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
add_strings_row_to_table("Position", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
sprintf(buf, "%.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
add_strings_row_to_table("Normal", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
ImGui::EndTable();
}
}
else
imgui.text("NO HIT");
ImGui::Separator();
imgui.text("Registered for picking:");
sprintf(buf, "Beds: %d", (int)m_scene_raycaster.beds_count());
imgui.text(std::string(buf));
sprintf(buf, "Volumes: %d", (int)m_scene_raycaster.volumes_count());
imgui.text(std::string(buf));
sprintf(buf, "Gizmo elements: %d", (int)m_scene_raycaster.gizmos_count());
imgui.text(std::string(buf));
if (ImGui::BeginTable("Raycasters", 2)) {
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.beds_count(), (int)m_scene_raycaster.active_beds_count());
add_strings_row_to_table("Beds", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.volumes_count(), (int)m_scene_raycaster.active_volumes_count());
add_strings_row_to_table("Volumes", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.gizmos_count(), (int)m_scene_raycaster.active_gizmos_count());
add_strings_row_to_table("Gizmo elements", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
ImGui::EndTable();
}
imgui.end();
#endif // ENABLE_RAYCAST_PICKING_DEBUG
}

View file

@ -157,7 +157,7 @@ namespace GUI {
GLModel::Geometry init_data;
#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P4 };
init_data.reserve_vertices(8);
init_data.reserve_vertices(5);
init_data.reserve_indices(8);
#else
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
@ -173,25 +173,19 @@ namespace GUI {
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
perimeter += width;
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
perimeter += height;
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
perimeter += width;
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
perimeter += height;
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
// indices
init_data.add_line(0, 1);
init_data.add_line(1, 2);
init_data.add_line(2, 3);
init_data.add_line(4, 5);
init_data.add_line(6, 7);
init_data.add_line(3, 4);
#else
init_data.add_vertex(Vec2f(left, bottom));
init_data.add_vertex(Vec2f(right, bottom));

View file

@ -1898,7 +1898,7 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
{
input_files.Clear();
wxFileDialog dialog(parent ? parent : GetTopWindow(),
_L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA/STEP):"),
_L("Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"),
from_u8(app_config->get_last_dir()), "",
file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
@ -2522,9 +2522,9 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con
{
if (has_current_preset_changes()) {
const std::string app_config_key = remember_choice ? "default_action_on_close_application" : "";
int act_buttons = UnsavedChangesDialog::ActionButtons::SAVE;
int act_buttons = ActionButtons::SAVE;
if (dont_save_insted_of_discard)
act_buttons |= UnsavedChangesDialog::ActionButtons::DONT_SAVE;
act_buttons |= ActionButtons::DONT_SAVE;
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)

View file

@ -991,7 +991,7 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
void ObjectList::extruder_editing()
{
wxDataViewItem item = GetSelection();
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject | itLayer)))
return;
wxRect rect = this->GetItemRect(item, GetColumn(colExtruder));
@ -1016,6 +1016,7 @@ void ObjectList::extruder_editing()
m_extruder_editor->Hide();
update_extruder_in_config(item);
Refresh();
};
// to avoid event propagation to other sidebar items

View file

@ -590,7 +590,10 @@ void ObjectManipulation::update_ui_from_settings()
for (int i = 0; i < 3; ++i) {
auto update = [this, i](/*ManipulationEditorKey*/int key_id, const Vec3d& new_value) {
wxString new_text = double_to_string(m_imperial_units ? new_value(i) * mm_to_in : new_value(i), 2);
double value = new_value(i);
if (m_imperial_units)
value *= mm_to_in;
wxString new_text = double_to_string(value, m_imperial_units && key_id == 3/*meSize*/ ? 4 : 2);
const int id = key_id * 3 + i;
if (id >= 0) m_editors[id]->set_value(new_text);
};
@ -776,14 +779,22 @@ void ObjectManipulation::update_if_dirty()
for (int i = 0; i < 3; ++ i) {
auto update = [this, i](Vec3d &cached, Vec3d &cached_rounded, ManipulationEditorKey key_id, const Vec3d &new_value) {
wxString new_text = double_to_string(new_value(i), 2);
wxString new_text = double_to_string(new_value(i), m_imperial_units && key_id == meSize ? 4 : 2);
double new_rounded;
new_text.ToDouble(&new_rounded);
if (std::abs(cached_rounded(i) - new_rounded) > EPSILON) {
cached_rounded(i) = new_rounded;
const int id = key_id*3+i;
if (m_imperial_units && (key_id == mePosition || key_id == meSize))
new_text = double_to_string(new_value(i)*mm_to_in, 2);
if (m_imperial_units) {
double inch_value = new_value(i) * mm_to_in;
if (key_id == mePosition)
new_text = double_to_string(inch_value, 2);
if (key_id == meSize) {
if(std::abs(m_cache.size_inches(i) - inch_value) > EPSILON)
m_cache.size_inches(i) = inch_value;
new_text = double_to_string(inch_value, 4);
}
}
if (id >= 0) m_editors[id]->set_value(new_text);
}
cached(i) = new_value(i);
@ -1137,6 +1148,13 @@ void ObjectManipulation::change_size_value(int axis, double value)
if (value <= 0.0)
return;
if (m_imperial_units) {
if (std::abs(m_cache.size_inches(axis) - value) < EPSILON)
return;
m_cache.size_inches(axis) = value;
value *= in_to_mm;
}
if (std::abs(m_cache.size_rounded(axis) - value) < EPSILON)
return;
@ -1237,11 +1255,11 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
if (!m_cache.is_valid())
return;
if (m_imperial_units && (opt_key == "position" || opt_key == "size"))
new_value *= in_to_mm;
if (opt_key == "position")
if (opt_key == "position") {
if (m_imperial_units)
new_value *= in_to_mm;
change_position_value(axis, new_value);
}
else if (opt_key == "rotation")
change_rotation_value(axis, new_value);
else if (opt_key == "scale") {

View file

@ -85,6 +85,7 @@ private:
Vec3d scale;
Vec3d scale_rounded;
Vec3d size;
Vec3d size_inches;
Vec3d size_rounded;
wxString move_label_string;

View file

@ -705,8 +705,17 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time);
}
// check if ticks_info_from_model contains ColorChange g-code
bool color_change_already_exists = false;
for (const CustomGCode::Item& gcode: ticks_info_from_model.gcodes)
if (gcode.type == CustomGCode::Type::ColorChange) {
color_change_already_exists = true;
break;
}
// Suggest the auto color change, if model looks like sign
if (wxGetApp().app_config->get("allow_auto_color_change") == "1" &&
if (!color_change_already_exists &&
wxGetApp().app_config->get("allow_auto_color_change") == "1" &&
m_layers_slider->IsNewPrint())
{
const Print& print = wxGetApp().plater()->fff_print();
@ -804,6 +813,7 @@ void Preview::update_layers_slider_mode()
for (const auto& range : object->layer_config_ranges)
if (range.second.has("extruder") &&
range.second.option("extruder")->getInt() != 0 && // extruder isn't default
range.second.option("extruder")->getInt() != extruder)
return false;
}

View file

@ -10,6 +10,8 @@
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include "slic3r/GUI/format.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/Print.hpp"
#include "slic3r/GUI/MsgDialog.hpp"
#include <GL/glew.h>
@ -39,6 +41,8 @@ bool GLGizmoFdmSupports::on_init()
{
m_shortcut_key = WXK_CONTROL_L;
m_desc["auto_generate"] = _L("Auto-generate supports");
m_desc["generating"] = _L("Generating supports...");
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
m_desc["reset_direction"] = _L("Reset direction");
m_desc["cursor_size"] = _L("Brush size") + ": ";
@ -91,7 +95,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
if (! m_c->selection_info()->model_object())
return;
const float approx_height = m_imgui->scaled(23.f);
const float approx_height = m_imgui->scaled(25.f);
y = std::min(y, bottom_limit - approx_height);
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
@ -153,6 +157,15 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::Separator();
if (waiting_for_autogenerated_supports) {
m_imgui->text(m_desc.at("generating"));
} else {
bool generate = m_imgui->button(m_desc.at("auto_generate"));
if (generate)
auto_generate();
}
ImGui::Separator();
float position_before_text_y = ImGui::GetCursorPos().y;
ImGui::AlignTextToFramePadding();
m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width);
@ -319,6 +332,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
}
update_model_object();
this->waiting_for_autogenerated_supports = false;
m_parent.set_as_dirty();
}
@ -366,9 +380,54 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
: _L("Add supports by angle"));
update_model_object();
this->waiting_for_autogenerated_supports = false;
m_parent.set_as_dirty();
}
void GLGizmoFdmSupports::data_changed()
{
GLGizmoPainterBase::data_changed();
if (! m_c->selection_info())
return;
ModelObject* mo = m_c->selection_info()->model_object();
if (mo && this->waiting_for_autogenerated_supports) {
get_data_from_backend();
} else {
this->waiting_for_autogenerated_supports = false;
}
}
void GLGizmoFdmSupports::get_data_from_backend()
{
if (! has_backend_supports())
return;
ModelObject* mo = m_c->selection_info()->model_object();
// find the respective PrintObject, we need a pointer to it
for (const PrintObject* po : m_parent.fff_print()->objects()) {
if (po->model_object()->id() == mo->id()) {
std::unordered_map<size_t, const ModelVolume*> mvs;
for (const ModelVolume* mv : po->model_object()->volumes) {
if (mv->is_model_part()) {
mvs.emplace(mv->id().id, mv);
}
}
int mesh_id = -1.0f;
for (ModelVolume* mv : mo->volumes){
if (mv->is_model_part()){
mesh_id++;
mv->supported_facets.assign(mvs[mv->id().id]->supported_facets);
m_triangle_selectors[mesh_id]->deserialize(mv->supported_facets.get_data(), true);
m_triangle_selectors[mesh_id]->request_update_render_data();
}
}
this->waiting_for_autogenerated_supports = false;
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
m_parent.set_as_dirty();
}
}
}
void GLGizmoFdmSupports::update_model_object() const
@ -391,8 +450,6 @@ void GLGizmoFdmSupports::update_model_object() const
}
}
void GLGizmoFdmSupports::update_from_model_object()
{
wxBusyCursor wait;
@ -417,6 +474,58 @@ void GLGizmoFdmSupports::update_from_model_object()
}
}
bool GLGizmoFdmSupports::has_backend_supports() const
{
const ModelObject* mo = m_c->selection_info()->model_object();
if (! mo)
return false;
// find PrintObject with this ID
for (const PrintObject* po : m_parent.fff_print()->objects()) {
if (po->model_object()->id() == mo->id())
return po->is_step_done(posSupportSpotsSearch);
}
return false;
}
void GLGizmoFdmSupports::reslice_FDM_supports(bool postpone_error_messages) const {
wxGetApp().CallAfter(
[this, postpone_error_messages]() {
wxGetApp().plater()->reslice_FFF_until_step(posSupportSpotsSearch,
*m_c->selection_info()->model_object(), postpone_error_messages);
});
}
void GLGizmoFdmSupports::auto_generate()
{
ModelObject *mo = m_c->selection_info()->model_object();
bool not_painted = std::all_of(mo->volumes.begin(), mo->volumes.end(), [](const ModelVolume* vol){
return vol->type() != ModelVolumeType::MODEL_PART || vol->supported_facets.empty();
});
MessageDialog dlg(GUI::wxGetApp().plater(),
_L("Autogeneration will erase all currently painted areas.") + "\n\n" +
_L("Are you sure you want to do it?") + "\n",
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (not_painted || dlg.ShowModal() == wxID_YES) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
int mesh_id = -1.0f;
for (ModelVolume *mv : mo->volumes) {
if (mv->is_model_part()) {
mesh_id++;
mv->supported_facets.reset();
m_triangle_selectors[mesh_id]->reset();
m_triangle_selectors[mesh_id]->request_update_render_data();
}
}
mo->config.set("support_material", true);
mo->config.set("support_material_auto", false);
this->waiting_for_autogenerated_supports = true;
wxGetApp().CallAfter([this]() { reslice_FDM_supports(); });
}
}
PainterGizmoType GLGizmoFdmSupports::get_painter_type() const

View file

@ -26,6 +26,7 @@ protected:
private:
bool on_init() override;
void data_changed() override;
void update_model_object() const override;
void update_from_model_object() override;
@ -39,6 +40,13 @@ private:
// This map holds all translated description texts, so they can be easily referenced during layout calculations
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
std::map<std::string, wxString> m_desc;
bool waiting_for_autogenerated_supports = false;
bool has_backend_supports() const;
void reslice_FDM_supports(bool postpone_error_messages = false) const;
void auto_generate();
void get_data_from_backend();
};

View file

@ -59,6 +59,9 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::PreferencesHoverButton, "notification_preferences_hover"},
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
{ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" },
};
static const std::map<const wchar_t, std::string> font_icons_large = {
#if ENABLE_LEGEND_TOOLBAR_ICONS
{ImGui::LegendTravel , "legend_travel" },
{ImGui::LegendWipe , "legend_wipe" },
@ -73,9 +76,6 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::LegendShells , "legend_shells" },
{ImGui::LegendToolMarker , "legend_toolmarker" },
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
};
static const std::map<const wchar_t, std::string> font_icons_large = {
{ImGui::CloseNotifButton , "notification_close" },
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
{ImGui::EjectButton , "notification_eject_sd" },
@ -97,7 +97,6 @@ static const std::map<const wchar_t, std::string> font_icons_large = {
static const std::map<const wchar_t, std::string> font_icons_extra_large = {
{ImGui::ClippyMarker , "notification_clippy" },
};
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.33f, 0.33f, 0.33f, 1.0f };

View file

@ -75,12 +75,12 @@ void KBShortcutsDialog::fill_shortcuts()
Shortcuts commands_shortcuts = {
// File
{ ctrl + "N", L("New project, clear plater") },
{ ctrl + "O", L("Open project STL/OBJ/AMF/3MF with config, clear plater") },
{ ctrl + "O", L("Open project AMF/3MF with config, clear plater") },
{ ctrl + "S", L("Save project (3mf)") },
{ ctrl + alt + "S", L("Save project as (3mf)") },
{ ctrl + "R", L("(Re)slice") },
// File>Import
{ ctrl + "I", L("Import STL/OBJ/AMF/3MF/STEP without config, keep plater") },
{ ctrl + "I", L("Import STL/3MF/STEP/OBJ/AMF without config, keep plater") },
{ ctrl + "L", L("Import Config from ini/amf/3mf/gcode") },
{ ctrl + alt + "L", L("Load Config from ini/amf/3mf/gcode and merge") },
// File>Export

View file

@ -277,8 +277,52 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
preferences_dialog = new PreferencesDialog(this);
}
// bind events from DiffDlg
bind_diff_dialog();
}
void MainFrame::bind_diff_dialog()
{
auto get_tab = [](Preset::Type type) {
Tab* null_tab = nullptr;
for (Tab* tab : wxGetApp().tabs_list)
if (tab->type() == type)
return tab;
return null_tab;
};
auto transfer = [this, get_tab](Preset::Type type) {
get_tab(type)->transfer_options(diff_dialog.get_left_preset_name(type),
diff_dialog.get_right_preset_name(type),
std::move(diff_dialog.get_selected_options(type)));
};
auto save = [this, get_tab](Preset::Type type) {
get_tab(type)->save_options(diff_dialog.get_left_preset_name(type),
diff_dialog.get_right_preset_name(type),
std::move(diff_dialog.get_selected_options(type)));
};
auto process_options = [this](std::function<void(Preset::Type)> process) {
const Preset::Type diff_dlg_type = diff_dialog.view_type();
if (diff_dlg_type == Preset::TYPE_INVALID) {
for (const Preset::Type& type : diff_dialog.printer_technology() == ptFFF ?
std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_PRINT, Preset::TYPE_FILAMENT} :
std::initializer_list<Preset::Type>{ Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL } )
process(type);
}
else
process(diff_dlg_type);
};
diff_dialog.Bind(EVT_DIFF_DIALOG_TRANSFER, [this, process_options, transfer](SimpleEvent&) { process_options(transfer); });
diff_dialog.Bind(EVT_DIFF_DIALOG_SAVE, [this, process_options, save](SimpleEvent&) { process_options(save); });
}
#ifdef _MSW_DARK_MODE
static wxString pref() { return " [ "; }
static wxString suff() { return " ] "; }
@ -1219,7 +1263,7 @@ void MainFrame::init_menubar_as_editor()
fileMenu->AppendSeparator();
wxMenu* import_menu = new wxMenu();
append_menu_item(import_menu, wxID_ANY, _L("Import STL/OBJ/AM&F/3MF/STEP") + dots + "\tCtrl+I", _L("Load a model"),
append_menu_item(import_menu, wxID_ANY, _L("Import STL/3MF/STEP/OBJ/AM&F") + dots + "\tCtrl+I", _L("Load a model"),
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater", nullptr,
[this](){return m_plater != nullptr; }, this);
@ -2130,9 +2174,6 @@ void MainFrame::add_to_recent_projects(const wxString& filename)
void MainFrame::technology_changed()
{
// upadte DiffDlg
diff_dialog.update_presets();
// update menu titles
PrinterTechnology pt = plater()->printer_technology();
if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND)

View file

@ -107,6 +107,7 @@ class MainFrame : public DPIFrame
bool can_delete() const;
bool can_delete_all() const;
bool can_reslice() const;
void bind_diff_dialog();
// MenuBar items changeable in respect to printer technology
enum MenuItems

Some files were not shown because too many files have changed in this diff Show more