mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 02:55:55 +08:00
Merge remote-tracking branch 'remotes/prusa/master'
not merged: fill.cpp, perimeter_generator, because they ahve been reworked and need to be understand fully before adding my extensive modifications. To verify: glcanvas: maybe filament color selection is deleted (or the other one i added?)
This commit is contained in:
commit
2f042e030c
@ -368,7 +368,7 @@ target_include_directories(cereal INTERFACE include)
|
||||
# l10n
|
||||
set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization")
|
||||
add_custom_target(pot
|
||||
COMMAND xgettext --keyword=L --add-comments=TRN --from-code=UTF-8 --debug
|
||||
COMMAND xgettext --keyword=L --keyword=L_CONTEXT:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --debug
|
||||
-f "${L10N_DIR}/list.txt"
|
||||
-o "${L10N_DIR}/Slic3r++.pot"
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
@ -398,8 +398,10 @@ endif()
|
||||
# Resources install target, configure fhs.hpp on UNIX
|
||||
if (WIN32)
|
||||
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
|
||||
else ()
|
||||
elseif (SLIC3R_FHS)
|
||||
set(SLIC3R_FHS_RESOURCES "${CMAKE_INSTALL_FULL_DATAROOTDIR}/slic3r++")
|
||||
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${SLIC3R_FHS_RESOURCES}")
|
||||
else ()
|
||||
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
|
||||
endif ()
|
||||
configure_file(${LIBDIR}/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/platform/unix/fhs.hpp)
|
||||
|
13
resources/icons/redo_menu.svg
Normal file
13
resources/icons/redo_menu.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<path id="undo_1_" fill="#808080" d="M1.95,7.01h10.24L8.86,2.51c-0.31-0.42-0.22-1.01,0.2-1.32c0.42-0.31,1.01-0.22,1.32,0.2
|
||||
l4.44,6.01c0,0.01,0.01,0.01,0.01,0.02c0.01,0.01,0.02,0.03,0.03,0.04c0.01,0.02,0.03,0.05,0.04,0.07c0.01,0.02,0.02,0.03,0.03,0.05
|
||||
c0.01,0.01,0.01,0.03,0.02,0.04c0.01,0.02,0.02,0.05,0.02,0.07c0.01,0.02,0.01,0.04,0.02,0.06c0,0.01,0,0.03,0.01,0.04
|
||||
c0,0.02,0.01,0.05,0.01,0.07c0,0.02,0.01,0.05,0.01,0.07c0,0.01,0,0.01,0,0.02c0,0.01,0,0.01,0,0.02c0,0.02,0,0.05-0.01,0.07
|
||||
c0,0.02,0,0.05-0.01,0.07c0,0.01,0,0.03-0.01,0.04c0,0.02-0.01,0.04-0.02,0.06c-0.01,0.02-0.01,0.05-0.02,0.07
|
||||
c-0.01,0.01-0.01,0.03-0.02,0.04c-0.01,0.02-0.02,0.04-0.03,0.05c-0.01,0.02-0.02,0.04-0.04,0.07c-0.01,0.01-0.02,0.03-0.03,0.04
|
||||
c0,0.01-0.01,0.01-0.01,0.02l-4.54,6.05c-0.19,0.25-0.47,0.38-0.76,0.38c-0.2,0-0.4-0.06-0.57-0.19c-0.42-0.31-0.5-0.91-0.19-1.32
|
||||
l3.41-4.54H1.95C1.42,8.91,1,8.48,1,7.96C1,7.44,1.42,7.01,1.95,7.01z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="redo">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" d="M13.39,11
|
||||
c-0.91,1.78-2.76,3-4.89,3C5.46,14,3,11.54,3,8.5C3,5.46,5.46,3,8.5,3C8.67,3,8.84,3.01,9,3.03"/>
|
||||
|
||||
<polygon fill="#ED6B21" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
|
||||
9,1 9,5 12,3 "/>
|
||||
</g>
|
||||
<path id="undo_1_" fill="#ED6B21" d="M1.95,7.01h10.24L8.86,2.51c-0.31-0.42-0.22-1.01,0.2-1.32c0.42-0.31,1.01-0.22,1.32,0.2
|
||||
l4.44,6.01c0,0.01,0.01,0.01,0.01,0.02c0.01,0.01,0.02,0.03,0.03,0.04c0.01,0.02,0.03,0.05,0.04,0.07c0.01,0.02,0.02,0.03,0.03,0.05
|
||||
c0.01,0.01,0.01,0.03,0.02,0.04c0.01,0.02,0.02,0.05,0.02,0.07c0.01,0.02,0.01,0.04,0.02,0.06c0,0.01,0,0.03,0.01,0.04
|
||||
c0,0.02,0.01,0.05,0.01,0.07c0,0.02,0.01,0.05,0.01,0.07c0,0.01,0,0.01,0,0.02c0,0.01,0,0.01,0,0.02c0,0.02,0,0.05-0.01,0.07
|
||||
c0,0.02,0,0.05-0.01,0.07c0,0.01,0,0.03-0.01,0.04c0,0.02-0.01,0.04-0.02,0.06c-0.01,0.02-0.01,0.05-0.02,0.07
|
||||
c-0.01,0.01-0.01,0.03-0.02,0.04c-0.01,0.02-0.02,0.04-0.03,0.05c-0.01,0.02-0.02,0.04-0.04,0.07c-0.01,0.01-0.02,0.03-0.03,0.04
|
||||
c0,0.01-0.01,0.01-0.01,0.02l-4.54,6.05c-0.19,0.25-0.47,0.38-0.76,0.38c-0.2,0-0.4-0.06-0.57-0.19c-0.42-0.31-0.5-0.91-0.19-1.32
|
||||
l3.41-4.54H1.95C1.42,8.91,1,8.48,1,7.96C1,7.44,1.42,7.01,1.95,7.01z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 734 B After Width: | Height: | Size: 1.2 KiB |
13
resources/icons/undo_menu.svg
Normal file
13
resources/icons/undo_menu.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<path id="undo_1_" fill="#808080" d="M14.05,7.01H3.82l3.32-4.51c0.31-0.42,0.22-1.01-0.2-1.32c-0.42-0.31-1.01-0.22-1.32,0.2
|
||||
L1.18,7.4c0,0.01-0.01,0.01-0.01,0.02C1.17,7.43,1.16,7.44,1.15,7.46C1.13,7.48,1.12,7.5,1.11,7.53C1.1,7.54,1.09,7.56,1.08,7.58
|
||||
C1.08,7.59,1.07,7.61,1.06,7.62C1.06,7.65,1.05,7.67,1.04,7.69C1.04,7.71,1.03,7.73,1.02,7.75c0,0.01,0,0.03-0.01,0.04
|
||||
c0,0.02-0.01,0.05-0.01,0.07C1.01,7.89,1,7.92,1,7.94c0,0.01,0,0.01,0,0.02c0,0.01,0,0.01,0,0.02c0,0.02,0,0.05,0.01,0.07
|
||||
c0,0.02,0,0.05,0.01,0.07c0,0.01,0,0.03,0.01,0.04c0,0.02,0.01,0.04,0.02,0.06C1.05,8.26,1.06,8.28,1.07,8.3
|
||||
c0.01,0.01,0.01,0.03,0.02,0.04C1.09,8.36,1.1,8.38,1.11,8.4c0.01,0.02,0.02,0.04,0.04,0.07c0.01,0.01,0.02,0.03,0.03,0.04
|
||||
c0,0.01,0.01,0.01,0.01,0.02l4.54,6.05c0.19,0.25,0.47,0.38,0.76,0.38c0.2,0,0.4-0.06,0.57-0.19c0.42-0.31,0.5-0.91,0.19-1.32
|
||||
L3.84,8.91h10.22c0.52,0,0.95-0.42,0.95-0.95C15,7.44,14.58,7.01,14.05,7.01z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="undo">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" d="M3,11
|
||||
c0.91,1.78,2.76,3,4.89,3c3.04,0,5.5-2.46,5.5-5.5c0-3.04-2.46-5.5-5.5-5.5c-0.17,0-0.34,0.01-0.5,0.03"/>
|
||||
|
||||
<polygon fill="#ED6B21" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
|
||||
7.39,1 7.39,5 4.39,3 "/>
|
||||
</g>
|
||||
<path id="undo_1_" fill="#ED6B21" d="M14.05,7.01H3.82l3.32-4.51c0.31-0.42,0.22-1.01-0.2-1.32c-0.42-0.31-1.01-0.22-1.32,0.2
|
||||
L1.18,7.4c0,0.01-0.01,0.01-0.01,0.02C1.17,7.43,1.16,7.44,1.15,7.46C1.13,7.48,1.12,7.5,1.11,7.53C1.1,7.54,1.09,7.56,1.08,7.58
|
||||
C1.08,7.59,1.07,7.61,1.06,7.62C1.06,7.65,1.05,7.67,1.04,7.69C1.04,7.71,1.03,7.73,1.02,7.75c0,0.01,0,0.03-0.01,0.04
|
||||
c0,0.02-0.01,0.05-0.01,0.07C1.01,7.89,1,7.92,1,7.94c0,0.01,0,0.01,0,0.02c0,0.01,0,0.01,0,0.02c0,0.02,0,0.05,0.01,0.07
|
||||
c0,0.02,0,0.05,0.01,0.07c0,0.01,0,0.03,0.01,0.04c0,0.02,0.01,0.04,0.02,0.06C1.05,8.26,1.06,8.28,1.07,8.3
|
||||
c0.01,0.01,0.01,0.03,0.02,0.04C1.09,8.36,1.1,8.38,1.11,8.4c0.01,0.02,0.02,0.04,0.04,0.07c0.01,0.01,0.02,0.03,0.03,0.04
|
||||
c0,0.01,0.01,0.01,0.01,0.02l4.54,6.05c0.19,0.25,0.47,0.38,0.76,0.38c0.2,0,0.4-0.06,0.57-0.19c0.42-0.31,0.5-0.91,0.19-1.32
|
||||
L3.84,8.91h10.22c0.52,0,0.95-0.42,0.95-0.95C15,7.44,14.58,7.01,14.05,7.01z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 746 B After Width: | Height: | Size: 1.2 KiB |
File diff suppressed because it is too large
Load Diff
BIN
resources/localization/cs/PrusaSlicer.mo
Normal file
BIN
resources/localization/cs/PrusaSlicer.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
resources/localization/de/PrusaSlicer.mo
Normal file
BIN
resources/localization/de/PrusaSlicer.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
resources/localization/fr/PrusaSlicer.mo
Normal file
BIN
resources/localization/fr/PrusaSlicer.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
resources/localization/ko/PrusaSlicer.mo
Normal file
BIN
resources/localization/ko/PrusaSlicer.mo
Normal file
Binary file not shown.
8977
resources/localization/ko/PrusaSlicer_ko_KR.po
Normal file
8977
resources/localization/ko/PrusaSlicer_ko_KR.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -9,14 +9,17 @@ src/slic3r/GUI/ConfigWizard.cpp
|
||||
src/slic3r/GUI/Field.cpp
|
||||
src/slic3r/GUI/FirmwareDialog.cpp
|
||||
src/slic3r/GUI/GLCanvas3D.cpp
|
||||
src/slic3r/GUI/GLCanvas3DManager.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
|
||||
src/slic3r/GUI/GUI.cpp
|
||||
src/slic3r/GUI/GUI_App.cpp
|
||||
src/slic3r/GUI/GUI_ObjectLayers.cpp
|
||||
src/slic3r/GUI/GUI_ObjectList.cpp
|
||||
src/slic3r/GUI/GUI_ObjectManipulation.cpp
|
||||
src/slic3r/GUI/GUI_ObjectSettings.cpp
|
||||
@ -24,6 +27,7 @@ src/slic3r/GUI/GUI_Preview.cpp
|
||||
src/slic3r/GUI/KBShortcutsDialog.cpp
|
||||
src/slic3r/GUI/MainFrame.cpp
|
||||
src/slic3r/GUI/MsgDialog.cpp
|
||||
src/slic3r/GUI/OptionsGroup.cpp
|
||||
src/slic3r/GUI/Plater.cpp
|
||||
src/slic3r/GUI/Preferences.cpp
|
||||
src/slic3r/GUI/Preset.cpp
|
||||
@ -32,6 +36,7 @@ src/slic3r/GUI/PresetHints.cpp
|
||||
src/slic3r/GUI/PrintHostDialogs.cpp
|
||||
src/slic3r/GUI/ProgressStatusBar.cpp
|
||||
src/slic3r/GUI/RammingChart.cpp
|
||||
src/slic3r/GUI/Selection.cpp
|
||||
src/slic3r/GUI/SysInfoDialog.cpp
|
||||
src/slic3r/GUI/Tab.cpp
|
||||
src/slic3r/GUI/Tab.hpp
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
resources/localization/zh_cn/PrusaSlicer.mo
Normal file
BIN
resources/localization/zh_cn/PrusaSlicer.mo
Normal file
Binary file not shown.
8889
resources/localization/zh_cn/PrusaSlicer_zh_CN.po
Normal file
8889
resources/localization/zh_cn/PrusaSlicer_zh_CN.po
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,14 @@
|
||||
min_slic3r_version = 2.1.0-alpha0
|
||||
1.0.1 Updated MK3 firmware version check to 3.8.0, new soluble support profiles for 0.6mm nozzle diameter MMU2S printers.
|
||||
1.0.0 Updated end G-code for the MMU2 profiles to lift the extruder at the end of print. Wipe tower bridging distance was made smaller for soluble supports.
|
||||
1.0.0-beta1 Updated color for the ASA filaments to differ from the other filaments. Single extruder printers now have no extruder color assigned, obects and toolpaths will be colored with the color of the active filament.
|
||||
1.0.0-beta0 Printer model checks in start G-codes, ASA filament profiles, limits on min / max SL1 exposition times
|
||||
1.0.0-alpha2 Printer model and nozzle diameter check
|
||||
1.0.0-alpha1 Added Prusament ASA profile
|
||||
1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX
|
||||
min_slic3r_version = 1.42.0-alpha6
|
||||
0.8.5 Updated SL1 printer and material settings
|
||||
0.8.4 Added Prusament ASA profile
|
||||
0.8.3 FW version and SL1 materials update
|
||||
0.8.2 FFF and SL1 settings update
|
||||
0.8.1 Output settings and SLA materials update
|
||||
|
@ -8,7 +8,7 @@ technologies = FFF; SLA
|
||||
|
||||
# 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-beta1
|
||||
config_version = 1.0.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
|
||||
changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -266,6 +266,8 @@ perimeter_extrusion_width = 0.65
|
||||
solid_infill_extrusion_width = 0.65
|
||||
top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.55
|
||||
support_material_contact_distance = 0.15
|
||||
support_material_xy_spacing = 80%
|
||||
output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
|
||||
|
||||
[print:*0.6nozzleMK3*]
|
||||
@ -279,6 +281,8 @@ top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.55
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 25
|
||||
support_material_contact_distance = 0.15
|
||||
support_material_xy_spacing = 80%
|
||||
output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
|
||||
|
||||
[print:*soluble_support*]
|
||||
@ -295,7 +299,8 @@ support_material_interface_spacing = 0.1
|
||||
support_material_synchronize_layers = 1
|
||||
support_material_threshold = 80
|
||||
support_material_with_sheath = 1
|
||||
wipe_tower_bridging = 8
|
||||
wipe_tower_bridging = 6
|
||||
support_material_interface_speed = 80%
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.05mm ---XXX
|
||||
@ -759,6 +764,27 @@ perimeter_speed = 45
|
||||
solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
|
||||
[print:0.30mm SOLUBLE FULL 0.6 nozzle MK3]
|
||||
inherits = 0.30mm QUALITY 0.6 nozzle MK3; *soluble_support*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 and num_extruders>1
|
||||
notes = Set your soluble extruder in Multiple Extruders > Support material/raft/skirt extruder & Support material/raft interface extruder
|
||||
support_material_extruder = 5
|
||||
support_material_interface_extruder = 5
|
||||
support_material_speed = 40
|
||||
perimeter_speed = 40
|
||||
solid_infill_speed = 40
|
||||
top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.6
|
||||
top_solid_infill_speed = 30
|
||||
support_material_xy_spacing = 80%
|
||||
|
||||
[print:0.30mm SOLUBLE INTERFACE 0.6 nozzle MK3]
|
||||
inherits = 0.30mm SOLUBLE FULL 0.6 nozzle MK3
|
||||
notes = Set your soluble extruder in Multiple Extruders > Support material/raft interface extruder
|
||||
support_material_extruder = 0
|
||||
support_material_interface_layers = 3
|
||||
support_material_with_sheath = 0
|
||||
|
||||
[print:0.30mm DRAFT MK3]
|
||||
inherits = *0.30mm*; *MK3*
|
||||
bottom_solid_layers = 3
|
||||
@ -780,7 +806,7 @@ infill_extrusion_width = 0.5
|
||||
perimeter_extrusion_width = 0.5
|
||||
solid_infill_extrusion_width = 0.5
|
||||
top_infill_extrusion_width = 0.45
|
||||
support_material_extrusion_width = 0.35
|
||||
support_material_extrusion_width = 0.38
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.35mm ---XXX
|
||||
@ -824,17 +850,19 @@ inherits = *0.35mm*; *0.6nozzle*; *soluble_support*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_model=="MK2SMM" and nozzle_diameter[0]==0.6 and num_extruders>1
|
||||
external_perimeter_extrusion_width = 0.6
|
||||
external_perimeter_speed = 30
|
||||
notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder
|
||||
notes = Set your soluble extruder in Multiple Extruders > Support material/raft interface extruder
|
||||
perimeter_speed = 40
|
||||
support_material_interface_layers = 3
|
||||
support_material_speed = 40
|
||||
support_material_interface_layers = 2
|
||||
support_material_xy_spacing = 120%
|
||||
top_infill_extrusion_width = 0.57
|
||||
top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.6
|
||||
|
||||
# MK2 MMU #
|
||||
[print:0.35mm FAST sol int 0.6 nozzle]
|
||||
inherits = 0.35mm FAST sol full 0.6 nozzle
|
||||
support_material_extruder = 0
|
||||
support_material_interface_layers = 2
|
||||
support_material_interface_layers = 3
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 150%
|
||||
|
||||
@ -953,6 +981,29 @@ inherits = 0.35mm FAST
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.5.*/ and nozzle_diameter[0]==0.4
|
||||
single_extruder_multi_material_priming = 0
|
||||
|
||||
# MK2.5 MMU2 0.6 nozzle#
|
||||
[print:0.35mm SOLUBLE FULL 0.6 nozzle MK2.5]
|
||||
inherits = *0.35mm*; *0.6nozzle*; *soluble_support*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and printer_model!="MK2SMM" and nozzle_diameter[0]==0.6 and num_extruders>1
|
||||
external_perimeter_extrusion_width = 0.6
|
||||
external_perimeter_speed = 30
|
||||
notes = Set your soluble extruder in Multiple Extruders > Support material/raft interface extruder
|
||||
perimeter_speed = 40
|
||||
support_material_speed = 40
|
||||
support_material_interface_layers = 2
|
||||
support_material_xy_spacing = 80%
|
||||
support_material_extruder = 5
|
||||
support_material_interface_extruder = 5
|
||||
top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.6
|
||||
|
||||
[print:0.35mm SOLUBLE INTERFACE 0.6 nozzle MK2.5]
|
||||
inherits = 0.35mm SOLUBLE FULL 0.6 nozzle MK2.5
|
||||
support_material_extruder = 0
|
||||
support_material_interface_layers = 3
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 80%
|
||||
|
||||
# XXXXXXxxXXXXXXXXXXXXXX
|
||||
# XXX--- filament ---XXX
|
||||
# XXXXXXXXxxXXXXXXXXXXXX
|
||||
@ -1065,7 +1116,7 @@ disable_fan_first_layers = 1
|
||||
extrusion_multiplier = 1.2
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #00CA0A
|
||||
filament_colour = #008000
|
||||
filament_max_volumetric_speed = 1.5
|
||||
filament_type = FLEX
|
||||
first_layer_bed_temperature = 50
|
||||
@ -1217,6 +1268,11 @@ inherits = *ABS*
|
||||
filament_cost = 38.7
|
||||
filament_density = 1.07
|
||||
fan_always_on = 1
|
||||
cooling = 1
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 20
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 15
|
||||
first_layer_temperature = 265
|
||||
temperature = 265
|
||||
filament_type = ASA
|
||||
@ -1230,7 +1286,11 @@ first_layer_temperature = 260
|
||||
first_layer_bed_temperature = 105
|
||||
temperature = 260
|
||||
bed_temperature = 110
|
||||
cooling = 1
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 20
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 15
|
||||
disable_fan_first_layers = 4
|
||||
filament_type = ASA
|
||||
filament_colour = #FFF2EC
|
||||
@ -1305,11 +1365,11 @@ filament_density = 1.23
|
||||
cooling = 0
|
||||
fan_always_on = 0
|
||||
filament_colour = #FFFFD7
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_max_volumetric_speed = 3.8
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'"
|
||||
filament_ramming_parameters = "120 100 8.3871 8.6129 8.93548 9.22581 9.48387 9.70968 9.87097 10.0323 10.2258 10.4194 10.6452 10.8065| 0.05 8.34193 0.45 8.73548 0.95 9.34836 1.45 9.78385 1.95 10.0871 2.45 10.5161 2.95 10.8903 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_soluble = 1
|
||||
filament_type = PLA
|
||||
filament_type = PVA
|
||||
first_layer_temperature = 195
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
|
||||
temperature = 195
|
||||
@ -1345,7 +1405,11 @@ first_layer_temperature = 260
|
||||
first_layer_bed_temperature = 105
|
||||
temperature = 260
|
||||
bed_temperature = 110
|
||||
cooling = 1
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 20
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 15
|
||||
disable_fan_first_layers = 4
|
||||
filament_cooling_final_speed = 2
|
||||
filament_cooling_initial_speed = 3
|
||||
@ -1542,7 +1606,7 @@ filament_colour = #FFFFD7
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nVerbatim BVOH"
|
||||
filament_soluble = 1
|
||||
filament_type = PLA
|
||||
filament_type = PVA
|
||||
first_layer_bed_temperature = 60
|
||||
first_layer_temperature = 215
|
||||
max_fan_speed = 100
|
||||
@ -1559,7 +1623,7 @@ first_layer_temperature = 200
|
||||
filament_cooling_final_speed = 1
|
||||
filament_cooling_initial_speed = 2
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_type = PLA
|
||||
filament_type = PVA
|
||||
filament_cooling_moves = 1
|
||||
filament_load_time = 15
|
||||
filament_loading_speed = 14
|
||||
@ -1588,13 +1652,13 @@ filament_diameter = 1.75
|
||||
filament_load_time = 15
|
||||
filament_loading_speed = 14
|
||||
filament_loading_speed_start = 19
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_minimal_purge_on_wipe_tower = 5
|
||||
filament_max_volumetric_speed = 3.8
|
||||
filament_minimal_purge_on_wipe_tower = 15
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+"
|
||||
filament_ramming_parameters = "120 110 3.83871 3.90323 3.96774 4.03226 4.09677 4.19355 4.3871 4.83871 5.67742 6.93548 8.54839 10.3226 11.9677 13.2581 14.129 14.5806| 0.05 3.8258 0.45 3.89676 0.95 4.05807 1.45 4.23548 1.95 5.18386 2.45 7.80651 2.95 11.5356 3.45 13.9872 3.95 14.7613 4.45 7.6 4.95 7.6"
|
||||
filament_soluble = 1
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = PLA
|
||||
filament_type = PVA
|
||||
filament_unload_time = 12
|
||||
filament_unloading_speed = 20
|
||||
filament_unloading_speed_start = 100
|
||||
@ -2352,19 +2416,19 @@ min_layer_height = 0.1
|
||||
inherits = Original Prusa i3 MK2S
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.25 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.6 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 Single]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2*
|
||||
@ -2393,8 +2457,8 @@ machine_min_travel_rate = 0
|
||||
default_print_profile = 0.15mm OPTIMAL MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; load to nozzle\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; load to nozzle\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 Single 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S Single 0.6 nozzle
|
||||
@ -2435,23 +2499,23 @@ single_extruder_multi_material = 1
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S]
|
||||
inherits = Original Prusa i3 MK2.5
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 0.25 nozzle
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 0.6 nozzle
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S Single]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2s*
|
||||
@ -2480,8 +2544,8 @@ machine_min_travel_rate = 0
|
||||
default_print_profile = 0.15mm OPTIMAL MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S Single 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5S MMU2S Single
|
||||
@ -2500,7 +2564,7 @@ min_layer_height = 0.05
|
||||
nozzle_diameter = 0.25
|
||||
printer_variant = 0.25
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2s*
|
||||
@ -2533,7 +2597,7 @@ single_extruder_multi_material = 1
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S 0.6 nozzle]
|
||||
@ -2580,7 +2644,7 @@ remaining_times = 1
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
|
||||
retract_lift_below = 209
|
||||
max_print_height = 210
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
printer_model = MK3
|
||||
default_print_profile = 0.15mm QUALITY MK3
|
||||
|
||||
@ -2590,7 +2654,7 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3 0.6 nozzle]
|
||||
@ -2604,17 +2668,17 @@ default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
|
||||
[printer:Original Prusa i3 MK3S]
|
||||
inherits = Original Prusa i3 MK3
|
||||
printer_model = MK3S
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Original Prusa i3 MK3S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK3 0.25 nozzle
|
||||
printer_model = MK3S
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Original Prusa i3 MK3S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3 0.6 nozzle
|
||||
printer_model = MK3S
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:*mm2*]
|
||||
inherits = Original Prusa i3 MK3
|
||||
@ -2644,8 +2708,8 @@ default_filament_profile = Prusament PLA MMU2
|
||||
inherits = *mm2*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2 Single 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3 MMU2 Single
|
||||
@ -2663,7 +2727,7 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F1000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F1000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2]
|
||||
@ -2674,15 +2738,15 @@ inherits = *mm2*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S Single]
|
||||
inherits = *mm2s*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S Single 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3S MMU2S Single
|
||||
@ -2700,7 +2764,7 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S]
|
||||
@ -2708,7 +2772,7 @@ inherits = *mm2s*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.8.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n
|
||||
|
||||
## 0.6mm nozzle MMU2/S printer profiles
|
||||
|
@ -170,7 +170,7 @@ if (WIN32)
|
||||
target_link_options(slic3r_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||
endif()
|
||||
target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
||||
add_dependencies(slic3r_app_gui PrusaSlicer)
|
||||
add_dependencies(slic3r_app_gui slic3r)
|
||||
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "prusa-slicer")
|
||||
target_link_libraries(slic3r_app_gui PRIVATE boost_headeronly)
|
||||
|
||||
@ -180,7 +180,7 @@ if (WIN32)
|
||||
target_link_options(slic3r_app_console PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||
endif ()
|
||||
target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
||||
add_dependencies(slic3r_app_console PrusaSlicer)
|
||||
add_dependencies(slic3r_app_console slic3r)
|
||||
set_target_properties(slic3r_app_console PROPERTIES OUTPUT_NAME "prusa-slicer-console")
|
||||
target_link_libraries(slic3r_app_console PRIVATE boost_headeronly)
|
||||
endif ()
|
||||
|
@ -247,7 +247,7 @@ extern void its_transform(indexed_triangle_set &its, T *trafo3x4)
|
||||
template<typename T>
|
||||
inline void its_transform(indexed_triangle_set &its, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& t)
|
||||
{
|
||||
const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0);
|
||||
//const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0);
|
||||
for (stl_vertex &v : its.vertices)
|
||||
v = (t * v.template cast<T>()).template cast<float>().eval();
|
||||
}
|
||||
|
@ -151,8 +151,8 @@ bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
||||
memcpy(buffer, &stl->stats.number_of_facets, 4);
|
||||
stl_internal_reverse_quads(buffer, 4);
|
||||
fwrite(buffer, 4, 1, fp);
|
||||
for (i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||
memcpy(buffer, stl->facet_start + i, 50);
|
||||
for (const stl_facet &facet : stl->facet_start) {
|
||||
memcpy(buffer, &facet, 50);
|
||||
// Convert to little endian.
|
||||
stl_internal_reverse_quads(buffer, 48);
|
||||
fwrite(buffer, SIZEOF_STL_FACET, 1, fp);
|
||||
|
@ -162,24 +162,31 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first)
|
||||
// Read a single facet from an ASCII .STL file
|
||||
// skip solid/endsolid
|
||||
// (in this order, otherwise it won't work when they are paired in the middle of a file)
|
||||
fscanf(fp, "endsolid %*[^\n]\n");
|
||||
fscanf(fp, "solid %*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
|
||||
fscanf(fp, " endsolid%*[^\n]\n");
|
||||
fscanf(fp, " solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
|
||||
// Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs.
|
||||
int res_normal = fscanf(fp, " facet normal %31s %31s %31s ", normal_buf[0], normal_buf[1], normal_buf[2]);
|
||||
int res_normal = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]);
|
||||
assert(res_normal == 3);
|
||||
int res_outer_loop = fscanf(fp, " outer loop ");
|
||||
int res_outer_loop = fscanf(fp, " outer loop");
|
||||
assert(res_outer_loop == 0);
|
||||
int res_vertex1 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
|
||||
int res_vertex1 = fscanf(fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
|
||||
assert(res_vertex1 == 3);
|
||||
int res_vertex2 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
|
||||
int res_vertex2 = fscanf(fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
|
||||
assert(res_vertex2 == 3);
|
||||
// Trailing whitespace is there to eat all whitespaces and empty lines up to the next non-whitespace.
|
||||
int res_vertex3 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
|
||||
assert(res_vertex3 == 3);
|
||||
int res_endloop = fscanf(fp, " endloop %*[^\n]\n");
|
||||
assert(res_endloop == 0);
|
||||
// There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines.
|
||||
int res_endfacet = fscanf(fp, " endfacet %*[^\n]\n");
|
||||
if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) {
|
||||
// Some G-code generators tend to produce text after "endloop" and "endfacet". Just ignore it.
|
||||
char buf[2048];
|
||||
fgets(buf, 2047, fp);
|
||||
bool endloop_ok = strncmp(buf, "endloop", 7) == 0 && (buf[7] == '\r' || buf[7] == '\n' || buf[7] == ' ' || buf[7] == '\t');
|
||||
assert(endloop_ok);
|
||||
// Skip the trailing whitespaces and empty lines.
|
||||
fscanf(fp, " ");
|
||||
fgets(buf, 2047, fp);
|
||||
bool endfacet_ok = strncmp(buf, "endfacet", 8) == 0 && (buf[8] == '\r' || buf[8] == '\n' || buf[8] == ' ' || buf[8] == '\t');
|
||||
assert(endfacet_ok);
|
||||
if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || ! endloop_ok || ! endfacet_ok) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Something is syntactically very wrong with this ASCII STL! ";
|
||||
return false;
|
||||
}
|
||||
|
@ -1,3 +1,12 @@
|
||||
2018-01-17 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
(cherry-picked)
|
||||
Submitted by Reinhard Max
|
||||
patch #8311: Add IPv6 support to the -Pnet:host:port option
|
||||
* ser_posix.c (net_open): Rewrite to use getaddrinfo()
|
||||
rather than gethostbyname()
|
||||
* avrdude.1: Document IPv6 feature
|
||||
* doc/avrdude.texi: (Dito)
|
||||
|
||||
2016-05-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
|
||||
Submitted by Hannes Jochriem:
|
||||
|
@ -204,18 +204,6 @@ AvrDude::Ptr AvrDude::run()
|
||||
message_fn("\n", 1);
|
||||
}
|
||||
|
||||
if (self->p->complete_fn) {
|
||||
self->p->complete_fn();
|
||||
}
|
||||
} catch (...) {
|
||||
self->p->exit_code = EXIT_EXCEPTION;
|
||||
|
||||
static const char *msg = "An unkown exception was thrown in the background thread.\n";
|
||||
|
||||
if (self->p->message_fn) {
|
||||
self->p->message_fn(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
if (self->p->complete_fn) {
|
||||
self->p->complete_fn();
|
||||
}
|
||||
|
@ -505,12 +505,19 @@ network connection to (TCP)
|
||||
on
|
||||
.Ar host
|
||||
is established.
|
||||
Square brackets may be placed around
|
||||
.Ar host
|
||||
to improve readability, for numeric IPv6 addresses (e.g.
|
||||
.Li net:[2001:db8::42]:1337 ) .
|
||||
The remote endpoint is assumed to be a terminal or console server
|
||||
that connects the network stream to a local serial port where the
|
||||
actual programmer has been attached to.
|
||||
The port is assumed to be properly configured, for example using a
|
||||
transparent 8-bit data connection without parity at 115200 Baud
|
||||
for a STK500.
|
||||
.Pp
|
||||
Note: The ability to handle IPv6 hostnames and addresses is limited to
|
||||
Posix systems (by now).
|
||||
.It Fl q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device. Specify it a second time for even quieter operation.
|
||||
|
@ -214,7 +214,7 @@ AC_HEADER_TIME
|
||||
AC_CHECK_LIB([ws2_32], [puts])
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep])
|
||||
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep getaddrinfo])
|
||||
|
||||
AC_MSG_CHECKING([for a Win32 HID libray])
|
||||
SAVED_LIBS="${LIBS}"
|
||||
|
@ -557,6 +557,9 @@ higher level protocol (as opposed to bit-bang style programmers),
|
||||
In this case, instead of trying to open a local device, a TCP
|
||||
network connection to (TCP) @var{port} on @var{host}
|
||||
is established.
|
||||
Square brackets may be placed around @var{host} to improve
|
||||
readability for numeric IPv6 addresses (e.g.
|
||||
@code{net:[2001:db8::42]:1337}).
|
||||
The remote endpoint is assumed to be a terminal or console server
|
||||
that connects the network stream to a local serial port where the
|
||||
actual programmer has been attached to.
|
||||
@ -564,6 +567,8 @@ The port is assumed to be properly configured, for example using a
|
||||
transparent 8-bit data connection without parity at 115200 Baud
|
||||
for a STK500.
|
||||
|
||||
Note: The ability to handle IPv6 hostnames and addresses is limited to
|
||||
Posix systems (by now).
|
||||
|
||||
@item -q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
|
@ -90,7 +90,7 @@ static speed_t serial_baud_lookup(long baud)
|
||||
* If a non-standard BAUD rate is used, issue
|
||||
* a warning (if we are verbose) and return the raw rate
|
||||
*/
|
||||
avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld",
|
||||
avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld\n",
|
||||
progname, baud);
|
||||
|
||||
return baud;
|
||||
@ -110,7 +110,7 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
|
||||
*/
|
||||
rc = tcgetattr(fd->ifd, &termios);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_setspeed(): tcgetattr() failed",
|
||||
avrdude_message(MSG_INFO, "%s: ser_setspeed(): tcgetattr() failed\n",
|
||||
progname);
|
||||
return -errno;
|
||||
}
|
||||
@ -150,6 +150,7 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
// Timeout read & write variants
|
||||
// Additionally to the regular -1 on I/O error, they return -2 on timeout
|
||||
@ -221,23 +222,35 @@ ssize_t write_timeout(int fd, const void *buf, size_t count, long timeout)
|
||||
static int
|
||||
net_open(const char *port, union filedescriptor *fdp)
|
||||
{
|
||||
char *hstr, *pstr, *end;
|
||||
unsigned int pnum;
|
||||
int fd;
|
||||
struct sockaddr_in sockaddr;
|
||||
struct hostent *hp;
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
char *hp, *hstr, *pstr;
|
||||
int s, fd, ret = -1;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
|
||||
if ((hstr = strdup(port)) == NULL) {
|
||||
if ((hstr = hp = strdup(port)) == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Out of memory!\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
||||
/*
|
||||
* As numeric IPv6 addresses use colons as separators, we need to
|
||||
* look for the last colon here, which separates the port number or
|
||||
* service name from the host or IP address.
|
||||
*/
|
||||
if (((pstr = strrchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Mangled host:port string \"%s\"\n",
|
||||
progname, hstr);
|
||||
free(hstr);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove brackets from the host part, if present.
|
||||
*/
|
||||
if (*hstr == '[' && *(pstr-1) == ']') {
|
||||
hstr++;
|
||||
*(pstr-1) = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
@ -245,43 +258,49 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||
*/
|
||||
*pstr++ = '\0';
|
||||
|
||||
pnum = strtoul(pstr, &end, 10);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
s = getaddrinfo(hstr, pstr, &hints, &result);
|
||||
|
||||
if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Bad port number \"%s\"\n",
|
||||
progname, pstr);
|
||||
free(hstr);
|
||||
return -1;
|
||||
if (s != 0) {
|
||||
avrdude_message(MSG_INFO,
|
||||
"%s: net_open(): Cannot resolve "
|
||||
"host=\"%s\", port=\"%s\": %s\n",
|
||||
progname, hstr, pstr, gai_strerror(s));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((hp = gethostbyname(hstr)) == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): unknown host \"%s\"\n",
|
||||
progname, hstr);
|
||||
free(hstr);
|
||||
return -1;
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if (fd == -1) {
|
||||
/* This one failed, loop over */
|
||||
continue;
|
||||
}
|
||||
if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
||||
/* Success, we are connected */
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
free(hstr);
|
||||
|
||||
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n",
|
||||
progname, strerror(errno));
|
||||
return -1;
|
||||
if (rp == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot connect: %s\n",
|
||||
progname, strerror(errno));
|
||||
}
|
||||
|
||||
memset(&sockaddr, 0, sizeof(struct sockaddr_in));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(pnum);
|
||||
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n",
|
||||
progname, strerror(errno));
|
||||
return -1;
|
||||
else {
|
||||
fdp->ifd = fd;
|
||||
ret = 0;
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
|
||||
fdp->ifd = fd;
|
||||
return 0;
|
||||
error:
|
||||
free(hp);
|
||||
return ret;
|
||||
#else
|
||||
avrdude_message(MSG_INFO,
|
||||
"%s: Networking is not supported on your platform.\n"
|
||||
"If you need it, please open a bug report.\n", progname);
|
||||
return -1;
|
||||
#endif /* HAVE_GETADDRINFO */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,39 +1,45 @@
|
||||
|
||||
add_executable(encoding-check encoding-check.cpp)
|
||||
option(SLIC3R_ENC_CHECK "Verify encoding of source files" 1)
|
||||
|
||||
# A global no-op target which depends on all encodings checks,
|
||||
# and on which in turn all checked targets depend.
|
||||
# This is done to make encoding checks the first thing to be
|
||||
# performed before actually compiling any sources of the checked targets
|
||||
# to make the check fail as early as possible.
|
||||
add_custom_target(global-encoding-check
|
||||
ALL
|
||||
DEPENDS encoding-check
|
||||
)
|
||||
if (SLIC3R_ENC_CHECK)
|
||||
add_executable(encoding-check encoding-check.cpp)
|
||||
|
||||
# A global no-op target which depends on all encodings checks,
|
||||
# and on which in turn all checked targets depend.
|
||||
# This is done to make encoding checks the first thing to be
|
||||
# performed before actually compiling any sources of the checked targets
|
||||
# to make the check fail as early as possible.
|
||||
add_custom_target(global-encoding-check
|
||||
ALL
|
||||
DEPENDS encoding-check
|
||||
)
|
||||
endif()
|
||||
|
||||
# Function that adds source file encoding check to a target
|
||||
# using the above encoding-check binary
|
||||
|
||||
function(encoding_check TARGET)
|
||||
# Obtain target source files
|
||||
get_target_property(T_SOURCES ${TARGET} SOURCES)
|
||||
if (SLIC3R_ENC_CHECK)
|
||||
# Obtain target source files
|
||||
get_target_property(T_SOURCES ${TARGET} SOURCES)
|
||||
|
||||
# Define top-level encoding check target for this ${TARGET}
|
||||
add_custom_target(encoding-check-${TARGET}
|
||||
DEPENDS encoding-check ${T_SOURCES}
|
||||
COMMENT "Checking source files encodings for target ${TARGET}"
|
||||
)
|
||||
|
||||
# Add checking of each source file as a subcommand of encoding-check-${TARGET}
|
||||
foreach(file ${T_SOURCES})
|
||||
add_custom_command(TARGET encoding-check-${TARGET}
|
||||
COMMAND $<TARGET_FILE:encoding-check> ${TARGET} ${file}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
# Define top-level encoding check target for this ${TARGET}
|
||||
add_custom_target(encoding-check-${TARGET}
|
||||
DEPENDS encoding-check ${T_SOURCES}
|
||||
COMMENT "Checking source files encodings for target ${TARGET}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# This adds dependency on encoding-check-${TARGET} to ${TARET}
|
||||
# via the global-encoding-check
|
||||
add_dependencies(global-encoding-check encoding-check-${TARGET})
|
||||
add_dependencies(${TARGET} global-encoding-check)
|
||||
# Add checking of each source file as a subcommand of encoding-check-${TARGET}
|
||||
foreach(file ${T_SOURCES})
|
||||
add_custom_command(TARGET encoding-check-${TARGET}
|
||||
COMMAND $<TARGET_FILE:encoding-check> ${TARGET} ${file}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# This adds dependency on encoding-check-${TARGET} to ${TARET}
|
||||
# via the global-encoding-check
|
||||
add_dependencies(global-encoding-check encoding-check-${TARGET})
|
||||
add_dependencies(${TARGET} global-encoding-check)
|
||||
endif()
|
||||
endfunction()
|
||||
|
@ -4,4 +4,6 @@ cmake_minimum_required(VERSION 2.6)
|
||||
add_library(clipper STATIC
|
||||
clipper.cpp
|
||||
clipper.hpp
|
||||
clipper_z.cpp
|
||||
clipper_z.hpp
|
||||
)
|
||||
|
@ -51,7 +51,11 @@
|
||||
#include <Shiny/Shiny.h>
|
||||
#include <libslic3r/Int128.hpp>
|
||||
|
||||
#ifdef use_xyz
|
||||
namespace ClipperLib_Z {
|
||||
#else /* use_xyz */
|
||||
namespace ClipperLib {
|
||||
#endif /* use_xyz */
|
||||
|
||||
static double const pi = 3.141592653589793238;
|
||||
static double const two_pi = pi *2;
|
||||
@ -1616,7 +1620,7 @@ void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2)
|
||||
else if (pt == e1.Top) pt.Z = e1.Top.Z;
|
||||
else if (pt == e2.Bot) pt.Z = e2.Bot.Z;
|
||||
else if (pt == e2.Top) pt.Z = e2.Top.Z;
|
||||
else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt);
|
||||
else m_ZFill(e1.Bot, e1.Top, e2.Bot, e2.Top, pt);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define clipper_hpp
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <functional>
|
||||
|
||||
#define CLIPPER_VERSION "6.2.6"
|
||||
|
||||
@ -56,7 +57,11 @@
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
|
||||
#ifdef use_xyz
|
||||
namespace ClipperLib_Z {
|
||||
#else /* use_xyz */
|
||||
namespace ClipperLib {
|
||||
#endif /* use_xyz */
|
||||
|
||||
enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
|
||||
enum PolyType { ptSubject, ptClip };
|
||||
@ -114,7 +119,7 @@ struct DoublePoint
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef use_xyz
|
||||
typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
|
||||
typedef std::function<void(const IntPoint& e1bot, const IntPoint& e1top, const IntPoint& e2bot, const IntPoint& e2top, IntPoint& pt)> ZFillCallback;
|
||||
#endif
|
||||
|
||||
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
|
||||
|
7
src/clipper/clipper_z.cpp
Normal file
7
src/clipper/clipper_z.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
// Hackish wrapper around the ClipperLib library to compile the Clipper library with the Z support.
|
||||
|
||||
// Enable the Z coordinate support.
|
||||
#define use_xyz
|
||||
|
||||
// and let it compile
|
||||
#include "clipper.cpp"
|
18
src/clipper/clipper_z.hpp
Normal file
18
src/clipper/clipper_z.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// Hackish wrapper around the ClipperLib library to compile the Clipper library with the Z support.
|
||||
|
||||
#ifndef clipper_z_hpp
|
||||
#ifdef clipper_hpp
|
||||
#error "You should include the clipper_z.hpp first"
|
||||
#endif
|
||||
|
||||
#define clipper_z_hpp
|
||||
|
||||
// Enable the Z coordinate support.
|
||||
#define use_xyz
|
||||
|
||||
#include "clipper.hpp"
|
||||
|
||||
#undef clipper_hpp
|
||||
#undef use_xyz
|
||||
|
||||
#endif clipper_z_hpp
|
@ -546,7 +546,12 @@ public:
|
||||
|
||||
inline explicit _NofitPolyPlacer(const BinType& bin):
|
||||
Base(bin),
|
||||
norm_(std::sqrt(sl::area(bin))) {}
|
||||
norm_(std::sqrt(sl::area(bin)))
|
||||
{
|
||||
// In order to not have items out of bin, it will be shrinked by an
|
||||
// very little empiric offset value.
|
||||
// sl::offset(bin_, 1e-5 * norm_);
|
||||
}
|
||||
|
||||
_NofitPolyPlacer(const _NofitPolyPlacer&) = default;
|
||||
_NofitPolyPlacer& operator=(const _NofitPolyPlacer&) = default;
|
||||
@ -1179,7 +1184,14 @@ private:
|
||||
}
|
||||
|
||||
void setInitialPosition(Item& item) {
|
||||
Box&& bb = item.boundingBox();
|
||||
auto sh = item.rawShape();
|
||||
sl::translate(sh, item.translation());
|
||||
sl::rotate(sh, item.rotation());
|
||||
|
||||
Box bb = sl::boundingBox(sh);
|
||||
bb.minCorner() += item.translation();
|
||||
bb.maxCorner() += item.translation();
|
||||
|
||||
Vertex ci, cb;
|
||||
auto bbin = sl::boundingBox(bin_);
|
||||
|
||||
|
@ -550,16 +550,7 @@ public:
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Safety test: try to pack each item into an empty bin. If it fails
|
||||
// then it should be removed from the not_packed list
|
||||
{ auto it = store_.begin();
|
||||
while (it != store_.end() && !this->stopcond_()) {
|
||||
Placer p(bin); p.configure(pconfig);
|
||||
if(!p.pack(*it, rem(it, store_))) {
|
||||
it = store_.erase(it);
|
||||
} else it++;
|
||||
}
|
||||
}
|
||||
this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
|
||||
|
||||
int acounter = int(store_.size());
|
||||
std::atomic_flag flg = ATOMIC_FLAG_INIT;
|
||||
|
@ -30,7 +30,8 @@ public:
|
||||
TBin&& bin,
|
||||
PConfig&& pconfig = PConfig())
|
||||
{
|
||||
|
||||
using Placer = PlacementStrategyLike<TPlacer>;
|
||||
|
||||
store_.clear();
|
||||
auto total = last-first;
|
||||
store_.reserve(total);
|
||||
@ -57,10 +58,12 @@ public:
|
||||
auto sortfunc = [](Item& i1, Item& i2) {
|
||||
return i1.area() > i2.area();
|
||||
};
|
||||
|
||||
|
||||
this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
|
||||
|
||||
std::sort(store_.begin(), store_.end(), sortfunc);
|
||||
|
||||
PlacementStrategyLike<TPlacer> placer(bin);
|
||||
Placer placer(bin);
|
||||
placer.configure(pconfig);
|
||||
|
||||
auto it = store_.begin();
|
||||
|
@ -77,17 +77,8 @@ public:
|
||||
};
|
||||
|
||||
auto& cancelled = this->stopcond_;
|
||||
|
||||
// Safety test: try to pack each item into an empty bin. If it fails
|
||||
// then it should be removed from the list
|
||||
{ auto it = store_.begin();
|
||||
while (it != store_.end() && !cancelled()) {
|
||||
Placer p(bin); p.configure(pconfig);
|
||||
if(!p.pack(*it)) {
|
||||
it = store_.erase(it);
|
||||
} else it++;
|
||||
}
|
||||
}
|
||||
|
||||
this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
|
||||
|
||||
auto it = store_.begin();
|
||||
|
||||
|
@ -25,6 +25,28 @@ public:
|
||||
inline void clear() { packed_bins_.clear(); }
|
||||
|
||||
protected:
|
||||
|
||||
template<class Placer, class Container, class Bin, class PCfg>
|
||||
void remove_unpackable_items(Container &c, const Bin &bin, const PCfg& pcfg)
|
||||
{
|
||||
// Safety test: try to pack each item into an empty bin. If it fails
|
||||
// then it should be removed from the list
|
||||
auto it = c.begin();
|
||||
while (it != c.end() && !stopcond_()) {
|
||||
|
||||
// WARNING: The copy of itm needs to be created before Placer.
|
||||
// Placer is working with references and its destructor still
|
||||
// manipulates the item this is why the order of stack creation
|
||||
// matters here.
|
||||
const Item& itm = *it;
|
||||
Item cpy{itm};
|
||||
|
||||
Placer p{bin};
|
||||
p.configure(pcfg);
|
||||
if (!p.pack(cpy)) it = c.erase(it);
|
||||
else it++;
|
||||
}
|
||||
}
|
||||
|
||||
PackGroup packed_bins_;
|
||||
ProgressFunction progress_ = [](unsigned){};
|
||||
|
@ -350,6 +350,12 @@ public:
|
||||
m_pck.configure(m_pconf);
|
||||
}
|
||||
|
||||
AutoArranger(const TBin & bin,
|
||||
std::function<void(unsigned)> progressind,
|
||||
std::function<bool(void)> stopcond)
|
||||
: AutoArranger{bin, 0 /* no min distance */, progressind, stopcond}
|
||||
{}
|
||||
|
||||
template<class It> inline void operator()(It from, It to) {
|
||||
m_rtree.clear();
|
||||
m_item_count += size_t(to - from);
|
||||
@ -553,13 +559,21 @@ BedShapeHint &BedShapeHint::operator=(const BedShapeHint &cpy)
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Bin> void remove_large_items(std::vector<Item> &items, Bin &&bin)
|
||||
{
|
||||
auto it = items.begin();
|
||||
while (it != items.end())
|
||||
sl::isInside(it->transformedShape(), bin) ?
|
||||
++it : it = items.erase(it);
|
||||
}
|
||||
|
||||
template<class BinT> // Arrange for arbitrary bin type
|
||||
void _arrange(
|
||||
std::vector<Item> & shapes,
|
||||
std::vector<Item> & excludes,
|
||||
const BinT & bin,
|
||||
coord_t minobjd,
|
||||
std::function<void(unsigned)> prind,
|
||||
std::function<void(unsigned)> progressfn,
|
||||
std::function<bool()> stopfn)
|
||||
{
|
||||
// Integer ceiling the min distance from the bed perimeters
|
||||
@ -569,16 +583,13 @@ void _arrange(
|
||||
auto corrected_bin = bin;
|
||||
sl::offset(corrected_bin, md);
|
||||
|
||||
AutoArranger<BinT> arranger{corrected_bin, 0, prind, stopfn};
|
||||
AutoArranger<BinT> arranger{corrected_bin, progressfn, stopfn};
|
||||
|
||||
auto infl = coord_t(std::ceil(minobjd / 2.0));
|
||||
for (Item& itm : shapes) itm.inflate(infl);
|
||||
for (Item& itm : excludes) itm.inflate(infl);
|
||||
|
||||
auto it = excludes.begin();
|
||||
while (it != excludes.end())
|
||||
sl::isInside(it->transformedShape(), corrected_bin) ?
|
||||
++it : it = excludes.erase(it);
|
||||
remove_large_items(excludes, corrected_bin);
|
||||
|
||||
// If there is something on the plate
|
||||
if (!excludes.empty()) arranger.preload(excludes);
|
||||
@ -674,7 +685,7 @@ void arrange(ArrangePolygons & arrangables,
|
||||
_arrange(items, fixeditems, Box::infinite(), min_obj_dist, pri, cfn);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < items.size(); ++i) {
|
||||
clppr::IntPoint tr = items[i].translation();
|
||||
|
@ -169,6 +169,8 @@ add_library(libslic3r STATIC
|
||||
TriangleMesh.hpp
|
||||
utils.cpp
|
||||
Utils.hpp
|
||||
Time.cpp
|
||||
Time.hpp
|
||||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
|
@ -138,9 +138,9 @@ public:
|
||||
virtual ConfigOption* clone() const = 0;
|
||||
// Set a value from a ConfigOption. The two options should be compatible.
|
||||
virtual void set(const ConfigOption *option) = 0;
|
||||
virtual int getInt() const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); return 0; }
|
||||
virtual double getFloat() const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); return 0; }
|
||||
virtual bool getBool() const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption"); return 0; }
|
||||
virtual int getInt() const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); }
|
||||
virtual double getFloat() const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
|
||||
virtual bool getBool() const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
|
||||
virtual void setInt(int /* val */) { throw std::runtime_error("Calling ConfigOption::setInt on a non-int ConfigOption"); }
|
||||
virtual bool operator==(const ConfigOption &rhs) const = 0;
|
||||
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
|
||||
@ -225,6 +225,12 @@ public:
|
||||
// Is the value nil? That should only be possible if this->nullable().
|
||||
virtual bool is_nil(size_t idx) const = 0;
|
||||
|
||||
// We just overloaded and hid two base class virtual methods.
|
||||
// Let's show it was intentional (warnings).
|
||||
using ConfigOption::set;
|
||||
using ConfigOption::is_nil;
|
||||
|
||||
|
||||
protected:
|
||||
// Used to verify type compatibility when assigning to / from a scalar ConfigOption.
|
||||
ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); }
|
||||
@ -565,7 +571,7 @@ public:
|
||||
static ConfigOptionType static_type() { return coInt; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
int getInt() const override { return this->value; }
|
||||
void setInt(int val) { this->value = val; }
|
||||
void setInt(int val) override { this->value = val; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
|
||||
bool operator==(const ConfigOptionInt &rhs) const { return this->value == rhs.value; }
|
||||
|
||||
@ -723,7 +729,7 @@ public:
|
||||
ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
|
||||
ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; }
|
||||
bool is_nil(size_t idx) const override { return false; }
|
||||
bool is_nil(size_t) const override { return false; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
@ -938,7 +944,7 @@ public:
|
||||
ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
|
||||
ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; }
|
||||
bool is_nil(size_t idx) const override { return false; }
|
||||
bool is_nil(size_t) const override { return false; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
@ -1523,7 +1529,7 @@ protected:
|
||||
// Both opt_key and value may be modified by handle_legacy().
|
||||
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
|
||||
// handle_legacy() is called internally by set_deserialize().
|
||||
virtual void handle_legacy(t_config_option_key &opt_key, std::string &value) const {}
|
||||
virtual void handle_legacy(t_config_option_key &/*opt_key*/, std::string &/*value*/) const {}
|
||||
|
||||
public:
|
||||
// Non-virtual methods:
|
||||
@ -1597,7 +1603,7 @@ public:
|
||||
DynamicConfig() {}
|
||||
DynamicConfig(const DynamicConfig& other) { *this = other; }
|
||||
DynamicConfig(DynamicConfig&& other) : options(std::move(other.options)) { other.options.clear(); }
|
||||
virtual ~DynamicConfig() { clear(); }
|
||||
virtual ~DynamicConfig() override { clear(); }
|
||||
|
||||
// Copy a content of one DynamicConfig to another DynamicConfig.
|
||||
// If rhs.def() is not null, then it has to be equal to this->def().
|
||||
@ -1718,14 +1724,14 @@ public:
|
||||
const std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) const { return const_cast<DynamicConfig*>(this)->opt_string(opt_key, idx); }
|
||||
|
||||
double& opt_float(const t_config_option_key &opt_key) { return this->option<ConfigOptionFloat>(opt_key)->value; }
|
||||
const double opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
|
||||
const double& opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
|
||||
double& opt_float(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); }
|
||||
const double opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
|
||||
const double& opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
|
||||
|
||||
int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
|
||||
const int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
|
||||
int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
|
||||
int& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
|
||||
const int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
|
||||
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
|
||||
|
||||
template<typename ENUM>
|
||||
ENUM opt_enum(const t_config_option_key &opt_key) const { return (ENUM)dynamic_cast<const ConfigOptionEnumGeneric*>(this->option(opt_key))->value; }
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#define L(s) (s)
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//// extrusion entity visitor
|
||||
@ -31,39 +33,31 @@ ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, Extru
|
||||
this->_inflate_collection(intersection_pl(this->polyline, collection), retval);
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
||||
void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
||||
{
|
||||
this->_inflate_collection(diff_pl(this->polyline, collection), retval);
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionPath::clip_end(double distance)
|
||||
void ExtrusionPath::clip_end(double distance)
|
||||
{
|
||||
this->polyline.clip_end(distance);
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionPath::simplify(double tolerance)
|
||||
void ExtrusionPath::simplify(double tolerance)
|
||||
{
|
||||
this->polyline.simplify(tolerance);
|
||||
}
|
||||
|
||||
double
|
||||
ExtrusionPath::length() const
|
||||
double ExtrusionPath::length() const
|
||||
{
|
||||
return this->polyline.length();
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
|
||||
void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
|
||||
{
|
||||
for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it) {
|
||||
ExtrusionPath* path = this->clone();
|
||||
path->polyline = *it;
|
||||
collection->entities.push_back(path);
|
||||
for (const Polyline &polyline : polylines)
|
||||
collection->entities.emplace_back(new ExtrusionPath(polyline, *this));
|
||||
}
|
||||
}
|
||||
|
||||
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
@ -78,52 +72,46 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale
|
||||
polygons_append(out, offset(this->polyline, 0.5f * double(flow.scaled_spacing()) + scaled_epsilon));
|
||||
}
|
||||
|
||||
bool
|
||||
ExtrusionLoop::make_clockwise()
|
||||
bool ExtrusionLoop::make_clockwise()
|
||||
{
|
||||
bool was_ccw = this->polygon().is_counter_clockwise();
|
||||
if (was_ccw) this->reverse();
|
||||
return was_ccw;
|
||||
}
|
||||
|
||||
bool
|
||||
ExtrusionLoop::make_counter_clockwise()
|
||||
bool ExtrusionLoop::make_counter_clockwise()
|
||||
{
|
||||
bool was_cw = this->polygon().is_clockwise();
|
||||
if (was_cw) this->reverse();
|
||||
return was_cw;
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionLoop::reverse()
|
||||
void ExtrusionLoop::reverse()
|
||||
{
|
||||
for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
path->reverse();
|
||||
for (ExtrusionPath &path : this->paths)
|
||||
path.reverse();
|
||||
std::reverse(this->paths.begin(), this->paths.end());
|
||||
}
|
||||
|
||||
Polygon
|
||||
ExtrusionLoop::polygon() const
|
||||
Polygon ExtrusionLoop::polygon() const
|
||||
{
|
||||
Polygon polygon;
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
||||
for (const ExtrusionPath &path : this->paths) {
|
||||
// for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
|
||||
polygon.points.insert(polygon.points.end(), path->polyline.points.begin(), path->polyline.points.end()-1);
|
||||
polygon.points.insert(polygon.points.end(), path.polyline.points.begin(), path.polyline.points.end()-1);
|
||||
}
|
||||
return polygon;
|
||||
}
|
||||
|
||||
double
|
||||
ExtrusionLoop::length() const
|
||||
double ExtrusionLoop::length() const
|
||||
{
|
||||
double len = 0;
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
len += path->polyline.length();
|
||||
for (const ExtrusionPath &path : this->paths)
|
||||
len += path.polyline.length();
|
||||
return len;
|
||||
}
|
||||
|
||||
bool
|
||||
ExtrusionLoop::split_at_vertex(const Point &point)
|
||||
bool ExtrusionLoop::split_at_vertex(const Point &point)
|
||||
{
|
||||
for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
||||
int idx = path->polyline.find_point(point);
|
||||
@ -177,18 +165,18 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
|
||||
Point p_non_overhang;
|
||||
size_t path_idx_non_overhang = 0;
|
||||
double min_non_overhang = std::numeric_limits<double>::max();
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
||||
Point p_tmp = point.projection_onto(path->polyline);
|
||||
for (const ExtrusionPath &path : this->paths) {
|
||||
Point p_tmp = point.projection_onto(path.polyline);
|
||||
double dist = (p_tmp - point).cast<double>().norm();
|
||||
if (dist < min) {
|
||||
p = p_tmp;
|
||||
min = dist;
|
||||
path_idx = path - this->paths.begin();
|
||||
path_idx = &path - &this->paths.front();
|
||||
}
|
||||
if (prefer_non_overhang && ! is_bridge(path->role()) && dist < min_non_overhang) {
|
||||
if (prefer_non_overhang && ! is_bridge(path.role()) && dist < min_non_overhang) {
|
||||
p_non_overhang = p_tmp;
|
||||
min_non_overhang = dist;
|
||||
path_idx_non_overhang = path - this->paths.begin();
|
||||
path_idx_non_overhang = &path - &this->paths.front();
|
||||
}
|
||||
}
|
||||
if (prefer_non_overhang && min_non_overhang != std::numeric_limits<double>::max()) {
|
||||
@ -224,8 +212,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
|
||||
this->split_at_vertex(p);
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
|
||||
void ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
|
||||
{
|
||||
*paths = this->paths;
|
||||
|
||||
@ -242,15 +229,14 @@ ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ExtrusionLoop::has_overhang_point(const Point &point) const
|
||||
bool ExtrusionLoop::has_overhang_point(const Point &point) const
|
||||
{
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
||||
int pos = path->polyline.find_point(point);
|
||||
for (const ExtrusionPath &path : this->paths) {
|
||||
int pos = path.polyline.find_point(point);
|
||||
if (pos != -1) {
|
||||
// point belongs to this path
|
||||
// we consider it overhang only if it's not an endpoint
|
||||
return (is_bridge(path->role()) && pos > 0 && pos != (int)(path->polyline.points.size())-1);
|
||||
return (is_bridge(path.role()) && pos > 0 && pos != (int)(path.polyline.points.size())-1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -258,29 +244,52 @@ ExtrusionLoop::has_overhang_point(const Point &point) const
|
||||
|
||||
void ExtrusionLoop::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
path->polygons_covered_by_width(out, scaled_epsilon);
|
||||
for (const ExtrusionPath &path : this->paths)
|
||||
path.polygons_covered_by_width(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
void ExtrusionLoop::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
path->polygons_covered_by_spacing(out, scaled_epsilon);
|
||||
for (const ExtrusionPath &path : this->paths)
|
||||
path.polygons_covered_by_spacing(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
double
|
||||
ExtrusionLoop::min_mm3_per_mm() const
|
||||
double ExtrusionLoop::min_mm3_per_mm() const
|
||||
{
|
||||
double min_mm3_per_mm = std::numeric_limits<double>::max();
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
min_mm3_per_mm = std::min(min_mm3_per_mm, path->mm3_per_mm);
|
||||
for (const ExtrusionPath &path : this->paths)
|
||||
min_mm3_per_mm = std::min(min_mm3_per_mm, path.mm3_per_mm);
|
||||
return min_mm3_per_mm;
|
||||
}
|
||||
|
||||
void ExtrusionPrinter::use(const ExtrusionPath &path) {
|
||||
|
||||
std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
|
||||
{
|
||||
switch (role) {
|
||||
case erNone : return L("None");
|
||||
case erPerimeter : return L("Perimeter");
|
||||
case erExternalPerimeter : return L("External perimeter");
|
||||
case erOverhangPerimeter : return L("Overhang perimeter");
|
||||
case erInternalInfill : return L("Internal infill");
|
||||
case erSolidInfill : return L("Solid infill");
|
||||
case erTopSolidInfill : return L("Top solid infill");
|
||||
case erBridgeInfill : return L("Bridge infill");
|
||||
case erGapFill : return L("Gap fill");
|
||||
case erSkirt : return L("Skirt");
|
||||
case erSupportMaterial : return L("Support material");
|
||||
case erSupportMaterialInterface : return L("Support material interface");
|
||||
case erWipeTower : return L("Wipe tower");
|
||||
case erCustom : return L("Custom");
|
||||
case erMixed : return L("Mixed");
|
||||
default : assert(false);
|
||||
}
|
||||
|
||||
return "";
|
||||
}void ExtrusionPrinter::use(const ExtrusionPath &path) {
|
||||
ss << "Path_" << path.polyline.size();
|
||||
for (const Point &p : path.polyline.points)
|
||||
ss << "->" << (int)(100 * unscale_(p.x())) << ":" << (int)(100 * unscale_(p.y()));
|
||||
|
||||
}
|
||||
void ExtrusionPrinter::use(const ExtrusionPath3D &path3D) {
|
||||
ss << "Path3D_" << path3D.polyline.size();
|
||||
|
@ -11,7 +11,7 @@ class ExPolygonCollection;
|
||||
class ExtrusionEntityCollection;
|
||||
class Extruder;
|
||||
|
||||
/* Each ExtrusionRole value identifies a distinct set of { extruder, speed } */
|
||||
// Each ExtrusionRole value identifies a distinct set of { extruder, speed }
|
||||
enum ExtrusionRole {
|
||||
erNone,
|
||||
erPerimeter,
|
||||
@ -29,11 +29,20 @@ enum ExtrusionRole {
|
||||
erCustom,
|
||||
// Extrusion role for a collection with multiple extrusion roles.
|
||||
erMixed,
|
||||
erCount
|
||||
};
|
||||
// perimeter / infill / support / skirt / gapfill / wipetower / custom / mixed
|
||||
// side / internal / top / bottom
|
||||
// bridge
|
||||
|
||||
// Special flags describing loop
|
||||
enum ExtrusionLoopRole {
|
||||
elrDefault,
|
||||
elrContourInternalPerimeter,
|
||||
elrSkirt,
|
||||
};
|
||||
|
||||
|
||||
inline bool is_perimeter(ExtrusionRole role)
|
||||
{
|
||||
return role == erPerimeter
|
||||
@ -61,13 +70,6 @@ inline bool is_bridge(ExtrusionRole role) {
|
||||
|| role == erOverhangPerimeter;
|
||||
}
|
||||
|
||||
/* Special flags describing loop */
|
||||
enum ExtrusionLoopRole {
|
||||
elrDefault,
|
||||
elrContourInternalPerimeter,
|
||||
elrSkirt,
|
||||
};
|
||||
|
||||
|
||||
class ExtrusionEntity;
|
||||
class ExtrusionPath;
|
||||
@ -126,7 +128,9 @@ public:
|
||||
virtual bool is_loop() const { return false; }
|
||||
virtual bool can_reverse() const { return true; }
|
||||
virtual ExtrusionEntity* clone() const = 0;
|
||||
virtual ~ExtrusionEntity() {};
|
||||
// Create a new object, initialize it with this object using the move semantics.
|
||||
virtual ExtrusionEntity* clone_move() = 0;
|
||||
virtual ~ExtrusionEntity() {}
|
||||
virtual void reverse() = 0;
|
||||
virtual Point first_point() const = 0;
|
||||
virtual Point last_point() const = 0;
|
||||
@ -150,6 +154,8 @@ public:
|
||||
virtual double total_volume() const = 0;
|
||||
virtual void visit(ExtrusionVisitor &visitor) = 0;
|
||||
virtual void visit(ExtrusionVisitorConst &visitor) const = 0;
|
||||
|
||||
static std::string role_to_string(ExtrusionRole role);
|
||||
};
|
||||
|
||||
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
|
||||
@ -162,25 +168,29 @@ public:
|
||||
double mm3_per_mm;
|
||||
// Width of the extrusion, used for visualization purposes.
|
||||
float width;
|
||||
// Height of the extrusion, used for visualization purposed.
|
||||
// Height of the extrusion, used for visualization purposes.
|
||||
float height;
|
||||
// Feedrate of the extrusion, used for visualization purposed.
|
||||
// Feedrate of the extrusion, used for visualization purposes.
|
||||
float feedrate;
|
||||
// Id of the extruder, used for visualization purposed.
|
||||
// Id of the extruder, used for visualization purposes.
|
||||
unsigned int extruder_id;
|
||||
// Id of the color, used for visualization purposed in the color printing case.
|
||||
// Id of the color, used for visualization purposes in the color printing case.
|
||||
unsigned int cp_color_id;
|
||||
|
||||
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {};
|
||||
ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {};
|
||||
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {}
|
||||
ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {}
|
||||
ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
|
||||
ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs) : polyline(polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
|
||||
ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
|
||||
ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs) : polyline(std::move(polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
|
||||
// ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f), extruder_id(0) {};
|
||||
|
||||
ExtrusionPath& operator=(const ExtrusionPath &rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = rhs.polyline; return *this; }
|
||||
ExtrusionPath& operator=(ExtrusionPath &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = std::move(rhs.polyline); return *this; }
|
||||
ExtrusionPath& operator=(const ExtrusionPath &rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate; this->extruder_id = rhs.extruder_id; this->cp_color_id = rhs.cp_color_id; this->polyline = rhs.polyline; return *this; }
|
||||
ExtrusionPath& operator=(ExtrusionPath &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate; this->extruder_id = rhs.extruder_id; this->cp_color_id = rhs.cp_color_id; this->polyline = std::move(rhs.polyline); return *this; }
|
||||
|
||||
virtual ExtrusionPath* clone() const override { return new ExtrusionPath(*this); }
|
||||
// Create a new object, initialize it with this object using the move semantics.
|
||||
virtual ExtrusionPath* clone_move() override { return new ExtrusionPath(std::move(*this)); }
|
||||
void reverse() override { this->polyline.reverse(); }
|
||||
Point first_point() const override { return this->polyline.points.front(); }
|
||||
Point last_point() const override { return this->polyline.points.back(); }
|
||||
@ -205,6 +215,10 @@ public:
|
||||
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
||||
// Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
|
||||
void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override;
|
||||
virtual Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const
|
||||
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; }
|
||||
virtual Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
|
||||
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
|
||||
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
|
||||
double min_mm3_per_mm() const override { return this->mm3_per_mm; }
|
||||
Polyline as_polyline() const override { return this->polyline; }
|
||||
@ -238,7 +252,8 @@ public:
|
||||
ExtrusionPath3D& operator=(ExtrusionPath3D &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height;
|
||||
this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = std::move(rhs.polyline); z_offsets = std::move(rhs.z_offsets); return *this;
|
||||
}
|
||||
ExtrusionPath3D* clone() const { return new ExtrusionPath3D(*this); }
|
||||
virtual ExtrusionPath3D* clone() const { return new ExtrusionPath3D(*this); }
|
||||
virtual ExtrusionPath3D* clone_move() override { return new ExtrusionPath3D(std::move(*this)); }
|
||||
virtual void visit(ExtrusionVisitor &visitor) override { visitor.use(*this); };
|
||||
virtual void visit(ExtrusionVisitorConst &visitor) const override { visitor.use(*this); };
|
||||
|
||||
@ -344,6 +359,7 @@ public:
|
||||
ExtrusionMultiPath(const ExtrusionPath &path) :ExtrusionMultiEntity(path) {}
|
||||
|
||||
virtual ExtrusionMultiPath* clone() const override { return new ExtrusionMultiPath(*this); }
|
||||
virtual ExtrusionMultiPath* clone_move() override { return new ExtrusionMultiPath(std::move(*this)); }
|
||||
|
||||
virtual void visit(ExtrusionVisitor &visitor) override { visitor.use(*this); };
|
||||
virtual void visit(ExtrusionVisitorConst &visitor) const override { visitor.use(*this); };
|
||||
@ -359,13 +375,14 @@ public:
|
||||
ExtrusionMultiPath3D(const ExtrusionPath3D &path) :ExtrusionMultiEntity(path) {}
|
||||
|
||||
virtual ExtrusionMultiPath3D* clone() const override { return new ExtrusionMultiPath3D(*this); }
|
||||
virtual ExtrusionMultiPath3D* clone_move() override { return new ExtrusionMultiPath3D(std::move(*this)); }
|
||||
|
||||
virtual void visit(ExtrusionVisitor &visitor) override { visitor.use(*this); };
|
||||
virtual void visit(ExtrusionVisitorConst &visitor) const override { visitor.use(*this); };
|
||||
|
||||
virtual bool can_reverse() const override { return false; }
|
||||
virtual void reverse() override {
|
||||
std::cout << "I SAID NO REVERSE§§§FFFS\n";
|
||||
std::cout << "I SAID NO REVERSE!!!FFFS\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -375,19 +392,21 @@ class ExtrusionLoop : public ExtrusionEntity
|
||||
public:
|
||||
ExtrusionPaths paths;
|
||||
|
||||
ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {};
|
||||
ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {};
|
||||
ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {};
|
||||
ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}
|
||||
ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}
|
||||
ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}
|
||||
ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
|
||||
{ this->paths.push_back(path); };
|
||||
{ this->paths.push_back(path); }
|
||||
ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
|
||||
{ this->paths.emplace_back(std::move(path)); };
|
||||
bool is_loop() const { return true; }
|
||||
bool can_reverse() const { return false; }
|
||||
ExtrusionLoop* clone() const { return new ExtrusionLoop (*this); }
|
||||
{ this->paths.emplace_back(std::move(path)); }
|
||||
virtual bool is_loop() const override{ return true; }
|
||||
virtual bool can_reverse() const override { return false; }
|
||||
virtual ExtrusionEntity* clone() const override{ return new ExtrusionLoop (*this); }
|
||||
// Create a new object, initialize it with this object using the move semantics.
|
||||
ExtrusionEntity* clone_move() override { return new ExtrusionLoop(std::move(*this)); }
|
||||
bool make_clockwise();
|
||||
bool make_counter_clockwise();
|
||||
void reverse();
|
||||
virtual void reverse() override;
|
||||
Point first_point() const override { return this->paths.front().polyline.points.front(); }
|
||||
Point last_point() const override { assert(first_point() == this->paths.back().polyline.points.back()); return first_point(); }
|
||||
Polygon polygon() const;
|
||||
@ -402,23 +421,25 @@ public:
|
||||
ExtrusionLoopRole loop_role() const { return m_loop_role; }
|
||||
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
|
||||
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
||||
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const;
|
||||
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
|
||||
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
|
||||
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
||||
// Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
|
||||
void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const;
|
||||
void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override;
|
||||
Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const
|
||||
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; }
|
||||
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
|
||||
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
|
||||
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
|
||||
double min_mm3_per_mm() const;
|
||||
Polyline as_polyline() const { return this->polygon().split_at_first_point(); }
|
||||
double min_mm3_per_mm() const override;
|
||||
Polyline as_polyline() const override { return this->polygon().split_at_first_point(); }
|
||||
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
|
||||
double total_volume() const override { double volume = 0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
|
||||
virtual void visit(ExtrusionVisitor &visitor) override { visitor.use(*this); };
|
||||
virtual void visit(ExtrusionVisitorConst &visitor) const override { visitor.use(*this); };
|
||||
|
||||
//static inline std::string role_to_string(ExtrusionLoopRole role);
|
||||
|
||||
private:
|
||||
ExtrusionLoopRole m_loop_role;
|
||||
};
|
||||
|
@ -21,8 +21,7 @@ ExtrusionEntityCollection& ExtrusionEntityCollection::operator= (const Extrusion
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c)
|
||||
void ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c)
|
||||
{
|
||||
std::swap(this->entities, c.entities);
|
||||
std::swap(this->orig_indices, c.orig_indices);
|
||||
@ -39,15 +38,14 @@ void ExtrusionEntityCollection::clear()
|
||||
ExtrusionEntityCollection::operator ExtrusionPaths() const
|
||||
{
|
||||
ExtrusionPaths paths;
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
|
||||
if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(*it))
|
||||
for (const ExtrusionEntity *ptr : this->entities) {
|
||||
if (const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ptr))
|
||||
paths.push_back(*path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
ExtrusionEntityCollection*
|
||||
ExtrusionEntityCollection::clone() const
|
||||
ExtrusionEntityCollection* ExtrusionEntityCollection::clone() const
|
||||
{
|
||||
ExtrusionEntityCollection* coll = new ExtrusionEntityCollection(*this);
|
||||
for (size_t i = 0; i < coll->entities.size(); ++i)
|
||||
@ -55,41 +53,38 @@ ExtrusionEntityCollection::clone() const
|
||||
return coll;
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::reverse()
|
||||
void ExtrusionEntityCollection::reverse()
|
||||
{
|
||||
for (ExtrusionEntitiesPtr::iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
|
||||
for (ExtrusionEntity *ptr : this->entities)
|
||||
{
|
||||
// Don't reverse it if it's a loop, as it doesn't change anything in terms of elements ordering
|
||||
// and caller might rely on winding order
|
||||
if (!(*it)->can_reverse()) (*it)->reverse();
|
||||
if (!ptr->can_reverse())
|
||||
ptr->reverse();
|
||||
}
|
||||
std::reverse(this->entities.begin(), this->entities.end());
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity)
|
||||
void ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity)
|
||||
{
|
||||
delete this->entities[i];
|
||||
this->entities[i] = entity.clone();
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::remove(size_t i)
|
||||
void ExtrusionEntityCollection::remove(size_t i)
|
||||
{
|
||||
delete this->entities[i];
|
||||
this->entities.erase(this->entities.begin() + i);
|
||||
}
|
||||
|
||||
ExtrusionEntityCollection
|
||||
ExtrusionEntityCollection::chained_path(bool no_reverse, ExtrusionRole role) const
|
||||
ExtrusionEntityCollection ExtrusionEntityCollection::chained_path(bool no_reverse, ExtrusionRole role) const
|
||||
{
|
||||
ExtrusionEntityCollection coll;
|
||||
this->chained_path(&coll, no_reverse, role);
|
||||
return coll;
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::chained_path(ExtrusionEntityCollection* retval, bool no_reverse, ExtrusionRole role, std::vector<size_t>* orig_indices) const
|
||||
void ExtrusionEntityCollection::chained_path(ExtrusionEntityCollection* retval, bool no_reverse, ExtrusionRole role, std::vector<size_t>* orig_indices) const
|
||||
{
|
||||
if (this->entities.empty()) return;
|
||||
this->chained_path_from(this->entities.front()->first_point(), retval, no_reverse, role, orig_indices);
|
||||
@ -108,6 +103,7 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
|
||||
*retval = *this;
|
||||
return;
|
||||
}
|
||||
|
||||
retval->entities.reserve(this->entities.size());
|
||||
retval->orig_indices.reserve(this->entities.size());
|
||||
|
||||
@ -115,10 +111,10 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
|
||||
std::map<ExtrusionEntity*,size_t> indices_map;
|
||||
|
||||
ExtrusionEntitiesPtr my_paths;
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
|
||||
for (ExtrusionEntity * const &entity_src : this->entities) {
|
||||
if (role != erMixed) {
|
||||
// The caller wants only paths with a specific extrusion role.
|
||||
ExtrusionRole role2 = (*it)->role();
|
||||
ExtrusionRole role2 = entity_src->role();
|
||||
if (role != role2) {
|
||||
// This extrusion entity does not match the role asked.
|
||||
assert(role2 != erMixed);
|
||||
@ -126,18 +122,19 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
|
||||
}
|
||||
}
|
||||
|
||||
ExtrusionEntity* entity = (*it)->clone();
|
||||
ExtrusionEntity *entity = entity_src->clone();
|
||||
my_paths.push_back(entity);
|
||||
if (orig_indices != NULL) indices_map[entity] = it - this->entities.begin();
|
||||
if (orig_indices != nullptr)
|
||||
indices_map[entity] = &entity_src - &this->entities.front();
|
||||
}
|
||||
|
||||
Points endpoints;
|
||||
for (ExtrusionEntitiesPtr::iterator it = my_paths.begin(); it != my_paths.end(); ++it) {
|
||||
endpoints.push_back((*it)->first_point());
|
||||
if (no_reverse || !(*it)->can_reverse()) {
|
||||
endpoints.push_back((*it)->first_point());
|
||||
for (const ExtrusionEntity *entity : my_paths) {
|
||||
endpoints.push_back(entity->first_point());
|
||||
if (no_reverse || !entity->can_reverse()) {
|
||||
endpoints.push_back(entity->first_point());
|
||||
} else {
|
||||
endpoints.push_back((*it)->last_point());
|
||||
endpoints.push_back(entity->last_point());
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,11 +144,11 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
|
||||
int path_index = start_index/2;
|
||||
ExtrusionEntity* entity = my_paths.at(path_index);
|
||||
// never reverse loops, since it's pointless for chained path and callers might depend on orientation
|
||||
if (start_index % 2 && !no_reverse && entity->can_reverse()) {
|
||||
if (start_index % 2 && !no_reverse && entity->can_reverse())
|
||||
entity->reverse();
|
||||
}
|
||||
retval->entities.push_back(my_paths.at(path_index));
|
||||
if (orig_indices != NULL) orig_indices->push_back(indices_map[entity]);
|
||||
if (orig_indices != nullptr)
|
||||
orig_indices->push_back(indices_map[entity]);
|
||||
my_paths.erase(my_paths.begin() + path_index);
|
||||
endpoints.erase(endpoints.begin() + 2*path_index, endpoints.begin() + 2*path_index + 2);
|
||||
start_near = retval->entities.back()->last_point();
|
||||
@ -160,19 +157,18 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
|
||||
|
||||
void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
|
||||
(*it)->polygons_covered_by_width(out, scaled_epsilon);
|
||||
for (const ExtrusionEntity *entity : this->entities)
|
||||
entity->polygons_covered_by_width(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
|
||||
(*it)->polygons_covered_by_spacing(out, scaled_epsilon);
|
||||
for (const ExtrusionEntity *entity : this->entities)
|
||||
entity->polygons_covered_by_spacing(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
/* Recursively count paths and loops contained in this collection */
|
||||
size_t
|
||||
ExtrusionEntityCollection::items_count() const
|
||||
// Recursively count paths and loops contained in this collection.
|
||||
size_t ExtrusionEntityCollection::items_count() const
|
||||
{
|
||||
return CountEntities().count(*this);
|
||||
}
|
||||
@ -231,12 +227,14 @@ FlatenEntities::use(const ExtrusionEntityCollection &coll) {
|
||||
entity->visit(unsortable);
|
||||
}
|
||||
to_fill.append(std::move(unsortable.to_fill));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (const ExtrusionEntity* entity : coll.entities) {
|
||||
entity->visit(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExtrusionEntityCollection&&
|
||||
FlatenEntities::flatten(const ExtrusionEntityCollection &to_flatten) && {
|
||||
use(to_flatten);
|
||||
@ -248,8 +246,8 @@ double
|
||||
ExtrusionEntityCollection::min_mm3_per_mm() const
|
||||
{
|
||||
double min_mm3_per_mm = std::numeric_limits<double>::max();
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
|
||||
min_mm3_per_mm = std::min(min_mm3_per_mm, (*it)->min_mm3_per_mm());
|
||||
for (const ExtrusionEntity *entity : this->entities)
|
||||
min_mm3_per_mm = std::min(min_mm3_per_mm, entity->min_mm3_per_mm());
|
||||
return min_mm3_per_mm;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,10 @@ namespace Slic3r {
|
||||
class ExtrusionEntityCollection : public ExtrusionEntity
|
||||
{
|
||||
public:
|
||||
ExtrusionEntityCollection* clone() const;
|
||||
virtual ExtrusionEntityCollection* clone() const override;
|
||||
// Create a new object, initialize it with this object using the move semantics.
|
||||
virtual ExtrusionEntityCollection* clone_move() override { return new ExtrusionEntityCollection(std::move(*this)); }
|
||||
|
||||
|
||||
/// Owned ExtrusionEntities and descendent ExtrusionEntityCollections.
|
||||
/// Iterating over this needs to check each child to see if it, too is a collection.
|
||||
@ -43,11 +46,12 @@ public:
|
||||
bool empty() const { return this->entities.empty(); };
|
||||
void clear();
|
||||
void swap (ExtrusionEntityCollection &c);
|
||||
void append(const ExtrusionEntity &entity) { this->entities.push_back(entity.clone()); }
|
||||
void append(const ExtrusionEntity &entity) { this->entities.emplace_back(entity.clone()); }
|
||||
void append(ExtrusionEntity &&entity) { this->entities.emplace_back(entity.clone_move()); }
|
||||
void append(const ExtrusionEntitiesPtr &entities) {
|
||||
this->entities.reserve(this->entities.size() + entities.size());
|
||||
for (ExtrusionEntitiesPtr::const_iterator ptr = entities.begin(); ptr != entities.end(); ++ptr)
|
||||
this->entities.push_back((*ptr)->clone());
|
||||
for (const ExtrusionEntity *ptr : entities)
|
||||
this->entities.emplace_back(ptr->clone());
|
||||
}
|
||||
void append(ExtrusionEntitiesPtr &&src) {
|
||||
if (entities.empty())
|
||||
|
@ -55,6 +55,24 @@ Fill* Fill::new_from_type(const std::string &type)
|
||||
return (it == enum_keys_map.end()) ? nullptr : new_from_type(InfillPattern(it->second));
|
||||
}
|
||||
|
||||
// Force initialization of the Fill::use_bridge_flow() internal static map in a thread safe fashion even on compilers
|
||||
// not supporting thread safe non-static data member initializers.
|
||||
static bool use_bridge_flow_initializer = Fill::use_bridge_flow(ipGrid);
|
||||
|
||||
bool Fill::use_bridge_flow(const InfillPattern type)
|
||||
{
|
||||
static std::vector<unsigned char> cached;
|
||||
if (cached.empty()) {
|
||||
cached.assign(size_t(ipCount), 0);
|
||||
for (size_t i = 0; i < cached.size(); ++ i) {
|
||||
auto *fill = Fill::new_from_type((InfillPattern)i);
|
||||
cached[i] = fill->use_bridge_flow();
|
||||
delete fill;
|
||||
}
|
||||
}
|
||||
return cached[type] != 0;
|
||||
}
|
||||
|
||||
Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms)
|
||||
{
|
||||
// Perform offset.
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
|
||||
static Fill* new_from_type(const InfillPattern type);
|
||||
static Fill* new_from_type(const std::string &type);
|
||||
static bool use_bridge_flow(const InfillPattern type);
|
||||
|
||||
void set_bounding_box(const Slic3r::BoundingBox &bbox) { bounding_box = bbox; }
|
||||
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
// Enable some perimeter squish (see INSET_OVERLAP_TOLERANCE).
|
||||
// Here an overlap of 0.2x external perimeter spacing is allowed for by the elephant foot compensation.
|
||||
coord_t scaled_elephant_foot_spacing() const { return coord_t(0.5f * float(this->scaled_width() + 0.6f * this->scaled_spacing())); }
|
||||
|
||||
bool operator==(const Flow &rhs) const { return this->width == rhs.width && this->height == rhs.height && this->nozzle_diameter == rhs.nozzle_diameter && this->bridge == rhs.bridge; }
|
||||
|
||||
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio);
|
||||
// Create a flow from the spacing of extrusion lines.
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "3mf.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
@ -102,6 +103,13 @@ const char* INVALID_OBJECT_TYPES[] =
|
||||
"other"
|
||||
};
|
||||
|
||||
class version_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
version_error(const std::string& what_arg) : std::runtime_error(what_arg) {}
|
||||
version_error(const char* what_arg) : std::runtime_error(what_arg) {}
|
||||
};
|
||||
|
||||
const char* get_attribute_value_charptr(const char** attributes, unsigned int attributes_size, const char* attribute_key)
|
||||
{
|
||||
if ((attributes == nullptr) || (attributes_size == 0) || (attributes_size % 2 != 0) || (attribute_key == nullptr))
|
||||
@ -567,7 +575,7 @@ namespace Slic3r {
|
||||
{
|
||||
// ensure the zip archive is closed and rethrow the exception
|
||||
close_zip_reader(&archive);
|
||||
throw e;
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -705,25 +713,46 @@ namespace Slic3r {
|
||||
XML_SetElementHandler(m_xml_parser, _3MF_Importer::_handle_start_model_xml_element, _3MF_Importer::_handle_end_model_xml_element);
|
||||
XML_SetCharacterDataHandler(m_xml_parser, _3MF_Importer::_handle_model_xml_characters);
|
||||
|
||||
void* parser_buffer = XML_GetBuffer(m_xml_parser, (int)stat.m_uncomp_size);
|
||||
if (parser_buffer == nullptr)
|
||||
struct CallbackData
|
||||
{
|
||||
add_error("Unable to create buffer");
|
||||
XML_Parser& parser;
|
||||
const mz_zip_archive_file_stat& stat;
|
||||
|
||||
CallbackData(XML_Parser& parser, const mz_zip_archive_file_stat& stat) : parser(parser), stat(stat) {}
|
||||
};
|
||||
|
||||
CallbackData data(m_xml_parser, stat);
|
||||
|
||||
mz_bool res = 0;
|
||||
|
||||
try
|
||||
{
|
||||
res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0))
|
||||
{
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
throw std::runtime_error(error_buf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}, &data, 0);
|
||||
}
|
||||
catch (const version_error& e)
|
||||
{
|
||||
// rethrow the exception
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
add_error(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
add_error("Error while reading model data to buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!XML_ParseBuffer(m_xml_parser, (int)stat.m_uncomp_size, 1))
|
||||
{
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing xml file at line %d", XML_ErrorString(XML_GetErrorCode(m_xml_parser)), (int)XML_GetCurrentLineNumber(m_xml_parser));
|
||||
add_error(error_buf);
|
||||
add_error("Error while extracting model data from zip archive");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1423,8 +1452,8 @@ namespace Slic3r {
|
||||
|
||||
if (m_check_version && (m_version > VERSION_3MF))
|
||||
{
|
||||
std::string msg = _(L("The selected 3mf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatibile."));
|
||||
throw std::runtime_error(msg.c_str());
|
||||
std::string msg = _(L("The selected 3mf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
|
||||
throw version_error(msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -783,25 +783,42 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
XML_SetElementHandler(parser, AMFParserContext::startElement, AMFParserContext::endElement);
|
||||
XML_SetCharacterDataHandler(parser, AMFParserContext::characters);
|
||||
|
||||
void* parser_buffer = XML_GetBuffer(parser, (int)stat.m_uncomp_size);
|
||||
if (parser_buffer == nullptr)
|
||||
struct CallbackData
|
||||
{
|
||||
printf("Unable to create buffer\n");
|
||||
XML_Parser& parser;
|
||||
const mz_zip_archive_file_stat& stat;
|
||||
|
||||
CallbackData(XML_Parser& parser, const mz_zip_archive_file_stat& stat) : parser(parser), stat(stat) {}
|
||||
};
|
||||
|
||||
CallbackData data(parser, stat);
|
||||
|
||||
mz_bool res = 0;
|
||||
|
||||
try
|
||||
{
|
||||
res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0))
|
||||
{
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
throw std::runtime_error(error_buf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}, &data, 0);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
printf("%s\n", e.what());
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
printf("Error while reading model data to buffer\n");
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!XML_ParseBuffer(parser, (int)stat.m_uncomp_size, 1))
|
||||
{
|
||||
printf("Error (%s) while parsing xml file at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), (int)XML_GetCurrentLineNumber(parser));
|
||||
printf("Error while extracting model data from zip archive");
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
@ -810,7 +827,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
|
||||
if (check_version && (ctx.m_version > VERSION_AMF))
|
||||
{
|
||||
std::string msg = _(L("The selected amf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatibile."));
|
||||
std::string msg = _(L("The selected amf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
|
||||
throw std::runtime_error(msg.c_str());
|
||||
}
|
||||
|
||||
@ -855,7 +872,7 @@ bool load_amf_archive(const char* path, DynamicPrintConfig* config, Model* model
|
||||
{
|
||||
// ensure the zip archive is closed and rethrow the exception
|
||||
close_zip_reader(&archive);
|
||||
throw e;
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -159,9 +159,12 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
line = endptr;
|
||||
EATWS();
|
||||
}
|
||||
if (*line != 0)
|
||||
return false;
|
||||
data.coordinates.push_back((float)x);
|
||||
// the following check is commented out because there may be obj files containing extra data, as those generated by Meshlab,
|
||||
// see https://dev.prusa3d.com/browse/SPE-1019 for an example,
|
||||
// and this would lead to a crash because no vertex would be stored
|
||||
// if (*line != 0)
|
||||
// return false;
|
||||
data.coordinates.push_back((float)x);
|
||||
data.coordinates.push_back((float)y);
|
||||
data.coordinates.push_back((float)z);
|
||||
data.coordinates.push_back((float)w);
|
||||
@ -210,16 +213,16 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
}
|
||||
}
|
||||
if (vertex.coordIdx < 0)
|
||||
vertex.coordIdx += data.coordinates.size() / 4;
|
||||
else
|
||||
vertex.coordIdx += (int)data.coordinates.size() / 4;
|
||||
else
|
||||
-- vertex.coordIdx;
|
||||
if (vertex.normalIdx < 0)
|
||||
vertex.normalIdx += data.normals.size() / 3;
|
||||
else
|
||||
vertex.normalIdx += (int)data.normals.size() / 3;
|
||||
else
|
||||
-- vertex.normalIdx;
|
||||
if (vertex.textureCoordIdx < 0)
|
||||
vertex.textureCoordIdx += data.textureCoordinates.size() / 3;
|
||||
else
|
||||
vertex.textureCoordIdx += (int)data.textureCoordinates.size() / 3;
|
||||
else
|
||||
-- vertex.textureCoordIdx;
|
||||
data.vertices.push_back(vertex);
|
||||
EATWS();
|
||||
@ -256,8 +259,8 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
// printf("usemtl %s\r\n", line);
|
||||
EATWS();
|
||||
ObjUseMtl usemtl;
|
||||
usemtl.vertexIdxFirst = data.vertices.size();
|
||||
usemtl.name = line;
|
||||
usemtl.vertexIdxFirst = (int)data.vertices.size();
|
||||
usemtl.name = line;
|
||||
data.usemtls.push_back(usemtl);
|
||||
break;
|
||||
}
|
||||
@ -272,8 +275,8 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
if (*line != 0)
|
||||
return false;
|
||||
ObjObject object;
|
||||
object.vertexIdxFirst = data.vertices.size();
|
||||
object.name = line;
|
||||
object.vertexIdxFirst = (int)data.vertices.size();
|
||||
object.name = line;
|
||||
data.objects.push_back(object);
|
||||
break;
|
||||
}
|
||||
@ -282,8 +285,8 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
// g [group name]
|
||||
// printf("group %s\r\n", line);
|
||||
ObjGroup group;
|
||||
group.vertexIdxFirst = data.vertices.size();
|
||||
group.name = line;
|
||||
group.vertexIdxFirst = (int)data.vertices.size();
|
||||
group.name = line;
|
||||
data.groups.push_back(group);
|
||||
break;
|
||||
}
|
||||
@ -303,8 +306,8 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
if (*line != 0)
|
||||
return false;
|
||||
ObjSmoothingGroup group;
|
||||
group.vertexIdxFirst = data.vertices.size();
|
||||
group.smoothingGroupID = g;
|
||||
group.vertexIdxFirst = (int)data.vertices.size();
|
||||
group.smoothingGroupID = g;
|
||||
data.smoothingGroups.push_back(group);
|
||||
break;
|
||||
}
|
||||
@ -341,8 +344,9 @@ bool objparse(const char *path, ObjData &data)
|
||||
lenPrev = len - lastLine;
|
||||
memmove(buf, buf + lastLine, lenPrev);
|
||||
}
|
||||
} catch (std::bad_alloc &ex) {
|
||||
printf("Out of memory\r\n");
|
||||
}
|
||||
catch (std::bad_alloc&) {
|
||||
printf("Out of memory\r\n");
|
||||
}
|
||||
::fclose(pFile);
|
||||
|
||||
|
@ -51,6 +51,34 @@ static inline void check_add_eol(std::string &gcode)
|
||||
gcode += '\n';
|
||||
}
|
||||
|
||||
|
||||
// Return true if tch_prefix is found in custom_gcode
|
||||
static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std::string& tch_prefix, unsigned next_extruder)
|
||||
{
|
||||
bool ok = false;
|
||||
size_t from_pos = 0;
|
||||
size_t pos = 0;
|
||||
while ((pos = custom_gcode.find(tch_prefix, from_pos)) != std::string::npos) {
|
||||
if (pos+1 == custom_gcode.size())
|
||||
break;
|
||||
from_pos = pos+1;
|
||||
// only whitespace is allowed before the command
|
||||
while (--pos < custom_gcode.size() && custom_gcode[pos] != '\n') {
|
||||
if (! std::isspace(custom_gcode[pos]))
|
||||
goto NEXT;
|
||||
}
|
||||
{
|
||||
// we should also check that the extruder changes to what was expected
|
||||
std::istringstream ss(custom_gcode.substr(from_pos, std::string::npos));
|
||||
unsigned num = 0;
|
||||
if (ss >> num)
|
||||
ok = (num == next_extruder);
|
||||
}
|
||||
NEXT: ;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void AvoidCrossingPerimeters::init_external_mp(const Print &print)
|
||||
{
|
||||
m_external_mp = Slic3r::make_unique<MotionPlanner>(union_ex(this->collect_contours_all_layers(print.objects())));
|
||||
@ -314,8 +342,8 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
||||
std::string toolchange_command;
|
||||
if (tcr.priming || (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id)))
|
||||
toolchange_command = gcodegen.writer().toolchange(new_extruder_id);
|
||||
if (toolchange_gcode.empty())
|
||||
toolchange_gcode_str = toolchange_command;
|
||||
if (! custom_gcode_changes_tool(toolchange_gcode_str, gcodegen.writer().toolchange_prefix(), new_extruder_id))
|
||||
toolchange_gcode_str += toolchange_command;
|
||||
else {
|
||||
// We have informed the m_writer about the current extruder_id, we can ignore the generated G-code.
|
||||
}
|
||||
@ -508,6 +536,21 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||
std::vector<GCode::LayerToPrint> layers_to_print;
|
||||
layers_to_print.reserve(object.layers().size() + object.support_layers().size());
|
||||
|
||||
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
||||
// This is the same logic as in support generator.
|
||||
//FIXME should we use the printing extruders instead?
|
||||
double gap_over_supports = object.config().support_material_contact_distance_top;
|
||||
// FIXME should we test object.config().support_material_synchronize_layers ? IN prusa code, the support layers are synchronized with object layers iff soluble supports.
|
||||
//assert(gap_over_supports != 0. || object.config().support_material_synchronize_layers);
|
||||
if (gap_over_supports != 0.) {
|
||||
gap_over_supports = std::max(0., gap_over_supports);
|
||||
// Not a soluble support,
|
||||
double support_layer_height_min = 1000000.;
|
||||
for (auto lh : object.print()->config().min_layer_height.values)
|
||||
support_layer_height_min = std::min(support_layer_height_min, std::max(0.01, lh));
|
||||
gap_over_supports += support_layer_height_min;
|
||||
}
|
||||
|
||||
// Pair the object layers with the support layers by z.
|
||||
size_t idx_object_layer = 0;
|
||||
size_t idx_support_layer = 0;
|
||||
@ -530,18 +573,19 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||
|
||||
// In case there are extrusions on this layer, check there is a layer to lay it on.
|
||||
if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|
||||
|| (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions())) {
|
||||
// Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions.
|
||||
|| (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) {
|
||||
double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer)
|
||||
? object.config().support_material_contact_distance
|
||||
? gap_over_supports
|
||||
: 0.;
|
||||
double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.)
|
||||
+ layer_to_print.layer()->height
|
||||
+ std::max(0., support_contact_z);
|
||||
+ support_contact_z;
|
||||
// Negative support_contact_z is not taken into account, it can result in false positives in cases
|
||||
// where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752)
|
||||
|
||||
|
||||
if (layer_to_print.print_z() > maximal_print_z + EPSILON)
|
||||
if (layer_to_print.print_z() > maximal_print_z + 2. * EPSILON)
|
||||
throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" +
|
||||
_(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) +
|
||||
std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is "
|
||||
@ -661,15 +705,20 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
if (print->config().remaining_times.value) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode" << log_memory_info();
|
||||
m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||
GCodeTimeEstimator::PostProcessData normal_data = m_normal_time_estimator.get_post_process_data();
|
||||
GCodeTimeEstimator::PostProcessData silent_data = m_silent_time_estimator.get_post_process_data();
|
||||
|
||||
bool remaining_times_enabled = print->config().remaining_times.value;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Time estimator post processing" << log_memory_info();
|
||||
GCodeTimeEstimator::post_process(path_tmp, 60.0f, remaining_times_enabled ? &normal_data : nullptr,
|
||||
(remaining_times_enabled && m_silent_time_estimator_enabled) ? &silent_data : nullptr);
|
||||
|
||||
if (remaining_times_enabled)
|
||||
{
|
||||
m_normal_time_estimator.reset();
|
||||
if (m_silent_time_estimator_enabled) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode" << log_memory_info();
|
||||
m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||
if (m_silent_time_estimator_enabled)
|
||||
m_silent_time_estimator.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// starts analyzer calculations
|
||||
@ -773,6 +822,11 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
}
|
||||
m_analyzer.set_extruder_offsets(extruder_offsets);
|
||||
|
||||
// send extruders count to analyzer to allow it to detect invalid extruder idxs
|
||||
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(print.config().option("extruder_colour"));
|
||||
const ConfigOptionStrings* filamemts_opt = dynamic_cast<const ConfigOptionStrings*>(print.config().option("filament_colour"));
|
||||
m_analyzer.set_extruders_count(std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size()));
|
||||
|
||||
// tell analyzer about the gcode flavor
|
||||
m_analyzer.set_gcode_flavor(print.config().gcode_flavor);
|
||||
|
||||
@ -1758,13 +1812,9 @@ void GCode::process_layer(
|
||||
|
||||
// This extrusion is part of certain Region, which tells us which extruder should be used for it:
|
||||
int correct_extruder_id = Print::get_extruder(*fill, region);
|
||||
//FIXME what is this?
|
||||
entity_type=="infills" ?
|
||||
std::max<int>(0, (is_solid_infill(fill->entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) - 1) :
|
||||
std::max<int>(region.config().perimeter_extruder.value - 1, 0);
|
||||
|
||||
// Let's recover vector of extruder overrides:
|
||||
const ExtruderPerCopy* entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(fill, correct_extruder_id, (int)layer_to_print.object()->copies().size());
|
||||
const ExtruderPerCopy* entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(fill, correct_extruder_id, layer_to_print.object()->copies().size());
|
||||
|
||||
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
|
||||
for (unsigned int extruder : layer_tools.extruders)
|
||||
@ -1844,12 +1894,13 @@ void GCode::process_layer(
|
||||
if (!m_brim_done) {
|
||||
this->set_origin(0., 0.);
|
||||
m_avoid_crossing_perimeters.use_external_mp = true;
|
||||
for (const ExtrusionEntity *ee : print.brim().entities)
|
||||
for (const ExtrusionEntity *ee : print.brim().entities) {
|
||||
gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value);
|
||||
}
|
||||
m_brim_done = true;
|
||||
m_avoid_crossing_perimeters.use_external_mp = false;
|
||||
// Allow a straight travel move to the first object point.
|
||||
m_avoid_crossing_perimeters.disable_once = true;
|
||||
m_brim_done = true;
|
||||
}
|
||||
//extrude object-only skirt
|
||||
if (single_object_idx != size_t(-1) && !layers.front().object()->skirt().empty()
|
||||
@ -1965,7 +2016,7 @@ void GCode::process_layer(
|
||||
_write(file, gcode);
|
||||
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
|
||||
", time estimator memory: " <<
|
||||
format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) <<
|
||||
format_memsize_MB(m_normal_time_estimator.memory_used() + (m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0)) <<
|
||||
", analyzer memory: " <<
|
||||
format_memsize_MB(m_analyzer.memory_used()) <<
|
||||
log_memory_info();
|
||||
@ -2046,38 +2097,6 @@ std::string GCode::change_layer(coordf_t print_z)
|
||||
return gcode;
|
||||
}
|
||||
|
||||
static inline const char* ExtrusionRole2String(const ExtrusionRole role)
|
||||
{
|
||||
switch (role) {
|
||||
case erNone: return "erNone";
|
||||
case erPerimeter: return "erPerimeter";
|
||||
case erExternalPerimeter: return "erExternalPerimeter";
|
||||
case erOverhangPerimeter: return "erOverhangPerimeter";
|
||||
case erInternalInfill: return "erInternalInfill";
|
||||
case erSolidInfill: return "erSolidInfill";
|
||||
case erTopSolidInfill: return "erTopSolidInfill";
|
||||
case erBridgeInfill: return "erBridgeInfill";
|
||||
case erGapFill: return "erGapFill";
|
||||
case erSkirt: return "erSkirt";
|
||||
case erSupportMaterial: return "erSupportMaterial";
|
||||
case erSupportMaterialInterface: return "erSupportMaterialInterface";
|
||||
case erWipeTower: return "erWipeTower";
|
||||
case erMixed: return "erMixed";
|
||||
|
||||
default: return "erInvalid";
|
||||
};
|
||||
}
|
||||
|
||||
static inline const char* ExtrusionLoopRole2String(const ExtrusionLoopRole role)
|
||||
{
|
||||
switch (role) {
|
||||
case elrDefault: return "elrDefault";
|
||||
case elrContourInternalPerimeter: return "elrContourInternalPerimeter";
|
||||
case elrSkirt: return "elrSkirt";
|
||||
default: return "elrInvalid";
|
||||
}
|
||||
};
|
||||
|
||||
// Return a value in <0, 1> of a cubic B-spline kernel centered around zero.
|
||||
// The B-spline is re-scaled so it has value 1 at zero.
|
||||
static inline float bspline_kernel(float x)
|
||||
@ -2492,8 +2511,8 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
|
||||
// extrude along the path
|
||||
std::string gcode;
|
||||
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
|
||||
// description += ExtrusionLoopRole2String(loop.loop_role());
|
||||
// description += ExtrusionRole2String(path->role);
|
||||
// description += ExtrusionLoop::role_to_string(loop.loop_role());
|
||||
// description += ExtrusionEntity::role_to_string(path->role);
|
||||
path->simplify(SCALED_RESOLUTION);
|
||||
gcode += this->_extrude(*path, description, speed);
|
||||
}
|
||||
@ -2545,8 +2564,8 @@ std::string GCode::extrude_multi_path(const ExtrusionMultiPath &multipath, const
|
||||
// extrude along the path
|
||||
std::string gcode;
|
||||
for (ExtrusionPath path : multipath.paths) {
|
||||
// description += ExtrusionLoopRole2String(loop.loop_role());
|
||||
// description += ExtrusionRole2String(path->role);
|
||||
// description += ExtrusionLoop::role_to_string(loop.loop_role());
|
||||
// description += ExtrusionEntity::role_to_string(path->role);
|
||||
path.simplify(SCALED_RESOLUTION);
|
||||
gcode += this->_extrude(path, description, speed);
|
||||
}
|
||||
@ -2907,11 +2926,11 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
// PrusaMultiMaterial::Writer may generate GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines without updating m_last_height and m_last_width
|
||||
// so, if the last role was erWipeTower we force export of GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines
|
||||
bool last_was_wipe_tower = (m_last_analyzer_extrusion_role == erWipeTower);
|
||||
char buf[64];
|
||||
|
||||
if (path.role() != m_last_analyzer_extrusion_role)
|
||||
{
|
||||
m_last_analyzer_extrusion_role = path.role();
|
||||
char buf[32];
|
||||
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), int(m_last_analyzer_extrusion_role));
|
||||
gcode += buf;
|
||||
}
|
||||
@ -2919,8 +2938,6 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
if (last_was_wipe_tower || (m_last_mm3_per_mm != path.mm3_per_mm))
|
||||
{
|
||||
m_last_mm3_per_mm = path.mm3_per_mm;
|
||||
|
||||
char buf[32];
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||
gcode += buf;
|
||||
}
|
||||
@ -2928,8 +2945,6 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
if (last_was_wipe_tower || (m_last_width != path.width))
|
||||
{
|
||||
m_last_width = path.width;
|
||||
|
||||
char buf[32];
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), m_last_width);
|
||||
gcode += buf;
|
||||
}
|
||||
@ -2937,8 +2952,6 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
if (last_was_wipe_tower || (m_last_height != path.height))
|
||||
{
|
||||
m_last_height = path.height;
|
||||
|
||||
char buf[32];
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_last_height);
|
||||
gcode += buf;
|
||||
}
|
||||
@ -3125,6 +3138,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
||||
gcode += m_ooze_prevention.pre_toolchange(*this);
|
||||
|
||||
const std::string& toolchange_gcode = m_config.toolchange_gcode.value;
|
||||
std::string toolchange_gcode_parsed;
|
||||
|
||||
// Process the custom toolchange_gcode. If it is empty, insert just a Tn command.
|
||||
if (!toolchange_gcode.empty()) {
|
||||
@ -3133,13 +3147,14 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
||||
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
gcode += placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config);
|
||||
toolchange_gcode_parsed = placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config);
|
||||
gcode += toolchange_gcode_parsed;
|
||||
check_add_eol(gcode);
|
||||
}
|
||||
|
||||
// We inform the writer about what is happening, but we may not use the resulting gcode.
|
||||
std::string toolchange_command = m_writer.toolchange(extruder_id);
|
||||
if (toolchange_gcode.empty())
|
||||
if (! custom_gcode_changes_tool(toolchange_gcode_parsed, m_writer.toolchange_prefix(), extruder_id))
|
||||
gcode += toolchange_command;
|
||||
else {
|
||||
// user provided his own toolchange gcode, no need to do anything
|
||||
@ -3226,7 +3241,7 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
|
||||
|
||||
// This function takes the eec and appends its entities to either perimeters or infills of this Region (depending on the first parameter)
|
||||
// It also saves pointer to ExtruderPerCopy struct (for each entity), that holds information about which extruders should be used for which copy.
|
||||
void GCode::ObjectByExtruder::Island::Region::append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copies_extruder, unsigned int object_copies_num)
|
||||
void GCode::ObjectByExtruder::Island::Region::append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copies_extruder, size_t object_copies_num)
|
||||
{
|
||||
// We are going to manipulate either perimeters or infills, exactly in the same way. Let's create pointers to the proper structure to not repeat ourselves:
|
||||
ExtrusionEntityCollection* perimeters_or_infills = &infills;
|
||||
|
@ -260,7 +260,7 @@ protected:
|
||||
std::vector<const ExtruderPerCopy*> perimeters_overrides;
|
||||
|
||||
// Appends perimeter/infill entities and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping
|
||||
void append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copy_extruders, unsigned int object_copies_num);
|
||||
void append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copy_extruders, size_t object_copies_num);
|
||||
};
|
||||
|
||||
std::vector<Region> by_region; // all extrusions for this island, grouped by regions
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "../Utils.hpp"
|
||||
#include "Print.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "Analyzer.hpp"
|
||||
#include "PreviewData.hpp"
|
||||
|
||||
@ -107,6 +109,11 @@ void GCodeAnalyzer::set_extruder_offsets(const GCodeAnalyzer::ExtruderOffsetsMap
|
||||
m_extruder_offsets = extruder_offsets;
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::set_extruders_count(unsigned int count)
|
||||
{
|
||||
m_extruders_count = count;
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::set_gcode_flavor(const GCodeFlavor& flavor)
|
||||
{
|
||||
m_gcode_flavor = flavor;
|
||||
@ -131,6 +138,7 @@ void GCodeAnalyzer::reset()
|
||||
|
||||
m_moves_map.clear();
|
||||
m_extruder_offsets.clear();
|
||||
m_extruders_count = 1;
|
||||
}
|
||||
|
||||
const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
|
||||
@ -520,7 +528,13 @@ void GCodeAnalyzer::_processT(const std::string& cmd)
|
||||
unsigned int id = (unsigned int)::strtol(cmd.substr(1).c_str(), nullptr, 10);
|
||||
if (_get_extruder_id() != id)
|
||||
{
|
||||
_set_extruder_id(id);
|
||||
if (id >= m_extruders_count)
|
||||
{
|
||||
if (m_extruders_count > 1)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeAnalyzer encountered an invalid toolchange, maybe from a custom gcode.";
|
||||
}
|
||||
else
|
||||
_set_extruder_id(id);
|
||||
|
||||
// stores tool change move
|
||||
_store_move(GCodeMove::Tool_change);
|
||||
|
@ -109,6 +109,7 @@ private:
|
||||
GCodeReader m_parser;
|
||||
TypeToMovesMap m_moves_map;
|
||||
ExtruderOffsetsMap m_extruder_offsets;
|
||||
unsigned int m_extruders_count;
|
||||
GCodeFlavor m_gcode_flavor;
|
||||
|
||||
// The output of process_layer()
|
||||
@ -118,6 +119,7 @@ public:
|
||||
GCodeAnalyzer();
|
||||
|
||||
void set_extruder_offsets(const ExtruderOffsetsMap& extruder_offsets);
|
||||
void set_extruders_count(unsigned int count);
|
||||
|
||||
void set_gcode_flavor(const GCodeFlavor& flavor);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "CoolingBuffer.hpp"
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <iostream>
|
||||
#include <float.h>
|
||||
|
||||
@ -417,13 +418,22 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
|
||||
line.type = CoolingLine::TYPE_EXTRUDE_END;
|
||||
active_speed_modifier = size_t(-1);
|
||||
} else if (boost::starts_with(sline, toolchange_prefix)) {
|
||||
// Switch the tool.
|
||||
line.type = CoolingLine::TYPE_SET_TOOL;
|
||||
unsigned int new_extruder = (unsigned int)atoi(sline.c_str() + toolchange_prefix.size());
|
||||
if (new_extruder != current_extruder) {
|
||||
current_extruder = new_extruder;
|
||||
adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
|
||||
// Only change extruder in case the number is meaningful. User could provide an out-of-range index through custom gcodes - those shall be ignored.
|
||||
if (new_extruder < map_extruder_to_per_extruder_adjustment.size()) {
|
||||
if (new_extruder != current_extruder) {
|
||||
// Switch the tool.
|
||||
line.type = CoolingLine::TYPE_SET_TOOL;
|
||||
current_extruder = new_extruder;
|
||||
adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Only log the error in case of MM printer. Single extruder printers likely ignore any T anyway.
|
||||
if (map_extruder_to_per_extruder_adjustment.size() > 1)
|
||||
BOOST_LOG_TRIVIAL(error) << "CoolingBuffer encountered an invalid toolchange, maybe from a custom gcode: " << sline;
|
||||
}
|
||||
|
||||
} else if (boost::starts_with(sline, ";_BRIDGE_FAN_START")) {
|
||||
line.type = CoolingLine::TYPE_BRIDGE_FAN_START;
|
||||
} else if (boost::starts_with(sline, ";_BRIDGE_FAN_END")) {
|
||||
|
@ -13,22 +13,6 @@ namespace Slic3r {
|
||||
|
||||
const GCodePreviewData::Color GCodePreviewData::Color::Dummy(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
GCodePreviewData::Color::Color()
|
||||
{
|
||||
rgba[0] = 1.0f;
|
||||
rgba[1] = 1.0f;
|
||||
rgba[2] = 1.0f;
|
||||
rgba[3] = 1.0f;
|
||||
}
|
||||
|
||||
GCodePreviewData::Color::Color(float r, float g, float b, float a)
|
||||
{
|
||||
rgba[0] = r;
|
||||
rgba[1] = g;
|
||||
rgba[2] = b;
|
||||
rgba[3] = a;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> GCodePreviewData::Color::as_bytes() const
|
||||
{
|
||||
std::vector<unsigned char> ret;
|
||||
@ -137,7 +121,7 @@ GCodePreviewData::LegendItem::LegendItem(const std::string& text, const GCodePre
|
||||
{
|
||||
}
|
||||
|
||||
const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[Num_Extrusion_Roles] =
|
||||
const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] =
|
||||
{
|
||||
Color(0.0f, 0.0f, 0.0f, 1.0f), // erNone
|
||||
Color(1.0f, 0.0f, 0.0f, 1.0f), // erPerimeter
|
||||
@ -156,44 +140,20 @@ const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Rol
|
||||
Color(0.0f, 0.0f, 0.0f, 1.0f) // erMixed
|
||||
};
|
||||
|
||||
// todo: merge with Slic3r::ExtrusionRole2String() from GCode.cpp
|
||||
const std::string GCodePreviewData::Extrusion::Default_Extrusion_Role_Names[Num_Extrusion_Roles]
|
||||
{
|
||||
L("None"),
|
||||
L("Perimeter"),
|
||||
L("External perimeter"),
|
||||
L("Overhang perimeter"),
|
||||
L("Internal infill"),
|
||||
L("Solid infill"),
|
||||
L("Top solid infill"),
|
||||
L("Bridge infill"),
|
||||
L("Gap fill"),
|
||||
L("Skirt"),
|
||||
L("Support material"),
|
||||
L("Support material interface"),
|
||||
L("Wipe tower"),
|
||||
L("Custom"),
|
||||
L("Mixed")
|
||||
};
|
||||
|
||||
const GCodePreviewData::Extrusion::EViewType GCodePreviewData::Extrusion::Default_View_Type = GCodePreviewData::Extrusion::FeatureType;
|
||||
|
||||
void GCodePreviewData::Extrusion::set_default()
|
||||
{
|
||||
view_type = Default_View_Type;
|
||||
|
||||
::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, Num_Extrusion_Roles * sizeof(Color));
|
||||
::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, erCount * sizeof(Color));
|
||||
|
||||
for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
|
||||
{
|
||||
role_names[i] = Default_Extrusion_Role_Names[i];
|
||||
}
|
||||
for (unsigned int i = 0; i < erCount; ++i)
|
||||
role_names[i] = ExtrusionEntity::role_to_string(ExtrusionRole(i));
|
||||
|
||||
role_flags = 0;
|
||||
for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < erCount; ++i)
|
||||
role_flags |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
bool GCodePreviewData::Extrusion::is_role_flag_set(ExtrusionRole role) const
|
||||
@ -334,7 +294,7 @@ GCodePreviewData::Color GCodePreviewData::get_volumetric_rate_color(float rate)
|
||||
|
||||
void GCodePreviewData::set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha)
|
||||
{
|
||||
for (unsigned int i = 0; i < Extrusion::Num_Extrusion_Roles; ++i)
|
||||
for (unsigned int i = 0; i < erCount; ++i)
|
||||
{
|
||||
if (role_name == extrusion.role_names[i])
|
||||
{
|
||||
|
@ -14,14 +14,14 @@ public:
|
||||
{
|
||||
float rgba[4];
|
||||
|
||||
Color();
|
||||
Color(float r, float g, float b, float a);
|
||||
Color(const float *argba) { memcpy(this->rgba, argba, sizeof(float) * 4); }
|
||||
Color(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) { rgba[0] = r; rgba[1] = g; rgba[2] = b; rgba[3] = a; }
|
||||
|
||||
std::vector<unsigned char> as_bytes() const;
|
||||
|
||||
static const Color Dummy;
|
||||
};
|
||||
|
||||
|
||||
// Color mapping from a <min, max> range into a smooth rainbow of 10 colors.
|
||||
struct Range
|
||||
{
|
||||
@ -81,9 +81,8 @@ public:
|
||||
Num_View_Types
|
||||
};
|
||||
|
||||
static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1;
|
||||
static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles];
|
||||
static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles];
|
||||
static const Color Default_Extrusion_Role_Colors[erCount];
|
||||
static const std::string Default_Extrusion_Role_Names[erCount];
|
||||
static const EViewType Default_View_Type;
|
||||
|
||||
struct Layer
|
||||
@ -97,8 +96,8 @@ public:
|
||||
typedef std::vector<Layer> LayersList;
|
||||
|
||||
EViewType view_type;
|
||||
Color role_colors[Num_Extrusion_Roles];
|
||||
std::string role_names[Num_Extrusion_Roles];
|
||||
Color role_colors[erCount];
|
||||
std::string role_names[erCount];
|
||||
LayersList layers;
|
||||
unsigned int role_flags;
|
||||
|
||||
|
@ -329,6 +329,28 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
||||
}
|
||||
}
|
||||
|
||||
// If the model contains empty layers (such as https://github.com/prusa3d/Slic3r/issues/1266), there might be layers
|
||||
// that were not marked as has_wipe_tower, even when they should have been. This produces a crash with soluble supports
|
||||
// and maybe other problems. We will therefore go through layer_tools and detect and fix this.
|
||||
// So, if there is a non-object layer starting with different extruder than the last one ended with (or containing more than one extruder),
|
||||
// we'll mark it with has_wipe tower.
|
||||
for (unsigned int i=0; i+1<m_layer_tools.size(); ++i) {
|
||||
LayerTools& lt = m_layer_tools[i];
|
||||
LayerTools& lt_next = m_layer_tools[i+1];
|
||||
if (lt.extruders.empty() || lt_next.extruders.empty())
|
||||
break;
|
||||
if (!lt_next.has_wipe_tower && (lt_next.extruders.front() != lt.extruders.back() || lt_next.extruders.size() > 1))
|
||||
lt_next.has_wipe_tower = true;
|
||||
// We should also check that the next wipe tower layer is no further than max_layer_height:
|
||||
unsigned int j = i+1;
|
||||
double last_wipe_tower_print_z = lt_next.print_z;
|
||||
while (++j < m_layer_tools.size()-1 && !m_layer_tools[j].has_wipe_tower)
|
||||
if (m_layer_tools[j+1].print_z - last_wipe_tower_print_z > max_layer_height) {
|
||||
m_layer_tools[j].has_wipe_tower = true;
|
||||
last_wipe_tower_print_z = m_layer_tools[j].print_z;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the wipe_tower_layer_height values.
|
||||
coordf_t wipe_tower_print_z_last = 0.;
|
||||
for (LayerTools < : m_layer_tools)
|
||||
@ -458,14 +480,14 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& object = object_list[i];
|
||||
const PrintObject* object = object_list[i];
|
||||
|
||||
// Finds this layer:
|
||||
auto this_layer_it = std::find_if(object->layers().begin(), object->layers().end(), [<](const Layer* lay) { return std::abs(lt.print_z - lay->print_z)<EPSILON; });
|
||||
if (this_layer_it == object->layers().end())
|
||||
continue;
|
||||
const Layer* this_layer = *this_layer_it;
|
||||
unsigned int num_of_copies = object->copies().size();
|
||||
size_t num_of_copies = object->copies().size();
|
||||
|
||||
for (unsigned int copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves
|
||||
|
||||
@ -494,7 +516,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
|
||||
if ((!is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume)) { // this infill will be used to wipe this extruder
|
||||
set_extruder_override(fill, copy, new_extruder, num_of_copies);
|
||||
volume_to_wipe -= fill->total_volume();
|
||||
volume_to_wipe -= float(fill->total_volume());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -512,7 +534,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
|
||||
if ((!is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume)) {
|
||||
set_extruder_override(fill, copy, new_extruder, num_of_copies);
|
||||
volume_to_wipe -= fill->total_volume();
|
||||
volume_to_wipe -= float(fill->total_volume());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -540,9 +562,9 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
|
||||
if (this_layer_it == object->layers().end())
|
||||
continue;
|
||||
const Layer* this_layer = *this_layer_it;
|
||||
unsigned int num_of_copies = object->copies().size();
|
||||
size_t num_of_copies = object->copies().size();
|
||||
|
||||
for (unsigned int copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves
|
||||
for (size_t copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves
|
||||
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) {
|
||||
const auto& region = *object->print()->regions()[region_id];
|
||||
|
||||
@ -598,7 +620,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
|
||||
// so -1 was used as "print as usual".
|
||||
// The resulting vector has to keep track of which extrusions are the ones that were overridden and which were not. In the extruder is used as overridden,
|
||||
// its number is saved as it is (zero-based index). Usual extrusions are saved as -number-1 (unfortunately there is no negative zero).
|
||||
const std::vector<int>* WipingExtrusions::get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, int num_of_copies)
|
||||
const std::vector<int>* WipingExtrusions::get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies)
|
||||
{
|
||||
auto entity_map_it = entity_map.find(entity);
|
||||
if (entity_map_it == entity_map.end())
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
}
|
||||
|
||||
// This is called from GCode::process_layer - see implementation for further comments:
|
||||
const std::vector<int>* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, int num_of_copies);
|
||||
const std::vector<int>* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies);
|
||||
|
||||
// This function goes through all infill entities, decides which ones will be used for wiping and
|
||||
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
|
||||
@ -44,7 +44,7 @@ private:
|
||||
void set_extruder_override(const ExtrusionEntity* entity, unsigned int copy_id, int extruder, unsigned int num_of_copies);
|
||||
|
||||
// Returns true in case that entity is not printed with its usual extruder for a given copy:
|
||||
bool is_entity_overridden(const ExtrusionEntity* entity, int copy_id) const {
|
||||
bool is_entity_overridden(const ExtrusionEntity* entity, size_t copy_id) const {
|
||||
return (entity_map.find(entity) == entity_map.end() ? false : entity_map.at(entity).at(copy_id) != -1);
|
||||
}
|
||||
|
||||
|
@ -36,19 +36,6 @@ TODO LIST
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
// Rotate the point around center of the wipe tower about given angle (in degrees)
|
||||
static Vec2f rotate(const Vec2f& pt, float width, float depth, float angle)
|
||||
{
|
||||
Vec2f out(0,0);
|
||||
float temp_x = pt(0) - width / 2.f;
|
||||
float temp_y = pt(1) - depth / 2.f;
|
||||
angle *= float(M_PI/180.);
|
||||
out.x() += temp_x * cos(angle) - temp_y * sin(angle) + width / 2.f;
|
||||
out.y() += temp_x * sin(angle) + temp_y * cos(angle) + depth / 2.f;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
class WipeTowerWriter
|
||||
{
|
||||
public:
|
||||
@ -82,7 +69,7 @@ public:
|
||||
}
|
||||
|
||||
WipeTowerWriter& change_analyzer_mm3_per_mm(float len, float e) {
|
||||
static const float area = M_PI * 1.75f * 1.75f / 4.f;
|
||||
static const float area = float(M_PI) * 1.75f * 1.75f / 4.f;
|
||||
float mm3_per_mm = (len == 0.f ? 0.f : area * e / len);
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
@ -95,12 +82,12 @@ public:
|
||||
m_wipe_tower_width = width;
|
||||
m_wipe_tower_depth = depth;
|
||||
m_internal_angle = internal_angle;
|
||||
m_start_pos = rotate(pos + Vec2f(0.f,m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle);
|
||||
m_start_pos = this->rotate(pos);
|
||||
m_current_pos = pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
WipeTowerWriter& set_initial_tool(const unsigned int tool) { m_current_tool = tool; return *this; }
|
||||
WipeTowerWriter& set_initial_tool(size_t tool) { m_current_tool = tool; return *this; }
|
||||
|
||||
WipeTowerWriter& set_z(float z)
|
||||
{ m_current_z = z; return *this; }
|
||||
@ -138,7 +125,7 @@ public:
|
||||
float y() const { return m_current_pos.y(); }
|
||||
const Vec2f& pos() const { return m_current_pos; }
|
||||
const Vec2f start_pos_rotated() const { return m_start_pos; }
|
||||
const Vec2f pos_rotated() const { return rotate(m_current_pos + Vec2f(0.f, m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle); }
|
||||
const Vec2f pos_rotated() const { return this->rotate(m_current_pos); }
|
||||
float elapsed_time() const { return m_elapsed_time; }
|
||||
float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; }
|
||||
|
||||
@ -151,19 +138,19 @@ public:
|
||||
|
||||
float dx = x - m_current_pos.x();
|
||||
float dy = y - m_current_pos.y();
|
||||
double len = sqrt(dx*dx+dy*dy);
|
||||
float len = std::sqrt(dx*dx+dy*dy);
|
||||
if (record_length)
|
||||
m_used_filament_length += e;
|
||||
|
||||
// Now do the "internal rotation" with respect to the wipe tower center
|
||||
Vec2f rotated_current_pos(rotate(m_current_pos + Vec2f(0.f,m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we are
|
||||
Vec2f rot(rotate(Vec2f(x,y+m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we want to go
|
||||
Vec2f rotated_current_pos(this->pos_rotated());
|
||||
Vec2f rot(this->rotate(Vec2f(x,y))); // this is where we want to go
|
||||
|
||||
if (! m_preview_suppressed && e > 0.f && len > 0.) {
|
||||
if (! m_preview_suppressed && e > 0.f && len > 0.f) {
|
||||
change_analyzer_mm3_per_mm(len, e);
|
||||
// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
|
||||
// This is left zero if it is a travel move.
|
||||
float width = float(double(e) * m_filpar[0].filament_area / (len * m_layer_height));
|
||||
float width = e * m_filpar[0].filament_area / (len * m_layer_height);
|
||||
// Correct for the roundings of a squished extrusion.
|
||||
width += m_layer_height * float(1. - M_PI / 4.);
|
||||
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos)
|
||||
@ -172,10 +159,10 @@ public:
|
||||
}
|
||||
|
||||
m_gcode += "G1";
|
||||
if (std::abs(rot.x() - rotated_current_pos.x()) > EPSILON)
|
||||
if (std::abs(rot.x() - rotated_current_pos.x()) > (float)EPSILON)
|
||||
m_gcode += set_format_X(rot.x());
|
||||
|
||||
if (std::abs(rot.y() - rotated_current_pos.y()) > EPSILON)
|
||||
if (std::abs(rot.y() - rotated_current_pos.y()) > (float)EPSILON)
|
||||
m_gcode += set_format_Y(rot.y());
|
||||
|
||||
|
||||
@ -184,7 +171,7 @@ public:
|
||||
|
||||
if (f != 0.f && f != m_current_feedrate) {
|
||||
if (limit_volumetric_flow) {
|
||||
float e_speed = e / (((len == 0) ? std::abs(e) : len) / f * 60.f);
|
||||
float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f);
|
||||
f /= std::max(1.f, e_speed / m_filpar[m_current_tool].max_e_speed);
|
||||
}
|
||||
m_gcode += set_format_F(f);
|
||||
@ -194,7 +181,7 @@ public:
|
||||
m_current_pos.y() = y;
|
||||
|
||||
// Update the elapsed time with a rough estimate.
|
||||
m_elapsed_time += ((len == 0) ? std::abs(e) : len) / m_current_feedrate * 60.f;
|
||||
m_elapsed_time += ((len == 0.f) ? std::abs(e) : len) / m_current_feedrate * 60.f;
|
||||
m_gcode += "\n";
|
||||
return *this;
|
||||
}
|
||||
@ -214,7 +201,7 @@ public:
|
||||
{
|
||||
float dx = x - m_current_pos.x();
|
||||
float dy = y - m_current_pos.y();
|
||||
return extrude_explicit(x, y, sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true);
|
||||
return extrude_explicit(x, y, std::sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true);
|
||||
}
|
||||
|
||||
WipeTowerWriter& extrude(const Vec2f &dest, const float f = 0.f)
|
||||
@ -311,7 +298,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
WipeTowerWriter& set_tool(int tool)
|
||||
WipeTowerWriter& set_tool(size_t tool)
|
||||
{
|
||||
m_current_tool = tool;
|
||||
return *this;
|
||||
@ -320,57 +307,52 @@ public:
|
||||
// Set extruder temperature, don't wait by default.
|
||||
WipeTowerWriter& set_extruder_temp(int temperature, bool wait = false)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M%d S%d\n", wait ? 109 : 104, temperature);
|
||||
m_gcode += buf;
|
||||
m_gcode += "M" + std::to_string(wait ? 109 : 104) + " S" + std::to_string(temperature) + "\n";
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
// Wait for a period of time (seconds).
|
||||
WipeTowerWriter& wait(float time)
|
||||
{
|
||||
if (time==0)
|
||||
if (time==0.f)
|
||||
return *this;
|
||||
char buf[128];
|
||||
sprintf(buf, "G4 S%.3f\n", time);
|
||||
m_gcode += buf;
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
// Set speed factor override percentage.
|
||||
WipeTowerWriter& speed_override(int speed)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M220 S%d\n", speed);
|
||||
m_gcode += buf;
|
||||
m_gcode += "M220 S" + std::to_string(speed) + "\n";
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
// Let the firmware back up the active speed override value.
|
||||
WipeTowerWriter& speed_override_backup()
|
||||
{
|
||||
m_gcode += "M220 B\n";
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
// Let the firmware restore the active speed override value.
|
||||
WipeTowerWriter& speed_override_restore()
|
||||
{
|
||||
m_gcode += "M220 R\n";
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
// Set digital trimpot motor
|
||||
WipeTowerWriter& set_extruder_trimpot(int current)
|
||||
{
|
||||
char buf[128];
|
||||
if (m_gcode_flavor == gcfRepRap)
|
||||
sprintf(buf, "M906 E%d\n", current);
|
||||
m_gcode += "M906 E";
|
||||
else
|
||||
sprintf(buf, "M907 E%d\n", current);
|
||||
m_gcode += buf;
|
||||
m_gcode += "M907 E";
|
||||
m_gcode += std::to_string(current) + "\n";
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
WipeTowerWriter& flush_planner_queue()
|
||||
{
|
||||
@ -387,27 +369,19 @@ public:
|
||||
|
||||
WipeTowerWriter& comment_with_value(const char *comment, int value)
|
||||
{
|
||||
char strvalue[64];
|
||||
sprintf(strvalue, "%d", value);
|
||||
m_gcode += std::string(";") + comment + strvalue + "\n";
|
||||
m_gcode += std::string(";") + comment + std::to_string(value) + "\n";
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
WipeTowerWriter& set_fan(unsigned int speed)
|
||||
WipeTowerWriter& set_fan(unsigned speed)
|
||||
{
|
||||
if (speed == m_last_fan_speed)
|
||||
return *this;
|
||||
|
||||
if (speed == 0)
|
||||
m_gcode += "M107\n";
|
||||
else
|
||||
{
|
||||
m_gcode += "M106 S";
|
||||
char buf[128];
|
||||
sprintf(buf,"%u\n",(unsigned int)(255.0 * speed / 100.0));
|
||||
m_gcode += buf;
|
||||
}
|
||||
m_gcode += "M106 S" + std::to_string(unsigned(255.0 * speed / 100.0)) + "\n";
|
||||
m_last_fan_speed = speed;
|
||||
return *this;
|
||||
}
|
||||
@ -419,7 +393,7 @@ private:
|
||||
Vec2f m_current_pos;
|
||||
float m_current_z;
|
||||
float m_current_feedrate;
|
||||
unsigned int m_current_tool;
|
||||
size_t m_current_tool;
|
||||
float m_layer_height;
|
||||
float m_extrusion_flow;
|
||||
bool m_preview_suppressed;
|
||||
@ -430,7 +404,7 @@ private:
|
||||
float m_y_shift = 0.f;
|
||||
float m_wipe_tower_width = 0.f;
|
||||
float m_wipe_tower_depth = 0.f;
|
||||
float m_last_fan_speed = 0.f;
|
||||
unsigned m_last_fan_speed = 0;
|
||||
int current_temp = -1;
|
||||
const float m_default_analyzer_line_width;
|
||||
float m_used_filament_length = 0.f;
|
||||
@ -472,6 +446,18 @@ private:
|
||||
}
|
||||
|
||||
WipeTowerWriter& operator=(const WipeTowerWriter &rhs);
|
||||
|
||||
// Rotate the point around center of the wipe tower about given angle (in degrees)
|
||||
Vec2f rotate(Vec2f pt) const
|
||||
{
|
||||
pt.x() -= m_wipe_tower_width / 2.f;
|
||||
pt.y() += m_y_shift - m_wipe_tower_depth / 2.f;
|
||||
double angle = m_internal_angle * float(M_PI/180.);
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
return Vec2f(float(pt.x() * c - pt.y() * s) + m_wipe_tower_width / 2.f, float(pt.x() * s + pt.y() * c) + m_wipe_tower_depth / 2.f);
|
||||
}
|
||||
|
||||
}; // class WipeTowerWriter
|
||||
|
||||
|
||||
@ -479,12 +465,12 @@ private:
|
||||
WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool) :
|
||||
m_semm(config.single_extruder_multi_material.value),
|
||||
m_wipe_tower_pos(config.wipe_tower_x, config.wipe_tower_y),
|
||||
m_wipe_tower_width(config.wipe_tower_width),
|
||||
m_wipe_tower_rotation_angle(config.wipe_tower_rotation_angle),
|
||||
m_wipe_tower_width(float(config.wipe_tower_width)),
|
||||
m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)),
|
||||
m_y_shift(0.f),
|
||||
m_z_pos(0.f),
|
||||
m_is_first_layer(false),
|
||||
m_bridging(config.wipe_tower_bridging),
|
||||
m_bridging(float(config.wipe_tower_bridging)),
|
||||
m_gcode_flavor(config.gcode_flavor),
|
||||
m_current_tool(initial_tool),
|
||||
wipe_volumes(wiping_matrix)
|
||||
@ -492,16 +478,16 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (m_semm) {
|
||||
m_cooling_tube_retraction = config.cooling_tube_retraction;
|
||||
m_cooling_tube_length = config.cooling_tube_length;
|
||||
m_parking_pos_retraction = config.parking_pos_retraction;
|
||||
m_extra_loading_move = config.extra_loading_move;
|
||||
m_cooling_tube_retraction = float(config.cooling_tube_retraction);
|
||||
m_cooling_tube_length = float(config.cooling_tube_length);
|
||||
m_parking_pos_retraction = float(config.parking_pos_retraction);
|
||||
m_extra_loading_move = float(config.extra_loading_move);
|
||||
m_set_extruder_trimpot = config.high_current_on_filament_swap;
|
||||
}
|
||||
// Calculate where the priming lines should be - very naive test not detecting parallelograms or custom shapes
|
||||
const std::vector<Vec2d>& bed_points = config.bed_shape.values;
|
||||
m_bed_shape = (bed_points.size() == 4 ? RectangularBed : CircularBed);
|
||||
m_bed_width = BoundingBoxf(bed_points).size().x();
|
||||
m_bed_width = float(BoundingBoxf(bed_points).size().x());
|
||||
}
|
||||
|
||||
|
||||
@ -518,21 +504,21 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
|
||||
// If this is a single extruder MM printer, we will use all the SE-specific config values.
|
||||
// Otherwise, the defaults will be used to turn off the SE stuff.
|
||||
if (m_semm) {
|
||||
m_filpar[idx].loading_speed = config.filament_loading_speed.get_at(idx);
|
||||
m_filpar[idx].loading_speed_start = config.filament_loading_speed_start.get_at(idx);
|
||||
m_filpar[idx].unloading_speed = config.filament_unloading_speed.get_at(idx);
|
||||
m_filpar[idx].unloading_speed_start = config.filament_unloading_speed_start.get_at(idx);
|
||||
m_filpar[idx].delay = config.filament_toolchange_delay.get_at(idx);
|
||||
m_filpar[idx].loading_speed = float(config.filament_loading_speed.get_at(idx));
|
||||
m_filpar[idx].loading_speed_start = float(config.filament_loading_speed_start.get_at(idx));
|
||||
m_filpar[idx].unloading_speed = float(config.filament_unloading_speed.get_at(idx));
|
||||
m_filpar[idx].unloading_speed_start = float(config.filament_unloading_speed_start.get_at(idx));
|
||||
m_filpar[idx].delay = float(config.filament_toolchange_delay.get_at(idx));
|
||||
m_filpar[idx].cooling_moves = config.filament_cooling_moves.get_at(idx);
|
||||
m_filpar[idx].cooling_initial_speed = config.filament_cooling_initial_speed.get_at(idx);
|
||||
m_filpar[idx].cooling_final_speed = config.filament_cooling_final_speed.get_at(idx);
|
||||
m_filpar[idx].cooling_initial_speed = float(config.filament_cooling_initial_speed.get_at(idx));
|
||||
m_filpar[idx].cooling_final_speed = float(config.filament_cooling_final_speed.get_at(idx));
|
||||
}
|
||||
|
||||
m_filpar[idx].filament_area = float((M_PI/4.f) * pow(config.filament_diameter.get_at(idx), 2)); // all extruders are assumed to have the same filament diameter at this point
|
||||
float nozzle_diameter = config.nozzle_diameter.get_at(idx);
|
||||
float nozzle_diameter = float(config.nozzle_diameter.get_at(idx));
|
||||
m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM
|
||||
|
||||
float max_vol_speed = config.filament_max_volumetric_speed.get_at(idx);
|
||||
float max_vol_speed = float(config.filament_max_volumetric_speed.get_at(idx));
|
||||
if (max_vol_speed!= 0.f)
|
||||
m_filpar[idx].max_e_speed = (max_vol_speed / filament_area());
|
||||
|
||||
@ -561,7 +547,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||
const std::vector<unsigned int> &tools,
|
||||
// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
|
||||
// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
|
||||
bool last_wipe_inside_wipe_tower)
|
||||
bool /*last_wipe_inside_wipe_tower*/)
|
||||
{
|
||||
this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
|
||||
this->m_current_tool = tools.front();
|
||||
@ -581,7 +567,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||
|
||||
// Iterate over all priming toolchanges and push respective ToolChangeResults into results vector.
|
||||
for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
|
||||
int old_tool = m_current_tool;
|
||||
size_t old_tool = m_current_tool;
|
||||
|
||||
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
|
||||
writer.set_extrusion_flow(m_extrusion_flow)
|
||||
@ -630,8 +616,8 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||
|
||||
ToolChangeResult result;
|
||||
result.priming = true;
|
||||
result.initial_tool = old_tool;
|
||||
result.new_tool = m_current_tool;
|
||||
result.initial_tool = int(old_tool);
|
||||
result.new_tool = int(m_current_tool);
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
@ -666,12 +652,12 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||
return results;
|
||||
}
|
||||
|
||||
WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_in_layer)
|
||||
WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool last_in_layer)
|
||||
{
|
||||
if ( m_print_brim )
|
||||
return toolchange_Brim();
|
||||
|
||||
int old_tool = m_current_tool;
|
||||
size_t old_tool = m_current_tool;
|
||||
|
||||
float wipe_area = 0.f;
|
||||
bool last_change_in_layer = false;
|
||||
@ -696,7 +682,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
|
||||
box_coordinates cleaning_box(
|
||||
Vec2f(m_perimeter_width / 2.f, m_perimeter_width / 2.f),
|
||||
m_wipe_tower_width - m_perimeter_width,
|
||||
(tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5*m_perimeter_width
|
||||
(tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5f*m_perimeter_width
|
||||
: m_wipe_tower_depth-m_perimeter_width));
|
||||
|
||||
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
|
||||
@ -764,8 +750,8 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
|
||||
|
||||
ToolChangeResult result;
|
||||
result.priming = false;
|
||||
result.initial_tool = old_tool;
|
||||
result.new_tool = m_current_tool;
|
||||
result.initial_tool = int(old_tool);
|
||||
result.new_tool = int(m_current_tool);
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
@ -778,7 +764,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
|
||||
|
||||
WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_offset)
|
||||
{
|
||||
int old_tool = m_current_tool;
|
||||
size_t old_tool = m_current_tool;
|
||||
|
||||
const box_coordinates wipeTower_box(
|
||||
Vec2f::Zero(),
|
||||
@ -822,8 +808,8 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of
|
||||
|
||||
ToolChangeResult result;
|
||||
result.priming = false;
|
||||
result.initial_tool = old_tool;
|
||||
result.new_tool = m_current_tool;
|
||||
result.initial_tool = int(old_tool);
|
||||
result.new_tool = int(m_current_tool);
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
@ -911,8 +897,8 @@ void WipeTower::toolchange_Unload(
|
||||
const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * 0.25f, line_width, m_layer_height);
|
||||
const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / filament_area(); // transform volume per sec to E move;
|
||||
const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround
|
||||
const float actual_time = dist/x * 0.25;
|
||||
writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), dist / (actual_time / 60.));
|
||||
const float actual_time = dist/x * 0.25f;
|
||||
writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0.f, 0.f, e * (dist / x), dist / (actual_time / 60.f));
|
||||
remaining -= dist;
|
||||
|
||||
if (remaining < WT_EPSILON) { // we reached a turning point
|
||||
@ -947,12 +933,17 @@ void WipeTower::toolchange_Unload(
|
||||
.travel(old_x, writer.y()) // in case previous move was shortened to limit feedrate*/
|
||||
.resume_preview();
|
||||
}
|
||||
// Wipe tower should only change temperature with single extruder MM. Otherwise, all temperatures should
|
||||
// be already set and there is no need to change anything. Also, the temperature could be changed
|
||||
// for wrong extruder.
|
||||
if (m_semm) {
|
||||
if (new_temperature != 0 && (new_temperature != m_old_temperature || m_is_first_layer) ) { // Set the extruder temperature, but don't wait.
|
||||
// If the required temperature is the same as last time, don't emit the M104 again (if user adjusted the value, it would be reset)
|
||||
// However, always change temperatures on the first layer (this is to avoid issues with priming lines turned off).
|
||||
writer.set_extruder_temp(new_temperature, false);
|
||||
m_old_temperature = new_temperature;
|
||||
}
|
||||
}
|
||||
|
||||
// Cooling:
|
||||
const int& number_of_moves = m_filpar[m_current_tool].cooling_moves;
|
||||
@ -990,7 +981,7 @@ void WipeTower::toolchange_Unload(
|
||||
// Change the tool, set a speed override for soluble and flex materials.
|
||||
void WipeTower::toolchange_Change(
|
||||
WipeTowerWriter &writer,
|
||||
const unsigned int new_tool,
|
||||
const size_t new_tool,
|
||||
const std::string& new_material)
|
||||
{
|
||||
// Ask the writer about how much of the old filament we consumed:
|
||||
@ -1002,6 +993,11 @@ void WipeTower::toolchange_Change(
|
||||
writer.append("[end_filament_gcode]\n");
|
||||
writer.append("[toolchange_gcode]\n");
|
||||
|
||||
// Travel to where we assume we are. Custom toolchange or some special T code handling (parking extruder etc)
|
||||
// gcode could have left the extruder somewhere, we cannot just start extruding.
|
||||
Vec2f current_pos = writer.pos_rotated();
|
||||
writer.append(std::string("G1 X") + std::to_string(current_pos.x()) + " Y" + std::to_string(current_pos.y()) + "\n");
|
||||
|
||||
// The toolchange Tn command will be inserted later, only in case that the user does
|
||||
// not provide a custom toolchange gcode.
|
||||
writer.set_tool(new_tool); // This outputs nothing, the writer just needs to know the tool has changed.
|
||||
@ -1082,21 +1078,21 @@ void WipeTower::toolchange_Wipe(
|
||||
|
||||
float traversed_x = writer.x();
|
||||
if (m_left_to_right)
|
||||
writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
|
||||
writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
|
||||
else
|
||||
writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
|
||||
writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
|
||||
|
||||
if (writer.y()+EPSILON > cleaning_box.lu.y()-0.5f*m_perimeter_width)
|
||||
if (writer.y()+float(EPSILON) > cleaning_box.lu.y()-0.5f*m_perimeter_width)
|
||||
break; // in case next line would not fit
|
||||
|
||||
traversed_x -= writer.x();
|
||||
x_to_wipe -= fabs(traversed_x);
|
||||
x_to_wipe -= std::abs(traversed_x);
|
||||
if (x_to_wipe < WT_EPSILON) {
|
||||
writer.travel(m_left_to_right ? xl + 1.5*m_perimeter_width : xr - 1.5*m_perimeter_width, writer.y(), 7200);
|
||||
writer.travel(m_left_to_right ? xl + 1.5f*m_perimeter_width : xr - 1.5f*m_perimeter_width, writer.y(), 7200);
|
||||
break;
|
||||
}
|
||||
// stepping to the next line:
|
||||
writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * 1.5*m_perimeter_width, writer.y() + dy);
|
||||
writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * 1.5f*m_perimeter_width, writer.y() + dy);
|
||||
m_left_to_right = !m_left_to_right;
|
||||
}
|
||||
|
||||
@ -1119,7 +1115,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
||||
// Otherwise the caller would likely travel to the wipe tower in vain.
|
||||
assert(! this->layer_finished());
|
||||
|
||||
int old_tool = m_current_tool;
|
||||
size_t old_tool = m_current_tool;
|
||||
|
||||
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
|
||||
writer.set_extrusion_flow(m_extrusion_flow)
|
||||
@ -1179,7 +1175,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
||||
writer.travel(fill_box.ld + Vec2f(m_perimeter_width * 2, 0.f))
|
||||
.extrude(fill_box.lu + Vec2f(m_perimeter_width * 2, 0.f), 2900 * speed_factor);
|
||||
|
||||
const int n = 1+(right-left)/(m_bridging);
|
||||
const int n = 1+int((right-left)/m_bridging);
|
||||
const float dx = (right-left)/n;
|
||||
for (int i=1;i<=n;++i) {
|
||||
float x=left+dx*i;
|
||||
@ -1202,8 +1198,8 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
|
||||
|
||||
ToolChangeResult result;
|
||||
result.priming = false;
|
||||
result.initial_tool = old_tool;
|
||||
result.new_tool = m_current_tool;
|
||||
result.initial_tool = int(old_tool);
|
||||
result.new_tool = int(m_current_tool);
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
@ -1258,7 +1254,7 @@ void WipeTower::plan_tower()
|
||||
for (auto& layer : m_plan)
|
||||
layer.depth = 0.f;
|
||||
|
||||
for (int layer_index = m_plan.size() - 1; layer_index >= 0; --layer_index)
|
||||
for (int layer_index = int(m_plan.size()) - 1; layer_index >= 0; --layer_index)
|
||||
{
|
||||
float this_layer_depth = std::max(m_plan[layer_index].depth, m_plan[layer_index].toolchanges_depth());
|
||||
m_plan[layer_index].depth = this_layer_depth;
|
||||
|
@ -7,21 +7,21 @@
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
class WipeTowerWriter;
|
||||
|
||||
class PrintConfig;
|
||||
enum GCodeFlavor : unsigned char;
|
||||
|
||||
|
||||
class WipeTower
|
||||
{
|
||||
public:
|
||||
struct Extrusion
|
||||
{
|
||||
{
|
||||
Extrusion(const Vec2f &pos, float width, unsigned int tool) : pos(pos), width(width), tool(tool) {}
|
||||
// End position of this extrusion.
|
||||
Vec2f pos;
|
||||
@ -79,7 +79,6 @@ public:
|
||||
// width -- width of wipe tower in mm ( default 60 mm - leave as it is )
|
||||
// wipe_area -- space available for one toolchange in mm
|
||||
WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool);
|
||||
virtual ~WipeTower() {}
|
||||
|
||||
// Set the extruder properties.
|
||||
void set_extruder(size_t idx, const PrintConfig& config);
|
||||
@ -148,7 +147,7 @@ public:
|
||||
|
||||
// Returns gcode for a toolchange and a final print head position.
|
||||
// On the first layer, extrude a brim around the future wipe tower first.
|
||||
ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer);
|
||||
ToolChangeResult tool_change(size_t new_tool, bool last_in_layer);
|
||||
|
||||
// Fill the unfilled space with a sparse infill.
|
||||
// Call this method only if layer_finished() is false.
|
||||
@ -194,7 +193,7 @@ private:
|
||||
const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet
|
||||
const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
|
||||
const float WT_EPSILON = 1e-3f;
|
||||
const float filament_area() const {
|
||||
float filament_area() const {
|
||||
return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point
|
||||
}
|
||||
|
||||
@ -244,7 +243,7 @@ private:
|
||||
bool m_print_brim = true;
|
||||
// A fill-in direction (positive Y, negative Y) alternates with each layer.
|
||||
wipe_shape m_current_shape = SHAPE_NORMAL;
|
||||
unsigned int m_current_tool = 0;
|
||||
size_t m_current_tool = 0;
|
||||
const std::vector<std::vector<float>> wipe_volumes;
|
||||
|
||||
float m_depth_traversed = 0.f; // Current y position at the wipe tower.
|
||||
@ -309,13 +308,13 @@ private:
|
||||
// to store information about tool changes for a given layer
|
||||
struct WipeTowerInfo{
|
||||
struct ToolChange {
|
||||
unsigned int old_tool;
|
||||
unsigned int new_tool;
|
||||
size_t old_tool;
|
||||
size_t new_tool;
|
||||
float required_depth;
|
||||
float ramming_depth;
|
||||
float first_wipe_line;
|
||||
float wipe_volume;
|
||||
ToolChange(unsigned int old, unsigned int newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f)
|
||||
ToolChange(size_t old, size_t newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f)
|
||||
: old_tool{old}, new_tool{newtool}, required_depth{depth}, ramming_depth{ramming_depth}, first_wipe_line{fwl}, wipe_volume{wv} {}
|
||||
};
|
||||
float z; // z position of the layer
|
||||
@ -350,7 +349,7 @@ private:
|
||||
|
||||
void toolchange_Change(
|
||||
WipeTowerWriter &writer,
|
||||
const unsigned int new_tool,
|
||||
const size_t new_tool,
|
||||
const std::string& new_material);
|
||||
|
||||
void toolchange_Load(
|
||||
|
@ -173,9 +173,7 @@ namespace Slic3r {
|
||||
const std::string GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag = "; _TE_NORMAL_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
|
||||
// temporary human readable form to use until not removed from gcode by the new post-process method
|
||||
const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE";
|
||||
// const std::string GCodeTimeEstimator::Color_Change_Tag = "_TE_COLOR_CHANGE";
|
||||
|
||||
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
|
||||
: m_mode(mode)
|
||||
@ -273,130 +271,138 @@ namespace Slic3r {
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
}
|
||||
|
||||
bool GCodeTimeEstimator::post_process_remaining_times(const std::string& filename, float interval)
|
||||
bool GCodeTimeEstimator::post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode)
|
||||
{
|
||||
boost::nowide::ifstream in(filename);
|
||||
if (!in.good())
|
||||
throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for reading.\n"));
|
||||
throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for reading.\n"));
|
||||
|
||||
std::string path_tmp = filename + ".times";
|
||||
std::string path_tmp = filename + ".postprocess";
|
||||
|
||||
FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb");
|
||||
if (out == nullptr)
|
||||
throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for writing.\n"));
|
||||
throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for writing.\n"));
|
||||
|
||||
std::string time_mask;
|
||||
switch (m_mode)
|
||||
{
|
||||
default:
|
||||
case Normal:
|
||||
{
|
||||
time_mask = "M73 P%s R%s\n";
|
||||
break;
|
||||
}
|
||||
case Silent:
|
||||
{
|
||||
time_mask = "M73 Q%s S%s\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string normal_time_mask = "M73 P%s R%s\n";
|
||||
std::string silent_time_mask = "M73 Q%s S%s\n";
|
||||
char line_M73[64];
|
||||
|
||||
unsigned int g1_lines_count = 0;
|
||||
float last_recorded_time = 0.0f;
|
||||
std::string gcode_line;
|
||||
// buffer line to export only when greater than 64K to reduce writing calls
|
||||
std::string export_line;
|
||||
char time_line[64];
|
||||
G1LineIdToBlockIdMap::const_iterator it_line_id = m_g1_line_ids.begin();
|
||||
while (std::getline(in, gcode_line))
|
||||
{
|
||||
if (!in.good())
|
||||
{
|
||||
fclose(out);
|
||||
throw std::runtime_error(std::string("Remaining times export failed.\nError while reading from file.\n"));
|
||||
}
|
||||
|
||||
// replaces placeholders for initial line M73 with the real lines
|
||||
if (((m_mode == Normal) && (gcode_line == Normal_First_M73_Output_Placeholder_Tag)) ||
|
||||
((m_mode == Silent) && (gcode_line == Silent_First_M73_Output_Placeholder_Tag)))
|
||||
{
|
||||
sprintf(time_line, time_mask.c_str(), "0", _get_time_minutes(m_time).c_str());
|
||||
gcode_line = time_line;
|
||||
}
|
||||
// replaces placeholders for final line M73 with the real lines
|
||||
else if (((m_mode == Normal) && (gcode_line == Normal_Last_M73_Output_Placeholder_Tag)) ||
|
||||
((m_mode == Silent) && (gcode_line == Silent_Last_M73_Output_Placeholder_Tag)))
|
||||
{
|
||||
sprintf(time_line, time_mask.c_str(), "100", "0");
|
||||
gcode_line = time_line;
|
||||
}
|
||||
else
|
||||
gcode_line += "\n";
|
||||
|
||||
|
||||
// add remaining time lines where needed
|
||||
m_parser.parse_line(gcode_line,
|
||||
[this, &it_line_id, &g1_lines_count, &last_recorded_time, &time_line, &gcode_line, time_mask, interval](GCodeReader& reader, const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (line.cmd_is("G1"))
|
||||
{
|
||||
++g1_lines_count;
|
||||
|
||||
assert(it_line_id == m_g1_line_ids.end() || it_line_id->first >= g1_lines_count);
|
||||
|
||||
const Block *block = nullptr;
|
||||
if (it_line_id != m_g1_line_ids.end() && it_line_id->first == g1_lines_count) {
|
||||
if (line.has_e() && it_line_id->second < (unsigned int)m_blocks.size())
|
||||
block = &m_blocks[it_line_id->second];
|
||||
++it_line_id;
|
||||
}
|
||||
|
||||
if (block != nullptr && block->elapsed_time != -1.0f) {
|
||||
float block_remaining_time = m_time - block->elapsed_time;
|
||||
if (std::abs(last_recorded_time - block_remaining_time) > interval)
|
||||
{
|
||||
sprintf(time_line, time_mask.c_str(), std::to_string((int)(100.0f * block->elapsed_time / m_time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
|
||||
gcode_line += time_line;
|
||||
|
||||
last_recorded_time = block_remaining_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export_line += gcode_line;
|
||||
if (export_line.length() > 65535)
|
||||
{
|
||||
fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
|
||||
if (ferror(out))
|
||||
{
|
||||
in.close();
|
||||
fclose(out);
|
||||
boost::nowide::remove(path_tmp.c_str());
|
||||
throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
|
||||
}
|
||||
export_line.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (export_line.length() > 0)
|
||||
{
|
||||
// helper function to write to disk
|
||||
auto write_string = [&](const std::string& str) {
|
||||
fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
|
||||
if (ferror(out))
|
||||
{
|
||||
in.close();
|
||||
fclose(out);
|
||||
boost::nowide::remove(path_tmp.c_str());
|
||||
throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
|
||||
throw std::runtime_error(std::string("Time estimator post process export failed.\nIs the disk full?\n"));
|
||||
}
|
||||
export_line.clear();
|
||||
};
|
||||
|
||||
GCodeReader parser;
|
||||
unsigned int g1_lines_count = 0;
|
||||
int normal_g1_line_id = 0;
|
||||
float normal_last_recorded_time = 0.0f;
|
||||
int silent_g1_line_id = 0;
|
||||
float silent_last_recorded_time = 0.0f;
|
||||
|
||||
// helper function to process g1 lines
|
||||
auto process_g1_line = [&](const PostProcessData* const data, const GCodeReader::GCodeLine& line, int& g1_line_id, float& last_recorded_time, const std::string& time_mask) {
|
||||
if (data == nullptr)
|
||||
return;
|
||||
|
||||
assert((g1_line_id >= (int)data->g1_line_ids.size()) || (data->g1_line_ids[g1_line_id].first >= g1_lines_count));
|
||||
const Block* block = nullptr;
|
||||
const G1LineIdToBlockId& map_item = data->g1_line_ids[g1_line_id];
|
||||
if ((g1_line_id < (int)data->g1_line_ids.size()) && (map_item.first == g1_lines_count))
|
||||
{
|
||||
if (line.has_e() && (map_item.second < (unsigned int)data->blocks.size()))
|
||||
block = &data->blocks[map_item.second];
|
||||
++g1_line_id;
|
||||
}
|
||||
|
||||
if ((block != nullptr) && (block->elapsed_time != -1.0f))
|
||||
{
|
||||
float block_remaining_time = data->time - block->elapsed_time;
|
||||
if (std::abs(last_recorded_time - block_remaining_time) > interval_sec)
|
||||
{
|
||||
sprintf(line_M73, time_mask.c_str(), std::to_string((int)(100.0f * block->elapsed_time / data->time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
|
||||
gcode_line += line_M73;
|
||||
|
||||
last_recorded_time = block_remaining_time;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while (std::getline(in, gcode_line))
|
||||
{
|
||||
if (!in.good())
|
||||
{
|
||||
fclose(out);
|
||||
throw std::runtime_error(std::string("Time estimator post process export failed.\nError while reading from file.\n"));
|
||||
}
|
||||
|
||||
// check tags
|
||||
// remove color change tag
|
||||
if (gcode_line == "; " + Color_Change_Tag)
|
||||
continue;
|
||||
|
||||
// replaces placeholders for initial line M73 with the real lines
|
||||
if ((normal_mode != nullptr) && (gcode_line == Normal_First_M73_Output_Placeholder_Tag))
|
||||
{
|
||||
sprintf(line_M73, normal_time_mask.c_str(), "0", _get_time_minutes(normal_mode->time).c_str());
|
||||
gcode_line = line_M73;
|
||||
}
|
||||
else if ((silent_mode != nullptr) && (gcode_line == Silent_First_M73_Output_Placeholder_Tag))
|
||||
{
|
||||
sprintf(line_M73, silent_time_mask.c_str(), "0", _get_time_minutes(silent_mode->time).c_str());
|
||||
gcode_line = line_M73;
|
||||
}
|
||||
// replaces placeholders for final line M73 with the real lines
|
||||
else if ((normal_mode != nullptr) && (gcode_line == Normal_Last_M73_Output_Placeholder_Tag))
|
||||
{
|
||||
sprintf(line_M73, normal_time_mask.c_str(), "100", "0");
|
||||
gcode_line = line_M73;
|
||||
}
|
||||
else if ((silent_mode != nullptr) && (gcode_line == Silent_Last_M73_Output_Placeholder_Tag))
|
||||
{
|
||||
sprintf(line_M73, silent_time_mask.c_str(), "100", "0");
|
||||
gcode_line = line_M73;
|
||||
}
|
||||
else
|
||||
gcode_line += "\n";
|
||||
|
||||
// add remaining time lines where needed
|
||||
parser.parse_line(gcode_line,
|
||||
[&](GCodeReader& reader, const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (line.cmd_is("G1"))
|
||||
{
|
||||
++g1_lines_count;
|
||||
process_g1_line(silent_mode, line, silent_g1_line_id, silent_last_recorded_time, silent_time_mask);
|
||||
process_g1_line(normal_mode, line, normal_g1_line_id, normal_last_recorded_time, normal_time_mask);
|
||||
}
|
||||
});
|
||||
|
||||
export_line += gcode_line;
|
||||
if (export_line.length() > 65535)
|
||||
write_string(export_line);
|
||||
}
|
||||
|
||||
if (!export_line.empty())
|
||||
write_string(export_line);
|
||||
|
||||
fclose(out);
|
||||
in.close();
|
||||
|
||||
if (rename_file(path_tmp, filename))
|
||||
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
|
||||
"Is " + path_tmp + " locked?" + '\n');
|
||||
"Is " + path_tmp + " locked?" + '\n');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -213,9 +213,19 @@ namespace Slic3r {
|
||||
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
public:
|
||||
typedef std::pair<unsigned int, unsigned int> G1LineIdToBlockId;
|
||||
typedef std::vector<G1LineIdToBlockId> G1LineIdToBlockIdMap;
|
||||
|
||||
struct PostProcessData
|
||||
{
|
||||
const G1LineIdToBlockIdMap& g1_line_ids;
|
||||
const BlocksList& blocks;
|
||||
float time;
|
||||
|
||||
PostProcessData(const G1LineIdToBlockIdMap& g1_line_ids, const BlocksList& blocks, float time) : g1_line_ids(g1_line_ids), blocks(blocks), time(time) {}
|
||||
};
|
||||
|
||||
private:
|
||||
EMode m_mode;
|
||||
GCodeReader m_parser;
|
||||
@ -263,11 +273,12 @@ namespace Slic3r {
|
||||
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
|
||||
|
||||
// Process the gcode contained in the file with the given filename,
|
||||
// placing in it new lines (M73) containing the remaining time, at the given interval in seconds
|
||||
// and saving the result back in the same file
|
||||
// This time estimator should have been already used to calculate the time estimate for the gcode
|
||||
// contained in the given file before to call this method
|
||||
bool post_process_remaining_times(const std::string& filename, float interval_sec);
|
||||
// replacing placeholders with correspondent new lines M73
|
||||
// placing new lines M73 (containing the remaining time) where needed (in dependence of the given interval in seconds)
|
||||
// and removing working tags (as those used for color changes)
|
||||
// if normal_mode == nullptr no M73 line will be added for normal mode
|
||||
// if silent_mode == nullptr no M73 line will be added for silent mode
|
||||
static bool post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode);
|
||||
|
||||
// Set current position on the given axis with the given value
|
||||
void set_axis_position(EAxis axis, float position);
|
||||
@ -362,6 +373,8 @@ namespace Slic3r {
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
size_t memory_used() const;
|
||||
|
||||
PostProcessData get_post_process_data() const { return PostProcessData(m_g1_line_ids, m_blocks, m_time); }
|
||||
|
||||
private:
|
||||
void _reset();
|
||||
void _reset_time();
|
||||
|
@ -298,7 +298,11 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
|
||||
used for unlift. */
|
||||
if (!this->will_move_z(point.z())) {
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted = m_lifted - (point.z() - nominal_z);
|
||||
m_lifted -= (point.z() - nominal_z);
|
||||
// In case that retract_lift == layer_height we could end up with almost zero in_m_lifted
|
||||
// and a retract could be skipped (https://github.com/prusa3d/PrusaSlicer/issues/2154
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
m_lifted = 0.;
|
||||
return this->travel_to_xy(to_2d(point));
|
||||
}
|
||||
|
||||
@ -324,7 +328,9 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
|
||||
reducing the lift amount that will be used for unlift. */
|
||||
if (!this->will_move_z(z)) {
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted = m_lifted - (z - nominal_z);
|
||||
m_lifted -= (z - nominal_z);
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
m_lifted = 0.;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -121,9 +121,8 @@ void Layer::make_perimeters()
|
||||
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) {
|
||||
LayerRegion* other_layerm = *it;
|
||||
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
||||
|
||||
/// !!! add here the settings you want to be added in the per-object menu.
|
||||
/// if you don't do that, objects will share the same region, and the same settings.
|
||||
/// !!! add here the settings you want to be added in the per-object menu.
|
||||
/// if you don't do that, objects will share the same region, and the same settings.
|
||||
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||
&& config.perimeters == other_config.perimeters
|
||||
&& config.only_one_perimeter_top == other_config.only_one_perimeter_top
|
||||
@ -137,6 +136,7 @@ void Layer::make_perimeters()
|
||||
&& config.thin_walls_min_width == other_config.thin_walls_min_width
|
||||
&& config.thin_walls_overlap == other_config.thin_walls_overlap
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first
|
||||
&& config.infill_overlap == other_config.infill_overlap
|
||||
&& config.perimeter_loop == other_config.perimeter_loop) {
|
||||
layerms.push_back(other_layerm);
|
||||
done[it - m_regions.begin()] = true;
|
||||
@ -149,12 +149,17 @@ void Layer::make_perimeters()
|
||||
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
|
||||
} else {
|
||||
SurfaceCollection new_slices;
|
||||
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
|
||||
LayerRegion *layerm_config = layerms.front();
|
||||
{
|
||||
// group slices (surfaces) according to number of extra perimeters
|
||||
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegion *layerm : layerms)
|
||||
for (LayerRegion *layerm : layerms) {
|
||||
for (Surface &surface : layerm->slices.surfaces)
|
||||
slices[surface.extra_perimeters].emplace_back(surface);
|
||||
if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
|
||||
layerm_config = layerm;
|
||||
}
|
||||
// merge the surfaces assigned to each group
|
||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
|
||||
@ -162,7 +167,7 @@ void Layer::make_perimeters()
|
||||
|
||||
// make perimeters
|
||||
SurfaceCollection fill_surfaces;
|
||||
(*layerm)->make_perimeters(new_slices, &fill_surfaces);
|
||||
layerm_config->make_perimeters(new_slices, &fill_surfaces);
|
||||
|
||||
// assign fill_surfaces to each layer
|
||||
if (!fill_surfaces.surfaces.empty()) {
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
void slices_to_fill_surfaces_clipped();
|
||||
void prepare_fill_surfaces();
|
||||
void make_perimeters(SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
|
||||
void process_external_surfaces(const Layer* lower_layer);
|
||||
void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered);
|
||||
double infill_area_threshold() const;
|
||||
// Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
|
||||
void trim_surfaces(const Polygons &trimming_polygons);
|
||||
|
@ -93,7 +93,7 @@ void LayerRegion::make_perimeters(SurfaceCollection &slices, SurfaceCollection*
|
||||
//#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
|
||||
#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtSquare, 0.
|
||||
|
||||
void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered)
|
||||
{
|
||||
|
||||
coord_t max_margin = 0;
|
||||
@ -124,27 +124,28 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
// Internal surfaces, not grown.
|
||||
Surfaces internal;
|
||||
// Areas, where an infill of various types (top, bottom, bottom bride, sparse, void) could be placed.
|
||||
//FIXME if non zero infill, then fill_boundaries could be cheaply initialized from layerm->fill_expolygons.
|
||||
Polygons fill_boundaries;
|
||||
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
|
||||
Polygons lower_layer_covered_tmp;
|
||||
|
||||
// Collect top surfaces and internal surfaces.
|
||||
// Collect fill_boundaries: If we're slicing with no infill, we can't extend external surfaces over non-existent infill.
|
||||
// This loop destroys the surfaces (aliasing this->fill_surfaces.surfaces) by moving into top/internal/fill_boundaries!
|
||||
|
||||
{
|
||||
// bottom_polygons are used to trim inflated top surfaces.
|
||||
fill_boundaries.reserve(number_polygons(surfaces));
|
||||
// Voids are sparse infills if infill rate is zero.
|
||||
Polygons voids;
|
||||
bool has_infill = this->region()->config().fill_density.value > 0.;
|
||||
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
||||
if (surface.has_pos_top()) {
|
||||
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
||||
// This gives the priority to bottom surfaces.
|
||||
surfaces_append(top, offset_ex(surface.expolygon, double(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
||||
} else if (surface.has_pos_bottom() && (!surface.has_mod_bridge() || lower_layer == NULL)) {
|
||||
} else if (surface.has_pos_bottom() && (!surface.has_mod_bridge() || lower_layer == nullptr)) {
|
||||
// Grown by 3mm.
|
||||
surfaces_append(bottom, offset_ex(surface.expolygon, double(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
||||
} else if (surface.has_pos_bottom() && surface.has_mod_bridge()) {
|
||||
if (! surface.empty())
|
||||
bridges.push_back(surface);
|
||||
bridges.emplace_back(surface);
|
||||
}
|
||||
if (has_infill || !(surface.has_pos_internal() && surface.has_fill_sparse())) {
|
||||
if (!surface.has_pos_external())
|
||||
@ -152,8 +153,11 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
internal.push_back(surface);
|
||||
polygons_append(fill_boundaries, std::move(surface.expolygon));
|
||||
} else{
|
||||
if (!surface.has_pos_external())
|
||||
if (!surface.has_pos_external()){
|
||||
if (! has_infill && lower_layer != nullptr)
|
||||
polygons_append(voids, surface.expolygon);
|
||||
internal.push_back(std::move(surface));
|
||||
}
|
||||
//push surface as perimeter-only inside the fill_boundaries
|
||||
if (margin_bridged > 0) {
|
||||
ExPolygons peri_poly = diff_ex(ExPolygons() = { surface.expolygon }, offset_ex(surface.expolygon, -margin_bridged));
|
||||
@ -161,6 +165,16 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! has_infill && lower_layer != nullptr && ! voids.empty()) {
|
||||
// Remove voids from fill_boundaries, that are not supported by the layer below.
|
||||
if (lower_layer_covered == nullptr) {
|
||||
lower_layer_covered = &lower_layer_covered_tmp;
|
||||
lower_layer_covered_tmp = to_polygons(lower_layer->slices.expolygons);
|
||||
}
|
||||
if (! lower_layer_covered->empty())
|
||||
voids = diff(voids, *lower_layer_covered);
|
||||
fill_boundaries = diff(fill_boundaries, voids);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -214,7 +228,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
(this->flow(frInfill).scaled_width() / 2) + float(margin_bridged),
|
||||
EXTERNAL_SURFACES_OFFSET_PARAMETERS);
|
||||
if (idx_island == -1) {
|
||||
printf("Bridge did not fall into the source region!\r\n");
|
||||
BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
|
||||
} else {
|
||||
// Found an island, to which this bridge region belongs. Trim it,
|
||||
polys = intersection(polys, to_polygons(fill_boundaries_ex[idx_island]));
|
||||
@ -252,7 +266,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
|
||||
// 3) Merge the groups with the same group id, detect bridges.
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z << ", bridge groups: " << n_groups;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges. layer" << this->layer()->print_z << ", bridge groups: " << n_groups;
|
||||
for (size_t group_id = 0; group_id < n_groups; ++ group_id) {
|
||||
size_t n_bridges_merged = 0;
|
||||
size_t idx_last = (size_t)-1;
|
||||
@ -286,25 +300,25 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
#ifdef SLIC3R_DEBUG
|
||||
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
||||
#endif
|
||||
double custom_angle = Geometry::deg2rad(this->region()->config().bridge_angle.value);
|
||||
if (bd.detect_angle(custom_angle)) {
|
||||
double custom_angle = Geometry::deg2rad(this->region()->config().bridge_angle.value);
|
||||
if (bd.detect_angle(custom_angle)) {
|
||||
bridges[idx_last].bridge_angle = bd.angle;
|
||||
if (this->layer()->object()->config().support_material) {
|
||||
polygons_append(this->bridged, intersection(bd.coverage(), to_polygons(initial)));
|
||||
this->unsupported_bridge_edges.append(bd.unsupported_edges());
|
||||
}
|
||||
} else if (custom_angle > 0) {
|
||||
// Bridge was not detected (likely it is only supported at one side). Still it is a surface filled in
|
||||
// using a bridging flow, therefore it makes sense to respect the custom bridging direction.
|
||||
bridges[idx_last].bridge_angle = custom_angle;
|
||||
}
|
||||
} else if (custom_angle > 0) {
|
||||
// Bridge was not detected (likely it is only supported at one side). Still it is a surface filled in
|
||||
// using a bridging flow, therefore it makes sense to respect the custom bridging direction.
|
||||
bridges[idx_last].bridge_angle = custom_angle;
|
||||
}
|
||||
// without safety offset, artifacts are generated (GH #2494)
|
||||
surfaces_append(bottom, union_ex(grown, true), bridges[idx_last]);
|
||||
}
|
||||
|
||||
fill_boundaries = std::move(to_polygons(fill_boundaries_ex));
|
||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(trace) << "Processing external surface, detecting bridges - done";
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
|
@ -375,9 +375,9 @@ add_point_same_percent(ThickPolyline* pattern, ThickPolyline* to_modify)
|
||||
}
|
||||
|
||||
/// find the nearest angle in the contour (or 2 nearest if it's difficult to choose)
|
||||
/// return 1 for an angle of 90° and 0 for an angle of 0° or 180°
|
||||
/// return 1 for an angle of 90° and 0 for an angle of 0° or 180°
|
||||
/// find the nearest angle in the contour (or 2 nearest if it's difficult to choose)
|
||||
/// return 1 for an angle of 90° and 0 for an angle of 0° or 180°
|
||||
/// return 1 for an angle of 90° and 0 for an angle of 0° or 180°
|
||||
double
|
||||
get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t min_dist_between_point) {
|
||||
double nearest_dist = point.distance_to(contour.contour.points.front());
|
||||
@ -428,7 +428,7 @@ get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t mi
|
||||
//compute angle
|
||||
angle = point_nearest.ccw_angle(point_before, point_after);
|
||||
if (angle >= PI) angle = 2 * PI - angle; // smaller angle
|
||||
//compute the diff from 90°
|
||||
//compute the diff from 90°
|
||||
angle = abs(angle - PI / 2);
|
||||
if (point_near.coincides_with(point_nearest) && std::max(nearest_dist, near_dist) + SCALED_EPSILON < point_nearest.distance_to(point_near)) {
|
||||
//not only nearest
|
||||
@ -485,11 +485,11 @@ MedialAxis::fusion_curve(ThickPolylines &pp)
|
||||
//compute angle
|
||||
double coeff_contour_angle = this->expolygon.contour.points[closest_point_idx].ccw_angle(this->expolygon.contour.points[prev_idx], this->expolygon.contour.points[next_idx]);
|
||||
if (coeff_contour_angle >= PI) coeff_contour_angle = 2 * PI - coeff_contour_angle; // smaller angle
|
||||
//compute the diff from 90°
|
||||
//compute the diff from 90°
|
||||
coeff_contour_angle = abs(coeff_contour_angle - PI / 2);
|
||||
|
||||
|
||||
// look if other end is a cross point with almost 90° angle
|
||||
// look if other end is a cross point with almost 90° angle
|
||||
double sum_dot = 0;
|
||||
double min_dot = 0;
|
||||
// look if other end is a cross point with multiple other branch
|
||||
@ -522,7 +522,7 @@ MedialAxis::fusion_curve(ThickPolylines &pp)
|
||||
if (crosspoint.size() != 2) continue;
|
||||
if (sum_dot > 0.2) continue;
|
||||
if (min_dot > 0.5) continue;
|
||||
//don't remove useful bits. TODO: use the mindot to know by how much to multiply (1 when 90°, 1.42 when 45+, 1 when 0°)
|
||||
//don't remove useful bits. TODO: use the mindot to know by how much to multiply (1 when 90°, 1.42 when 45+, 1 when 0°)
|
||||
if (polyline.length() > polyline.width.front()*1.42) continue;
|
||||
|
||||
//don't pull, it distords the line if there are too many points.
|
||||
@ -872,10 +872,10 @@ MedialAxis::main_fusion(ThickPolylines& pp)
|
||||
|
||||
// Get the branch/line in wich we may merge, if possible
|
||||
// with that, we can decide what is important, and how we can merge that.
|
||||
// angle_poly - angle_candi =90° => one is useless
|
||||
// angle_poly - angle_candi =90° => one is useless
|
||||
// both angle are equal => both are useful with same strength
|
||||
// ex: Y => | both are useful to crete a nice line
|
||||
// ex2: TTTTT => ----- these 90° useless lines should be discarded
|
||||
// ex2: TTTTT => ----- these 90° useless lines should be discarded
|
||||
find_main_branch = false;
|
||||
biggest_main_branch_id = 0;
|
||||
biggest_main_branch_length = 0;
|
||||
@ -965,7 +965,7 @@ MedialAxis::main_fusion(ThickPolylines& pp)
|
||||
|
||||
//get the angle of the nearest points of the contour to see : _| (good) \_ (average) __(bad)
|
||||
//sqrt because the result are nicer this way: don't over-penalize /_ angles
|
||||
//TODO: try if we can achieve a better result if we use a different algo if the angle is <90°
|
||||
//TODO: try if we can achieve a better result if we use a different algo if the angle is <90°
|
||||
const double coeff_angle_poly = (coeff_angle_cache.find(polyline.points.back()) != coeff_angle_cache.end())
|
||||
? coeff_angle_cache[polyline.points.back()]
|
||||
: (get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, std::min(min_width, (coord_t)(polyline.length() / 2))));
|
||||
|
@ -529,8 +529,9 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
||||
}
|
||||
}
|
||||
|
||||
object->add_instance();
|
||||
object->instances[0]->set_offset(object->raw_mesh_bounding_box().center());
|
||||
// commented-out to fix #2868
|
||||
// object->add_instance();
|
||||
// object->instances[0]->set_offset(object->raw_mesh_bounding_box().center());
|
||||
|
||||
this->clear_objects();
|
||||
this->objects.push_back(object);
|
||||
@ -711,7 +712,7 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other, TriangleMesh &&me
|
||||
{
|
||||
ModelVolume* v = new ModelVolume(this, other, std::move(mesh));
|
||||
this->volumes.push_back(v);
|
||||
if(centered) v->center_geometry_after_creation();
|
||||
if(centered) v->center_geometry_after_creation();
|
||||
this->invalidate_bounding_box();
|
||||
return v;
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ private:
|
||||
explicit ModelInstance(ModelObject* object) : print_volume_state(PVS_Inside), printable(true), object(object) { assert(this->id().valid()); }
|
||||
// Constructor, which assigns a new unique ID.
|
||||
explicit ModelInstance(ModelObject *object, const ModelInstance &other) :
|
||||
m_transformation(other.m_transformation), print_volume_state(PVS_Inside), printable(true), object(object) {assert(this->id().valid() && this->id() != other.id());}
|
||||
m_transformation(other.m_transformation), print_volume_state(PVS_Inside), printable(other.printable), object(object) { assert(this->id().valid() && this->id() != other.id()); }
|
||||
|
||||
explicit ModelInstance(ModelInstance &&rhs) = delete;
|
||||
ModelInstance& operator=(const ModelInstance &rhs) = delete;
|
||||
|
@ -108,7 +108,6 @@ static inline bool opts_equal(const DynamicConfig &config_old, const DynamicConf
|
||||
|
||||
std::vector<std::string> PlaceholderParser::config_diff(const DynamicPrintConfig &rhs)
|
||||
{
|
||||
const ConfigDef *def = rhs.def();
|
||||
std::vector<std::string> diff_keys;
|
||||
for (const t_config_option_key &opt_key : rhs.keys())
|
||||
if (! opts_equal(m_config, rhs, opt_key))
|
||||
@ -124,7 +123,6 @@ std::vector<std::string> PlaceholderParser::config_diff(const DynamicPrintConfig
|
||||
// a current extruder ID is used.
|
||||
bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs)
|
||||
{
|
||||
const ConfigDef *def = rhs.def();
|
||||
bool modified = false;
|
||||
for (const t_config_option_key &opt_key : rhs.keys()) {
|
||||
if (! opts_equal(m_config, rhs, opt_key)) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include "clipper/clipper_z.hpp"
|
||||
|
||||
#include "Print.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
@ -1198,6 +1200,8 @@ std::string Print::validate() const
|
||||
return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors.");
|
||||
if (! m_config.use_relative_e_distances)
|
||||
return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
|
||||
if (m_config.ooze_prevention)
|
||||
return L("Ooze prevention is currently not supported with the wipe tower enabled.");
|
||||
|
||||
if (m_objects.size() > 1) {
|
||||
bool has_custom_layering = false;
|
||||
@ -1237,26 +1241,42 @@ std::string Print::validate() const
|
||||
if (has_custom_layering) {
|
||||
const std::vector<coordf_t> &layer_height_profile_tallest = layer_height_profiles[tallest_object_idx];
|
||||
for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
|
||||
if (idx_object == tallest_object_idx)
|
||||
continue;
|
||||
const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object];
|
||||
bool failed = false;
|
||||
if (layer_height_profile_tallest.size() >= layer_height_profile.size()) {
|
||||
size_t i = 0;
|
||||
while (i < layer_height_profile.size() && i < layer_height_profile_tallest.size()) {
|
||||
if (std::abs(layer_height_profile_tallest[i] - layer_height_profile[i])) {
|
||||
failed = true;
|
||||
break;
|
||||
|
||||
// The comparison of the profiles is not just about element-wise equality, some layers may not be
|
||||
// explicitely included. Always remember z and height of last reference layer that in the vector
|
||||
// and compare to that. In case some layers are in the vectors multiple times, only the last entry is
|
||||
// taken into account and compared.
|
||||
size_t i = 0; // index into tested profile
|
||||
size_t j = 0; // index into reference profile
|
||||
coordf_t ref_z = -1.;
|
||||
coordf_t next_ref_z = layer_height_profile_tallest[0];
|
||||
coordf_t ref_height = -1.;
|
||||
while (i < layer_height_profile.size()) {
|
||||
coordf_t this_z = layer_height_profile[i];
|
||||
// find the last entry with this z
|
||||
while (i+2 < layer_height_profile.size() && layer_height_profile[i+2] == this_z)
|
||||
i += 2;
|
||||
|
||||
coordf_t this_height = layer_height_profile[i+1];
|
||||
if (ref_height < -1. || next_ref_z < this_z + EPSILON) {
|
||||
ref_z = next_ref_z;
|
||||
do { // one layer can be in the vector several times
|
||||
ref_height = layer_height_profile_tallest[j+1];
|
||||
if (j+2 >= layer_height_profile_tallest.size())
|
||||
break;
|
||||
j += 2;
|
||||
next_ref_z = layer_height_profile_tallest[j];
|
||||
} while (ref_z == next_ref_z);
|
||||
}
|
||||
++ i;
|
||||
if (i == layer_height_profile.size() - 2) // this element contains this objects max z
|
||||
if (layer_height_profile_tallest[i] > layer_height_profile[i]) // the difference does not matter in this case
|
||||
++ i;
|
||||
if (std::abs(this_height - ref_height) > EPSILON)
|
||||
return L("The Wipe tower is only supported if all objects have the same layer height profile");
|
||||
i += 2;
|
||||
}
|
||||
} else
|
||||
failed = true;
|
||||
if (failed)
|
||||
return L("The Wipe tower is only supported if all objects have the same layer height profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1676,9 +1696,7 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
|
||||
|
||||
// Initial offset of the brim inner edge from the object (possible with a support & raft).
|
||||
// The skirt will touch the brim if the brim is extruded.
|
||||
Flow brim_flow = this->brim_flow();
|
||||
double actual_brim_width = brim_flow.spacing() * floor(m_config.brim_width.value / brim_flow.spacing());
|
||||
auto distance = float(scale_(std::max(m_config.skirt_distance.value, actual_brim_width) - spacing/2.));
|
||||
auto distance = float(scale_(m_config.skirt_distance.value) - spacing/2.);
|
||||
// Draw outlines from outside to inside.
|
||||
// Loop while we have less skirts than required or any extruder hasn't reached the min length if any.
|
||||
std::vector<coordf_t> extruded_length(extruders.size(), 0.);
|
||||
@ -1761,12 +1779,134 @@ void Print::_make_brim(const PrintObjectPtrs &objects, ExtrusionEntityCollection
|
||||
}
|
||||
polygons_append(loops, offset(islands, -0.5f * double(flow.scaled_spacing())));
|
||||
}
|
||||
|
||||
loops = union_pt_chained(loops, false);
|
||||
// The function above produces ordering well suited for concentric infill (from outside to inside).
|
||||
// For Brim, the ordering should be reversed (from inside to outside).
|
||||
std::reverse(loops.begin(), loops.end());
|
||||
extrusion_entities_append_loops(out.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height()));
|
||||
|
||||
// If there is a possibility that brim intersects skirt, go through loops and split those extrusions
|
||||
// The result is either the original Polygon or a list of Polylines
|
||||
if (! m_skirt.empty() && m_config.skirt_distance.value < m_config.brim_width)
|
||||
{
|
||||
// Find the bounding polygons of the skirt
|
||||
const Polygons skirt_inners = offset(dynamic_cast<ExtrusionLoop*>(m_skirt.entities.back())->polygon(),
|
||||
-float(scale_(this->skirt_flow().spacing()))/2.f,
|
||||
ClipperLib::jtRound,
|
||||
float(scale_(0.1)));
|
||||
const Polygons skirt_outers = offset(dynamic_cast<ExtrusionLoop*>(m_skirt.entities.front())->polygon(),
|
||||
float(scale_(this->skirt_flow().spacing()))/2.f,
|
||||
ClipperLib::jtRound,
|
||||
float(scale_(0.1)));
|
||||
|
||||
// First calculate the trimming region.
|
||||
ClipperLib_Z::Paths trimming;
|
||||
{
|
||||
ClipperLib_Z::Paths input_subject;
|
||||
ClipperLib_Z::Paths input_clip;
|
||||
for (const Polygon &poly : skirt_outers) {
|
||||
input_subject.emplace_back();
|
||||
ClipperLib_Z::Path &out = input_subject.back();
|
||||
out.reserve(poly.points.size());
|
||||
for (const Point &pt : poly.points)
|
||||
out.emplace_back(pt.x(), pt.y(), 0);
|
||||
}
|
||||
for (const Polygon &poly : skirt_inners) {
|
||||
input_clip.emplace_back();
|
||||
ClipperLib_Z::Path &out = input_clip.back();
|
||||
out.reserve(poly.points.size());
|
||||
for (const Point &pt : poly.points)
|
||||
out.emplace_back(pt.x(), pt.y(), 0);
|
||||
}
|
||||
// init Clipper
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
// add polygons
|
||||
clipper.AddPaths(input_subject, ClipperLib_Z::ptSubject, true);
|
||||
clipper.AddPaths(input_clip, ClipperLib_Z::ptClip, true);
|
||||
// perform operation
|
||||
clipper.Execute(ClipperLib_Z::ctDifference, trimming, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
}
|
||||
|
||||
// Second, trim the extrusion loops with the trimming regions.
|
||||
ClipperLib_Z::Paths loops_trimmed;
|
||||
{
|
||||
// Produce a closed polyline (repeat the first point at the end).
|
||||
ClipperLib_Z::Paths input_clip;
|
||||
for (const Polygon &loop : loops) {
|
||||
input_clip.emplace_back();
|
||||
ClipperLib_Z::Path& out = input_clip.back();
|
||||
out.reserve(loop.points.size());
|
||||
int64_t loop_idx = &loop - &loops.front();
|
||||
for (const Point& pt : loop.points)
|
||||
// The Z coordinate carries index of the source loop.
|
||||
out.emplace_back(pt.x(), pt.y(), loop_idx + 1);
|
||||
out.emplace_back(out.front());
|
||||
}
|
||||
// init Clipper
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot, const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
|
||||
// Assign a valid input loop identifier. Such an identifier is strictly positive, the next line is safe even in case one side of a segment
|
||||
// hat the Z coordinate not set to the contour coordinate.
|
||||
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
|
||||
});
|
||||
// add polygons
|
||||
clipper.AddPaths(input_clip, ClipperLib_Z::ptSubject, false);
|
||||
clipper.AddPaths(trimming, ClipperLib_Z::ptClip, true);
|
||||
// perform operation
|
||||
ClipperLib_Z::PolyTree loops_trimmed_tree;
|
||||
clipper.Execute(ClipperLib_Z::ctDifference, loops_trimmed_tree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
ClipperLib_Z::PolyTreeToPaths(loops_trimmed_tree, loops_trimmed);
|
||||
}
|
||||
|
||||
// Third, produce the extrusions, sorted by the source loop indices.
|
||||
{
|
||||
std::vector<std::pair<const ClipperLib_Z::Path*, size_t>> loops_trimmed_order;
|
||||
loops_trimmed_order.reserve(loops_trimmed.size());
|
||||
for (const ClipperLib_Z::Path &path : loops_trimmed) {
|
||||
size_t input_idx = 0;
|
||||
for (const ClipperLib_Z::IntPoint &pt : path)
|
||||
if (pt.Z > 0) {
|
||||
input_idx = (size_t)pt.Z;
|
||||
break;
|
||||
}
|
||||
assert(input_idx != 0);
|
||||
loops_trimmed_order.emplace_back(&path, input_idx);
|
||||
}
|
||||
std::stable_sort(loops_trimmed_order.begin(), loops_trimmed_order.end(),
|
||||
[](const std::pair<const ClipperLib_Z::Path*, size_t> &l, const std::pair<const ClipperLib_Z::Path*, size_t> &r) {
|
||||
return l.second < r.second;
|
||||
});
|
||||
Vec3f last_pt(0.f, 0.f, 0.f);
|
||||
|
||||
for (size_t i = 0; i < loops_trimmed_order.size();) {
|
||||
// Find all pieces that the initial loop was split into.
|
||||
size_t j = i + 1;
|
||||
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].first == loops_trimmed_order[j].first; ++ j) ;
|
||||
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
|
||||
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
|
||||
auto *loop = new ExtrusionLoop();
|
||||
out.entities.emplace_back(loop);
|
||||
loop->paths.emplace_back(erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height()));
|
||||
Points &points = loop->paths.front().polyline.points;
|
||||
points.reserve(first_path.size());
|
||||
for (const ClipperLib_Z::IntPoint &pt : first_path)
|
||||
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
|
||||
i = j;
|
||||
} else {
|
||||
//FIXME this is not optimal as the G-code generator will follow the sequence of paths verbatim without respect to minimum travel distance.
|
||||
for (; i < j; ++ i) {
|
||||
out.entities.emplace_back(new ExtrusionPath(erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height())));
|
||||
const ClipperLib_Z::Path &path = *loops_trimmed_order[i].first;
|
||||
Points &points = static_cast<ExtrusionPath*>(out.entities.back())->polyline.points;
|
||||
points.reserve(path.size());
|
||||
for (const ClipperLib_Z::IntPoint &pt : path)
|
||||
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
extrusion_entities_append_loops(out.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height()));
|
||||
}
|
||||
}
|
||||
|
||||
void Print::_make_brim_ears(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out) {
|
||||
|
@ -39,6 +39,8 @@ class PrintRegion
|
||||
public:
|
||||
const Print* print() const { return m_print; }
|
||||
const PrintRegionConfig& config() const { return m_config; }
|
||||
// 1-based extruder identifier for this region and role.
|
||||
unsigned int extruder(FlowRole role) const;
|
||||
Flow flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const;
|
||||
// Average diameter of nozzles participating on extruding this region.
|
||||
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
||||
|
@ -2603,13 +2603,13 @@ void PrintConfigDef::init_fff_params()
|
||||
{
|
||||
int threads = (unsigned int)boost::thread::hardware_concurrency();
|
||||
def->set_default_value(new ConfigOptionInt(threads > 0 ? threads : 2));
|
||||
def->cli == ConfigOptionDef::nocli;
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
}
|
||||
|
||||
def = this->add("toolchange_gcode", coString);
|
||||
def->label = L("Tool change G-code");
|
||||
def->tooltip = L("This custom code is inserted at every extruder change. If you don't leave this empty, you are "
|
||||
"expected to take care of the toolchange yourself - PrusaSlicer will not output any other G-code to "
|
||||
"expected to take care of the toolchange yourself - slic3r will not output any other G-code to "
|
||||
"change the filament. You can use placeholder variables for all Slic3r settings as well as [previous_extruder] "
|
||||
"and [next_extruder], so e.g. the standard toolchange command can be scripted as T[next_extruder].");
|
||||
def->multiline = true;
|
||||
@ -3262,7 +3262,8 @@ void PrintConfigDef::init_sla_params()
|
||||
def->category = L("Supports");
|
||||
def->tooltip = L("How much the supports should lift up the supported object. "
|
||||
"If this value is zero, the bottom of the model geometry "
|
||||
"will be considered as part of the pad.");
|
||||
"will be considered as part of the pad."
|
||||
"If \"Pad around object\" is enabled, this value is ignored.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 150; // This is the max height of print on SL1
|
||||
@ -3349,7 +3350,7 @@ void PrintConfigDef::init_sla_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(45.0));
|
||||
|
||||
def = this->add("pad_zero_elevation", coBool);
|
||||
def = this->add("pad_around_object", coBool);
|
||||
def->label = L("Pad around object");
|
||||
def->category = L("Pad");
|
||||
def->tooltip = L("Create pad around object and ignore the support elevation");
|
||||
@ -3370,8 +3371,7 @@ void PrintConfigDef::init_sla_params()
|
||||
def = this->add("pad_object_connector_stride", coFloat);
|
||||
def->label = L("Pad object connector stride");
|
||||
def->category = L("Pad");
|
||||
def->tooltip = L("Distance between two connector sticks between "
|
||||
"the object pad and the generated pad.");
|
||||
def->tooltip = L("Distance between two connector sticks which connect the object and the generated pad.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
@ -3380,8 +3380,7 @@ void PrintConfigDef::init_sla_params()
|
||||
def = this->add("pad_object_connector_width", coFloat);
|
||||
def->label = L("Pad object connector width");
|
||||
def->category = L("Pad");
|
||||
def->tooltip = L("The width of the connectors sticks which connect the "
|
||||
"object pad and the generated pad.");
|
||||
def->tooltip = L("Width of the connector sticks which connect the object and the generated pad.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
@ -3556,22 +3555,22 @@ double PrintConfig::min_object_distance() const
|
||||
double PrintConfig::min_object_distance(const ConfigBase *config)
|
||||
{
|
||||
double base_dist = 0;
|
||||
if (config->option("complete_objects")->getBool()){
|
||||
if (config->option("complete_objects")->getBool()) {
|
||||
std::vector<double> vals = dynamic_cast<const ConfigOptionFloats*>(config->option("nozzle_diameter"))->values;
|
||||
double max_nozzle_diam = 0;
|
||||
for (double val : vals) max_nozzle_diam = std::fmax(max_nozzle_diam, val);
|
||||
|
||||
// min object distance is max(duplicate_distance, clearance_radius)
|
||||
double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat();
|
||||
if (extruder_clearance_radius > base_dist){
|
||||
if (extruder_clearance_radius > base_dist) {
|
||||
base_dist = extruder_clearance_radius;
|
||||
}
|
||||
//add brim width
|
||||
if (config->option("brim_width")->getFloat() > 0){
|
||||
if (config->option("brim_width")->getFloat() > 0) {
|
||||
base_dist += config->option("brim_width")->getFloat() * 2;
|
||||
}
|
||||
//add the skirt
|
||||
if (config->option("skirts")->getInt() > 0){
|
||||
if (config->option("skirts")->getInt() > 0) {
|
||||
//add skirt dist
|
||||
double dist_skirt = config->option("skirt_distance")->getFloat();
|
||||
if (dist_skirt > config->option("brim_width")->getFloat())
|
||||
@ -3581,6 +3580,7 @@ double PrintConfig::min_object_distance(const ConfigBase *config)
|
||||
}
|
||||
}
|
||||
return base_dist;
|
||||
}
|
||||
|
||||
//FIXME localize this function.
|
||||
std::string FullPrintConfig::validate()
|
||||
|
@ -6,12 +6,23 @@
|
||||
//
|
||||
// The classes derived from StaticPrintConfig form a following hierarchy.
|
||||
//
|
||||
// FullPrintConfig
|
||||
// PrintObjectConfig
|
||||
// PrintRegionConfig
|
||||
// PrintConfig
|
||||
// GCodeConfig
|
||||
// HostConfig
|
||||
// class ConfigBase
|
||||
// class StaticConfig : public virtual ConfigBase
|
||||
// class StaticPrintConfig : public StaticConfig
|
||||
// class PrintObjectConfig : public StaticPrintConfig
|
||||
// class PrintRegionConfig : public StaticPrintConfig
|
||||
// class HostConfig : public StaticPrintConfig
|
||||
// class MachineEnvelopeConfig : public StaticPrintConfig
|
||||
// class GCodeConfig : public StaticPrintConfig
|
||||
// class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig
|
||||
// class FullPrintConfig : PrintObjectConfig,PrintRegionConfig,PrintConfig,HostConfig
|
||||
// class SLAPrintObjectConfig : public StaticPrintConfig
|
||||
// class SLAMaterialConfig : public StaticPrintConfig
|
||||
// class SLAPrinterConfig : public StaticPrintConfig
|
||||
// class DynamicConfig : public virtual ConfigBase
|
||||
// class DynamicPrintConfig : public DynamicConfig
|
||||
// class DynamicPrintAndCLIConfig : public DynamicPrintConfig
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef slic3r_PrintConfig_hpp_
|
||||
@ -30,7 +41,7 @@ enum WipeAlgo {
|
||||
waHyper,
|
||||
};
|
||||
|
||||
enum GCodeFlavor {
|
||||
enum GCodeFlavor : unsigned char {
|
||||
gcfRepRap, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlin, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfSmoothie, gcfNoExtrusion,
|
||||
};
|
||||
@ -42,7 +53,7 @@ enum PrintHostType {
|
||||
enum InfillPattern {
|
||||
ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
|
||||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSmooth, ipSmoothHilbert, ipSmoothTriple,
|
||||
ipRectiWithPerimeter, ipConcentricGapFill, ipScatteredRectilinear, ipSawtooth, ipRectilinearWGapFill
|
||||
ipRectiWithPerimeter, ipConcentricGapFill, ipScatteredRectilinear, ipSawtooth, ipRectilinearWGapFill, ipCount
|
||||
};
|
||||
|
||||
enum SupportMaterialPattern {
|
||||
@ -1201,7 +1212,7 @@ public:
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Disable the elevation (ignore its value) and use the zero elevation mode
|
||||
ConfigOptionBool pad_zero_elevation;
|
||||
ConfigOptionBool pad_around_object;
|
||||
|
||||
// This is the gap between the object bottom and the generated pad
|
||||
ConfigOptionFloat pad_object_gap;
|
||||
@ -1244,7 +1255,7 @@ protected:
|
||||
OPT_PTR(pad_max_merge_distance);
|
||||
// OPT_PTR(pad_edge_radius);
|
||||
OPT_PTR(pad_wall_slope);
|
||||
OPT_PTR(pad_zero_elevation);
|
||||
OPT_PTR(pad_around_object);
|
||||
OPT_PTR(pad_object_gap);
|
||||
OPT_PTR(pad_object_connector_stride);
|
||||
OPT_PTR(pad_object_connector_width);
|
||||
|
@ -105,7 +105,6 @@ PrintBase::ApplyStatus PrintObject::set_copies(const Points &points)
|
||||
// this should be idempotent
|
||||
void PrintObject::slice()
|
||||
{
|
||||
|
||||
if (! this->set_started(posSlice))
|
||||
return;
|
||||
m_print->set_status(10, L("Processing triangulated mesh"));
|
||||
@ -259,8 +258,8 @@ void PrintObject::prepare_infill()
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
// Decide what surfaces are to be filled.
|
||||
// Here the S_TYPE_TOP / S_TYPE_BOTTOMBRIDGE / S_TYPE_BOTTOM infill is turned to just S_TYPE_INTERNAL if zero top / bottom infill layers are configured.
|
||||
// Also tiny S_TYPE_INTERNAL surfaces are turned to S_TYPE_INTERNAL_SOLID.
|
||||
// Here the stTop / stBottomBridge / stBottom infill is turned to just stInternal if zero top / bottom infill layers are configured.
|
||||
// Also tiny stInternal surfaces are turned to stInternalSolid.
|
||||
BOOST_LOG_TRIVIAL(info) << "Preparing fill surfaces..." << log_memory_info();
|
||||
for (auto *layer : m_layers)
|
||||
for (auto *region : layer->m_regions) {
|
||||
@ -272,8 +271,8 @@ void PrintObject::prepare_infill()
|
||||
// and rearrange top/bottom/internal surfaces
|
||||
// It produces enlarged overlapping bridging areas.
|
||||
//
|
||||
// 1) S_TYPE_BOTTOMBRIDGE / S_TYPE_BOTTOM infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
|
||||
// 2) S_TYPE_TOP is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
|
||||
// 1) stBottomBridge / stBottom infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
|
||||
// 2) stTop is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
|
||||
// 3) Clip the internal surfaces by the grown top/bottom surfaces.
|
||||
// 4) Merge surfaces with the same style. This will mostly get rid of the overlaps.
|
||||
//FIXME This does not likely merge surfaces, which are supported by a material with different colors, but same properties.
|
||||
@ -335,7 +334,6 @@ void PrintObject::prepare_infill()
|
||||
|
||||
// the following step needs to be done before combination because it may need
|
||||
// to remove only half of the combined infill
|
||||
//if (this->)
|
||||
this->bridge_over_infill();
|
||||
m_print->throw_if_canceled();
|
||||
this->replaceSurfaceType(stPosInternal | stDensSolid,
|
||||
@ -388,15 +386,19 @@ void PrintObject::infill()
|
||||
|
||||
if (this->set_started(posInfill)) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
m_layers[layer_idx]->make_fills();
|
||||
}
|
||||
}
|
||||
);
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
m_layers[layer_idx]->make_fills();
|
||||
}
|
||||
}
|
||||
);
|
||||
//for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
|
||||
// m_print->throw_if_canceled();
|
||||
// m_layers[layer_idx]->make_fills();
|
||||
//}
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - end";
|
||||
/* we could free memory now, but this would make this step not idempotent
|
||||
@ -499,9 +501,17 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
|| opt_key == "xy_size_compensation"
|
||||
|| opt_key == "hole_size_compensation") {
|
||||
steps.emplace_back(posSlice);
|
||||
} else if (opt_key == "support_material") {
|
||||
steps.emplace_back(posSupportMaterial);
|
||||
if (m_config.support_material_contact_distance_top == 0. || m_config.support_material_contact_distance_bottom == 0.) {
|
||||
// Enabling / disabling supports while soluble support interface is enabled.
|
||||
// This changes the bridging logic (bridging enabled without supports, disabled with supports).
|
||||
// Reset everything.
|
||||
// See GH #1482 for details.
|
||||
steps.emplace_back(posSlice);
|
||||
}
|
||||
} else if (
|
||||
opt_key == "support_material"
|
||||
|| opt_key == "support_material_auto"
|
||||
opt_key == "support_material_auto"
|
||||
|| opt_key == "support_material_angle"
|
||||
|| opt_key == "support_material_buildplate_only"
|
||||
|| opt_key == "support_material_enforce_layers"
|
||||
@ -562,8 +572,13 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
steps.emplace_back(posPerimeters);
|
||||
steps.emplace_back(posSupportMaterial);
|
||||
} else if (opt_key == "bridge_flow_ratio") {
|
||||
steps.emplace_back(posPerimeters);
|
||||
steps.emplace_back(posInfill);
|
||||
//if (m_config.support_material_contact_distance > 0.) {
|
||||
// Only invalidate due to bridging if bridging is enabled.
|
||||
// If later "support_material_contact_distance" is modified, the complete PrintObject is invalidated anyway.
|
||||
steps.emplace_back(posPerimeters);
|
||||
steps.emplace_back(posInfill);
|
||||
steps.emplace_back(posSupportMaterial);
|
||||
//}
|
||||
} else if (
|
||||
opt_key == "seam_position"
|
||||
|| opt_key == "seam_travel"
|
||||
@ -629,12 +644,12 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
||||
|
||||
bool PrintObject::invalidate_all_steps()
|
||||
{
|
||||
// First call the "invalidate" functions, which may cancel background processing.
|
||||
// First call the "invalidate" functions, which may cancel background processing.
|
||||
bool result = Inherited::invalidate_all_steps() | m_print->invalidate_all_steps();
|
||||
// Then reset some of the depending values.
|
||||
this->m_slicing_params.valid = false;
|
||||
this->region_volumes.clear();
|
||||
return result;
|
||||
// Then reset some of the depending values.
|
||||
this->m_slicing_params.valid = false;
|
||||
this->region_volumes.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PrintObject::has_support_material() const
|
||||
@ -1067,15 +1082,73 @@ void PrintObject::process_external_surfaces()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Processing external surfaces..." << log_memory_info();
|
||||
|
||||
// Cached surfaces covered by some extrusion, defining regions, over which the from the surfaces one layer higher are allowed to expand.
|
||||
std::vector<Polygons> surfaces_covered;
|
||||
// Is there any printing region, that has zero infill? If so, then we don't want the expansion to be performed over the complete voids, but only
|
||||
// over voids, which are supported by the layer below.
|
||||
bool has_voids = false;
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
|
||||
if (! this->region_volumes.empty() && this->print()->regions()[region_id]->config().fill_density == 0) {
|
||||
has_voids = true;
|
||||
break;
|
||||
}
|
||||
if (has_voids && m_layers.size() > 1) {
|
||||
// All but stInternal-sparse fill surfaces will get expanded and possibly trimmed.
|
||||
std::vector<unsigned char> layer_expansions_and_voids(m_layers.size(), false);
|
||||
for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
|
||||
const Layer *layer = m_layers[layer_idx];
|
||||
bool expansions = false;
|
||||
bool voids = false;
|
||||
for (const LayerRegion *layerm : layer->regions()) {
|
||||
for (const Surface &surface : layerm->fill_surfaces.surfaces) {
|
||||
if (surface.surface_type == (stPosInternal | stDensSparse))
|
||||
voids = true;
|
||||
else
|
||||
expansions = true;
|
||||
if (voids && expansions) {
|
||||
layer_expansions_and_voids[layer_idx] = true;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
end:;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - start";
|
||||
surfaces_covered.resize(m_layers.size() - 1, Polygons());
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size() - 1),
|
||||
[this, &surfaces_covered, &layer_expansions_and_voids](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||
if (layer_expansions_and_voids[layer_idx + 1]) {
|
||||
m_print->throw_if_canceled();
|
||||
Polygons voids;
|
||||
for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) {
|
||||
/// supermerill: why *0.3 ???
|
||||
float unsupported_width = -float(scale_(0.3 * layerm->region()->config().external_infill_margin));
|
||||
if (layerm->region()->config().fill_density.value == 0.)
|
||||
for (const Surface &surface : layerm->fill_surfaces.surfaces)
|
||||
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
|
||||
polygons_append(voids, offset(surface.expolygon, unsupported_width));
|
||||
}
|
||||
surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->slices.expolygons), voids);
|
||||
}
|
||||
}
|
||||
);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - end";
|
||||
}
|
||||
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this, region_id](const tbb::blocked_range<size_t>& range) {
|
||||
[this, &surfaces_covered, region_id](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
||||
m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
||||
m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces(
|
||||
(layer_idx == 0) ? nullptr : m_layers[layer_idx - 1],
|
||||
(layer_idx == 0 || surfaces_covered.empty() || surfaces_covered[layer_idx - 1].empty()) ? nullptr : &surfaces_covered[layer_idx - 1]);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -1573,7 +1646,7 @@ void PrintObject::bridge_over_infill()
|
||||
)};
|
||||
push @new_surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => S_TYPE_INTERNALVOID,
|
||||
surface_type => stInternalVoid,
|
||||
), @{intersection_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map @$_, @$to_bridge ],
|
||||
@ -1685,7 +1758,7 @@ PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegion
|
||||
PrintRegionConfig config = default_region_config;
|
||||
normalize_and_apply_config(config, volume.get_object()->config);
|
||||
if (layer_range_config != nullptr)
|
||||
normalize_and_apply_config(config, *layer_range_config);
|
||||
normalize_and_apply_config(config, *layer_range_config);
|
||||
normalize_and_apply_config(config, volume.config);
|
||||
if (! volume.material_id().empty())
|
||||
normalize_and_apply_config(config, volume.material()->config);
|
||||
@ -1705,36 +1778,36 @@ void PrintObject::update_slicing_parameters()
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z)
|
||||
{
|
||||
PrintConfig print_config;
|
||||
PrintObjectConfig object_config;
|
||||
PrintRegionConfig default_region_config;
|
||||
print_config.apply(full_config, true);
|
||||
object_config.apply(full_config, true);
|
||||
default_region_config.apply(full_config, true);
|
||||
size_t num_extruders = print_config.nozzle_diameter.size();
|
||||
object_config = object_config_from_model_object(object_config, model_object, num_extruders);
|
||||
PrintConfig print_config;
|
||||
PrintObjectConfig object_config;
|
||||
PrintRegionConfig default_region_config;
|
||||
print_config.apply(full_config, true);
|
||||
object_config.apply(full_config, true);
|
||||
default_region_config.apply(full_config, true);
|
||||
size_t num_extruders = print_config.nozzle_diameter.size();
|
||||
object_config = object_config_from_model_object(object_config, model_object, num_extruders);
|
||||
|
||||
std::vector<unsigned int> object_extruders;
|
||||
for (const ModelVolume* model_volume : model_object.volumes)
|
||||
if (model_volume->is_model_part()) {
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, nullptr, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range_and_config : model_object.layer_config_ranges)
|
||||
if (range_and_config.second.has("perimeter_extruder") ||
|
||||
range_and_config.second.has("infill_extruder") ||
|
||||
range_and_config.second.has("solid_infill_extruder"))
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, &range_and_config.second, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
}
|
||||
std::vector<unsigned int> object_extruders;
|
||||
for (const ModelVolume* model_volume : model_object.volumes)
|
||||
if (model_volume->is_model_part()) {
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, nullptr, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range_and_config : model_object.layer_config_ranges)
|
||||
if (range_and_config.second.has("perimeter_extruder") ||
|
||||
range_and_config.second.has("infill_extruder") ||
|
||||
range_and_config.second.has("solid_infill_extruder"))
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, &range_and_config.second, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
}
|
||||
sort_remove_duplicates(object_extruders);
|
||||
|
||||
if (object_max_z <= 0.f)
|
||||
object_max_z = (float)model_object.raw_bounding_box().size().z();
|
||||
return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders);
|
||||
return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders);
|
||||
}
|
||||
|
||||
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
|
||||
@ -1767,12 +1840,9 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
|
||||
layer_height_profile.clear();
|
||||
|
||||
if (layer_height_profile.empty()) {
|
||||
if (0)
|
||||
// if (this->layer_height_profile.empty())
|
||||
layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
|
||||
else
|
||||
layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); // #ys_FIXME_experiment
|
||||
updated = true;
|
||||
//layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
|
||||
layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges);
|
||||
updated = true;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
@ -1827,27 +1897,27 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
|
||||
// Count model parts and modifier meshes, check whether the model parts are of the same region.
|
||||
int all_volumes_single_region = -2; // not set yet
|
||||
bool has_z_ranges = false;
|
||||
size_t num_volumes = 0;
|
||||
bool has_z_ranges = false;
|
||||
size_t num_volumes = 0;
|
||||
size_t num_modifiers = 0;
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
int last_volume_id = -1;
|
||||
int last_volume_id = -1;
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const int volume_id = volume_and_range.second;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
const int volume_id = volume_and_range.second;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_model_part()) {
|
||||
if (last_volume_id == volume_id) {
|
||||
has_z_ranges = true;
|
||||
} else {
|
||||
last_volume_id = volume_id;
|
||||
if (all_volumes_single_region == -2)
|
||||
// first model volume met
|
||||
all_volumes_single_region = region_id;
|
||||
else if (all_volumes_single_region != region_id)
|
||||
// multiple volumes met and they are not equal
|
||||
all_volumes_single_region = -1;
|
||||
++ num_volumes;
|
||||
}
|
||||
if (last_volume_id == volume_id) {
|
||||
has_z_ranges = true;
|
||||
} else {
|
||||
last_volume_id = volume_id;
|
||||
if (all_volumes_single_region == -2)
|
||||
// first model volume met
|
||||
all_volumes_single_region = region_id;
|
||||
else if (all_volumes_single_region != region_id)
|
||||
// multiple volumes met and they are not equal
|
||||
all_volumes_single_region = -1;
|
||||
++ num_volumes;
|
||||
}
|
||||
} else if (model_volume->is_modifier())
|
||||
++ num_modifiers;
|
||||
}
|
||||
@ -2353,12 +2423,13 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
|
||||
merge.assign(out.size(), false);
|
||||
} else {
|
||||
for (size_t i = 0; i < out.size(); ++ i)
|
||||
if (! this_slices[i].empty())
|
||||
if (! this_slices[i].empty()) {
|
||||
if (! out[i].empty()) {
|
||||
append(out[i], this_slices[i]);
|
||||
merge[i] = true;
|
||||
} else
|
||||
out[i] = std::move(this_slices[i]);
|
||||
}
|
||||
}
|
||||
i = j;
|
||||
} else
|
||||
@ -2721,8 +2792,7 @@ void PrintObject::clip_fill_surfaces()
|
||||
// Detect things that we need to support.
|
||||
// Cummulative slices.
|
||||
Polygons slices;
|
||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||
polygons_append(slices, to_polygons(expoly));
|
||||
polygons_append(slices, layer->slices.expolygons);
|
||||
// Cummulative fill surfaces.
|
||||
Polygons fill_surfaces;
|
||||
// Solid surfaces to be supported.
|
||||
@ -2832,7 +2902,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
polygons_append(solid, to_polygons(surface.expolygon));
|
||||
if (solid.empty())
|
||||
continue;
|
||||
// Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
||||
// Slic3r::debugf "Layer %d has %s surfaces\n", $i, (($type & stTop) != 0) ? 'top' : 'bottom';
|
||||
|
||||
size_t solid_layers = ((type & stPosTop) == stPosTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
||||
for (int n = ((type & stPosTop) == stPosTop) ? (i - 1) : (i + 1); std::abs(n - (int)i) < solid_layers; ((type & stPosTop) == stPosTop) ? (--n) : (++n)) {
|
||||
@ -2851,7 +2921,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
// shells to be generated in the base but not in the walls (where there are many
|
||||
// narrow bottom surfaces): reassigning $solid will consider the 'shadow' of the
|
||||
// upper perimeter as an obstacle and shell will not be propagated to more upper layers
|
||||
//FIXME How does it work for S_TYPE_INTERNALBRIDGE? This is set for sparse infill. Likely this does not work.
|
||||
//FIXME How does it work for stInternalBRIDGE? This is set for sparse infill. Likely this does not work.
|
||||
Polygons new_internal_solid;
|
||||
{
|
||||
Polygons internal;
|
||||
@ -3045,7 +3115,7 @@ void PrintObject::combine_infill()
|
||||
continue;
|
||||
// Slic3r::debugf " combining %d %s regions from layers %d-%d\n",
|
||||
// scalar(@$intersection),
|
||||
// ($type == S_TYPE_INTERNAL ? 'internal' : 'internal-solid'),
|
||||
// ($type == stInternal ? 'internal' : 'internal-solid'),
|
||||
// $layer_idx-($every-1), $layer_idx;
|
||||
// intersection now contains the regions that can be combined across the full amount of layers,
|
||||
// so let's remove those areas from all layers.
|
||||
|
@ -2,6 +2,21 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// 1-based extruder identifier for this region and role.
|
||||
unsigned int PrintRegion::extruder(FlowRole role) const
|
||||
{
|
||||
size_t extruder = 0;
|
||||
if (role == frPerimeter || role == frExternalPerimeter)
|
||||
extruder = m_config.perimeter_extruder;
|
||||
else if (role == frInfill)
|
||||
extruder = m_config.infill_extruder;
|
||||
else if (role == frSolidInfill || role == frTopSolidInfill)
|
||||
extruder = m_config.solid_infill_extruder;
|
||||
else
|
||||
throw std::invalid_argument("Unknown role");
|
||||
return extruder;
|
||||
}
|
||||
|
||||
Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const
|
||||
{
|
||||
ConfigOptionFloatOrPercent config_width;
|
||||
@ -28,24 +43,13 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
|
||||
throw std::invalid_argument("Unknown role");
|
||||
}
|
||||
}
|
||||
if (config_width.value == 0) {
|
||||
|
||||
if (config_width.value == 0)
|
||||
config_width = object.config().extrusion_width;
|
||||
}
|
||||
|
||||
// get the configured nozzle_diameter for the extruder associated
|
||||
// to the flow role requested
|
||||
size_t extruder = 0; // 1-based
|
||||
if (role == frPerimeter || role == frExternalPerimeter) {
|
||||
extruder = m_config.perimeter_extruder;
|
||||
} else if (role == frInfill) {
|
||||
extruder = m_config.infill_extruder;
|
||||
} else if (role == frSolidInfill || role == frTopSolidInfill) {
|
||||
extruder = m_config.solid_infill_extruder;
|
||||
} else {
|
||||
throw std::invalid_argument("Unknown role");
|
||||
}
|
||||
double nozzle_diameter = m_print->config().nozzle_diameter.get_at(extruder-1);
|
||||
|
||||
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
|
||||
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
|
||||
double nozzle_diameter = m_print->config().nozzle_diameter.get_at(this->extruder(role) - 1);
|
||||
return Flow::new_from_config_width(role, config_width, (float)nozzle_diameter, (float)layer_height, bridge ? (float)m_config.bridge_flow_ratio : 0.0f);
|
||||
}
|
||||
|
||||
@ -79,12 +83,14 @@ void PrintRegion::collect_object_printing_extruders(const PrintConfig &print_con
|
||||
|
||||
void PrintRegion::collect_object_printing_extruders(std::vector<unsigned int> &object_extruders) const
|
||||
{
|
||||
auto num_extruders = (int)print()->config().nozzle_diameter.size();
|
||||
// PrintRegion, if used by some PrintObject, shall have all the extruders set to an existing printer extruder.
|
||||
// If not, then there must be something wrong with the Print::apply() function.
|
||||
#ifndef NDEBUG
|
||||
auto num_extruders = (int)print()->config().nozzle_diameter.size();
|
||||
assert(this->config().perimeter_extruder <= num_extruders);
|
||||
assert(this->config().infill_extruder <= num_extruders);
|
||||
assert(this->config().solid_infill_extruder <= num_extruders);
|
||||
#endif
|
||||
collect_object_printing_extruders(print()->config(), this->config(), object_extruders);
|
||||
}
|
||||
|
||||
|
@ -185,8 +185,6 @@ private:
|
||||
|
||||
SLAAutoSupports::Config m_config;
|
||||
|
||||
float m_supports_force_total = 0.f;
|
||||
|
||||
void process(const std::vector<ExPolygons>& slices, const std::vector<float>& heights);
|
||||
void uniformly_cover(const ExPolygons& islands, Structure& structure, PointGrid3D &grid3d, bool is_new_island = false, bool just_one = false);
|
||||
void project_onto_mesh(std::vector<sla::SupportPoint>& points) const;
|
||||
|
@ -68,15 +68,14 @@ public:
|
||||
|
||||
/// Type that represents a resolution in pixels.
|
||||
struct Resolution {
|
||||
unsigned width_px;
|
||||
unsigned height_px;
|
||||
size_t width_px;
|
||||
size_t height_px;
|
||||
|
||||
inline Resolution(unsigned w = 0, unsigned h = 0):
|
||||
width_px(w), height_px(h) {}
|
||||
inline Resolution(size_t w = 0, size_t h = 0)
|
||||
: width_px(w), height_px(h)
|
||||
{}
|
||||
|
||||
inline unsigned pixels() const /*noexcept*/ {
|
||||
return width_px * height_px;
|
||||
}
|
||||
inline size_t pixels() const { return width_px * height_px; }
|
||||
};
|
||||
|
||||
/// Types that represents the dimension of a pixel in millimeters.
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "SLARasterWriter.hpp"
|
||||
#include "libslic3r/Zipper.hpp"
|
||||
#include "libslic3r/Time.hpp"
|
||||
|
||||
#include "ExPolygon.hpp"
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
|
||||
@ -10,25 +12,13 @@ namespace Slic3r { namespace sla {
|
||||
|
||||
std::string SLARasterWriter::createIniContent(const std::string& projectname) const
|
||||
{
|
||||
auto expt_str = std::to_string(m_exp_time_s);
|
||||
auto expt_first_str = std::to_string(m_exp_time_first_s);
|
||||
auto layerh_str = std::to_string(m_layer_height);
|
||||
|
||||
const std::string cnt_fade_layers = std::to_string(m_cnt_fade_layers);
|
||||
const std::string cnt_slow_layers = std::to_string(m_cnt_slow_layers);
|
||||
const std::string cnt_fast_layers = std::to_string(m_cnt_fast_layers);
|
||||
const std::string used_material = std::to_string(m_used_material);
|
||||
|
||||
return std::string(
|
||||
"action = print\n"
|
||||
"jobDir = ") + projectname + "\n" +
|
||||
"expTime = " + expt_str + "\n"
|
||||
"expTimeFirst = " + expt_first_str + "\n"
|
||||
"numFade = " + cnt_fade_layers + "\n"
|
||||
"layerHeight = " + layerh_str + "\n"
|
||||
"usedMaterial = " + used_material + "\n"
|
||||
"numSlow = " + cnt_slow_layers + "\n"
|
||||
"numFast = " + cnt_fast_layers + "\n";
|
||||
std::string out("action = print\njobDir = ");
|
||||
out += projectname + "\n";
|
||||
|
||||
for (auto ¶m : m_config)
|
||||
out += param.first + " = " + param.second + "\n";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void SLARasterWriter::flpXY(ClipperLib::Polygon &poly)
|
||||
@ -53,38 +43,14 @@ void SLARasterWriter::flpXY(ExPolygon &poly)
|
||||
}
|
||||
}
|
||||
|
||||
SLARasterWriter::SLARasterWriter(const SLAPrinterConfig &cfg,
|
||||
const SLAMaterialConfig &mcfg,
|
||||
double layer_height)
|
||||
SLARasterWriter::SLARasterWriter(const Raster::Resolution &res,
|
||||
const Raster::PixelDim &pixdim,
|
||||
const std::array<bool, 2> &mirror,
|
||||
double gamma)
|
||||
: m_res(res), m_pxdim(pixdim), m_mirror(mirror), m_gamma(gamma)
|
||||
{
|
||||
double w = cfg.display_width.getFloat();
|
||||
double h = cfg.display_height.getFloat();
|
||||
auto pw = unsigned(cfg.display_pixels_x.getInt());
|
||||
auto ph = unsigned(cfg.display_pixels_y.getInt());
|
||||
|
||||
m_mirror[X] = cfg.display_mirror_x.getBool();
|
||||
|
||||
// PNG raster will implicitly do an Y mirror
|
||||
m_mirror[Y] = ! cfg.display_mirror_y.getBool();
|
||||
|
||||
auto ro = cfg.display_orientation.getInt();
|
||||
|
||||
if(ro == roPortrait) {
|
||||
std::swap(w, h);
|
||||
std::swap(pw, ph);
|
||||
m_o = roPortrait;
|
||||
|
||||
// XY flipping implicitly does an X mirror
|
||||
m_mirror[X] = ! m_mirror[X];
|
||||
} else m_o = roLandscape;
|
||||
|
||||
m_res = Raster::Resolution(pw, ph);
|
||||
m_pxdim = Raster::PixelDim(w/pw, h/ph);
|
||||
m_exp_time_s = mcfg.exposure_time.getFloat();
|
||||
m_exp_time_first_s = mcfg.initial_exposure_time.getFloat();
|
||||
m_layer_height = layer_height;
|
||||
|
||||
m_gamma = cfg.gamma_correction.getFloat();
|
||||
m_mirror[1] = !m_mirror[1];
|
||||
}
|
||||
|
||||
void SLARasterWriter::save(const std::string &fpath, const std::string &prjname)
|
||||
@ -121,15 +87,44 @@ void SLARasterWriter::save(const std::string &fpath, const std::string &prjname)
|
||||
}
|
||||
}
|
||||
|
||||
void SLARasterWriter::set_statistics(const std::vector<double> statistics)
|
||||
namespace {
|
||||
|
||||
std::string get_cfg_value(const DynamicPrintConfig &cfg, const std::string &key)
|
||||
{
|
||||
if (statistics.size() != psCnt)
|
||||
return;
|
||||
std::string ret;
|
||||
|
||||
m_used_material = statistics[psUsedMaterial];
|
||||
m_cnt_fade_layers = int(statistics[psNumFade]);
|
||||
m_cnt_slow_layers = int(statistics[psNumSlow]);
|
||||
m_cnt_fast_layers = int(statistics[psNumFast]);
|
||||
if (cfg.has(key)) {
|
||||
auto opt = cfg.option(key);
|
||||
if (opt) ret = opt->serialize();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SLARasterWriter::set_config(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
m_config["layerHeight"] = get_cfg_value(cfg, "layer_height");
|
||||
m_config["expTime"] = get_cfg_value(cfg, "exposure_time");
|
||||
m_config["expTimeFirst"] = get_cfg_value(cfg, "initial_exposure_time");
|
||||
m_config["materialName"] = get_cfg_value(cfg, "sla_material_settings_id");
|
||||
m_config["printerModel"] = get_cfg_value(cfg, "printer_model");
|
||||
m_config["printerVariant"] = get_cfg_value(cfg, "printer_variant");
|
||||
m_config["printerProfile"] = get_cfg_value(cfg, "printer_settings_id");
|
||||
m_config["printProfile"] = get_cfg_value(cfg, "sla_print_settings_id");
|
||||
|
||||
m_config["fileCreationTimestamp"] = Utils::current_utc_time2str();
|
||||
m_config["prusaSlicerVersion"] = SLIC3R_BUILD_ID;
|
||||
}
|
||||
|
||||
void SLARasterWriter::set_statistics(const PrintStatistics &stats)
|
||||
{
|
||||
m_config["usedMaterial"] = std::to_string(stats.used_material);
|
||||
m_config["numFade"] = std::to_string(stats.num_fade);
|
||||
m_config["numSlow"] = std::to_string(stats.num_slow);
|
||||
m_config["numFast"] = std::to_string(stats.num_fast);
|
||||
m_config["printTime"] = std::to_string(stats.estimated_print_time_s);
|
||||
}
|
||||
|
||||
} // namespace sla
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
// For png export of the sliced model
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
@ -23,20 +25,19 @@ namespace Slic3r { namespace sla {
|
||||
class SLARasterWriter
|
||||
{
|
||||
public:
|
||||
enum RasterOrientation {
|
||||
enum Orientation {
|
||||
roLandscape,
|
||||
roPortrait
|
||||
};
|
||||
|
||||
// Used for addressing parameters of set_statistics()
|
||||
enum ePrintStatistics
|
||||
{
|
||||
psUsedMaterial = 0,
|
||||
psNumFade,
|
||||
psNumSlow,
|
||||
psNumFast,
|
||||
|
||||
psCnt
|
||||
struct PrintStatistics
|
||||
{
|
||||
double used_material = 0.;
|
||||
double estimated_print_time_s = 0.;
|
||||
size_t num_fade = 0;
|
||||
size_t num_slow = 0;
|
||||
size_t num_fast = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
@ -47,21 +48,13 @@ private:
|
||||
RawBytes rawbytes;
|
||||
|
||||
Layer() = default;
|
||||
Layer(const Layer&) = delete; // The image is big, do not copy by accident
|
||||
Layer& operator=(const Layer&) = delete;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
// FIXME: the following is needed for MSVC2013 compatibility
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
// The image is big, do not copy by accident
|
||||
Layer(const Layer&) = delete;
|
||||
Layer& operator=(const Layer&) = delete;
|
||||
|
||||
// Layer(Layer&& m) = default;
|
||||
// Layer& operator=(Layer&&) = default;
|
||||
Layer(Layer &&m):
|
||||
raster(std::move(m.raster)), rawbytes(std::move(m.rawbytes)) {}
|
||||
Layer& operator=(Layer &&m) {
|
||||
raster = std::move(m.raster); rawbytes = std::move(m.rawbytes);
|
||||
return *this;
|
||||
}
|
||||
Layer(Layer &&m) = default;
|
||||
Layer &operator=(Layer &&) = default;
|
||||
};
|
||||
|
||||
// We will save the compressed PNG data into RawBytes type buffers in
|
||||
@ -69,66 +62,46 @@ private:
|
||||
std::vector<Layer> m_layers_rst;
|
||||
Raster::Resolution m_res;
|
||||
Raster::PixelDim m_pxdim;
|
||||
double m_exp_time_s = .0, m_exp_time_first_s = .0;
|
||||
double m_layer_height = .0;
|
||||
RasterOrientation m_o = roPortrait;
|
||||
std::array<bool, 2> m_mirror;
|
||||
|
||||
double m_gamma;
|
||||
|
||||
double m_used_material = 0.0;
|
||||
int m_cnt_fade_layers = 0;
|
||||
int m_cnt_slow_layers = 0;
|
||||
int m_cnt_fast_layers = 0;
|
||||
|
||||
|
||||
std::map<std::string, std::string> m_config;
|
||||
|
||||
std::string createIniContent(const std::string& projectname) const;
|
||||
|
||||
static void flpXY(ClipperLib::Polygon& poly);
|
||||
static void flpXY(ExPolygon& poly);
|
||||
|
||||
public:
|
||||
|
||||
SLARasterWriter(const SLAPrinterConfig& cfg,
|
||||
const SLAMaterialConfig& mcfg,
|
||||
double layer_height);
|
||||
SLARasterWriter(const Raster::Resolution &res,
|
||||
const Raster::PixelDim &pixdim,
|
||||
const std::array<bool, 2> &mirror,
|
||||
double gamma = 1.);
|
||||
|
||||
SLARasterWriter(const SLARasterWriter& ) = delete;
|
||||
SLARasterWriter& operator=(const SLARasterWriter&) = delete;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// FIXME: the following is needed for MSVC2013 compatibility
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SLARasterWriter(SLARasterWriter&& m) = default;
|
||||
// SLARasterWriter& operator=(SLARasterWriter&&) = default;
|
||||
SLARasterWriter(SLARasterWriter&& m):
|
||||
m_layers_rst(std::move(m.m_layers_rst)),
|
||||
m_res(m.m_res),
|
||||
m_pxdim(m.m_pxdim),
|
||||
m_exp_time_s(m.m_exp_time_s),
|
||||
m_exp_time_first_s(m.m_exp_time_first_s),
|
||||
m_layer_height(m.m_layer_height),
|
||||
m_o(m.m_o),
|
||||
m_mirror(std::move(m.m_mirror)),
|
||||
m_gamma(m.m_gamma),
|
||||
m_used_material(m.m_used_material),
|
||||
m_cnt_fade_layers(m.m_cnt_fade_layers),
|
||||
m_cnt_slow_layers(m.m_cnt_slow_layers),
|
||||
m_cnt_fast_layers(m.m_cnt_fast_layers)
|
||||
{}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
SLARasterWriter(SLARasterWriter&& m) = default;
|
||||
SLARasterWriter& operator=(SLARasterWriter&&) = default;
|
||||
|
||||
inline void layers(unsigned cnt) { if(cnt > 0) m_layers_rst.resize(cnt); }
|
||||
inline unsigned layers() const { return unsigned(m_layers_rst.size()); }
|
||||
|
||||
template<class Poly> void draw_polygon(const Poly& p, unsigned lyr) {
|
||||
template<class Poly> void draw_polygon(const Poly& p, unsigned lyr,
|
||||
Orientation o = roPortrait)
|
||||
{
|
||||
assert(lyr < m_layers_rst.size());
|
||||
if(m_o == roPortrait) {
|
||||
Poly poly(p); flpXY(poly);
|
||||
|
||||
switch (o) {
|
||||
case roPortrait: {
|
||||
Poly poly(p);
|
||||
flpXY(poly);
|
||||
m_layers_rst[lyr].raster.draw(poly);
|
||||
break;
|
||||
}
|
||||
case roLandscape:
|
||||
m_layers_rst[lyr].raster.draw(p);
|
||||
break;
|
||||
}
|
||||
else m_layers_rst[lyr].raster.draw(p);
|
||||
}
|
||||
|
||||
inline void begin_layer(unsigned lyr) {
|
||||
@ -156,9 +129,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void save(const std::string& fpath, const std::string& prjname = "");
|
||||
void save(const std::string &fpath, const std::string &prjname = "");
|
||||
|
||||
void set_statistics(const std::vector<double> statistics);
|
||||
void set_statistics(const PrintStatistics &statistics);
|
||||
|
||||
void set_config(const DynamicPrintConfig &cfg);
|
||||
};
|
||||
|
||||
} // namespace sla
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user