Merge branch 'master' into fs_svg

This commit is contained in:
Filip Sykala - NTB T15p 2023-06-02 10:53:47 +02:00
commit 5de06a9ef8
260 changed files with 148982 additions and 75328 deletions

View File

@ -406,6 +406,7 @@ endif()
set(TBB_DEBUG 1) set(TBB_DEBUG 1)
find_package(TBB REQUIRED) find_package(TBB REQUIRED)
slic3r_remap_configs(TBB::tbb RelWithDebInfo Release) slic3r_remap_configs(TBB::tbb RelWithDebInfo Release)
slic3r_remap_configs(TBB::tbbmalloc RelWithDebInfo Release)
# include_directories(${TBB_INCLUDE_DIRS}) # include_directories(${TBB_INCLUDE_DIRS})
# add_definitions(${TBB_DEFINITIONS}) # add_definitions(${TBB_DEFINITIONS})
# if(MSVC) # if(MSVC)
@ -545,6 +546,7 @@ foreach(po_file ${L10N_PO_FILES})
endforeach() endforeach()
find_package(NLopt 1.4 REQUIRED) find_package(NLopt 1.4 REQUIRED)
slic3r_remap_configs(NLopt::nlopt RelWithDebInfo Release)
if(SLIC3R_STATIC) if(SLIC3R_STATIC)
set(OPENVDB_USE_STATIC_LIBS ON) set(OPENVDB_USE_STATIC_LIBS ON)

Binary file not shown.

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="800px"
height="800px"
viewBox="0 0 1024 1024"
class="icon"
version="1.1"
id="svg842"
sodipodi:docname="sla_view_original.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs846" />
<sodipodi:namedview
id="namedview844"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="0.69208076"
inkscape:cx="399.51985"
inkscape:cy="496.32936"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg842" />
<path
d="M964.266667 812.8c2.133333-8.533333 2.133333-17.066667 2.133333-23.466667s0-17.066667-2.133333-23.466666l49.066666-36.266667c4.266667-4.266667 6.4-10.666667 4.266667-14.933333l-49.066667-83.2c-2.133333-4.266667-8.533333-6.4-14.933333-4.266667l-55.466667 25.6c-12.8-10.666667-27.733333-19.2-42.666666-25.6l-6.4-61.866667c0-6.4-6.4-10.666667-10.666667-10.666666h-96c-6.4 0-10.666667 4.266667-10.666667 10.666666l-6.4 61.866667c-14.933333 6.4-29.866667 14.933333-42.666666 25.6l-55.466667-25.6c-6.4-2.133333-12.8 0-14.933333 4.266667l-49.066667 83.2c-2.133333 4.266667-2.133333 12.8 4.266667 14.933333l49.066666 36.266667c-2.133333 8.533333-2.133333 17.066667-2.133333 23.466666s0 17.066667 2.133333 23.466667l-49.066666 36.266667c-4.266667 4.266667-6.4 10.666667-4.266667 14.933333l49.066667 83.2c2.133333 4.266667 8.533333 6.4 14.933333 4.266667l55.466667-25.6c12.8 10.666667 27.733333 19.2 42.666666 25.6l6.4 61.866666c0 6.4 6.4 10.666667 10.666667 10.666667h96c6.4 0 10.666667-4.266667 10.666667-10.666667l6.4-61.866666c14.933333-6.4 29.866667-14.933333 42.666666-25.6l55.466667 25.6c6.4 2.133333 12.8 0 14.933333-4.266667l49.066667-83.2c2.133333-4.266667 2.133333-12.8-4.266667-14.933333l-49.066666-36.266667zM789.333333 900.266667c-61.866667 0-110.933333-49.066667-110.933333-110.933334 0-61.866667 49.066667-110.933333 110.933333-110.933333 61.866667 0 110.933333 49.066667 110.933334 110.933333 0 61.866667-49.066667 110.933333-110.933334 110.933334z"
fill="#607D8B"
id="path838"
style="fill:#ffffff;fill-opacity:1" />
<path
d="M789.333333 661.333333c-70.4 0-128 57.6-128 128s57.6 128 128 128 128-57.6 128-128-57.6-128-128-128z m0 192c-36.266667 0-64-27.733333-64-64s27.733333-64 64-64 64 27.733333 64 64-27.733333 64-64 64z"
fill="#455A64"
id="path840"
style="fill:#646464;fill-opacity:0" />
<path
d="M 464.75606,385.71647 H 220.52618 c -23.46667,0 -42.66667,19.2 -42.66667,42.66668 v 171.15708 c 0,23.46667 19.2,42.66667 42.66667,42.66667 h 244.22988 c 23.46668,0 42.66668,-19.2 42.66668,-42.66667 V 428.38315 c 0,-23.46668 -19.2,-42.66668 -42.66668,-42.66668 z"
style="fill:#f7c0a1;stroke-width:1.28;fill-opacity:1"
id="path1447"
sodipodi:nodetypes="sssssssss" />
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0;paint-order:stroke fill markers"
d="m 158.31475,281.62793 c -9.13538,-2.47451 -17.55246,-9.78885 -21.77597,-18.92305 -2.14973,-4.64921 -2.18374,-5.6297 -2.18374,-62.96031 v -58.23755 l 2.5171,-5.10855 c 3.53239,-7.16911 11.05319,-14.20236 17.94366,-16.78042 l 5.66954,-2.12124 H 400 639.51466 l 5.66953,2.12124 c 6.89048,2.57806 14.41128,9.61131 17.94367,16.78042 l 2.5171,5.10855 v 58.23755 58.23755 l -2.83063,5.76399 c -3.30254,6.725 -10.14711,13.42226 -16.91326,16.54928 l -4.77719,2.2078 -239.08046,0.19191 c -186.73355,0.14989 -240.09819,-0.0838 -243.72867,-1.06717 z"
id="path7485"
transform="scale(1.28)" />
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0;paint-order:stroke fill markers"
d="m 437.21118,499.60629 c -10.08409,-1.70675 -19.55357,-8.84836 -24.15393,-18.21621 l -2.84014,-5.78344 v -75.09578 -75.09579 l 2.84014,-5.78344 c 3.4061,-6.93594 9.17745,-12.3958 16.96062,-16.04525 l 5.74203,-2.69238 h 102.17113 102.17114 l 5.74203,2.69238 c 7.78317,3.64945 13.55451,9.10931 16.96062,16.04525 l 2.84014,5.78344 0.12731,66.92209 c 0.10556,55.49011 -0.0746,65.14125 -1.0544,56.49709 -0.97739,-8.62265 -1.60428,-10.87483 -3.62597,-13.02682 l -2.44427,-2.60181 h -41.24765 -41.24765 l -2.50783,2.50784 c -1.37931,1.37931 -2.5167,3.56322 -2.52753,4.85313 -0.0297,3.54851 -4.90813,49.01817 -5.27775,49.19231 -0.17708,0.0835 -5.14956,2.57971 -11.04995,5.54727 l -10.72797,5.39556 -14.94254,-0.0316 -14.94253,-0.0316 -12.03854,-5.65658 c -16.76712,-7.87841 -21.03033,-7.77771 -25.74014,0.60802 l -2.83433,5.04647 -15.83653,-0.11915 c -8.71009,-0.0655 -17.94207,-0.47549 -20.51551,-0.91106 z"
id="path7524"
transform="scale(1.28)" />
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0;paint-order:stroke fill markers"
d="m 154.98937,680.48972 c -7.22252,-2.82207 -13.15353,-8.19884 -17.12576,-15.5254 l -3.50857,-6.47134 v -58.23755 c 0,-57.52794 0.0269,-58.29576 2.20781,-63.01474 3.12702,-6.76614 9.82428,-13.61071 16.54928,-16.91326 l 5.76399,-2.83062 152.41872,-0.27172 152.41871,-0.27172 -12.21117,20.70595 c -6.71614,11.38827 -12.48085,21.74042 -12.81046,23.00479 -1.33796,5.13249 0.30977,6.86623 21.05574,22.15497 11.25014,8.29079 20.61354,15.37577 20.80755,15.7444 0.194,0.36863 -0.1096,4.69322 -0.67466,9.61021 -0.66837,5.81596 -0.68702,12.03751 -0.0533,17.80415 l 0.97403,8.86416 -19.66637,14.61906 c -10.8165,8.04047 -20.1462,15.51562 -20.73266,16.61144 -1.65622,3.09465 -1.2651,7.94874 0.99788,12.38455 l 2.06417,4.04614 -141.78323,-0.0478 c -136.20291,-0.0459 -141.9764,-0.12328 -146.69167,-1.96569 z"
id="path7563"
transform="scale(1.28)" />
<path
style="fill:#ffffff;fill-opacity:1;stroke-width:0;paint-order:stroke fill markers;fill-rule:nonzero;stroke:none;stroke-opacity:1"
d="m 604.62085,664.56707 c -24.60818,-5.96525 -40.42276,-29.63578 -36.74461,-54.99766 4.89008,-33.71857 40.85293,-52.20054 71.62153,-36.80764 18.19443,9.1023 28.95735,30.19449 25.97417,50.90177 -4.18305,29.03597 -32.17825,47.85408 -60.85109,40.90353 z"
id="path7602"
transform="scale(1.28)" />
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="800px"
height="800px"
viewBox="0 0 1024 1024"
class="icon"
version="1.1"
id="svg842"
sodipodi:docname="sla_view_processed.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs846" />
<sodipodi:namedview
id="namedview844"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="0.69208076"
inkscape:cx="392.29526"
inkscape:cy="502.10903"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg842" />
<path
d="M789.333333 661.333333c-70.4 0-128 57.6-128 128s57.6 128 128 128 128-57.6 128-128-57.6-128-128-128z m0 192c-36.266667 0-64-27.733333-64-64s27.733333-64 64-64 64 27.733333 64 64-27.733333 64-64 64z"
fill="#455A64"
id="path840"
style="fill:#646464;fill-opacity:0" />
<path
d="M 809.35888,294.17114 H 565.129 c -23.46667,0 -42.66667,19.2 -42.66667,42.66668 l 0,356.86333 c 0,23.46667 19.2,42.66667 42.66667,42.66667 h 244.22988 c 23.46668,0 42.66668,-19.2 42.66668,-42.66667 l 0,-356.86333 c 0,-23.46668 -19.2,-42.66668 -42.66668,-42.66668 z"
style="fill:#ed6b21;fill-opacity:1;stroke-width:1.28"
id="path1447-4"
sodipodi:nodetypes="sssssssss" />
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0;paint-order:stroke fill markers"
d="m 158.31475,281.62793 c -9.13538,-2.47451 -17.55246,-9.78885 -21.77597,-18.92305 -2.14973,-4.64921 -2.18374,-5.6297 -2.18374,-62.96031 v -58.23755 l 2.5171,-5.10855 c 3.53239,-7.16911 11.05319,-14.20236 17.94366,-16.78042 l 5.66954,-2.12124 H 400 639.51466 l 5.66953,2.12124 c 6.89048,2.57806 14.41128,9.61131 17.94367,16.78042 l 2.5171,5.10855 v 58.23755 58.23755 l -2.83063,5.76399 c -3.30254,6.725 -10.14711,13.42226 -16.91326,16.54928 l -4.77719,2.2078 -239.08046,0.19191 c -186.73355,0.14989 -240.09819,-0.0838 -243.72867,-1.06717 z"
id="path7485"
transform="scale(1.28)" />
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0;paint-order:stroke fill markers"
d="m 201.98898,872.0074 c -11.69328,-3.16737 -22.46714,-12.52973 -27.87324,-24.2215 -2.75165,-5.95099 -2.79518,-7.20602 -2.79518,-80.5892 v -74.54406 l 3.22188,-6.53895 c 4.52146,-9.17646 14.14809,-18.17902 22.96789,-21.47894 l 7.25701,-2.71518 H 511.3461 817.92486 l 7.257,2.71518 c 8.81982,3.29992 18.44644,12.30248 22.9679,21.47894 l 3.22189,6.53895 v 74.54406 74.54406 l -3.62321,7.37791 c -4.22725,8.608 -12.9883,17.18049 -21.64897,21.18308 l -6.1148,2.82598 -306.02299,0.24565 C 274.94273,873.56524 206.636,873.26611 201.98898,872.0074 Z"
id="path7485-7" />
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -98,7 +98,7 @@ src/slic3r/Utils/Process.cpp
src/slic3r/Utils/Repetier.cpp src/slic3r/Utils/Repetier.cpp
src/slic3r/Config/Snapshot.cpp src/slic3r/Config/Snapshot.cpp
src/libslic3r/GCode.cpp src/libslic3r/GCode.cpp
src/libslic3r/ExtrusionEntity.cpp src/libslic3r/ExtrusionRole.cpp
src/libslic3r/Flow.cpp src/libslic3r/Flow.cpp
src/libslic3r/Format/3mf.cpp src/libslic3r/Format/3mf.cpp
src/libslic3r/Format/AMF.cpp src/libslic3r/Format/AMF.cpp
@ -111,6 +111,7 @@ src/libslic3r/SLA/Pad.cpp
src/libslic3r/SLA/Hollowing.cpp src/libslic3r/SLA/Hollowing.cpp
src/libslic3r/SLAPrint.cpp src/libslic3r/SLAPrint.cpp
src/libslic3r/SLAPrintSteps.cpp src/libslic3r/SLAPrintSteps.cpp
src/libslic3r/Utils.cpp
src/libslic3r/PrintBase.cpp src/libslic3r/PrintBase.cpp
src/libslic3r/PrintConfig.cpp src/libslic3r/PrintConfig.cpp
src/libslic3r/Zipper.cpp src/libslic3r/Zipper.cpp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,3 +1,8 @@
min_slic3r_version = 2.6.0-beta2
1.9.0-beta2 Added profiles for Original Prusa MK4 Input Shaper (Alpha).
min_slic3r_version = 2.6.0-beta0
1.9.0-beta1 Updated cooling settings for some ASA filaments to increase interlayer adhesion (XL/MK4).
1.9.0-beta0 Updated start g-code script for MK4/XL.
min_slic3r_version = 2.6.0-alpha5 min_slic3r_version = 2.6.0-alpha5
1.9.0-alpha4 Updated XL and MK4 profiles. Updated PC Blend Carbon Fiber density. 1.9.0-alpha4 Updated XL and MK4 profiles. Updated PC Blend Carbon Fiber density.
1.9.0-alpha3 Updated compatibility condition for MMU1 filaments. 1.9.0-alpha3 Updated compatibility condition for MMU1 filaments.
@ -12,11 +17,15 @@ min_slic3r_version = 2.6.0-alpha1
1.6.0-alpha1 Updated FW version notification. Decreased min layer time for PLA. 1.6.0-alpha1 Updated FW version notification. Decreased min layer time for PLA.
1.6.0-alpha0 Default top fill set to monotonic lines. Updated infill/perimeter overlap values. Updated output filename format. Enabled dynamic overhang speeds. 1.6.0-alpha0 Default top fill set to monotonic lines. Updated infill/perimeter overlap values. Updated output filename format. Enabled dynamic overhang speeds.
min_slic3r_version = 2.5.2-rc0 min_slic3r_version = 2.5.2-rc0
1.7.5 Updated cooling settings for some ASA filaments to increase interlayer adhesion (XL/MK4). Updated LA values (XL/MK4).
1.7.4 Updated start g-code script for MK4/XL (fixed pre-print temperature for PA filaments).
1.7.3 Updated XL and MK4 profiles. Updated PC Blend Carbon Fiber density. 1.7.3 Updated XL and MK4 profiles. Updated PC Blend Carbon Fiber density.
1.7.2 Updated compatibility condition for MMU1 filaments. 1.7.2 Updated compatibility condition for MMU1 filaments.
1.7.1 Added SLA materials. Updated MK4 and XL profiles. 1.7.1 Added SLA materials. Updated MK4 and XL profiles.
1.7.0 Added profiles for Original Prusa MK4. 1.7.0 Added profiles for Original Prusa MK4.
min_slic3r_version = 2.5.1-rc0 min_slic3r_version = 2.5.1-rc0
1.6.6 Updated cooling settings for some ASA filaments to increase interlayer adhesion (XL/MK4).
1.6.5 Updated start g-code script for MK4/XL (fixed pre-print temperature for PA filaments).
1.6.4 Fixed compatibility condition for MMU1 filaments. 1.6.4 Fixed compatibility condition for MMU1 filaments.
1.6.3 Added SLA materials. 1.6.3 Added SLA materials.
1.6.2 Updated compatibility condition in some filament profiles (Prusa XL). 1.6.2 Updated compatibility condition in some filament profiles (Prusa XL).

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

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

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,3 +1,4 @@
min_slic3r_version = 2.6.0-alpha0 min_slic3r_version = 2.6.0-alpha0
1.0.2 Updated compatible printer conditions.
1.0.1 Added Prusament PETG Carbon Fiber, Fiberthree F3 PA-GF30 Pro. 1.0.1 Added Prusament PETG Carbon Fiber, Fiberthree F3 PA-GF30 Pro.
1.0.0 Initial 1.0.0 Initial

View File

@ -2,7 +2,7 @@
[vendor] [vendor]
name = Templates name = Templates
config_version = 1.0.1 config_version = 1.0.2
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Templates/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Templates/
templates_profile = 1 templates_profile = 1
@ -11,12 +11,12 @@ templates_profile = 1
[filament:*common*] [filament:*common*]
cooling = 1 cooling = 1
compatible_printers = compatible_printers =
compatible_printers_condition = compatible_printers_condition = printer_notes!~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes!~/.*PRINTER_MODEL_MK4IS.*/
end_filament_gcode = "; Filament-specific end gcode" end_filament_gcode = "; Filament-specific end gcode"
extrusion_multiplier = 1 extrusion_multiplier = 1
filament_loading_speed = 14 filament_loading_speed = 14
filament_loading_speed_start = 19 filament_loading_speed_start = 19
filament_unloading_speed = 90 filament_unloading_speed = 20
filament_unloading_speed_start = 100 filament_unloading_speed_start = 100
filament_toolchange_delay = 0 filament_toolchange_delay = 0
filament_cooling_moves = 1 filament_cooling_moves = 1
@ -1460,7 +1460,6 @@ cooling = 0
fan_always_on = 0 fan_always_on = 0
filament_max_volumetric_speed = 4 filament_max_volumetric_speed = 4
filament_type = METAL filament_type = METAL
compatible_printers_condition = nozzle_diameter[0]>=0.4
filament_colour = #FFFFFF filament_colour = #FFFFFF
[filament:Polymaker PC-Max] [filament:Polymaker PC-Max]
@ -1519,7 +1518,6 @@ first_layer_temperature = 230
max_fan_speed = 20 max_fan_speed = 20
min_fan_speed = 20 min_fan_speed = 20
temperature = 230 temperature = 230
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
[filament:Prusa PETG] [filament:Prusa PETG]
inherits = *PET* inherits = *PET*

View File

@ -8,3 +8,5 @@ add_library(clipper STATIC
clipper_z.cpp clipper_z.cpp
clipper_z.hpp clipper_z.hpp
) )
target_link_libraries(clipper TBB::tbb TBB::tbbmalloc)

View File

@ -73,25 +73,6 @@ static int const Skip = -2; //edge that would otherwise close a path
#define TOLERANCE (1.0e-20) #define TOLERANCE (1.0e-20)
#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) #define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE))
// Output polygon.
struct OutRec {
int Idx;
bool IsHole;
bool IsOpen;
//The 'FirstLeft' field points to another OutRec that contains or is the
//'parent' of OutRec. It is 'first left' because the ActiveEdgeList (AEL) is
//parsed left from the current edge (owning OutRec) until the owner OutRec
//is found. This field simplifies sorting the polygons into a tree structure
//which reflects the parent/child relationships of all polygons.
//This field should be renamed Parent, and will be later.
OutRec *FirstLeft;
// Used only by void Clipper::BuildResult2(PolyTree& polytree)
PolyNode *PolyNd;
// Linked list of output points, dynamically allocated.
OutPt *Pts;
OutPt *BottomPt;
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline IntPoint IntPoint2d(cInt x, cInt y) inline IntPoint IntPoint2d(cInt x, cInt y)
@ -131,7 +112,7 @@ int PolyTree::Total() const
void PolyNode::AddChild(PolyNode& child) void PolyNode::AddChild(PolyNode& child)
{ {
unsigned cnt = (unsigned)Childs.size(); unsigned cnt = (unsigned)Childs.size();
Childs.push_back(&child); Childs.emplace_back(&child);
child.Parent = this; child.Parent = this;
child.Index = cnt; child.Index = cnt;
} }
@ -693,7 +674,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
locMin.RightBound = E; locMin.RightBound = E;
E->WindDelta = 0; E->WindDelta = 0;
Result = ProcessBound(E, NextIsForward); Result = ProcessBound(E, NextIsForward);
m_MinimaList.push_back(locMin); m_MinimaList.emplace_back(locMin);
} }
return Result; return Result;
} }
@ -784,7 +765,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
return false; return false;
// Allocate a new edge array. // Allocate a new edge array.
std::vector<TEdge> edges(highI + 1); Edges edges(highI + 1);
// Fill in the edge array. // Fill in the edge array.
bool result = AddPathInternal(pg, highI, PolyTyp, Closed, edges.data()); bool result = AddPathInternal(pg, highI, PolyTyp, Closed, edges.data());
if (result) if (result)
@ -915,7 +896,7 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
E->NextInLML = E->Next; E->NextInLML = E->Next;
E = E->Next; E = E->Next;
} }
m_MinimaList.push_back(locMin); m_MinimaList.emplace_back(locMin);
return true; return true;
} }
@ -968,7 +949,7 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
locMin.LeftBound = 0; locMin.LeftBound = 0;
else if (locMin.RightBound->OutIdx == Skip) else if (locMin.RightBound->OutIdx == Skip)
locMin.RightBound = 0; locMin.RightBound = 0;
m_MinimaList.push_back(locMin); m_MinimaList.emplace_back(locMin);
if (!leftBoundIsForward) E = E2; if (!leftBoundIsForward) E = E2;
} }
return true; return true;
@ -1061,8 +1042,7 @@ IntRect ClipperBase::GetBounds()
Clipper::Clipper(int initOptions) : Clipper::Clipper(int initOptions) :
ClipperBase(), ClipperBase(),
m_OutPtsFree(nullptr), m_OutPtsFree(nullptr),
m_OutPtsChunkSize(32), m_OutPtsChunkLast(m_OutPtsChunkSize),
m_OutPtsChunkLast(32),
m_ActiveEdges(nullptr), m_ActiveEdges(nullptr),
m_SortedEdges(nullptr) m_SortedEdges(nullptr)
{ {
@ -1079,7 +1059,7 @@ Clipper::Clipper(int initOptions) :
void Clipper::Reset() void Clipper::Reset()
{ {
ClipperBase::Reset(); ClipperBase::Reset();
m_Scanbeam = std::priority_queue<cInt>(); m_Scanbeam = std::priority_queue<cInt, cInts>{};
m_Maxima.clear(); m_Maxima.clear();
m_ActiveEdges = 0; m_ActiveEdges = 0;
m_SortedEdges = 0; m_SortedEdges = 0;
@ -1153,23 +1133,23 @@ bool Clipper::ExecuteInternal()
//FIXME Vojtech: Does it not invalidate the loop hierarchy maintained as OutRec::FirstLeft pointers? //FIXME Vojtech: Does it not invalidate the loop hierarchy maintained as OutRec::FirstLeft pointers?
//FIXME Vojtech: The area is calculated with floats, it may not be numerically stable! //FIXME Vojtech: The area is calculated with floats, it may not be numerically stable!
{ {
for (OutRec *outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
if (outRec->Pts && !outRec->IsOpen && (outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) if (outRec.Pts && !outRec.IsOpen && (outRec.IsHole ^ m_ReverseOutput) == (Area(outRec) > 0))
ReversePolyPtLinks(outRec->Pts); ReversePolyPtLinks(outRec.Pts);
} }
JoinCommonEdges(); JoinCommonEdges();
//unfortunately FixupOutPolygon() must be done after JoinCommonEdges() //unfortunately FixupOutPolygon() must be done after JoinCommonEdges()
{ {
for (OutRec *outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
if (outRec->Pts) { if (outRec.Pts) {
if (outRec->IsOpen) if (outRec.IsOpen)
// Removes duplicate points. // Removes duplicate points.
FixupOutPolyline(*outRec); FixupOutPolyline(outRec);
else else
// Removes duplicate points and simplifies consecutive parallel edges by removing the middle vertex. // Removes duplicate points and simplifies consecutive parallel edges by removing the middle vertex.
FixupOutPolygon(*outRec); FixupOutPolygon(outRec);
} }
} }
// For each polygon, search for exactly duplicate non-successive points. // For each polygon, search for exactly duplicate non-successive points.
@ -1194,22 +1174,18 @@ OutPt* Clipper::AllocateOutPt()
m_OutPtsFree = pt->Next; m_OutPtsFree = pt->Next;
} else if (m_OutPtsChunkLast < m_OutPtsChunkSize) { } else if (m_OutPtsChunkLast < m_OutPtsChunkSize) {
// Get a point from the last chunk. // Get a point from the last chunk.
pt = m_OutPts.back() + (m_OutPtsChunkLast ++); pt = &m_OutPts.back()[m_OutPtsChunkLast ++];
} else { } else {
// The last chunk is full. Allocate a new one. // The last chunk is full. Allocate a new one.
m_OutPts.push_back(new OutPt[m_OutPtsChunkSize]); m_OutPts.emplace_back();
m_OutPtsChunkLast = 1; m_OutPtsChunkLast = 1;
pt = m_OutPts.back(); pt = &m_OutPts.back().front();
} }
return pt; return pt;
} }
void Clipper::DisposeAllOutRecs() void Clipper::DisposeAllOutRecs()
{ {
for (OutPt *pts : m_OutPts)
delete[] pts;
for (OutRec *rec : m_PolyOuts)
delete rec;
m_OutPts.clear(); m_OutPts.clear();
m_OutPtsFree = nullptr; m_OutPtsFree = nullptr;
m_OutPtsChunkLast = m_OutPtsChunkSize; m_OutPtsChunkLast = m_OutPtsChunkSize;
@ -1832,7 +1808,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Clipper::SetHoleState(TEdge *e, OutRec *outrec) const void Clipper::SetHoleState(TEdge *e, OutRec *outrec)
{ {
bool IsHole = false; bool IsHole = false;
TEdge *e2 = e->PrevInAEL; TEdge *e2 = e->PrevInAEL;
@ -1842,7 +1818,7 @@ void Clipper::SetHoleState(TEdge *e, OutRec *outrec) const
{ {
IsHole = !IsHole; IsHole = !IsHole;
if (! outrec->FirstLeft) if (! outrec->FirstLeft)
outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; outrec->FirstLeft = &m_PolyOuts[e2->OutIdx];
} }
e2 = e2->PrevInAEL; e2 = e2->PrevInAEL;
} }
@ -1883,18 +1859,18 @@ bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2)
OutRec* Clipper::GetOutRec(int Idx) OutRec* Clipper::GetOutRec(int Idx)
{ {
OutRec* outrec = m_PolyOuts[Idx]; OutRec* outrec = &m_PolyOuts[Idx];
while (outrec != m_PolyOuts[outrec->Idx]) while (outrec != &m_PolyOuts[outrec->Idx])
outrec = m_PolyOuts[outrec->Idx]; outrec = &m_PolyOuts[outrec->Idx];
return outrec; return outrec;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) const void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
{ {
//get the start and ends of both output polygons ... //get the start and ends of both output polygons ...
OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; OutRec *outRec1 = &m_PolyOuts[e1->OutIdx];
OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; OutRec *outRec2 = &m_PolyOuts[e2->OutIdx];
OutRec *holeStateRec; OutRec *holeStateRec;
if (Param1RightOfParam2(outRec1, outRec2)) if (Param1RightOfParam2(outRec1, outRec2))
@ -1991,16 +1967,16 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) const
OutRec* Clipper::CreateOutRec() OutRec* Clipper::CreateOutRec()
{ {
OutRec* result = new OutRec; m_PolyOuts.emplace_back();
result->IsHole = false; OutRec &result = m_PolyOuts.back();
result->IsOpen = false; result.IsHole = false;
result->FirstLeft = 0; result.IsOpen = false;
result->Pts = 0; result.FirstLeft = 0;
result->BottomPt = 0; result.Pts = 0;
result->PolyNd = 0; result.BottomPt = 0;
m_PolyOuts.push_back(result); result.PolyNd = 0;
result->Idx = (int)m_PolyOuts.size()-1; result.Idx = (int)m_PolyOuts.size()-1;
return result; return &result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -2022,7 +1998,7 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
return newOp; return newOp;
} else } else
{ {
OutRec *outRec = m_PolyOuts[e->OutIdx]; OutRec *outRec = &m_PolyOuts[e->OutIdx];
//OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most'
OutPt* op = outRec->Pts; OutPt* op = outRec->Pts;
@ -2045,7 +2021,7 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
OutPt* Clipper::GetLastOutPt(TEdge *e) OutPt* Clipper::GetLastOutPt(TEdge *e)
{ {
OutRec *outRec = m_PolyOuts[e->OutIdx]; OutRec *outRec = &m_PolyOuts[e->OutIdx];
if (e->Side == esLeft) if (e->Side == esLeft)
return outRec->Pts; return outRec->Pts;
else else
@ -2216,7 +2192,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
{ {
Direction dir; Direction dir;
cInt horzLeft, horzRight; cInt horzLeft, horzRight;
bool IsOpen = (horzEdge->OutIdx >= 0 && m_PolyOuts[horzEdge->OutIdx]->IsOpen); bool IsOpen = (horzEdge->OutIdx >= 0 && m_PolyOuts[horzEdge->OutIdx].IsOpen);
GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
@ -2226,8 +2202,8 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
if (!eLastHorz->NextInLML) if (!eLastHorz->NextInLML)
eMaxPair = GetMaximaPair(eLastHorz); eMaxPair = GetMaximaPair(eLastHorz);
std::vector<cInt>::const_iterator maxIt; cInts::const_iterator maxIt;
std::vector<cInt>::const_reverse_iterator maxRit; cInts::const_reverse_iterator maxRit;
if (!m_Maxima.empty()) if (!m_Maxima.empty())
{ {
//get the first maxima in range (X) ... //get the first maxima in range (X) ...
@ -2600,7 +2576,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
if(IsMaximaEdge) if(IsMaximaEdge)
{ {
if (m_StrictSimple) m_Maxima.push_back(e->Top.x()); if (m_StrictSimple) m_Maxima.emplace_back(e->Top.x());
TEdge* ePrev = e->PrevInAEL; TEdge* ePrev = e->PrevInAEL;
DoMaxima(e); DoMaxima(e);
if( !ePrev ) e = m_ActiveEdges; if( !ePrev ) e = m_ActiveEdges;
@ -2778,12 +2754,12 @@ int PointCount(OutPt *Pts)
void Clipper::BuildResult(Paths &polys) void Clipper::BuildResult(Paths &polys)
{ {
polys.reserve(m_PolyOuts.size()); polys.reserve(m_PolyOuts.size());
for (OutRec* outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
{ {
assert(! outRec->IsOpen); assert(! outRec.IsOpen);
if (!outRec->Pts) continue; if (!outRec.Pts) continue;
Path pg; Path pg;
OutPt* p = outRec->Pts->Prev; OutPt* p = outRec.Pts->Prev;
int cnt = PointCount(p); int cnt = PointCount(p);
if (cnt < 2) continue; if (cnt < 2) continue;
pg.reserve(cnt); pg.reserve(cnt);
@ -2802,31 +2778,31 @@ void Clipper::BuildResult2(PolyTree& polytree)
polytree.Clear(); polytree.Clear();
polytree.AllNodes.reserve(m_PolyOuts.size()); polytree.AllNodes.reserve(m_PolyOuts.size());
//add each output polygon/contour to polytree ... //add each output polygon/contour to polytree ...
for (OutRec* outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
{ {
int cnt = PointCount(outRec->Pts); int cnt = PointCount(outRec.Pts);
if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) if ((outRec.IsOpen && cnt < 2) || (!outRec.IsOpen && cnt < 3))
// Ignore an invalid output loop or a polyline. // Ignore an invalid output loop or a polyline.
continue; continue;
//skip OutRecs that (a) contain outermost polygons or //skip OutRecs that (a) contain outermost polygons or
//(b) already have the correct owner/child linkage ... //(b) already have the correct owner/child linkage ...
if (outRec->FirstLeft && if (outRec.FirstLeft &&
(outRec->IsHole == outRec->FirstLeft->IsHole || ! outRec->FirstLeft->Pts)) { (outRec.IsHole == outRec.FirstLeft->IsHole || ! outRec.FirstLeft->Pts)) {
OutRec* orfl = outRec->FirstLeft; OutRec* orfl = outRec.FirstLeft;
while (orfl && ((orfl->IsHole == outRec->IsHole) || !orfl->Pts)) while (orfl && ((orfl->IsHole == outRec.IsHole) || !orfl->Pts))
orfl = orfl->FirstLeft; orfl = orfl->FirstLeft;
outRec->FirstLeft = orfl; outRec.FirstLeft = orfl;
} }
//nb: polytree takes ownership of all the PolyNodes //nb: polytree takes ownership of all the PolyNodes
polytree.AllNodes.emplace_back(PolyNode()); polytree.AllNodes.emplace_back(PolyNode());
PolyNode* pn = &polytree.AllNodes.back(); PolyNode* pn = &polytree.AllNodes.back();
outRec->PolyNd = pn; outRec.PolyNd = pn;
pn->Parent = 0; pn->Parent = 0;
pn->Index = 0; pn->Index = 0;
pn->Contour.reserve(cnt); pn->Contour.reserve(cnt);
OutPt *op = outRec->Pts->Prev; OutPt *op = outRec.Pts->Prev;
for (int j = 0; j < cnt; j++) for (int j = 0; j < cnt; j++)
{ {
pn->Contour.emplace_back(op->Pt); pn->Contour.emplace_back(op->Pt);
@ -2836,18 +2812,18 @@ void Clipper::BuildResult2(PolyTree& polytree)
//fixup PolyNode links etc ... //fixup PolyNode links etc ...
polytree.Childs.reserve(m_PolyOuts.size()); polytree.Childs.reserve(m_PolyOuts.size());
for (OutRec* outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
{ {
if (!outRec->PolyNd) continue; if (!outRec.PolyNd) continue;
if (outRec->IsOpen) if (outRec.IsOpen)
{ {
outRec->PolyNd->m_IsOpen = true; outRec.PolyNd->m_IsOpen = true;
polytree.AddChild(*outRec->PolyNd); polytree.AddChild(*outRec.PolyNd);
} }
else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) else if (outRec.FirstLeft && outRec.FirstLeft->PolyNd)
outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); outRec.FirstLeft->PolyNd->AddChild(*outRec.PolyNd);
else else
polytree.AddChild(*outRec->PolyNd); polytree.AddChild(*outRec.PolyNd);
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -3193,26 +3169,26 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// This is potentially very expensive! O(n^3)! // This is potentially very expensive! O(n^3)!
void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
{ {
//tests if NewOutRec contains the polygon before reassigning FirstLeft //tests if NewOutRec contains the polygon before reassigning FirstLeft
for (OutRec *outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
{ {
if (!outRec->Pts || !outRec->FirstLeft) continue; if (!outRec.Pts || !outRec.FirstLeft) continue;
OutRec* firstLeft = outRec->FirstLeft; OutRec* firstLeft = outRec.FirstLeft;
// Skip empty polygons. // Skip empty polygons.
while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft; while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft;
if (firstLeft == OldOutRec && Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) if (firstLeft == OldOutRec && Poly2ContainsPoly1(outRec.Pts, NewOutRec->Pts))
outRec->FirstLeft = NewOutRec; outRec.FirstLeft = NewOutRec;
} }
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
{ {
//reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon
for (OutRec *outRec : m_PolyOuts) for (OutRec &outRec : m_PolyOuts)
if (outRec->FirstLeft == OldOutRec) outRec->FirstLeft = NewOutRec; if (outRec.FirstLeft == OldOutRec) outRec.FirstLeft = NewOutRec;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -3253,13 +3229,13 @@ void Clipper::JoinCommonEdges()
if (m_UsingPolyTree) if (m_UsingPolyTree)
for (size_t j = 0; j < m_PolyOuts.size() - 1; j++) for (size_t j = 0; j < m_PolyOuts.size() - 1; j++)
{ {
OutRec* oRec = m_PolyOuts[j]; OutRec &oRec = m_PolyOuts[j];
OutRec* firstLeft = oRec->FirstLeft; OutRec* firstLeft = oRec.FirstLeft;
while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft; while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft;
if (!oRec->Pts || firstLeft != outRec1 || if (!oRec.Pts || firstLeft != outRec1 ||
oRec->IsHole == outRec1->IsHole) continue; oRec.IsHole == outRec1->IsHole) continue;
if (Poly2ContainsPoly1(oRec->Pts, join.OutPt2)) if (Poly2ContainsPoly1(oRec.Pts, join.OutPt2))
oRec->FirstLeft = outRec2; oRec.FirstLeft = outRec2;
} }
if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts))
@ -3373,7 +3349,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
break; break;
} }
newNode->Contour.reserve(highI + 1); newNode->Contour.reserve(highI + 1);
newNode->Contour.push_back(path[0]); newNode->Contour.emplace_back(path[0]);
int j = 0, k = 0; int j = 0, k = 0;
for (int i = 1; i <= highI; i++) { for (int i = 1; i <= highI; i++) {
bool same = false; bool same = false;
@ -3386,7 +3362,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
if (same) if (same)
continue; continue;
j++; j++;
newNode->Contour.push_back(path[i]); newNode->Contour.emplace_back(path[i]);
if (path[i].y() > newNode->Contour[k].y() || if (path[i].y() > newNode->Contour[k].y() ||
(path[i].y() == newNode->Contour[k].y() && (path[i].y() == newNode->Contour[k].y() &&
path[i].x() < newNode->Contour[k].x())) k = j; path[i].x() < newNode->Contour[k].x())) k = j;
@ -3514,7 +3490,7 @@ void ClipperOffset::DoOffset(double delta)
{ {
PolyNode& node = *m_polyNodes.Childs[i]; PolyNode& node = *m_polyNodes.Childs[i];
if (node.m_endtype == etClosedPolygon) if (node.m_endtype == etClosedPolygon)
m_destPolys.push_back(node.Contour); m_destPolys.emplace_back(node.Contour);
} }
return; return;
} }
@ -3556,7 +3532,7 @@ void ClipperOffset::DoOffset(double delta)
double X = 1.0, Y = 0.0; double X = 1.0, Y = 0.0;
for (cInt j = 1; j <= steps; j++) for (cInt j = 1; j <= steps; j++)
{ {
m_destPoly.push_back(IntPoint2d( m_destPoly.emplace_back(IntPoint2d(
Round(m_srcPoly[0].x() + X * delta), Round(m_srcPoly[0].x() + X * delta),
Round(m_srcPoly[0].y() + Y * delta))); Round(m_srcPoly[0].y() + Y * delta)));
double X2 = X; double X2 = X;
@ -3569,7 +3545,7 @@ void ClipperOffset::DoOffset(double delta)
double X = -1.0, Y = -1.0; double X = -1.0, Y = -1.0;
for (int j = 0; j < 4; ++j) for (int j = 0; j < 4; ++j)
{ {
m_destPoly.push_back(IntPoint2d( m_destPoly.emplace_back(IntPoint2d(
Round(m_srcPoly[0].x() + X * delta), Round(m_srcPoly[0].x() + X * delta),
Round(m_srcPoly[0].y() + Y * delta))); Round(m_srcPoly[0].y() + Y * delta)));
if (X < 0) X = 1; if (X < 0) X = 1;
@ -3577,32 +3553,32 @@ void ClipperOffset::DoOffset(double delta)
else X = -1; else X = -1;
} }
} }
m_destPolys.push_back(m_destPoly); m_destPolys.emplace_back(m_destPoly);
continue; continue;
} }
//build m_normals ... //build m_normals ...
m_normals.clear(); m_normals.clear();
m_normals.reserve(len); m_normals.reserve(len);
for (int j = 0; j < len - 1; ++j) for (int j = 0; j < len - 1; ++j)
m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); m_normals.emplace_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1]));
if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon)
m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); m_normals.emplace_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0]));
else else
m_normals.push_back(DoublePoint(m_normals[len - 2])); m_normals.emplace_back(DoublePoint(m_normals[len - 2]));
if (node.m_endtype == etClosedPolygon) if (node.m_endtype == etClosedPolygon)
{ {
int k = len - 1; int k = len - 1;
for (int j = 0; j < len; ++j) for (int j = 0; j < len; ++j)
OffsetPoint(j, k, node.m_jointype); OffsetPoint(j, k, node.m_jointype);
m_destPolys.push_back(m_destPoly); m_destPolys.emplace_back(m_destPoly);
} }
else if (node.m_endtype == etClosedLine) else if (node.m_endtype == etClosedLine)
{ {
int k = len - 1; int k = len - 1;
for (int j = 0; j < len; ++j) for (int j = 0; j < len; ++j)
OffsetPoint(j, k, node.m_jointype); OffsetPoint(j, k, node.m_jointype);
m_destPolys.push_back(m_destPoly); m_destPolys.emplace_back(m_destPoly);
m_destPoly.clear(); m_destPoly.clear();
//re-build m_normals ... //re-build m_normals ...
DoublePoint n = m_normals[len -1]; DoublePoint n = m_normals[len -1];
@ -3612,7 +3588,7 @@ void ClipperOffset::DoOffset(double delta)
k = 0; k = 0;
for (int j = len - 1; j >= 0; j--) for (int j = len - 1; j >= 0; j--)
OffsetPoint(j, k, node.m_jointype); OffsetPoint(j, k, node.m_jointype);
m_destPolys.push_back(m_destPoly); m_destPolys.emplace_back(m_destPoly);
} }
else else
{ {
@ -3625,9 +3601,9 @@ void ClipperOffset::DoOffset(double delta)
{ {
int j = len - 1; int j = len - 1;
pt1 = IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * delta), Round(m_srcPoly[j].y() + m_normals[j].y() * delta)); pt1 = IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * delta), Round(m_srcPoly[j].y() + m_normals[j].y() * delta));
m_destPoly.push_back(pt1); m_destPoly.emplace_back(pt1);
pt1 = IntPoint2d(Round(m_srcPoly[j].x() - m_normals[j].x() * delta), Round(m_srcPoly[j].y() - m_normals[j].y() * delta)); pt1 = IntPoint2d(Round(m_srcPoly[j].x() - m_normals[j].x() * delta), Round(m_srcPoly[j].y() - m_normals[j].y() * delta));
m_destPoly.push_back(pt1); m_destPoly.emplace_back(pt1);
} }
else else
{ {
@ -3652,9 +3628,9 @@ void ClipperOffset::DoOffset(double delta)
if (node.m_endtype == etOpenButt) if (node.m_endtype == etOpenButt)
{ {
pt1 = IntPoint2d(Round(m_srcPoly[0].x() - m_normals[0].x() * delta), Round(m_srcPoly[0].y() - m_normals[0].y() * delta)); pt1 = IntPoint2d(Round(m_srcPoly[0].x() - m_normals[0].x() * delta), Round(m_srcPoly[0].y() - m_normals[0].y() * delta));
m_destPoly.push_back(pt1); m_destPoly.emplace_back(pt1);
pt1 = IntPoint2d(Round(m_srcPoly[0].x() + m_normals[0].x() * delta), Round(m_srcPoly[0].y() + m_normals[0].y() * delta)); pt1 = IntPoint2d(Round(m_srcPoly[0].x() + m_normals[0].x() * delta), Round(m_srcPoly[0].y() + m_normals[0].y() * delta));
m_destPoly.push_back(pt1); m_destPoly.emplace_back(pt1);
} }
else else
{ {
@ -3665,7 +3641,7 @@ void ClipperOffset::DoOffset(double delta)
else else
DoRound(0, 1); DoRound(0, 1);
} }
m_destPolys.push_back(m_destPoly); m_destPolys.emplace_back(m_destPoly);
} }
} }
} }
@ -3681,7 +3657,7 @@ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
double cosA = (m_normals[k].x() * m_normals[j].x() + m_normals[j].y() * m_normals[k].y() ); double cosA = (m_normals[k].x() * m_normals[j].x() + m_normals[j].y() * m_normals[k].y() );
if (cosA > 0) // angle => 0 degrees if (cosA > 0) // angle => 0 degrees
{ {
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta), m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta))); Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
return; return;
} }
@ -3692,10 +3668,10 @@ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
if (m_sinA * m_delta < 0) if (m_sinA * m_delta < 0)
{ {
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta), m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta))); Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
m_destPoly.push_back(m_srcPoly[j]); m_destPoly.emplace_back(m_srcPoly[j]);
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta), m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta))); Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
} }
else else
@ -3719,10 +3695,10 @@ void ClipperOffset::DoSquare(int j, int k)
{ {
double dx = std::tan(std::atan2(m_sinA, double dx = std::tan(std::atan2(m_sinA,
m_normals[k].x() * m_normals[j].x() + m_normals[k].y() * m_normals[j].y()) / 4); m_normals[k].x() * m_normals[j].x() + m_normals[k].y() * m_normals[j].y()) / 4);
m_destPoly.push_back(IntPoint2d( m_destPoly.emplace_back(IntPoint2d(
Round(m_srcPoly[j].x() + m_delta * (m_normals[k].x() - m_normals[k].y() * dx)), Round(m_srcPoly[j].x() + m_delta * (m_normals[k].x() - m_normals[k].y() * dx)),
Round(m_srcPoly[j].y() + m_delta * (m_normals[k].y() + m_normals[k].x() * dx)))); Round(m_srcPoly[j].y() + m_delta * (m_normals[k].y() + m_normals[k].x() * dx))));
m_destPoly.push_back(IntPoint2d( m_destPoly.emplace_back(IntPoint2d(
Round(m_srcPoly[j].x() + m_delta * (m_normals[j].x() + m_normals[j].y() * dx)), Round(m_srcPoly[j].x() + m_delta * (m_normals[j].x() + m_normals[j].y() * dx)),
Round(m_srcPoly[j].y() + m_delta * (m_normals[j].y() - m_normals[j].x() * dx)))); Round(m_srcPoly[j].y() + m_delta * (m_normals[j].y() - m_normals[j].x() * dx))));
} }
@ -3731,7 +3707,7 @@ void ClipperOffset::DoSquare(int j, int k)
void ClipperOffset::DoMiter(int j, int k, double r) void ClipperOffset::DoMiter(int j, int k, double r)
{ {
double q = m_delta / r; double q = m_delta / r;
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + (m_normals[k].x() + m_normals[j].x()) * q), m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + (m_normals[k].x() + m_normals[j].x()) * q),
Round(m_srcPoly[j].y() + (m_normals[k].y() + m_normals[j].y()) * q))); Round(m_srcPoly[j].y() + (m_normals[k].y() + m_normals[j].y()) * q)));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -3745,14 +3721,14 @@ void ClipperOffset::DoRound(int j, int k)
double X = m_normals[k].x(), Y = m_normals[k].y(), X2; double X = m_normals[k].x(), Y = m_normals[k].y(), X2;
for (int i = 0; i < steps; ++i) for (int i = 0; i < steps; ++i)
{ {
m_destPoly.push_back(IntPoint2d( m_destPoly.emplace_back(IntPoint2d(
Round(m_srcPoly[j].x() + X * m_delta), Round(m_srcPoly[j].x() + X * m_delta),
Round(m_srcPoly[j].y() + Y * m_delta))); Round(m_srcPoly[j].y() + Y * m_delta)));
X2 = X; X2 = X;
X = X * m_cos - m_sin * Y; X = X * m_cos - m_sin * Y;
Y = X2 * m_sin + Y * m_cos; Y = X2 * m_sin + Y * m_cos;
} }
m_destPoly.push_back(IntPoint2d( m_destPoly.emplace_back(IntPoint2d(
Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta), Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta))); Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
} }
@ -3771,13 +3747,13 @@ void Clipper::DoSimplePolygons()
size_t i = 0; size_t i = 0;
while (i < m_PolyOuts.size()) while (i < m_PolyOuts.size())
{ {
OutRec* outrec = m_PolyOuts[i++]; OutRec &outrec = m_PolyOuts[i++];
OutPt* op = outrec->Pts; OutPt* op = outrec.Pts;
if (!op || outrec->IsOpen) continue; if (!op || outrec.IsOpen) continue;
do //for each Pt in Polygon until duplicate found do ... do //for each Pt in Polygon until duplicate found do ...
{ {
OutPt* op2 = op->Next; OutPt* op2 = op->Next;
while (op2 != outrec->Pts) while (op2 != outrec.Pts)
{ {
if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op)
{ {
@ -3789,37 +3765,37 @@ void Clipper::DoSimplePolygons()
op2->Prev = op3; op2->Prev = op3;
op3->Next = op2; op3->Next = op2;
outrec->Pts = op; outrec.Pts = op;
OutRec* outrec2 = CreateOutRec(); OutRec* outrec2 = CreateOutRec();
outrec2->Pts = op2; outrec2->Pts = op2;
UpdateOutPtIdxs(*outrec2); UpdateOutPtIdxs(*outrec2);
if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) if (Poly2ContainsPoly1(outrec2->Pts, outrec.Pts))
{ {
//OutRec2 is contained by OutRec1 ... //OutRec2 is contained by OutRec1 ...
outrec2->IsHole = !outrec->IsHole; outrec2->IsHole = !outrec.IsHole;
outrec2->FirstLeft = outrec; outrec2->FirstLeft = &outrec;
// For each m_PolyOuts, replace FirstLeft from outRec2 to outrec. // For each m_PolyOuts, replace FirstLeft from outRec2 to outrec.
if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); if (m_UsingPolyTree) FixupFirstLefts2(outrec2, &outrec);
} }
else else
if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) if (Poly2ContainsPoly1(outrec.Pts, outrec2->Pts))
{ {
//OutRec1 is contained by OutRec2 ... //OutRec1 is contained by OutRec2 ...
outrec2->IsHole = outrec->IsHole; outrec2->IsHole = outrec.IsHole;
outrec->IsHole = !outrec2->IsHole; outrec.IsHole = !outrec2->IsHole;
outrec2->FirstLeft = outrec->FirstLeft; outrec2->FirstLeft = outrec.FirstLeft;
outrec->FirstLeft = outrec2; outrec.FirstLeft = outrec2;
// For each m_PolyOuts, replace FirstLeft from outrec to outrec2. // For each m_PolyOuts, replace FirstLeft from outrec to outrec2.
if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); if (m_UsingPolyTree) FixupFirstLefts2(&outrec, outrec2);
} }
else else
{ {
//the 2 polygons are separate ... //the 2 polygons are separate ...
outrec2->IsHole = outrec->IsHole; outrec2->IsHole = outrec.IsHole;
outrec2->FirstLeft = outrec->FirstLeft; outrec2->FirstLeft = outrec.FirstLeft;
// For each polygon of m_PolyOuts, replace FirstLeft from outrec to outrec2 if the polygon is inside outRec2. // For each polygon of m_PolyOuts, replace FirstLeft from outrec to outrec2 if the polygon is inside outRec2.
//FIXME This is potentially very expensive! O(n^3)! //FIXME This is potentially very expensive! O(n^3)!
if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); if (m_UsingPolyTree) FixupFirstLefts1(&outrec, outrec2);
} }
op2 = op; //ie get ready for the Next iteration op2 = op; //ie get ready for the Next iteration
} }
@ -3827,7 +3803,7 @@ void Clipper::DoSimplePolygons()
} }
op = op->Next; op = op->Next;
} }
while (op != outrec->Pts); while (op != outrec.Pts);
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -3845,10 +3821,10 @@ void ReversePaths(Paths& p)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType) Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType, bool strictly_simple /* = true */)
{ {
Clipper c; Clipper c;
c.StrictlySimple(true); c.StrictlySimple(strictly_simple);
c.AddPath(in_poly, ptSubject, true); c.AddPath(in_poly, ptSubject, true);
Paths out; Paths out;
c.Execute(ctUnion, out, fillType, fillType); c.Execute(ctUnion, out, fillType, fillType);
@ -3941,7 +3917,7 @@ void CleanPolygon(const Path& in_poly, Path& out_poly, double distance)
return; return;
} }
std::vector<OutPt> outPts(size); OutPts outPts(size);
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
{ {
outPts[i].Pt = in_poly[i]; outPts[i].Pt = in_poly[i];
@ -4020,8 +3996,8 @@ void Minkowski(const Path& poly, const Path& path,
Path p; Path p;
p.reserve(polyCnt); p.reserve(polyCnt);
for (size_t j = 0; j < poly.size(); ++j) for (size_t j = 0; j < poly.size(); ++j)
p.push_back(IntPoint2d(path[i].x() + poly[j].x(), path[i].y() + poly[j].y())); p.emplace_back(IntPoint2d(path[i].x() + poly[j].x(), path[i].y() + poly[j].y()));
pp.push_back(p); pp.emplace_back(p);
} }
else else
for (size_t i = 0; i < pathCnt; ++i) for (size_t i = 0; i < pathCnt; ++i)
@ -4029,8 +4005,8 @@ void Minkowski(const Path& poly, const Path& path,
Path p; Path p;
p.reserve(polyCnt); p.reserve(polyCnt);
for (size_t j = 0; j < poly.size(); ++j) for (size_t j = 0; j < poly.size(); ++j)
p.push_back(IntPoint2d(path[i].x() - poly[j].x(), path[i].y() - poly[j].y())); p.emplace_back(IntPoint2d(path[i].x() - poly[j].x(), path[i].y() - poly[j].y()));
pp.push_back(p); pp.emplace_back(p);
} }
solution.clear(); solution.clear();
@ -4040,12 +4016,12 @@ void Minkowski(const Path& poly, const Path& path,
{ {
Path quad; Path quad;
quad.reserve(4); quad.reserve(4);
quad.push_back(pp[i % pathCnt][j % polyCnt]); quad.emplace_back(pp[i % pathCnt][j % polyCnt]);
quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); quad.emplace_back(pp[(i + 1) % pathCnt][j % polyCnt]);
quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); quad.emplace_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]);
quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); quad.emplace_back(pp[i % pathCnt][(j + 1) % polyCnt]);
if (!Orientation(quad)) ReversePath(quad); if (!Orientation(quad)) ReversePath(quad);
solution.push_back(quad); solution.emplace_back(quad);
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -4105,7 +4081,7 @@ void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& path
else if (nodetype == ntOpen) return; else if (nodetype == ntOpen) return;
if (!polynode.Contour.empty() && match) if (!polynode.Contour.empty() && match)
paths.push_back(polynode.Contour); paths.emplace_back(polynode.Contour);
for (int i = 0; i < polynode.ChildCount(); ++i) for (int i = 0; i < polynode.ChildCount(); ++i)
AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths);
} }
@ -4117,7 +4093,7 @@ void AddPolyNodeToPaths(PolyNode&& polynode, NodeType nodetype, Paths& paths)
else if (nodetype == ntOpen) return; else if (nodetype == ntOpen) return;
if (!polynode.Contour.empty() && match) if (!polynode.Contour.empty() && match)
paths.push_back(std::move(polynode.Contour)); paths.emplace_back(std::move(polynode.Contour));
for (int i = 0; i < polynode.ChildCount(); ++i) for (int i = 0; i < polynode.ChildCount(); ++i)
AddPolyNodeToPaths(std::move(*polynode.Childs[i]), nodetype, paths); AddPolyNodeToPaths(std::move(*polynode.Childs[i]), nodetype, paths);
} }
@ -4155,7 +4131,7 @@ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths)
//Open paths are top level only, so ... //Open paths are top level only, so ...
for (int i = 0; i < polytree.ChildCount(); ++i) for (int i = 0; i < polytree.ChildCount(); ++i)
if (polytree.Childs[i]->IsOpen()) if (polytree.Childs[i]->IsOpen())
paths.push_back(polytree.Childs[i]->Contour); paths.emplace_back(polytree.Childs[i]->Contour);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -39,6 +39,8 @@
#include <Eigen/Geometry> #include <Eigen/Geometry>
#include <oneapi/tbb/scalable_allocator.h>
#define CLIPPER_VERSION "6.2.6" #define CLIPPER_VERSION "6.2.6"
//CLIPPERLIB_USE_XYZ: adds a Z member to IntPoint. Adds a minor cost to perfomance. //CLIPPERLIB_USE_XYZ: adds a Z member to IntPoint. Adds a minor cost to perfomance.
@ -50,6 +52,7 @@
//use_deprecated: Enables temporary support for the obsolete functions //use_deprecated: Enables temporary support for the obsolete functions
//#define use_deprecated //#define use_deprecated
#include <array>
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <stdexcept> #include <stdexcept>
@ -112,8 +115,11 @@ using DoublePoint = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
typedef std::vector<IntPoint> Path; template<typename BaseType>
typedef std::vector<Path> Paths; using Allocator = tbb::scalable_allocator<BaseType>;
//using Allocator = std::allocator<BaseType>;
using Path = std::vector<IntPoint, Allocator<IntPoint>>;
using Paths = std::vector<Path, Allocator<Path>>;
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
@ -133,7 +139,7 @@ enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
class PolyNode; class PolyNode;
typedef std::vector< PolyNode* > PolyNodes; typedef std::vector<PolyNode*, Allocator<PolyNode*>> PolyNodes;
class PolyNode class PolyNode
{ {
@ -186,7 +192,7 @@ public:
private: private:
PolyTree(const PolyTree &src) = delete; PolyTree(const PolyTree &src) = delete;
PolyTree& operator=(const PolyTree &src) = delete; PolyTree& operator=(const PolyTree &src) = delete;
std::vector<PolyNode> AllNodes; std::vector<PolyNode, Allocator<PolyNode>> AllNodes;
friend class Clipper; //to access AllNodes friend class Clipper; //to access AllNodes
}; };
@ -194,7 +200,8 @@ double Area(const Path &poly);
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; } inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
int PointInPolygon(const IntPoint &pt, const Path &path); int PointInPolygon(const IntPoint &pt, const Path &path);
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType = pftEvenOdd); // Union with "strictly simple" fix enabled.
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType = pftNonZero, bool strictly_simple = true);
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
void CleanPolygon(Path& poly, double distance = 1.415); void CleanPolygon(Path& poly, double distance = 1.415);
@ -277,7 +284,27 @@ enum EdgeSide { esLeft = 1, esRight = 2};
OutPt *Prev; OutPt *Prev;
}; };
struct OutRec; using OutPts = std::vector<OutPt, Allocator<OutPt>>;
// Output polygon.
struct OutRec {
int Idx;
bool IsHole;
bool IsOpen;
//The 'FirstLeft' field points to another OutRec that contains or is the
//'parent' of OutRec. It is 'first left' because the ActiveEdgeList (AEL) is
//parsed left from the current edge (owning OutRec) until the owner OutRec
//is found. This field simplifies sorting the polygons into a tree structure
//which reflects the parent/child relationships of all polygons.
//This field should be renamed Parent, and will be later.
OutRec* FirstLeft;
// Used only by void Clipper::BuildResult2(PolyTree& polytree)
PolyNode* PolyNd;
// Linked list of output points, dynamically allocated.
OutPt* Pts;
OutPt* BottomPt;
};
struct Join { struct Join {
Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) : Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) :
OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {} OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {}
@ -312,7 +339,7 @@ public:
if (num_paths == 1) if (num_paths == 1)
return AddPath(*paths_provider.begin(), PolyTyp, Closed); return AddPath(*paths_provider.begin(), PolyTyp, Closed);
std::vector<int> num_edges(num_paths, 0); std::vector<int, Allocator<int>> num_edges(num_paths, 0);
int num_edges_total = 0; int num_edges_total = 0;
size_t i = 0; size_t i = 0;
for (const Path &pg : paths_provider) { for (const Path &pg : paths_provider) {
@ -333,7 +360,7 @@ public:
return false; return false;
// Allocate a new edge array. // Allocate a new edge array.
std::vector<TEdge> edges(num_edges_total); std::vector<TEdge, Allocator<TEdge>> edges(num_edges_total);
// Fill in the edge array. // Fill in the edge array.
bool result = false; bool result = false;
TEdge *p_edge = edges.data(); TEdge *p_edge = edges.data();
@ -369,7 +396,7 @@ protected:
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
// Local minima (Y, left edge, right edge) sorted by ascending Y. // Local minima (Y, left edge, right edge) sorted by ascending Y.
std::vector<LocalMinimum> m_MinimaList; std::vector<LocalMinimum, Allocator<LocalMinimum>> m_MinimaList;
#ifdef CLIPPERLIB_INT32 #ifdef CLIPPERLIB_INT32
static constexpr const bool m_UseFullRange = false; static constexpr const bool m_UseFullRange = false;
@ -380,7 +407,8 @@ protected:
#endif // CLIPPERLIB_INT32 #endif // CLIPPERLIB_INT32
// A vector of edges per each input path. // A vector of edges per each input path.
std::vector<std::vector<TEdge>> m_edges; using Edges = std::vector<TEdge, Allocator<TEdge>>;
std::vector<Edges, Allocator<Edges>> m_edges;
// Don't remove intermediate vertices of a collinear sequence of points. // Don't remove intermediate vertices of a collinear sequence of points.
bool m_PreserveCollinear; bool m_PreserveCollinear;
// Is any of the paths inserted by AddPath() or AddPaths() open? // Is any of the paths inserted by AddPath() or AddPaths() open?
@ -424,22 +452,23 @@ protected:
private: private:
// Output polygons. // Output polygons.
std::vector<OutRec*> m_PolyOuts; std::deque<OutRec, Allocator<OutRec>> m_PolyOuts;
// Output points, allocated by a continuous sets of m_OutPtsChunkSize. // Output points, allocated by a continuous sets of m_OutPtsChunkSize.
std::vector<OutPt*> m_OutPts; static constexpr const size_t m_OutPtsChunkSize = 32;
std::deque<std::array<OutPt, m_OutPtsChunkSize>, Allocator<std::array<OutPt, m_OutPtsChunkSize>>> m_OutPts;
// List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk. // List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk.
OutPt *m_OutPtsFree; OutPt *m_OutPtsFree;
size_t m_OutPtsChunkSize;
size_t m_OutPtsChunkLast; size_t m_OutPtsChunkLast;
std::vector<Join> m_Joins; std::vector<Join, Allocator<Join>> m_Joins;
std::vector<Join> m_GhostJoins; std::vector<Join, Allocator<Join>> m_GhostJoins;
std::vector<IntersectNode> m_IntersectList; std::vector<IntersectNode, Allocator<IntersectNode>> m_IntersectList;
ClipType m_ClipType; ClipType m_ClipType;
// A priority queue (a binary heap) of Y coordinates. // A priority queue (a binary heap) of Y coordinates.
std::priority_queue<cInt> m_Scanbeam; using cInts = std::vector<cInt, Allocator<cInt>>;
std::priority_queue<cInt, cInts> m_Scanbeam;
// Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal(). // Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal().
std::vector<cInt> m_Maxima; cInts m_Maxima;
TEdge *m_ActiveEdges; TEdge *m_ActiveEdges;
TEdge *m_SortedEdges; TEdge *m_SortedEdges;
PolyFillType m_ClipFillType; PolyFillType m_ClipFillType;
@ -473,7 +502,7 @@ private:
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutRec* GetOutRec(int idx); OutRec* GetOutRec(int idx);
void AppendPolygon(TEdge *e1, TEdge *e2) const; void AppendPolygon(TEdge *e1, TEdge *e2);
void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
OutRec* CreateOutRec(); OutRec* CreateOutRec();
OutPt* AddOutPt(TEdge *e, const IntPoint &pt); OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
@ -489,7 +518,7 @@ private:
void ProcessEdgesAtTopOfScanbeam(const cInt topY); void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Paths& polys); void BuildResult(Paths& polys);
void BuildResult2(PolyTree& polytree); void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *outrec) const; void SetHoleState(TEdge *e, OutRec *outrec);
bool FixupIntersectionOrder(); bool FixupIntersectionOrder();
void FixupOutPolygon(OutRec &outrec); void FixupOutPolygon(OutRec &outrec);
void FixupOutPolyline(OutRec &outrec); void FixupOutPolyline(OutRec &outrec);
@ -499,8 +528,8 @@ private:
bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint &Pt, bool DiscardLeft); bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint &Pt, bool DiscardLeft);
void JoinCommonEdges(); void JoinCommonEdges();
void DoSimplePolygons(); void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const; void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const; void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
#ifdef CLIPPERLIB_USE_XYZ #ifdef CLIPPERLIB_USE_XYZ
void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
#endif #endif
@ -530,7 +559,7 @@ private:
Paths m_destPolys; Paths m_destPolys;
Path m_srcPoly; Path m_srcPoly;
Path m_destPoly; Path m_destPoly;
std::vector<DoublePoint> m_normals; std::vector<DoublePoint, Allocator<DoublePoint>> m_normals;
double m_delta, m_sinA, m_sin, m_cos; double m_delta, m_sinA, m_sin, m_cos;
double m_miterLim, m_StepsPerRad; double m_miterLim, m_StepsPerRad;
// x: index of the lowest contour in m_polyNodes // x: index of the lowest contour in m_polyNodes
@ -558,10 +587,11 @@ class clipperException : public std::exception
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Union with "strictly simple" fix enabled.
template<typename PathsProvider> template<typename PathsProvider>
inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftEvenOdd) { inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftNonZero, bool strictly_simple = true) {
Clipper c; Clipper c;
c.StrictlySimple(true); c.StrictlySimple(strictly_simple);
c.AddPaths(std::forward<PathsProvider>(in_polys), ptSubject, true); c.AddPaths(std::forward<PathsProvider>(in_polys), ptSubject, true);
Paths out; Paths out;
c.Execute(ctUnion, out, fillType, fillType); c.Execute(ctUnion, out, fillType, fillType);

View File

@ -166,6 +166,8 @@ namespace ImGui
const wchar_t PauseHoverButton = 0x261B; const wchar_t PauseHoverButton = 0x261B;
const wchar_t OpenButton = 0x261C; const wchar_t OpenButton = 0x261C;
const wchar_t OpenHoverButton = 0x261D; const wchar_t OpenHoverButton = 0x261D;
const wchar_t SlaViewOriginal = 0x261E;
const wchar_t SlaViewProcessed = 0x261F;
const wchar_t LegendTravel = 0x2701; const wchar_t LegendTravel = 0x2701;
const wchar_t LegendWipe = 0x2702; const wchar_t LegendWipe = 0x2702;

View File

@ -568,9 +568,9 @@ namespace ImGui
// - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible.
// - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x // - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x
IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const char* current_label = NULL, const char* original_label = NULL);
IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL, const char* current_label = NULL, const char* original_label = NULL);
IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed.
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.

View File

@ -4689,7 +4689,7 @@ bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flag
// Edit colors components (each component in 0.0f..1.0f range). // Edit colors components (each component in 0.0f..1.0f range).
// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. // With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item.
bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags, const char* current_label/* = NULL*/, const char* original_label/* = NULL*/)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -4859,7 +4859,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x, current_label, original_label);
EndPopup(); EndPopup();
} }
} }
@ -4952,7 +4952,7 @@ static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2
// (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.) // (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.)
// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
// FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0) // FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0)
bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col, const char* current_label/*=NULL*/, const char* original_label/*=NULL*/)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -5126,13 +5126,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
if ((flags & ImGuiColorEditFlags_NoLabel)) if ((flags & ImGuiColorEditFlags_NoLabel))
Text("Current"); Text("%s", current_label ? current_label : "Current");
ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip; ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip;
ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)); ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2));
if (ref_col != NULL) if (ref_col != NULL)
{ {
Text("Original"); Text("%s", original_label ? original_label : "Original");
ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]); ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2))) if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)))
{ {

View File

@ -24,5 +24,5 @@ set(LIBNEST2D_SRCFILES
add_library(libnest2d STATIC ${LIBNEST2D_SRCFILES}) add_library(libnest2d STATIC ${LIBNEST2D_SRCFILES})
target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(libnest2d PUBLIC NLopt::nlopt TBB::tbb Boost::boost libslic3r) target_link_libraries(libnest2d PUBLIC NLopt::nlopt TBB::tbb TBB::tbbmalloc Boost::boost libslic3r)
target_compile_definitions(libnest2d PUBLIC LIBNEST2D_THREADING_tbb LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_libslic3r) target_compile_definitions(libnest2d PUBLIC LIBNEST2D_THREADING_tbb LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_libslic3r)

View File

@ -339,15 +339,15 @@ public:
return {distance, nearest_line_index_out, nearest_point_out}; return {distance, nearest_line_index_out, nearest_point_out};
} }
template<bool SIGNED_DISTANCE> Floating distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const template<bool SIGNED_DISTANCE> Floating distance_from_lines(const Vec<2, Scalar> &point) const
{ {
auto [dist, idx, np] = distance_from_lines_extra<SIGNED_DISTANCE>(point); auto [dist, idx, np] = distance_from_lines_extra<SIGNED_DISTANCE>(point);
return dist; return dist;
} }
std::vector<size_t> all_lines_in_radius(const Vec<2, typename LineType::Scalar> &point, Floating radius) std::vector<size_t> all_lines_in_radius(const Vec<2, Scalar> &point, Floating radius)
{ {
return all_lines_in_radius(this->lines, this->tree, point, radius * radius); return AABBTreeLines::all_lines_in_radius(this->lines, this->tree, point.template cast<Floating>(), radius * radius);
} }
template<bool sorted> std::vector<std::pair<Vec<2, Scalar>, size_t>> intersections_with_line(const LineType &line) const template<bool sorted> std::vector<std::pair<Vec<2, Scalar>, size_t>> intersections_with_line(const LineType &line) const

View File

@ -0,0 +1,128 @@
#ifndef SRC_LIBSLIC3R_PATH_SORTING_HPP_
#define SRC_LIBSLIC3R_PATH_SORTING_HPP_
#include "AABBTreeLines.hpp"
#include "BoundingBox.hpp"
#include "Line.hpp"
#include "ankerl/unordered_dense.h"
#include <algorithm>
#include <iterator>
#include <libslic3r/Point.hpp>
#include <libslic3r/Polygon.hpp>
#include <libslic3r/ExPolygon.hpp>
#include <limits>
#include <type_traits>
#include <unordered_set>
namespace Slic3r {
namespace Algorithm {
//Sorts the paths such that all paths between begin and last_seed are printed first, in some order. The rest of the paths is sorted
// such that the paths that are touching some of the already printed are printed first, sorted secondary by the distance to the last point of the last
// printed path.
// begin, end, and last_seed are random access iterators. touch_limit_distance is used to check if the paths are touching - if any part of the path gets this close
// to the second, then they touch.
// convert_to_lines is a lambda that should accept the path as argument and return it as Lines vector, in correct order.
template<typename RandomAccessIterator, typename ToLines>
void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point start, double touch_limit_distance, ToLines convert_to_lines)
{
size_t paths_count = std::distance(begin, end);
if (paths_count <= 1)
return;
auto paths_touch = [touch_limit_distance](const AABBTreeLines::LinesDistancer<Line> &left,
const AABBTreeLines::LinesDistancer<Line> &right) {
for (const Line &l : left.get_lines()) {
if (right.distance_from_lines<false>(l.a) < touch_limit_distance) {
return true;
}
}
if (right.distance_from_lines<false>(left.get_lines().back().b) < touch_limit_distance) {
return true;
}
for (const Line &l : right.get_lines()) {
if (left.distance_from_lines<false>(l.a) < touch_limit_distance) {
return true;
}
}
if (left.distance_from_lines<false>(right.get_lines().back().b) < touch_limit_distance) {
return true;
}
return false;
};
std::vector<AABBTreeLines::LinesDistancer<Line>> distancers(paths_count);
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
distancers[path_idx] = AABBTreeLines::LinesDistancer<Line>{convert_to_lines(*std::next(begin, path_idx))};
}
std::vector<std::unordered_set<size_t>> dependencies(paths_count);
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
for (size_t next_path_idx = path_idx + 1; next_path_idx < paths_count; next_path_idx++) {
if (paths_touch(distancers[path_idx], distancers[next_path_idx])) {
dependencies[next_path_idx].insert(path_idx);
}
}
}
Point current_point = start;
std::vector<std::pair<size_t, bool>> correct_order_and_direction(paths_count);
size_t unsorted_idx = 0;
size_t null_idx = size_t(-1);
size_t next_idx = null_idx;
bool reverse = false;
while (unsorted_idx < paths_count) {
next_idx = null_idx;
double lines_dist = std::numeric_limits<double>::max();
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
if (!dependencies[path_idx].empty())
continue;
double ldist = distancers[path_idx].distance_from_lines<false>(current_point);
if (ldist < lines_dist) {
const auto &lines = distancers[path_idx].get_lines();
double dist_a = (lines.front().a - current_point).cast<double>().squaredNorm();
double dist_b = (lines.back().b - current_point).cast<double>().squaredNorm();
next_idx = path_idx;
reverse = dist_b < dist_a;
lines_dist = ldist;
}
}
// we have valid next_idx, sort it, update dependencies, update current point
correct_order_and_direction[next_idx] = {unsorted_idx, reverse};
unsorted_idx++;
current_point = reverse ? distancers[next_idx].get_lines().front().a : distancers[next_idx].get_lines().back().b;
dependencies[next_idx].insert(null_idx); // prevent it from being selected again
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
dependencies[path_idx].erase(next_idx);
}
}
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
if (correct_order_and_direction[path_idx].second) {
std::next(begin, path_idx)->reverse();
}
}
for (size_t i = 0; i < correct_order_and_direction.size() - 1; i++) {
bool swapped = false;
for (size_t j = 0; j < correct_order_and_direction.size() - i - 1; j++) {
if (correct_order_and_direction[j].first > correct_order_and_direction[j + 1].first) {
std::swap(correct_order_and_direction[j], correct_order_and_direction[j + 1]);
std::iter_swap(std::next(begin, j), std::next(begin, j + 1));
swapped = true;
}
}
if (swapped == false) {
break;
}
}
}
}} // namespace Slic3r::Algorithm
#endif /*SRC_LIBSLIC3R_PATH_SORTING_HPP_*/

View File

@ -5,7 +5,6 @@
#include <stack> #include <stack>
#include <functional> #include <functional>
#include <unordered_set>
#include <sstream> #include <sstream>
#include <queue> #include <queue>
#include <functional> #include <functional>
@ -181,7 +180,7 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type&
} }
else else
{ {
std::vector<Point> discretized = discretize(vd_edge, segments); Points discretized = discretize(vd_edge, segments);
assert(discretized.size() >= 2); assert(discretized.size() >= 2);
if(discretized.size() < 2) if(discretized.size() < 2)
{ {
@ -236,7 +235,7 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type&
} }
} }
std::vector<Point> SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector<Segment>& segments) Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector<Segment>& segments)
{ {
/*Terminology in this function assumes that the edge moves horizontally from /*Terminology in this function assumes that the edge moves horizontally from
left to right. This is not necessarily the case; the edge can go in any left to right. This is not necessarily the case; the edge can go in any
@ -257,7 +256,7 @@ std::vector<Point> SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_
bool point_right = right_cell->contains_point(); bool point_right = right_cell->contains_point();
if ((!point_left && !point_right) || vd_edge.is_secondary()) // Source vert is directly connected to source segment if ((!point_left && !point_right) || vd_edge.is_secondary()) // Source vert is directly connected to source segment
{ {
return std::vector<Point>({ start, end }); return Points({ start, end });
} }
else if (point_left != point_right) //This is a parabolic edge between a point and a line. else if (point_left != point_right) //This is a parabolic edge between a point and a line.
{ {
@ -311,7 +310,7 @@ std::vector<Point> SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_
//Start generating points along the edge. //Start generating points along the edge.
Point a = start; Point a = start;
Point b = end; Point b = end;
std::vector<Point> ret; Points ret;
ret.emplace_back(a); ret.emplace_back(a);
//Introduce an extra edge at the borders of the markings? //Introduce an extra edge at the borders of the markings?
@ -522,9 +521,11 @@ static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph)
return false; return false;
} }
using PointMap = SkeletalTrapezoidation::PointMap;
inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph, inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph,
const double fix_angle, const double fix_angle,
const std::unordered_map<Point, Point, PointHash> &vertex_mapping) const PointMap &vertex_mapping)
{ {
for (STHalfEdgeNode &node : graph.nodes) { for (STHalfEdgeNode &node : graph.nodes) {
// If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction. // If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction.
@ -588,7 +589,7 @@ VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const Geometry::Voronoi
return VoronoiDiagramStatus::NO_ISSUE_DETECTED; return VoronoiDiagramStatus::NO_ISSUE_DETECTED;
} }
inline static std::pair<std::unordered_map<Point, Point, PointHash>, double> try_to_fix_degenerated_voronoi_diagram_by_rotation( inline static std::pair<PointMap, double> try_to_fix_degenerated_voronoi_diagram_by_rotation(
Geometry::VoronoiDiagram &voronoi_diagram, Geometry::VoronoiDiagram &voronoi_diagram,
const Polygons &polys, const Polygons &polys,
Polygons &polys_rotated, Polygons &polys_rotated,
@ -597,7 +598,7 @@ inline static std::pair<std::unordered_map<Point, Point, PointHash>, double> try
{ {
const Polygons polys_rotated_original = polys_rotated; const Polygons polys_rotated_original = polys_rotated;
double fixed_by_angle = fix_angles.front(); double fixed_by_angle = fix_angles.front();
std::unordered_map<Point, Point, PointHash> vertex_mapping; PointMap vertex_mapping;
for (const double &fix_angle : fix_angles) { for (const double &fix_angle : fix_angles) {
vertex_mapping.clear(); vertex_mapping.clear();
@ -685,7 +686,7 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
const std::vector<double> fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11}; const std::vector<double> fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11};
double fixed_by_angle = fix_angles.front(); double fixed_by_angle = fix_angles.front();
std::unordered_map<Point, Point, PointHash> vertex_mapping; PointMap vertex_mapping;
// polys_copy is referenced through items stored in the std::vector segments. // polys_copy is referenced through items stored in the std::vector segments.
Polygons polys_copy = polys; Polygons polys_copy = polys;
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) { if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
@ -813,9 +814,11 @@ process_voronoi_diagram:
edge.from->incident_edge = &edge; edge.from->incident_edge = &edge;
} }
using NodeSet = SkeletalTrapezoidation::NodeSet;
void SkeletalTrapezoidation::separatePointyQuadEndNodes() void SkeletalTrapezoidation::separatePointyQuadEndNodes()
{ {
std::unordered_set<node_t*> visited_nodes; NodeSet visited_nodes;
for (edge_t& edge : graph.edges) for (edge_t& edge : graph.edges)
{ {
if (edge.prev) if (edge.prev)
@ -2285,16 +2288,18 @@ void SkeletalTrapezoidation::addToolpathSegment(const ExtrusionJunction& from, c
void SkeletalTrapezoidation::connectJunctions(ptr_vector_t<LineJunctions>& edge_junctions) void SkeletalTrapezoidation::connectJunctions(ptr_vector_t<LineJunctions>& edge_junctions)
{ {
std::unordered_set<edge_t*> unprocessed_quad_starts(graph.edges.size() * 5 / 2); using EdgeSet = ankerl::unordered_dense::set<edge_t*>;
EdgeSet unprocessed_quad_starts(graph.edges.size() * 5 / 2);
for (edge_t& edge : graph.edges) for (edge_t& edge : graph.edges)
{ {
if (!edge.prev) if (!edge.prev)
{ {
unprocessed_quad_starts.insert(&edge); unprocessed_quad_starts.emplace(&edge);
} }
} }
std::unordered_set<edge_t*> passed_odd_edges; EdgeSet passed_odd_edges;
while (!unprocessed_quad_starts.empty()) while (!unprocessed_quad_starts.empty())
{ {

View File

@ -7,8 +7,10 @@
#include <boost/polygon/voronoi.hpp> #include <boost/polygon/voronoi.hpp>
#include <memory> // smart pointers #include <memory> // smart pointers
#include <unordered_map>
#include <utility> // pair #include <utility> // pair
#include <ankerl/unordered_dense.h>
#include <Arachne/utils/VoronoiUtils.hpp> #include <Arachne/utils/VoronoiUtils.hpp>
#include "utils/HalfEdgeGraph.hpp" #include "utils/HalfEdgeGraph.hpp"
@ -81,6 +83,8 @@ class SkeletalTrapezoidation
public: public:
using Segment = PolygonsSegmentIndex; using Segment = PolygonsSegmentIndex;
using PointMap = ankerl::unordered_dense::map<Point, Point, PointHash>;
using NodeSet = ankerl::unordered_dense::set<node_t*>;
/*! /*!
* Construct a new trapezoidation problem to solve. * Construct a new trapezoidation problem to solve.
@ -164,8 +168,8 @@ protected:
* mapping each voronoi VD edge to the corresponding halfedge HE edge * mapping each voronoi VD edge to the corresponding halfedge HE edge
* In case the result segment is discretized, we map the VD edge to the *last* HE edge * In case the result segment is discretized, we map the VD edge to the *last* HE edge
*/ */
std::unordered_map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge; ankerl::unordered_dense::map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
std::unordered_map<vd_t::vertex_type*, node_t*> vd_node_to_he_node; ankerl::unordered_dense::map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet. node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
/*! /*!
@ -204,7 +208,7 @@ protected:
* \return A number of coordinates along the edge where the edge is broken * \return A number of coordinates along the edge where the edge is broken
* up into discrete pieces. * up into discrete pieces.
*/ */
std::vector<Point> discretize(const vd_t::edge_type& segment, const std::vector<Segment>& segments); Points discretize(const vd_t::edge_type& segment, const std::vector<Segment>& segments);
/*! /*!
* Compute the range of line segments that surround a cell of the skeletal * Compute the range of line segments that surround a cell of the skeletal

View File

@ -2,7 +2,8 @@
//CuraEngine is released under the terms of the AGPLv3 or higher. //CuraEngine is released under the terms of the AGPLv3 or higher.
#include "SkeletalTrapezoidationGraph.hpp" #include "SkeletalTrapezoidationGraph.hpp"
#include <unordered_map>
#include <ankerl/unordered_dense.h>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
@ -180,8 +181,8 @@ bool STHalfEdgeNode::isLocalMaximum(bool strict) const
void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist) void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
{ {
std::unordered_map<edge_t*, std::list<edge_t>::iterator> edge_locator; ankerl::unordered_dense::map<edge_t*, Edges::iterator> edge_locator;
std::unordered_map<node_t*, std::list<node_t>::iterator> node_locator; ankerl::unordered_dense::map<node_t*, Nodes::iterator> node_locator;
for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it) for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it)
{ {
@ -193,7 +194,7 @@ void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
node_locator.emplace(&*node_it, node_it); node_locator.emplace(&*node_it, node_it);
} }
auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, std::list<edge_t>::iterator& current_edge_it, bool& edge_it_is_updated) auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, Edges::iterator& current_edge_it, bool& edge_it_is_updated)
{ {
if (current_edge_it != edges.end() if (current_edge_it != edges.end()
&& to_be_removed == &*current_edge_it) && to_be_removed == &*current_edge_it)

View File

@ -2,7 +2,6 @@
// CuraEngine is released under the terms of the AGPLv3 or higher. // CuraEngine is released under the terms of the AGPLv3 or higher.
#include <algorithm> //For std::partition_copy and std::min_element. #include <algorithm> //For std::partition_copy and std::min_element.
#include <unordered_set>
#include "WallToolPaths.hpp" #include "WallToolPaths.hpp"
@ -233,7 +232,7 @@ std::unique_ptr<LocToLineGrid> cre
void fixSelfIntersections(const coord_t epsilon, Polygons &thiss) void fixSelfIntersections(const coord_t epsilon, Polygons &thiss)
{ {
if (epsilon < 1) { if (epsilon < 1) {
ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss)); ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss), ClipperLib::pftEvenOdd);
return; return;
} }
@ -274,7 +273,7 @@ void fixSelfIntersections(const coord_t epsilon, Polygons &thiss)
} }
} }
ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss)); ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss), ClipperLib::pftEvenOdd);
} }
/*! /*!
@ -341,7 +340,7 @@ void removeSmallAreas(Polygons &thiss, const double min_area_size, const bool re
} }
} else { } else {
// For each polygon, computes the signed area, move small outlines at the end of the vector and keep pointer on small holes // For each polygon, computes the signed area, move small outlines at the end of the vector and keep pointer on small holes
std::vector<Polygon> small_holes; Polygons small_holes;
for (auto it = thiss.begin(); it < new_end;) { for (auto it = thiss.begin(); it < new_end;) {
if (double area = ClipperLib::Area(to_path(*it)); fabs(area) < min_area_size) { if (double area = ClipperLib::Area(to_path(*it)); fabs(area) < min_area_size) {
if (area >= 0) { if (area >= 0) {
@ -767,9 +766,9 @@ bool WallToolPaths::removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpa
* *
* \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one. * \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one.
*/ */
std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> WallToolPaths::getRegionOrder(const std::vector<ExtrusionLine *> &input, const bool outer_to_inner) WallToolPaths::ExtrusionLineSet WallToolPaths::getRegionOrder(const std::vector<ExtrusionLine *> &input, const bool outer_to_inner)
{ {
std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> order_requirements; ExtrusionLineSet order_requirements;
// We build a grid where we map toolpath vertex locations to toolpaths, // We build a grid where we map toolpath vertex locations to toolpaths,
// so that we can easily find which two toolpaths are next to each other, // so that we can easily find which two toolpaths are next to each other,

View File

@ -5,7 +5,8 @@
#define CURAENGINE_WALLTOOLPATHS_H #define CURAENGINE_WALLTOOLPATHS_H
#include <memory> #include <memory>
#include <unordered_set>
#include <ankerl/unordered_dense.h>
#include "BeadingStrategy/BeadingStrategyFactory.hpp" #include "BeadingStrategy/BeadingStrategyFactory.hpp"
#include "utils/ExtrusionLine.hpp" #include "utils/ExtrusionLine.hpp"
@ -73,6 +74,7 @@ public:
*/ */
static bool removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpaths); static bool removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpaths);
using ExtrusionLineSet = ankerl::unordered_dense::set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>>;
/*! /*!
* Get the order constraints of the insets when printing walls per region / hole. * Get the order constraints of the insets when printing walls per region / hole.
* Each returned pair consists of adjacent wall lines where the left has an inset_idx one lower than the right. * Each returned pair consists of adjacent wall lines where the left has an inset_idx one lower than the right.
@ -81,7 +83,7 @@ public:
* *
* \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one. * \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one.
*/ */
static std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> getRegionOrder(const std::vector<ExtrusionLine *> &input, bool outer_to_inner); static ExtrusionLineSet getRegionOrder(const std::vector<ExtrusionLine *> &input, bool outer_to_inner);
protected: protected:
/*! /*!

View File

@ -21,8 +21,10 @@ class HalfEdgeGraph
public: public:
using edge_t = derived_edge_t; using edge_t = derived_edge_t;
using node_t = derived_node_t; using node_t = derived_node_t;
std::list<edge_t> edges; using Edges = std::list<edge_t>;
std::list<node_t> nodes; using Nodes = std::list<node_t>;
Edges edges;
Nodes nodes;
}; };
} // namespace Slic3r::Arachne } // namespace Slic3r::Arachne

View File

@ -7,7 +7,6 @@
#include "SparsePointGrid.hpp" #include "SparsePointGrid.hpp"
#include "PolygonsPointIndex.hpp" #include "PolygonsPointIndex.hpp"
#include "../../Polygon.hpp" #include "../../Polygon.hpp"
#include <unordered_set>
#include <cassert> #include <cassert>
namespace Slic3r::Arachne namespace Slic3r::Arachne

View File

@ -6,7 +6,6 @@
#define UTILS_SPARSE_GRID_H #define UTILS_SPARSE_GRID_H
#include <cassert> #include <cassert>
#include <unordered_map>
#include <vector> #include <vector>
#include <functional> #include <functional>

View File

@ -6,7 +6,6 @@
#define UTILS_SPARSE_LINE_GRID_H #define UTILS_SPARSE_LINE_GRID_H
#include <cassert> #include <cassert>
#include <unordered_map>
#include <vector> #include <vector>
#include <functional> #include <functional>

View File

@ -6,7 +6,6 @@
#define UTILS_SPARSE_POINT_GRID_H #define UTILS_SPARSE_POINT_GRID_H
#include <cassert> #include <cassert>
#include <unordered_map>
#include <vector> #include <vector>
#include "SparseGrid.hpp" #include "SparseGrid.hpp"

View File

@ -7,7 +7,6 @@
#include "../../Point.hpp" #include "../../Point.hpp"
#include <cassert> #include <cassert>
#include <unordered_map>
#include <vector> #include <vector>
#include <functional> #include <functional>

View File

@ -138,9 +138,9 @@ public:
return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[2]), coord_t(p.x() * matrix[1] + p.y() * matrix[3])); return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[2]), coord_t(p.x() * matrix[1] + p.y() * matrix[3]));
} }
}; };
std::vector<Point> VoronoiUtils::discretizeParabola(const Point& p, const Segment& segment, Point s, Point e, coord_t approximate_step_size, float transitioning_angle) Points VoronoiUtils::discretizeParabola(const Point& p, const Segment& segment, Point s, Point e, coord_t approximate_step_size, float transitioning_angle)
{ {
std::vector<Point> discretized; Points discretized;
// x is distance of point projected on the segment ab // x is distance of point projected on the segment ab
// xx is point projected on the segment ab // xx is point projected on the segment ab
const Point a = segment.from(); const Point a = segment.from();

View File

@ -34,7 +34,7 @@ public:
* Discretize a parabola based on (approximate) step size. * Discretize a parabola based on (approximate) step size.
* The \p approximate_step_size is measured parallel to the \p source_segment, not along the parabola. * The \p approximate_step_size is measured parallel to the \p source_segment, not along the parabola.
*/ */
static std::vector<Point> discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle); static Points discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle);
static inline bool is_finite(const VoronoiUtils::vd_t::vertex_type &vertex) static inline bool is_finite(const VoronoiUtils::vd_t::vertex_type &vertex)
{ {

View File

@ -750,7 +750,7 @@ void arrange(ArrangePolygons &items,
d += corr; d += corr;
for (auto &itm : items) for (auto &itm : items)
if (itm.bed_idx == bedidx) if (itm.bed_idx == int(bedidx))
itm.translation += d; itm.translation += d;
} }
} }

View File

@ -1,9 +1,9 @@
#ifndef ARRANGE_HPP #ifndef ARRANGE_HPP
#define ARRANGE_HPP #define ARRANGE_HPP
#include "ExPolygon.hpp"
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <libslic3r/ExPolygon.hpp>
#include <libslic3r/BoundingBox.hpp> #include <libslic3r/BoundingBox.hpp>
namespace Slic3r { namespace Slic3r {

View File

@ -6,23 +6,19 @@
namespace Slic3r { namespace Slic3r {
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points); template BoundingBoxBase<Point, Points>::BoundingBoxBase(const Points &points);
template BoundingBoxBase<Vec2d>::BoundingBoxBase(const std::vector<Vec2d> &points); template BoundingBoxBase<Vec2d>::BoundingBoxBase(const std::vector<Vec2d> &points);
template BoundingBox3Base<Vec3d>::BoundingBox3Base(const std::vector<Vec3d> &points); template BoundingBox3Base<Vec3d>::BoundingBox3Base(const std::vector<Vec3d> &points);
void BoundingBox::polygon(Polygon* polygon) const void BoundingBox::polygon(Polygon* polygon) const
{ {
polygon->points.clear(); polygon->points = {
polygon->points.resize(4); this->min,
polygon->points[0](0) = this->min(0); { this->max.x(), this->min.y() },
polygon->points[0](1) = this->min(1); this->max,
polygon->points[1](0) = this->max(0); { this->min.x(), this->max.y() }
polygon->points[1](1) = this->min(1); };
polygon->points[2](0) = this->max(0);
polygon->points[2](1) = this->max(1);
polygon->points[3](0) = this->min(0);
polygon->points[3](1) = this->max(1);
} }
Polygon BoundingBox::polygon() const Polygon BoundingBox::polygon() const
@ -37,8 +33,8 @@ BoundingBox BoundingBox::rotated(double angle) const
BoundingBox out; BoundingBox out;
out.merge(this->min.rotated(angle)); out.merge(this->min.rotated(angle));
out.merge(this->max.rotated(angle)); out.merge(this->max.rotated(angle));
out.merge(Point(this->min(0), this->max(1)).rotated(angle)); out.merge(Point(this->min.x(), this->max.y()).rotated(angle));
out.merge(Point(this->max(0), this->min(1)).rotated(angle)); out.merge(Point(this->max.x(), this->min.y()).rotated(angle));
return out; return out;
} }
@ -47,23 +43,23 @@ BoundingBox BoundingBox::rotated(double angle, const Point &center) const
BoundingBox out; BoundingBox out;
out.merge(this->min.rotated(angle, center)); out.merge(this->min.rotated(angle, center));
out.merge(this->max.rotated(angle, center)); out.merge(this->max.rotated(angle, center));
out.merge(Point(this->min(0), this->max(1)).rotated(angle, center)); out.merge(Point(this->min.x(), this->max.y()).rotated(angle, center));
out.merge(Point(this->max(0), this->min(1)).rotated(angle, center)); out.merge(Point(this->max.x(), this->min.y()).rotated(angle, center));
return out; return out;
} }
template <class PointClass> void template <class PointType, typename APointsType> void
BoundingBoxBase<PointClass>::scale(double factor) BoundingBoxBase<PointType, APointsType>::scale(double factor)
{ {
this->min *= factor; this->min *= factor;
this->max *= factor; this->max *= factor;
} }
template void BoundingBoxBase<Point>::scale(double factor); template void BoundingBoxBase<Point, Points>::scale(double factor);
template void BoundingBoxBase<Vec2d>::scale(double factor); template void BoundingBoxBase<Vec2d>::scale(double factor);
template void BoundingBoxBase<Vec3d>::scale(double factor); template void BoundingBoxBase<Vec3d>::scale(double factor);
template <class PointClass> void template <class PointType, typename APointsType> void
BoundingBoxBase<PointClass>::merge(const PointClass &point) BoundingBoxBase<PointType, APointsType>::merge(const PointType &point)
{ {
if (this->defined) { if (this->defined) {
this->min = this->min.cwiseMin(point); this->min = this->min.cwiseMin(point);
@ -74,22 +70,22 @@ BoundingBoxBase<PointClass>::merge(const PointClass &point)
this->defined = true; this->defined = true;
} }
} }
template void BoundingBoxBase<Point>::merge(const Point &point); template void BoundingBoxBase<Point, Points>::merge(const Point &point);
template void BoundingBoxBase<Vec2f>::merge(const Vec2f &point); template void BoundingBoxBase<Vec2f>::merge(const Vec2f &point);
template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point); template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point);
template <class PointClass> void template <class PointType, typename APointsType> void
BoundingBoxBase<PointClass>::merge(const std::vector<PointClass> &points) BoundingBoxBase<PointType, APointsType>::merge(const PointsType &points)
{ {
this->merge(BoundingBoxBase(points)); this->merge(BoundingBoxBase(points));
} }
template void BoundingBoxBase<Point>::merge(const Points &points); template void BoundingBoxBase<Point, Points>::merge(const Points &points);
template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points); template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points);
template <class PointClass> void template <class PointType, typename APointsType> void
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb) BoundingBoxBase<PointType, APointsType>::merge(const BoundingBoxBase<PointType, PointsType> &bb)
{ {
assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1)); assert(bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y());
if (bb.defined) { if (bb.defined) {
if (this->defined) { if (this->defined) {
this->min = this->min.cwiseMin(bb.min); this->min = this->min.cwiseMin(bb.min);
@ -101,12 +97,12 @@ BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
} }
} }
} }
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb); template void BoundingBoxBase<Point, Points>::merge(const BoundingBoxBase<Point, Points> &bb);
template void BoundingBoxBase<Vec2f>::merge(const BoundingBoxBase<Vec2f> &bb); template void BoundingBoxBase<Vec2f>::merge(const BoundingBoxBase<Vec2f> &bb);
template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb); template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb);
template <class PointClass> void template <class PointType> void
BoundingBox3Base<PointClass>::merge(const PointClass &point) BoundingBox3Base<PointType>::merge(const PointType &point)
{ {
if (this->defined) { if (this->defined) {
this->min = this->min.cwiseMin(point); this->min = this->min.cwiseMin(point);
@ -120,17 +116,17 @@ BoundingBox3Base<PointClass>::merge(const PointClass &point)
template void BoundingBox3Base<Vec3f>::merge(const Vec3f &point); template void BoundingBox3Base<Vec3f>::merge(const Vec3f &point);
template void BoundingBox3Base<Vec3d>::merge(const Vec3d &point); template void BoundingBox3Base<Vec3d>::merge(const Vec3d &point);
template <class PointClass> void template <class PointType> void
BoundingBox3Base<PointClass>::merge(const std::vector<PointClass> &points) BoundingBox3Base<PointType>::merge(const PointsType &points)
{ {
this->merge(BoundingBox3Base(points)); this->merge(BoundingBox3Base(points));
} }
template void BoundingBox3Base<Vec3d>::merge(const Pointf3s &points); template void BoundingBox3Base<Vec3d>::merge(const Pointf3s &points);
template <class PointClass> void template <class PointType> void
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb) BoundingBox3Base<PointType>::merge(const BoundingBox3Base<PointType> &bb)
{ {
assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2)); assert(bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y() || bb.min.z() >= bb.max.z());
if (bb.defined) { if (bb.defined) {
if (this->defined) { if (this->defined) {
this->min = this->min.cwiseMin(bb.min); this->min = this->min.cwiseMin(bb.min);
@ -144,83 +140,78 @@ BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
} }
template void BoundingBox3Base<Vec3d>::merge(const BoundingBox3Base<Vec3d> &bb); template void BoundingBox3Base<Vec3d>::merge(const BoundingBox3Base<Vec3d> &bb);
template <class PointClass> PointClass template <class PointType, typename APointsType> PointType
BoundingBoxBase<PointClass>::size() const BoundingBoxBase<PointType, APointsType>::size() const
{ {
return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1)); return this->max - this->min;
} }
template Point BoundingBoxBase<Point>::size() const; template Point BoundingBoxBase<Point, Points>::size() const;
template Vec2f BoundingBoxBase<Vec2f>::size() const; template Vec2f BoundingBoxBase<Vec2f>::size() const;
template Vec2d BoundingBoxBase<Vec2d>::size() const; template Vec2d BoundingBoxBase<Vec2d>::size() const;
template <class PointClass> PointClass template <class PointType> PointType
BoundingBox3Base<PointClass>::size() const BoundingBox3Base<PointType>::size() const
{ {
return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1), this->max(2) - this->min(2)); return this->max - this->min;
} }
template Vec3f BoundingBox3Base<Vec3f>::size() const; template Vec3f BoundingBox3Base<Vec3f>::size() const;
template Vec3d BoundingBox3Base<Vec3d>::size() const; template Vec3d BoundingBox3Base<Vec3d>::size() const;
template <class PointClass> double BoundingBoxBase<PointClass>::radius() const template <class PointType, typename APointsType> double BoundingBoxBase<PointType, APointsType>::radius() const
{ {
assert(this->defined); assert(this->defined);
double x = this->max(0) - this->min(0); return 0.5 * (this->max - this->min).template cast<double>().norm();
double y = this->max(1) - this->min(1);
return 0.5 * sqrt(x*x+y*y);
} }
template double BoundingBoxBase<Point>::radius() const; template double BoundingBoxBase<Point, Points>::radius() const;
template double BoundingBoxBase<Vec2d>::radius() const; template double BoundingBoxBase<Vec2d>::radius() const;
template <class PointClass> double BoundingBox3Base<PointClass>::radius() const template <class PointType> double BoundingBox3Base<PointType>::radius() const
{ {
double x = this->max(0) - this->min(0); return 0.5 * (this->max - this->min).template cast<double>().norm();
double y = this->max(1) - this->min(1);
double z = this->max(2) - this->min(2);
return 0.5 * sqrt(x*x+y*y+z*z);
} }
template double BoundingBox3Base<Vec3d>::radius() const; template double BoundingBox3Base<Vec3d>::radius() const;
template <class PointClass> void template <class PointType, typename APointsType> void
BoundingBoxBase<PointClass>::offset(coordf_t delta) BoundingBoxBase<PointType, APointsType>::offset(coordf_t delta)
{ {
PointClass v(delta, delta); PointType v(delta, delta);
this->min -= v; this->min -= v;
this->max += v; this->max += v;
} }
template void BoundingBoxBase<Point>::offset(coordf_t delta); template void BoundingBoxBase<Point, Points>::offset(coordf_t delta);
template void BoundingBoxBase<Vec2d>::offset(coordf_t delta); template void BoundingBoxBase<Vec2d>::offset(coordf_t delta);
template <class PointClass> void template <class PointType> void
BoundingBox3Base<PointClass>::offset(coordf_t delta) BoundingBox3Base<PointType>::offset(coordf_t delta)
{ {
PointClass v(delta, delta, delta); PointType v(delta, delta, delta);
this->min -= v; this->min -= v;
this->max += v; this->max += v;
} }
template void BoundingBox3Base<Vec3d>::offset(coordf_t delta); template void BoundingBox3Base<Vec3d>::offset(coordf_t delta);
template <class PointClass> PointClass template <class PointType, typename APointsType> PointType
BoundingBoxBase<PointClass>::center() const BoundingBoxBase<PointType, APointsType>::center() const
{ {
return (this->min + this->max) / 2; return (this->min + this->max) / 2;
} }
template Point BoundingBoxBase<Point>::center() const; template Point BoundingBoxBase<Point, Points>::center() const;
template Vec2f BoundingBoxBase<Vec2f>::center() const; template Vec2f BoundingBoxBase<Vec2f>::center() const;
template Vec2d BoundingBoxBase<Vec2d>::center() const; template Vec2d BoundingBoxBase<Vec2d>::center() const;
template <class PointClass> PointClass template <class PointType> PointType
BoundingBox3Base<PointClass>::center() const BoundingBox3Base<PointType>::center() const
{ {
return (this->min + this->max) / 2; return (this->min + this->max) / 2;
} }
template Vec3f BoundingBox3Base<Vec3f>::center() const; template Vec3f BoundingBox3Base<Vec3f>::center() const;
template Vec3d BoundingBox3Base<Vec3d>::center() const; template Vec3d BoundingBox3Base<Vec3d>::center() const;
template <class PointClass> coordf_t template <class PointType> coordf_t
BoundingBox3Base<PointClass>::max_size() const BoundingBox3Base<PointType>::max_size() const
{ {
PointClass s = size(); PointType s = size();
return std::max(s(0), std::max(s(1), s(2))); return std::max(s.x(), std::max(s.y(), s.z()));
} }
template coordf_t BoundingBox3Base<Vec3f>::max_size() const; template coordf_t BoundingBox3Base<Vec3f>::max_size() const;
template coordf_t BoundingBox3Base<Vec3d>::max_size() const; template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
@ -228,8 +219,8 @@ template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
void BoundingBox::align_to_grid(const coord_t cell_size) void BoundingBox::align_to_grid(const coord_t cell_size)
{ {
if (this->defined) { if (this->defined) {
min(0) = Slic3r::align_to_grid(min(0), cell_size); min.x() = Slic3r::align_to_grid(min.x(), cell_size);
min(1) = Slic3r::align_to_grid(min(1), cell_size); min.y() = Slic3r::align_to_grid(min.y(), cell_size);
} }
} }
@ -238,14 +229,14 @@ BoundingBoxf3 BoundingBoxf3::transformed(const Transform3d& matrix) const
typedef Eigen::Matrix<double, 3, 8, Eigen::DontAlign> Vertices; typedef Eigen::Matrix<double, 3, 8, Eigen::DontAlign> Vertices;
Vertices src_vertices; Vertices src_vertices;
src_vertices(0, 0) = min(0); src_vertices(1, 0) = min(1); src_vertices(2, 0) = min(2); src_vertices(0, 0) = min.x(); src_vertices(1, 0) = min.y(); src_vertices(2, 0) = min.z();
src_vertices(0, 1) = max(0); src_vertices(1, 1) = min(1); src_vertices(2, 1) = min(2); src_vertices(0, 1) = max.x(); src_vertices(1, 1) = min.y(); src_vertices(2, 1) = min.z();
src_vertices(0, 2) = max(0); src_vertices(1, 2) = max(1); src_vertices(2, 2) = min(2); src_vertices(0, 2) = max.x(); src_vertices(1, 2) = max.y(); src_vertices(2, 2) = min.z();
src_vertices(0, 3) = min(0); src_vertices(1, 3) = max(1); src_vertices(2, 3) = min(2); src_vertices(0, 3) = min.x(); src_vertices(1, 3) = max.y(); src_vertices(2, 3) = min.z();
src_vertices(0, 4) = min(0); src_vertices(1, 4) = min(1); src_vertices(2, 4) = max(2); src_vertices(0, 4) = min.x(); src_vertices(1, 4) = min.y(); src_vertices(2, 4) = max.z();
src_vertices(0, 5) = max(0); src_vertices(1, 5) = min(1); src_vertices(2, 5) = max(2); src_vertices(0, 5) = max.x(); src_vertices(1, 5) = min.y(); src_vertices(2, 5) = max.z();
src_vertices(0, 6) = max(0); src_vertices(1, 6) = max(1); src_vertices(2, 6) = max(2); src_vertices(0, 6) = max.x(); src_vertices(1, 6) = max.y(); src_vertices(2, 6) = max.z();
src_vertices(0, 7) = min(0); src_vertices(1, 7) = max(1); src_vertices(2, 7) = max(2); src_vertices(0, 7) = min.x(); src_vertices(1, 7) = max.y(); src_vertices(2, 7) = max.z();
Vertices dst_vertices = matrix * src_vertices.colwise().homogeneous(); Vertices dst_vertices = matrix * src_vertices.colwise().homogeneous();

View File

@ -8,53 +8,54 @@
namespace Slic3r { namespace Slic3r {
template <class PointClass> template <typename PointType, typename APointsType = std::vector<PointType>>
class BoundingBoxBase class BoundingBoxBase
{ {
public: public:
PointClass min; using PointsType = APointsType;
PointClass max; PointType min;
PointType max;
bool defined; bool defined;
BoundingBoxBase() : min(PointClass::Zero()), max(PointClass::Zero()), defined(false) {} BoundingBoxBase() : min(PointType::Zero()), max(PointType::Zero()), defined(false) {}
BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) : BoundingBoxBase(const PointType &pmin, const PointType &pmax) :
min(pmin), max(pmax), defined(pmin.x() < pmax.x() && pmin.y() < pmax.y()) {} min(pmin), max(pmax), defined(pmin.x() < pmax.x() && pmin.y() < pmax.y()) {}
BoundingBoxBase(const PointClass &p1, const PointClass &p2, const PointClass &p3) : BoundingBoxBase(const PointType &p1, const PointType &p2, const PointType &p3) :
min(p1), max(p1), defined(false) { merge(p2); merge(p3); } min(p1), max(p1), defined(false) { merge(p2); merge(p3); }
template<class It, class = IteratorOnly<It>> template<class It, class = IteratorOnly<It>>
BoundingBoxBase(It from, It to) BoundingBoxBase(It from, It to)
{ construct(*this, from, to); } { construct(*this, from, to); }
BoundingBoxBase(const std::vector<PointClass> &points) BoundingBoxBase(const PointsType &points)
: BoundingBoxBase(points.begin(), points.end()) : BoundingBoxBase(points.begin(), points.end())
{} {}
void reset() { this->defined = false; this->min = PointClass::Zero(); this->max = PointClass::Zero(); } void reset() { this->defined = false; this->min = PointType::Zero(); this->max = PointType::Zero(); }
void merge(const PointClass &point); void merge(const PointType &point);
void merge(const std::vector<PointClass> &points); void merge(const PointsType &points);
void merge(const BoundingBoxBase<PointClass> &bb); void merge(const BoundingBoxBase<PointType, PointsType> &bb);
void scale(double factor); void scale(double factor);
PointClass size() const; PointType size() const;
double radius() const; double radius() const;
void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; } void translate(coordf_t x, coordf_t y) { assert(this->defined); PointType v(x, y); this->min += v; this->max += v; }
void translate(const PointClass &v) { this->min += v; this->max += v; } void translate(const PointType &v) { this->min += v; this->max += v; }
void offset(coordf_t delta); void offset(coordf_t delta);
BoundingBoxBase<PointClass> inflated(coordf_t delta) const throw() { BoundingBoxBase<PointClass> out(*this); out.offset(delta); return out; } BoundingBoxBase<PointType, PointsType> inflated(coordf_t delta) const throw() { BoundingBoxBase<PointType, PointsType> out(*this); out.offset(delta); return out; }
PointClass center() const; PointType center() const;
bool contains(const PointClass &point) const { bool contains(const PointType &point) const {
return point.x() >= this->min.x() && point.x() <= this->max.x() return point.x() >= this->min.x() && point.x() <= this->max.x()
&& point.y() >= this->min.y() && point.y() <= this->max.y(); && point.y() >= this->min.y() && point.y() <= this->max.y();
} }
bool contains(const BoundingBoxBase<PointClass> &other) const { bool contains(const BoundingBoxBase<PointType, PointsType> &other) const {
return contains(other.min) && contains(other.max); return contains(other.min) && contains(other.max);
} }
bool overlap(const BoundingBoxBase<PointClass> &other) const { bool overlap(const BoundingBoxBase<PointType, PointsType> &other) const {
return ! (this->max.x() < other.min.x() || this->min.x() > other.max.x() || return ! (this->max.x() < other.min.x() || this->min.x() > other.max.x() ||
this->max.y() < other.min.y() || this->min.y() > other.max.y()); this->max.y() < other.min.y() || this->min.y() > other.max.y());
} }
bool operator==(const BoundingBoxBase<PointClass> &rhs) { return this->min == rhs.min && this->max == rhs.max; } bool operator==(const BoundingBoxBase<PointType, PointsType> &rhs) { return this->min == rhs.min && this->max == rhs.max; }
bool operator!=(const BoundingBoxBase<PointClass> &rhs) { return ! (*this == rhs); } bool operator!=(const BoundingBoxBase<PointType, PointsType> &rhs) { return ! (*this == rhs); }
private: private:
// to access construct() // to access construct()
@ -69,10 +70,10 @@ private:
{ {
if (from != to) { if (from != to) {
auto it = from; auto it = from;
out.min = it->template cast<typename PointClass::Scalar>(); out.min = it->template cast<typename PointType::Scalar>();
out.max = out.min; out.max = out.min;
for (++ it; it != to; ++ it) { for (++ it; it != to; ++ it) {
auto vec = it->template cast<typename PointClass::Scalar>(); auto vec = it->template cast<typename PointType::Scalar>();
out.min = out.min.cwiseMin(vec); out.min = out.min.cwiseMin(vec);
out.max = out.max.cwiseMax(vec); out.max = out.max.cwiseMax(vec);
} }
@ -81,16 +82,18 @@ private:
} }
}; };
template <class PointClass> template <class PointType>
class BoundingBox3Base : public BoundingBoxBase<PointClass> class BoundingBox3Base : public BoundingBoxBase<PointType, std::vector<PointType>>
{ {
public: public:
BoundingBox3Base() : BoundingBoxBase<PointClass>() {} using PointsType = std::vector<PointType>;
BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) :
BoundingBoxBase<PointClass>(pmin, pmax) BoundingBox3Base() : BoundingBoxBase<PointType>() {}
{ if (pmin.z() >= pmax.z()) BoundingBoxBase<PointClass>::defined = false; } BoundingBox3Base(const PointType &pmin, const PointType &pmax) :
BoundingBox3Base(const PointClass &p1, const PointClass &p2, const PointClass &p3) : BoundingBoxBase<PointType>(pmin, pmax)
BoundingBoxBase<PointClass>(p1, p1) { merge(p2); merge(p3); } { if (pmin.z() >= pmax.z()) BoundingBoxBase<PointType>::defined = false; }
BoundingBox3Base(const PointType &p1, const PointType &p2, const PointType &p3) :
BoundingBoxBase<PointType>(p1, p1) { merge(p2); merge(p3); }
template<class It, class = IteratorOnly<It> > BoundingBox3Base(It from, It to) template<class It, class = IteratorOnly<It> > BoundingBox3Base(It from, It to)
{ {
@ -98,67 +101,67 @@ public:
throw Slic3r::InvalidArgument("Empty point set supplied to BoundingBox3Base constructor"); throw Slic3r::InvalidArgument("Empty point set supplied to BoundingBox3Base constructor");
auto it = from; auto it = from;
this->min = it->template cast<typename PointClass::Scalar>(); this->min = it->template cast<typename PointType::Scalar>();
this->max = this->min; this->max = this->min;
for (++ it; it != to; ++ it) { for (++ it; it != to; ++ it) {
auto vec = it->template cast<typename PointClass::Scalar>(); auto vec = it->template cast<typename PointType::Scalar>();
this->min = this->min.cwiseMin(vec); this->min = this->min.cwiseMin(vec);
this->max = this->max.cwiseMax(vec); this->max = this->max.cwiseMax(vec);
} }
this->defined = (this->min.x() < this->max.x()) && (this->min.y() < this->max.y()) && (this->min.z() < this->max.z()); this->defined = (this->min.x() < this->max.x()) && (this->min.y() < this->max.y()) && (this->min.z() < this->max.z());
} }
BoundingBox3Base(const std::vector<PointClass> &points) BoundingBox3Base(const PointsType &points)
: BoundingBox3Base(points.begin(), points.end()) : BoundingBox3Base(points.begin(), points.end())
{} {}
void merge(const PointClass &point); void merge(const PointType &point);
void merge(const std::vector<PointClass> &points); void merge(const PointsType &points);
void merge(const BoundingBox3Base<PointClass> &bb); void merge(const BoundingBox3Base<PointType> &bb);
PointClass size() const; PointType size() const;
double radius() const; double radius() const;
void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; } void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointType v(x, y, z); this->min += v; this->max += v; }
void translate(const Vec3d &v) { this->min += v; this->max += v; } void translate(const Vec3d &v) { this->min += v; this->max += v; }
void offset(coordf_t delta); void offset(coordf_t delta);
BoundingBox3Base<PointClass> inflated(coordf_t delta) const throw() { BoundingBox3Base<PointClass> out(*this); out.offset(delta); return out; } BoundingBox3Base<PointType> inflated(coordf_t delta) const throw() { BoundingBox3Base<PointType> out(*this); out.offset(delta); return out; }
PointClass center() const; PointType center() const;
coordf_t max_size() const; coordf_t max_size() const;
bool contains(const PointClass &point) const { bool contains(const PointType &point) const {
return BoundingBoxBase<PointClass>::contains(point) && point.z() >= this->min.z() && point.z() <= this->max.z(); return BoundingBoxBase<PointType>::contains(point) && point.z() >= this->min.z() && point.z() <= this->max.z();
} }
bool contains(const BoundingBox3Base<PointClass>& other) const { bool contains(const BoundingBox3Base<PointType>& other) const {
return contains(other.min) && contains(other.max); return contains(other.min) && contains(other.max);
} }
// Intersects without boundaries. // Intersects without boundaries.
bool intersects(const BoundingBox3Base<PointClass>& other) const { bool intersects(const BoundingBox3Base<PointType>& other) const {
return this->min.x() < other.max.x() && this->max.x() > other.min.x() && this->min.y() < other.max.y() && this->max.y() > other.min.y() && return this->min.x() < other.max.x() && this->max.x() > other.min.x() && this->min.y() < other.max.y() && this->max.y() > other.min.y() &&
this->min.z() < other.max.z() && this->max.z() > other.min.z(); this->min.z() < other.max.z() && this->max.z() > other.min.z();
} }
}; };
// Will prevent warnings caused by non existing definition of template in hpp // Will prevent warnings caused by non existing definition of template in hpp
extern template void BoundingBoxBase<Point>::scale(double factor); extern template void BoundingBoxBase<Point, Points>::scale(double factor);
extern template void BoundingBoxBase<Vec2d>::scale(double factor); extern template void BoundingBoxBase<Vec2d>::scale(double factor);
extern template void BoundingBoxBase<Vec3d>::scale(double factor); extern template void BoundingBoxBase<Vec3d>::scale(double factor);
extern template void BoundingBoxBase<Point>::offset(coordf_t delta); extern template void BoundingBoxBase<Point, Points>::offset(coordf_t delta);
extern template void BoundingBoxBase<Vec2d>::offset(coordf_t delta); extern template void BoundingBoxBase<Vec2d>::offset(coordf_t delta);
extern template void BoundingBoxBase<Point>::merge(const Point &point); extern template void BoundingBoxBase<Point, Points>::merge(const Point &point);
extern template void BoundingBoxBase<Vec2f>::merge(const Vec2f &point); extern template void BoundingBoxBase<Vec2f>::merge(const Vec2f &point);
extern template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point); extern template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point);
extern template void BoundingBoxBase<Point>::merge(const Points &points); extern template void BoundingBoxBase<Point, Points>::merge(const Points &points);
extern template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points); extern template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points);
extern template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb); extern template void BoundingBoxBase<Point, Points>::merge(const BoundingBoxBase<Point, Points> &bb);
extern template void BoundingBoxBase<Vec2f>::merge(const BoundingBoxBase<Vec2f> &bb); extern template void BoundingBoxBase<Vec2f>::merge(const BoundingBoxBase<Vec2f> &bb);
extern template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb); extern template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb);
extern template Point BoundingBoxBase<Point>::size() const; extern template Point BoundingBoxBase<Point, Points>::size() const;
extern template Vec2f BoundingBoxBase<Vec2f>::size() const; extern template Vec2f BoundingBoxBase<Vec2f>::size() const;
extern template Vec2d BoundingBoxBase<Vec2d>::size() const; extern template Vec2d BoundingBoxBase<Vec2d>::size() const;
extern template double BoundingBoxBase<Point>::radius() const; extern template double BoundingBoxBase<Point, Points>::radius() const;
extern template double BoundingBoxBase<Vec2d>::radius() const; extern template double BoundingBoxBase<Vec2d>::radius() const;
extern template Point BoundingBoxBase<Point>::center() const; extern template Point BoundingBoxBase<Point, Points>::center() const;
extern template Vec2f BoundingBoxBase<Vec2f>::center() const; extern template Vec2f BoundingBoxBase<Vec2f>::center() const;
extern template Vec2d BoundingBoxBase<Vec2d>::center() const; extern template Vec2d BoundingBoxBase<Vec2d>::center() const;
extern template void BoundingBox3Base<Vec3f>::merge(const Vec3f &point); extern template void BoundingBox3Base<Vec3f>::merge(const Vec3f &point);
@ -174,7 +177,7 @@ extern template Vec3d BoundingBox3Base<Vec3d>::center() const;
extern template coordf_t BoundingBox3Base<Vec3f>::max_size() const; extern template coordf_t BoundingBox3Base<Vec3f>::max_size() const;
extern template coordf_t BoundingBox3Base<Vec3d>::max_size() const; extern template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
class BoundingBox : public BoundingBoxBase<Point> class BoundingBox : public BoundingBoxBase<Point, Points>
{ {
public: public:
void polygon(Polygon* polygon) const; void polygon(Polygon* polygon) const;
@ -187,9 +190,9 @@ public:
// to encompass the original bounding box. // to encompass the original bounding box.
void align_to_grid(const coord_t cell_size); void align_to_grid(const coord_t cell_size);
BoundingBox() : BoundingBoxBase<Point>() {} BoundingBox() : BoundingBoxBase<Point, Points>() {}
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {} BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point, Points>(pmin, pmax) {}
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {} BoundingBox(const Points &points) : BoundingBoxBase<Point, Points>(points) {}
BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; } BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; }
@ -222,14 +225,14 @@ public:
BoundingBoxf3 transformed(const Transform3d& matrix) const; BoundingBoxf3 transformed(const Transform3d& matrix) const;
}; };
template<typename VT> template<typename PointType, typename PointsType>
inline bool empty(const BoundingBoxBase<VT> &bb) inline bool empty(const BoundingBoxBase<PointType, PointsType> &bb)
{ {
return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y(); return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y();
} }
template<typename VT> template<typename PointType>
inline bool empty(const BoundingBox3Base<VT> &bb) inline bool empty(const BoundingBox3Base<PointType> &bb)
{ {
return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y() || bb.min.z() >= bb.max.z(); return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y() || bb.min.z() >= bb.max.z();
} }

View File

@ -22,8 +22,9 @@ set(SLIC3R_SOURCES
AABBTreeLines.hpp AABBTreeLines.hpp
AABBMesh.hpp AABBMesh.hpp
AABBMesh.cpp AABBMesh.cpp
Algorithm/RegionExpansion.cpp Algorithm/PathSorting.hpp
Algorithm/RegionExpansion.hpp Algorithm/RegionExpansion.hpp
Algorithm/RegionExpansion.cpp
AnyPtr.hpp AnyPtr.hpp
BoundingBox.cpp BoundingBox.cpp
BoundingBox.hpp BoundingBox.hpp
@ -133,10 +134,14 @@ set(SLIC3R_SOURCES
Format/AnycubicSLA.cpp Format/AnycubicSLA.cpp
Format/STEP.hpp Format/STEP.hpp
Format/STEP.cpp Format/STEP.cpp
Format/SLAArchiveFormatRegistry.hpp
Format/SLAArchiveFormatRegistry.cpp
GCode/ThumbnailData.cpp GCode/ThumbnailData.cpp
GCode/ThumbnailData.hpp GCode/ThumbnailData.hpp
GCode/Thumbnails.cpp GCode/Thumbnails.cpp
GCode/Thumbnails.hpp GCode/Thumbnails.hpp
GCode/ConflictChecker.cpp
GCode/ConflictChecker.hpp
GCode/CoolingBuffer.cpp GCode/CoolingBuffer.cpp
GCode/CoolingBuffer.hpp GCode/CoolingBuffer.hpp
GCode/FindReplace.cpp GCode/FindReplace.cpp
@ -278,10 +283,25 @@ set(SLIC3R_SOURCES
SlicingAdaptive.hpp SlicingAdaptive.hpp
Subdivide.cpp Subdivide.cpp
Subdivide.hpp Subdivide.hpp
Support/SupportCommon.cpp
Support/SupportCommon.hpp
Support/SupportDebug.cpp
Support/SupportDebug.hpp
Support/SupportLayer.hpp
Support/SupportMaterial.cpp
Support/SupportMaterial.hpp
Support/SupportParameters.cpp
Support/SupportParameters.hpp
Support/OrganicSupport.cpp
Support/OrganicSupport.hpp
Support/TreeSupport.cpp
Support/TreeSupport.hpp
Support/TreeSupportCommon.cpp
Support/TreeSupportCommon.hpp
Support/TreeModelVolumes.cpp
Support/TreeModelVolumes.hpp
SupportSpotsGenerator.cpp SupportSpotsGenerator.cpp
SupportSpotsGenerator.hpp SupportSpotsGenerator.hpp
SupportMaterial.cpp
SupportMaterial.hpp
Surface.cpp Surface.cpp
Surface.hpp Surface.hpp
SurfaceCollection.cpp SurfaceCollection.cpp
@ -293,10 +313,6 @@ set(SLIC3R_SOURCES
Tesselate.cpp Tesselate.cpp
Tesselate.hpp Tesselate.hpp
TextConfiguration.hpp TextConfiguration.hpp
TreeSupport.cpp
TreeSupport.hpp
TreeModelVolumes.cpp
TreeModelVolumes.hpp
TriangleMesh.cpp TriangleMesh.cpp
TriangleMesh.hpp TriangleMesh.hpp
TriangleMeshSlicer.cpp TriangleMeshSlicer.cpp
@ -487,6 +503,7 @@ target_link_libraries(libslic3r
qhull qhull
semver semver
TBB::tbb TBB::tbb
TBB::tbbmalloc
libslic3r_cgal libslic3r_cgal
${CMAKE_DL_LIBS} ${CMAKE_DL_LIBS}
PNG::PNG PNG::PNG

View File

@ -3,6 +3,20 @@
#include "ShortestPath.hpp" #include "ShortestPath.hpp"
#include "Utils.hpp" #include "Utils.hpp"
// #define CLIPPER_UTILS_TIMING
#ifdef CLIPPER_UTILS_TIMING
// time limit for one ClipperLib operation (union / diff / offset), in ms
#define CLIPPER_UTILS_TIME_LIMIT_DEFAULT 50
#include <boost/current_function.hpp>
#include "Timer.hpp"
#define CLIPPER_UTILS_TIME_LIMIT_SECONDS(limit) Timing::TimeLimitAlarm time_limit_alarm(uint64_t(limit) * 1000000000l, BOOST_CURRENT_FUNCTION)
#define CLIPPER_UTILS_TIME_LIMIT_MILLIS(limit) Timing::TimeLimitAlarm time_limit_alarm(uint64_t(limit) * 1000000l, BOOST_CURRENT_FUNCTION)
#else
#define CLIPPER_UTILS_TIME_LIMIT_SECONDS(limit) do {} while(false)
#define CLIPPER_UTILS_TIME_LIMIT_MILLIS(limit) do {} while(false)
#endif // CLIPPER_UTILS_TIMING
// #define CLIPPER_UTILS_DEBUG // #define CLIPPER_UTILS_DEBUG
#ifdef CLIPPER_UTILS_DEBUG #ifdef CLIPPER_UTILS_DEBUG
@ -51,9 +65,11 @@ namespace ClipperUtils {
// Clip source polygon to be used as a clipping polygon with a bouding box around the source (to be clipped) polygon. // Clip source polygon to be used as a clipping polygon with a bouding box around the source (to be clipped) polygon.
// Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one // Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
// with a set of polygons covering the whole layer below. // with a set of polygons covering the whole layer below.
template<typename PointType> template<typename PointsType>
inline void clip_clipper_polygon_with_subject_bbox_templ(const std::vector<PointType> &src, const BoundingBox &bbox, std::vector<PointType> &out) inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out)
{ {
using PointType = typename PointsType::value_type;
out.clear(); out.clear();
const size_t cnt = src.size(); const size_t cnt = src.size();
if (cnt < 3) if (cnt < 3)
@ -108,10 +124,10 @@ namespace ClipperUtils {
void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out) void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out)
{ clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); } { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
template<typename PointType> template<typename PointsType>
[[nodiscard]] std::vector<PointType> clip_clipper_polygon_with_subject_bbox_templ(const std::vector<PointType> &src, const BoundingBox &bbox) [[nodiscard]] PointsType clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox)
{ {
std::vector<PointType> out; PointsType out;
clip_clipper_polygon_with_subject_bbox(src, bbox, out); clip_clipper_polygon_with_subject_bbox(src, bbox, out);
return out; return out;
} }
@ -258,6 +274,8 @@ bool has_duplicate_points(const ClipperLib::PolyTree &polytree)
template<typename PathsProvider, ClipperLib::EndType endType = ClipperLib::etClosedPolygon> template<typename PathsProvider, ClipperLib::EndType endType = ClipperLib::etClosedPolygon>
static ClipperLib::Paths raw_offset(PathsProvider &&paths, float offset, ClipperLib::JoinType joinType, double miterLimit) static ClipperLib::Paths raw_offset(PathsProvider &&paths, float offset, ClipperLib::JoinType joinType, double miterLimit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::ClipperOffset co; ClipperLib::ClipperOffset co;
ClipperLib::Paths out; ClipperLib::Paths out;
out.reserve(paths.size()); out.reserve(paths.size());
@ -299,6 +317,8 @@ TResult clipper_do(
TClip && clip, TClip && clip,
const ClipperLib::PolyFillType fillType) const ClipperLib::PolyFillType fillType)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
clipper.AddPaths(std::forward<TSubj>(subject), ClipperLib::ptSubject, true); clipper.AddPaths(std::forward<TSubj>(subject), ClipperLib::ptSubject, true);
clipper.AddPaths(std::forward<TClip>(clip), ClipperLib::ptClip, true); clipper.AddPaths(std::forward<TClip>(clip), ClipperLib::ptClip, true);
@ -328,6 +348,8 @@ TResult clipper_union(
// fillType pftNonZero and pftPositive "should" produce the same result for "normalized with implicit union" set of polygons // fillType pftNonZero and pftPositive "should" produce the same result for "normalized with implicit union" set of polygons
const ClipperLib::PolyFillType fillType = ClipperLib::pftNonZero) const ClipperLib::PolyFillType fillType = ClipperLib::pftNonZero)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
clipper.AddPaths(std::forward<TSubj>(subject), ClipperLib::ptSubject, true); clipper.AddPaths(std::forward<TSubj>(subject), ClipperLib::ptSubject, true);
TResult retval; TResult retval;
@ -366,6 +388,8 @@ template<> void remove_outermost_polygon<ClipperLib::PolyTree>(ClipperLib::PolyT
template<class TResult, typename PathsProvider> template<class TResult, typename PathsProvider>
static TResult shrink_paths(PathsProvider &&paths, float offset, ClipperLib::JoinType joinType, double miterLimit) static TResult shrink_paths(PathsProvider &&paths, float offset, ClipperLib::JoinType joinType, double miterLimit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
assert(offset > 0); assert(offset > 0);
TResult out; TResult out;
if (auto raw = raw_offset(std::forward<PathsProvider>(paths), - offset, joinType, miterLimit); ! raw.empty()) { if (auto raw = raw_offset(std::forward<PathsProvider>(paths), - offset, joinType, miterLimit); ! raw.empty()) {
@ -405,6 +429,8 @@ Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, C
// returns number of expolygons collected (0 or 1). // returns number of expolygons collected (0 or 1).
static int offset_expolygon_inner(const Slic3r::ExPolygon &expoly, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out) static int offset_expolygon_inner(const Slic3r::ExPolygon &expoly, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
// 1) Offset the outer contour. // 1) Offset the outer contour.
ClipperLib::Paths contours; ClipperLib::Paths contours;
{ {
@ -613,6 +639,8 @@ inline ClipperLib::PolyTree clipper_do_polytree(
PathProvider2 &&clip, PathProvider2 &&clip,
const ClipperLib::PolyFillType fillType) const ClipperLib::PolyFillType fillType)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
// Perform the operation with the output to input_subject. // Perform the operation with the output to input_subject.
// This pass does not generate a PolyTree, which is a very expensive operation with the current Clipper library // This pass does not generate a PolyTree, which is a very expensive operation with the current Clipper library
// if there are overapping edges. // if there are overapping edges.
@ -657,6 +685,8 @@ Slic3r::Polygons diff(const Slic3r::Surfaces &subject, const Slic3r::Polygons &c
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); } { return _clipper(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset) Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::SinglePathProvider(clip.points), do_safety_offset); } { return _clipper(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::SinglePathProvider(clip.points), do_safety_offset); }
Slic3r::Polygons intersection_clipped(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
{ return intersection(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset); }
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset) Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonProvider(clip), do_safety_offset); } { return _clipper(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonProvider(clip), do_safety_offset); }
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset) Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
@ -751,6 +781,8 @@ Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
template<typename PathsProvider1, typename PathsProvider2> template<typename PathsProvider1, typename PathsProvider2>
Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip) Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
clipper.AddPaths(std::forward<PathsProvider1>(subject), ClipperLib::ptSubject, false); clipper.AddPaths(std::forward<PathsProvider1>(subject), ClipperLib::ptSubject, false);
clipper.AddPaths(std::forward<PathsProvider2>(clip), ClipperLib::ptClip, true); clipper.AddPaths(std::forward<PathsProvider2>(clip), ClipperLib::ptClip, true);
@ -934,18 +966,17 @@ Polygons union_pt_chained_outside_in(const Polygons &subject)
return retval; return retval;
} }
Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear) Polygons simplify_polygons(const Polygons &subject)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths output; ClipperLib::Paths output;
if (preserve_collinear) {
ClipperLib::Clipper c; ClipperLib::Clipper c;
c.PreserveCollinear(true); // c.PreserveCollinear(true);
//FIXME StrictlySimple is very expensive! Is it needed?
c.StrictlySimple(true); c.StrictlySimple(true);
c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true); c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true);
c.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero); c.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
} else {
output = ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(subject), ClipperLib::pftNonZero);
}
// convert into Slic3r polygons // convert into Slic3r polygons
return to_polygons(std::move(output)); return to_polygons(std::move(output));
@ -953,12 +984,12 @@ Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear)
ExPolygons simplify_polygons_ex(const Polygons &subject, bool preserve_collinear) ExPolygons simplify_polygons_ex(const Polygons &subject, bool preserve_collinear)
{ {
if (! preserve_collinear) CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
return union_ex(simplify_polygons(subject, false));
ClipperLib::PolyTree polytree; ClipperLib::PolyTree polytree;
ClipperLib::Clipper c; ClipperLib::Clipper c;
c.PreserveCollinear(true); // c.PreserveCollinear(true);
//FIXME StrictlySimple is very expensive! Is it needed?
c.StrictlySimple(true); c.StrictlySimple(true);
c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true); c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true);
c.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); c.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
@ -969,6 +1000,8 @@ ExPolygons simplify_polygons_ex(const Polygons &subject, bool preserve_collinear
Polygons top_level_islands(const Slic3r::Polygons &polygons) Polygons top_level_islands(const Slic3r::Polygons &polygons)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
// init Clipper // init Clipper
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
clipper.Clear(); clipper.Clear();
@ -992,6 +1025,8 @@ ClipperLib::Paths fix_after_outer_offset(
ClipperLib::PolyFillType filltype, // = ClipperLib::pftPositive ClipperLib::PolyFillType filltype, // = ClipperLib::pftPositive
bool reverse_result) // = false bool reverse_result) // = false
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths solution; ClipperLib::Paths solution;
if (! input.empty()) { if (! input.empty()) {
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
@ -1010,6 +1045,8 @@ ClipperLib::Paths fix_after_inner_offset(
ClipperLib::PolyFillType filltype, // = ClipperLib::pftNegative ClipperLib::PolyFillType filltype, // = ClipperLib::pftNegative
bool reverse_result) // = true bool reverse_result) // = true
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths solution; ClipperLib::Paths solution;
if (! input.empty()) { if (! input.empty()) {
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
@ -1030,6 +1067,8 @@ ClipperLib::Paths fix_after_inner_offset(
ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit) ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
assert(contour.size() == deltas.size()); assert(contour.size() == deltas.size());
#ifndef NDEBUG #ifndef NDEBUG
@ -1170,6 +1209,8 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v
static void variable_offset_inner_raw(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit, ClipperLib::Paths &contours, ClipperLib::Paths &holes) static void variable_offset_inner_raw(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit, ClipperLib::Paths &contours, ClipperLib::Paths &holes)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
#ifndef NDEBUG #ifndef NDEBUG
// Verify that the deltas are all non positive. // Verify that the deltas are all non positive.
for (const std::vector<float> &ds : deltas) for (const std::vector<float> &ds : deltas)
@ -1203,6 +1244,8 @@ static void variable_offset_inner_raw(const ExPolygon &expoly, const std::vector
Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit) Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths contours, holes; ClipperLib::Paths contours, holes;
variable_offset_inner_raw(expoly, deltas, miter_limit, contours, holes); variable_offset_inner_raw(expoly, deltas, miter_limit, contours, holes);
@ -1225,6 +1268,8 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::v
ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit) ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths contours, holes; ClipperLib::Paths contours, holes;
variable_offset_inner_raw(expoly, deltas, miter_limit, contours, holes); variable_offset_inner_raw(expoly, deltas, miter_limit, contours, holes);
@ -1251,6 +1296,8 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
static void variable_offset_outer_raw(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit, ClipperLib::Paths &contours, ClipperLib::Paths &holes) static void variable_offset_outer_raw(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit, ClipperLib::Paths &contours, ClipperLib::Paths &holes)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
#ifndef NDEBUG #ifndef NDEBUG
// Verify that the deltas are all non positive. // Verify that the deltas are all non positive.
for (const std::vector<float> &ds : deltas) for (const std::vector<float> &ds : deltas)
@ -1286,6 +1333,8 @@ static void variable_offset_outer_raw(const ExPolygon &expoly, const std::vector
Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit) Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths contours, holes; ClipperLib::Paths contours, holes;
variable_offset_outer_raw(expoly, deltas, miter_limit, contours, holes); variable_offset_outer_raw(expoly, deltas, miter_limit, contours, holes);
@ -1307,6 +1356,8 @@ Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::v
ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit) ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
{ {
CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT);
ClipperLib::Paths contours, holes; ClipperLib::Paths contours, holes;
variable_offset_outer_raw(expoly, deltas, miter_limit, contours, holes); variable_offset_outer_raw(expoly, deltas, miter_limit, contours, holes);

View File

@ -133,21 +133,21 @@ namespace ClipperUtils {
const std::vector<PathType> &m_paths; const std::vector<PathType> &m_paths;
}; };
template<typename MultiPointType> template<typename MultiPointsType>
class MultiPointsProvider { class MultiPointsProvider {
public: public:
MultiPointsProvider(const std::vector<MultiPointType> &multipoints) : m_multipoints(multipoints) {} MultiPointsProvider(const MultiPointsType &multipoints) : m_multipoints(multipoints) {}
struct iterator : public PathsProviderIteratorBase { struct iterator : public PathsProviderIteratorBase {
public: public:
explicit iterator(typename std::vector<MultiPointType>::const_iterator it) : m_it(it) {} explicit iterator(typename MultiPointsType::const_iterator it) : m_it(it) {}
const Points& operator*() const { return m_it->points; } const Points& operator*() const { return m_it->points; }
bool operator==(const iterator &rhs) const { return m_it == rhs.m_it; } bool operator==(const iterator &rhs) const { return m_it == rhs.m_it; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); } bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
const Points& operator++(int) { return (m_it ++)->points; } const Points& operator++(int) { return (m_it ++)->points; }
iterator& operator++() { ++ m_it; return *this; } iterator& operator++() { ++ m_it; return *this; }
private: private:
typename std::vector<MultiPointType>::const_iterator m_it; typename MultiPointsType::const_iterator m_it;
}; };
iterator cbegin() const { return iterator(m_multipoints.begin()); } iterator cbegin() const { return iterator(m_multipoints.begin()); }
@ -157,11 +157,11 @@ namespace ClipperUtils {
size_t size() const { return m_multipoints.size(); } size_t size() const { return m_multipoints.size(); }
private: private:
const std::vector<MultiPointType> &m_multipoints; const MultiPointsType &m_multipoints;
}; };
using PolygonsProvider = MultiPointsProvider<Polygon>; using PolygonsProvider = MultiPointsProvider<Polygons>;
using PolylinesProvider = MultiPointsProvider<Polyline>; using PolylinesProvider = MultiPointsProvider<Polylines>;
struct ExPolygonProvider { struct ExPolygonProvider {
ExPolygonProvider(const ExPolygon &expoly) : m_expoly(expoly) {} ExPolygonProvider(const ExPolygon &expoly) : m_expoly(expoly) {}
@ -453,6 +453,9 @@ inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygon
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
// Optimized version clipping the "clipping" polygon using clip_clipper_polygon_with_subject_bbox().
// To be used with complex clipping polygons, where majority of the clipping polygons are outside of the source polygon.
Slic3r::Polygons intersection_clipped(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
@ -596,8 +599,8 @@ void traverse_pt(const ClipperLib::PolyNodes &nodes, ExOrJustPolygons *retval)
/* OTHER */ /* OTHER */
Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject, bool preserve_collinear = false); Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject);
Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject, bool preserve_collinear = false); Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject);
Polygons top_level_islands(const Slic3r::Polygons &polygons); Polygons top_level_islands(const Slic3r::Polygons &polygons);

View File

@ -40,7 +40,7 @@ inline ZPath to_zpath(const Points &path, coord_t z)
// Convert multiple paths to paths with a given Z coordinate. // Convert multiple paths to paths with a given Z coordinate.
// If Open, then duplicate the first point of each path at its end. // If Open, then duplicate the first point of each path at its end.
template<bool Open = false> template<bool Open = false>
inline ZPaths to_zpaths(const std::vector<Points> &paths, coord_t z) inline ZPaths to_zpaths(const VecOfPoints &paths, coord_t z)
{ {
ZPaths out; ZPaths out;
out.reserve(paths.size()); out.reserve(paths.size());
@ -86,16 +86,16 @@ inline Points from_zpath(const ZPoints &path)
// Convert multiple paths to paths with a given Z coordinate. // Convert multiple paths to paths with a given Z coordinate.
// If Open, then duplicate the first point of each path at its end. // If Open, then duplicate the first point of each path at its end.
template<bool Open = false> template<bool Open = false>
inline void from_zpaths(const ZPaths &paths, std::vector<Points> &out) inline void from_zpaths(const ZPaths &paths, VecOfPoints &out)
{ {
out.reserve(out.size() + paths.size()); out.reserve(out.size() + paths.size());
for (const ZPoints &path : paths) for (const ZPoints &path : paths)
out.emplace_back(from_zpath<Open>(path)); out.emplace_back(from_zpath<Open>(path));
} }
template<bool Open = false> template<bool Open = false>
inline std::vector<Points> from_zpaths(const ZPaths &paths) inline VecOfPoints from_zpaths(const ZPaths &paths)
{ {
std::vector<Points> out; VecOfPoints out;
from_zpaths(paths, out); from_zpaths(paths, out);
return out; return out;
} }

View File

@ -1991,7 +1991,7 @@ public:
void set_enum_labels(GUIType gui_type, const std::initializer_list<std::string_view> il) { void set_enum_labels(GUIType gui_type, const std::initializer_list<std::string_view> il) {
this->enum_def_new(); this->enum_def_new();
assert(gui_type == GUIType::i_enum_open || gui_type == GUIType::f_enum_open || gui_type == ConfigOptionDef::GUIType::select_open); assert(gui_type == GUIType::i_enum_open || gui_type == GUIType::f_enum_open || gui_type == ConfigOptionDef::GUIType::select_close);
this->gui_type = gui_type; this->gui_type = gui_type;
enum_def->set_labels(il); enum_def->set_labels(il);
} }

View File

@ -17,7 +17,7 @@ public:
Contour() = default; Contour() = default;
Contour(const Slic3r::Point *begin, const Slic3r::Point *end, bool open) : m_begin(begin), m_end(end), m_open(open) {} Contour(const Slic3r::Point *begin, const Slic3r::Point *end, bool open) : m_begin(begin), m_end(end), m_open(open) {}
Contour(const Slic3r::Point *data, size_t size, bool open) : Contour(data, data + size, open) {} Contour(const Slic3r::Point *data, size_t size, bool open) : Contour(data, data + size, open) {}
Contour(const std::vector<Slic3r::Point> &pts, bool open) : Contour(pts.data(), pts.size(), open) {} Contour(const Points &pts, bool open) : Contour(pts.data(), pts.size(), open) {}
const Slic3r::Point *begin() const { return m_begin; } const Slic3r::Point *begin() const { return m_begin; }
const Slic3r::Point *end() const { return m_end; } const Slic3r::Point *end() const { return m_end; }

View File

@ -184,14 +184,14 @@ Polygons ExPolygon::simplify_p(double tolerance) const
{ {
Polygon p = this->contour; Polygon p = this->contour;
p.points.push_back(p.points.front()); p.points.push_back(p.points.front());
p.points = MultiPoint::_douglas_peucker(p.points, tolerance); p.points = MultiPoint::douglas_peucker(p.points, tolerance);
p.points.pop_back(); p.points.pop_back();
pp.emplace_back(std::move(p)); pp.emplace_back(std::move(p));
} }
// holes // holes
for (Polygon p : this->holes) { for (Polygon p : this->holes) {
p.points.push_back(p.points.front()); p.points.push_back(p.points.front());
p.points = MultiPoint::_douglas_peucker(p.points, tolerance); p.points = MultiPoint::douglas_peucker(p.points, tolerance);
p.points.pop_back(); p.points.pop_back();
pp.emplace_back(std::move(p)); pp.emplace_back(std::move(p));
} }
@ -397,7 +397,7 @@ bool has_duplicate_points(const ExPolygon &expoly)
size_t cnt = expoly.contour.points.size(); size_t cnt = expoly.contour.points.size();
for (const Polygon &hole : expoly.holes) for (const Polygon &hole : expoly.holes)
cnt += hole.points.size(); cnt += hole.points.size();
std::vector<Point> allpts; Points allpts;
allpts.reserve(cnt); allpts.reserve(cnt);
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end()); allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
for (const Polygon &hole : expoly.holes) for (const Polygon &hole : expoly.holes)
@ -420,7 +420,7 @@ bool has_duplicate_points(const ExPolygons &expolys)
// Check globally. // Check globally.
#if 0 #if 0
// Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster. // Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster.
std::vector<Point> allpts; Points allpts;
allpts.reserve(count_points(expolys)); allpts.reserve(count_points(expolys));
for (const ExPolygon &expoly : expolys) { for (const ExPolygon &expoly : expolys) {
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end()); allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());

View File

@ -20,7 +20,7 @@
namespace Slic3r { namespace Slic3r {
static constexpr const float NarrowInfillAreaThresholdMM = 3.f; //static constexpr const float NarrowInfillAreaThresholdMM = 3.f;
struct SurfaceFillParams struct SurfaceFillParams
{ {
@ -306,43 +306,11 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
} }
} }
// Detect narrow internal solid infill area and use ipEnsuring pattern instead. // Use ipEnsuring pattern for all internal Solids.
{ {
std::vector<char> narrow_expolygons; for (size_t surface_fill_id = 0; surface_fill_id < surface_fills.size(); ++surface_fill_id)
static constexpr const auto narrow_pattern = ipEnsuring;
for (size_t surface_fill_id = 0, num_old_fills = surface_fills.size(); surface_fill_id < num_old_fills; ++ surface_fill_id)
if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) { if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) {
size_t num_expolygons = fill.expolygons.size(); fill.params.pattern = ipEnsuring;
narrow_expolygons.clear();
narrow_expolygons.reserve(num_expolygons);
// Detect narrow expolygons.
int num_narrow = 0;
for (const ExPolygon &ex : fill.expolygons) {
bool narrow = offset_ex(ex, -scaled<float>(NarrowInfillAreaThresholdMM)).empty();
num_narrow += int(narrow);
narrow_expolygons.emplace_back(narrow);
}
if (num_narrow == num_expolygons) {
// All expolygons are narrow, change the fill pattern.
fill.params.pattern = narrow_pattern;
} else if (num_narrow > 0) {
// Some expolygons are narrow, split the fills.
params = fill.params;
params.pattern = narrow_pattern;
surface_fills.emplace_back(params);
SurfaceFill &old_fill = surface_fills[surface_fill_id];
SurfaceFill &new_fill = surface_fills.back();
new_fill.region_id = old_fill.region_id;
new_fill.surface.surface_type = stInternalSolid;
new_fill.surface.thickness = old_fill.surface.thickness;
new_fill.expolygons.reserve(num_narrow);
for (size_t i = 0; i < narrow_expolygons.size(); ++ i)
if (narrow_expolygons[i])
new_fill.expolygons.emplace_back(std::move(old_fill.expolygons[i]));
old_fill.expolygons.erase(std::remove_if(old_fill.expolygons.begin(), old_fill.expolygons.end(),
[&narrow_expolygons, ex_first = old_fill.expolygons.data()](const ExPolygon& ex) { return narrow_expolygons[&ex - ex_first]; }),
old_fill.expolygons.end());
}
} }
} }

View File

@ -147,9 +147,9 @@ protected:
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; } virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
public: public:
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const double spacing, const FillParams &params); static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const double spacing, const FillParams &params);
static void connect_infill(Polylines &&infill_ordered, const Polygons &boundary, const BoundingBox& bbox, Polylines &polylines_out, const double spacing, const FillParams &params); static void connect_infill(Polylines &&infill_ordered, const Polygons &boundary, const BoundingBox& bbox, Polylines &polylines_out, const double spacing, const FillParams &params);
static void connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary, const BoundingBox &bbox, Polylines &polylines_out, double spacing, const FillParams &params); static void connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary, const BoundingBox &bbox, Polylines &polylines_out, double spacing, const FillParams &params);

View File

@ -2,28 +2,303 @@
#include "../ShortestPath.hpp" #include "../ShortestPath.hpp"
#include "../Arachne/WallToolPaths.hpp" #include "../Arachne/WallToolPaths.hpp"
#include "AABBTreeLines.hpp"
#include "Algorithm/PathSorting.hpp"
#include "BoundingBox.hpp"
#include "ExPolygon.hpp"
#include "FillEnsuring.hpp" #include "FillEnsuring.hpp"
#include "KDTreeIndirect.hpp"
#include "Line.hpp"
#include "Point.hpp"
#include "Polygon.hpp"
#include "Polyline.hpp"
#include "SVG.hpp"
#include "libslic3r.h"
#include <algorithm>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <functional>
#include <string>
#include <type_traits>
#include <unordered_set>
#include <vector>
namespace Slic3r { namespace Slic3r {
ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const FillParams &params) ThickPolylines make_fill_polylines(
const Fill *fill, const Surface *surface, const FillParams &params, bool stop_vibrations, bool fill_gaps, bool connect_extrusions)
{ {
assert(params.use_arachne); assert(fill->print_config != nullptr && fill->print_object_config != nullptr);
assert(this->print_config != nullptr && this->print_object_config != nullptr && this->print_region_config != nullptr);
const coord_t scaled_spacing = scaled<coord_t>(this->spacing); auto rotate_thick_polylines = [](ThickPolylines &tpolylines, double cos_angle, double sin_angle) {
for (ThickPolyline &tp : tpolylines) {
for (auto &p : tp.points) {
double px = double(p.x());
double py = double(p.y());
p.x() = coord_t(round(cos_angle * px - sin_angle * py));
p.y() = coord_t(round(cos_angle * py + sin_angle * px));
}
}
};
// Perform offset. auto segments_overlap = [](coord_t alow, coord_t ahigh, coord_t blow, coord_t bhigh) {
Slic3r::ExPolygons expp = this->overlap != 0. ? offset_ex(surface->expolygon, scaled<float>(this->overlap)) : ExPolygons{surface->expolygon}; return (alow >= blow && alow <= bhigh) || (ahigh >= blow && ahigh <= bhigh) || (blow >= alow && blow <= ahigh) ||
// Create the infills for each of the regions. (bhigh >= alow && bhigh <= ahigh);
ThickPolylines thick_polylines_out; };
for (ExPolygon &ex_poly : expp) {
Point bbox_size = ex_poly.contour.bounding_box().size(); const coord_t scaled_spacing = scaled<coord_t>(fill->spacing);
coord_t loops_count = std::max(bbox_size.x(), bbox_size.y()) / scaled_spacing + 1; double distance_limit_reconnection = 2.0 * double(scaled_spacing);
double squared_distance_limit_reconnection = distance_limit_reconnection * distance_limit_reconnection;
Polygons filled_area = to_polygons(surface->expolygon);
std::pair<float, Point> rotate_vector = fill->_infill_direction(surface);
double aligning_angle = -rotate_vector.first + PI;
polygons_rotate(filled_area, aligning_angle);
BoundingBox bb = get_extents(filled_area);
Polygons inner_area = stop_vibrations ? intersection(filled_area, opening(filled_area, 2 * scaled_spacing, 3 * scaled_spacing)) :
filled_area;
inner_area = shrink(inner_area, scaled_spacing * 0.5 - scaled<double>(fill->overlap));
AABBTreeLines::LinesDistancer<Line> area_walls{to_lines(inner_area)};
const size_t n_vlines = (bb.max.x() - bb.min.x() + scaled_spacing - 1) / scaled_spacing;
std::vector<Line> vertical_lines(n_vlines);
coord_t y_min = bb.min.y();
coord_t y_max = bb.max.y();
for (size_t i = 0; i < n_vlines; i++) {
coord_t x = bb.min.x() + i * double(scaled_spacing);
vertical_lines[i].a = Point{x, y_min};
vertical_lines[i].b = Point{x, y_max};
}
if (vertical_lines.size() > 0) {
vertical_lines.push_back(vertical_lines.back());
vertical_lines.back().a = Point{coord_t(bb.min.x() + n_vlines * double(scaled_spacing) + scaled_spacing * 0.5), y_min};
vertical_lines.back().b = Point{vertical_lines.back().a.x(), y_max};
}
std::vector<std::vector<Line>> polygon_sections(n_vlines);
for (size_t i = 0; i < n_vlines; i++) {
const auto intersections = area_walls.intersections_with_line<true>(vertical_lines[i]);
for (int intersection_idx = 0; intersection_idx < int(intersections.size()) - 1; intersection_idx++) {
const auto &a = intersections[intersection_idx];
const auto &b = intersections[intersection_idx + 1];
if (area_walls.outside((a.first + b.first) / 2) < 0) {
if (std::abs(a.first.y() - b.first.y()) > scaled_spacing) {
polygon_sections[i].emplace_back(a.first, b.first);
}
}
}
}
if (stop_vibrations) {
struct Node
{
int section_idx;
int line_idx;
int skips_taken = 0;
bool neighbours_explored = false;
std::vector<std::pair<int, int>> neighbours{};
};
coord_t length_filter = scale_(4);
size_t skips_allowed = 2;
size_t min_removal_conut = 5;
for (int section_idx = 0; section_idx < int(polygon_sections.size()); ++ section_idx) {
for (int line_idx = 0; line_idx < int(polygon_sections[section_idx].size()); ++ line_idx) {
if (const Line &line = polygon_sections[section_idx][line_idx]; line.a != line.b && line.length() < length_filter) {
std::set<std::pair<int, int>> to_remove{{section_idx, line_idx}};
std::vector<Node> to_visit{{section_idx, line_idx}};
bool initial_touches_long_lines = false;
if (section_idx > 0) {
for (int prev_line_idx = 0; prev_line_idx < int(polygon_sections[section_idx - 1].size()); ++ prev_line_idx) {
if (const Line &nl = polygon_sections[section_idx - 1][prev_line_idx];
nl.a != nl.b && segments_overlap(line.a.y(), line.b.y(), nl.a.y(), nl.b.y())) {
initial_touches_long_lines = true;
}
}
}
while (!to_visit.empty()) {
Node curr = to_visit.back();
const Line &curr_l = polygon_sections[curr.section_idx][curr.line_idx];
if (curr.neighbours_explored) {
bool is_valid_for_removal = (curr_l.length() < length_filter) &&
((int(to_remove.size()) - curr.skips_taken > int(min_removal_conut)) ||
(curr.neighbours.empty() && !initial_touches_long_lines));
if (!is_valid_for_removal) {
for (const auto &n : curr.neighbours) {
if (to_remove.find(n) != to_remove.end()) {
is_valid_for_removal = true;
break;
}
}
}
if (!is_valid_for_removal) {
to_remove.erase({curr.section_idx, curr.line_idx});
}
to_visit.pop_back();
} else {
to_visit.back().neighbours_explored = true;
int curr_index = to_visit.size() - 1;
bool can_use_skip = curr_l.length() <= length_filter && curr.skips_taken < int(skips_allowed);
if (curr.section_idx + 1 < int(polygon_sections.size())) {
for (int lidx = 0; lidx < int(polygon_sections[curr.section_idx + 1].size()); ++ lidx) {
if (const Line &nl = polygon_sections[curr.section_idx + 1][lidx];
nl.a != nl.b && segments_overlap(curr_l.a.y(), curr_l.b.y(), nl.a.y(), nl.b.y()) &&
(nl.length() < length_filter || can_use_skip)) {
to_visit[curr_index].neighbours.push_back({curr.section_idx + 1, lidx});
to_remove.insert({curr.section_idx + 1, lidx});
Node next_node{curr.section_idx + 1, lidx, curr.skips_taken + (nl.length() >= length_filter)};
to_visit.push_back(next_node);
}
}
}
}
}
for (const auto &pair : to_remove) {
Line &l = polygon_sections[pair.first][pair.second];
l.a = l.b;
}
}
}
}
}
for (size_t section_idx = 0; section_idx < polygon_sections.size(); section_idx++) {
polygon_sections[section_idx].erase(std::remove_if(polygon_sections[section_idx].begin(), polygon_sections[section_idx].end(),
[](const Line &s) { return s.a == s.b; }),
polygon_sections[section_idx].end());
std::sort(polygon_sections[section_idx].begin(), polygon_sections[section_idx].end(),
[](const Line &a, const Line &b) { return a.a.y() < b.b.y(); });
}
ThickPolylines thick_polylines;
{
for (const auto &polygon_slice : polygon_sections) {
for (const Line &segment : polygon_slice) {
ThickPolyline &new_path = thick_polylines.emplace_back();
new_path.points.push_back(segment.a);
new_path.width.push_back(scaled_spacing);
new_path.points.push_back(segment.b);
new_path.width.push_back(scaled_spacing);
new_path.endpoints = {true, true};
}
}
}
if (fill_gaps) {
Polygons reconstructed_area{};
// reconstruct polygon from polygon sections
{
struct TracedPoly
{
Points lows;
Points highs;
};
std::vector<std::vector<Line>> polygon_sections_w_width = polygon_sections;
for (auto &slice : polygon_sections_w_width) {
for (Line &l : slice) {
l.a -= Point{0.0, 0.5 * scaled_spacing};
l.b += Point{0.0, 0.5 * scaled_spacing};
}
}
std::vector<TracedPoly> current_traced_polys;
for (const auto &polygon_slice : polygon_sections_w_width) {
std::unordered_set<const Line *> used_segments;
for (TracedPoly &traced_poly : current_traced_polys) {
auto candidates_begin = std::upper_bound(polygon_slice.begin(), polygon_slice.end(), traced_poly.lows.back(),
[](const Point &low, const Line &seg) { return seg.b.y() > low.y(); });
auto candidates_end = std::upper_bound(polygon_slice.begin(), polygon_slice.end(), traced_poly.highs.back(),
[](const Point &high, const Line &seg) { return seg.a.y() > high.y(); });
bool segment_added = false;
for (auto candidate = candidates_begin; candidate != candidates_end && !segment_added; candidate++) {
if (used_segments.find(&(*candidate)) != used_segments.end()) {
continue;
}
if (connect_extrusions && (traced_poly.lows.back() - candidates_begin->a).cast<double>().squaredNorm() <
squared_distance_limit_reconnection) {
traced_poly.lows.push_back(candidates_begin->a);
} else {
traced_poly.lows.push_back(traced_poly.lows.back() + Point{scaled_spacing / 2, 0});
traced_poly.lows.push_back(candidates_begin->a - Point{scaled_spacing / 2, 0});
traced_poly.lows.push_back(candidates_begin->a);
}
if (connect_extrusions && (traced_poly.highs.back() - candidates_begin->b).cast<double>().squaredNorm() <
squared_distance_limit_reconnection) {
traced_poly.highs.push_back(candidates_begin->b);
} else {
traced_poly.highs.push_back(traced_poly.highs.back() + Point{scaled_spacing / 2, 0});
traced_poly.highs.push_back(candidates_begin->b - Point{scaled_spacing / 2, 0});
traced_poly.highs.push_back(candidates_begin->b);
}
segment_added = true;
used_segments.insert(&(*candidates_begin));
}
if (!segment_added) {
// Zero or multiple overlapping segments. Resolving this is nontrivial,
// so we just close this polygon and maybe open several new. This will hopefully happen much less often
traced_poly.lows.push_back(traced_poly.lows.back() + Point{scaled_spacing / 2, 0});
traced_poly.highs.push_back(traced_poly.highs.back() + Point{scaled_spacing / 2, 0});
Polygon &new_poly = reconstructed_area.emplace_back(std::move(traced_poly.lows));
new_poly.points.insert(new_poly.points.end(), traced_poly.highs.rbegin(), traced_poly.highs.rend());
traced_poly.lows.clear();
traced_poly.highs.clear();
}
}
current_traced_polys.erase(std::remove_if(current_traced_polys.begin(), current_traced_polys.end(),
[](const TracedPoly &tp) { return tp.lows.empty(); }),
current_traced_polys.end());
for (const auto &segment : polygon_slice) {
if (used_segments.find(&segment) == used_segments.end()) {
TracedPoly &new_tp = current_traced_polys.emplace_back();
new_tp.lows.push_back(segment.a - Point{scaled_spacing / 2, 0});
new_tp.lows.push_back(segment.a);
new_tp.highs.push_back(segment.b - Point{scaled_spacing / 2, 0});
new_tp.highs.push_back(segment.b);
}
}
}
// add not closed polys
for (TracedPoly &traced_poly : current_traced_polys) {
Polygon &new_poly = reconstructed_area.emplace_back(std::move(traced_poly.lows));
new_poly.points.insert(new_poly.points.end(), traced_poly.highs.rbegin(), traced_poly.highs.rend());
}
}
reconstructed_area = union_safety_offset(reconstructed_area);
ExPolygons gaps_for_additional_filling = diff_ex(filled_area, reconstructed_area);
if (fill->overlap != 0) {
gaps_for_additional_filling = offset_ex(gaps_for_additional_filling, scaled<float>(fill->overlap));
}
// BoundingBox bbox = get_extents(filled_area);
// bbox.offset(scale_(1.));
// ::Slic3r::SVG svg(debug_out_path(("surface" + std::to_string(surface->area())).c_str()).c_str(), bbox);
// svg.draw(to_lines(filled_area), "red", scale_(0.4));
// svg.draw(to_lines(reconstructed_area), "blue", scale_(0.3));
// svg.draw(to_lines(gaps_for_additional_filling), "green", scale_(0.2));
// svg.draw(vertical_lines, "black", scale_(0.1));
// svg.Close();
for (ExPolygon &ex_poly : gaps_for_additional_filling) {
BoundingBox ex_bb = ex_poly.contour.bounding_box();
coord_t loops_count = (std::max(ex_bb.size().x(), ex_bb.size().y()) + scaled_spacing - 1) / scaled_spacing;
Polygons polygons = to_polygons(ex_poly); Polygons polygons = to_polygons(ex_poly);
Arachne::WallToolPaths wall_tool_paths(polygons, scaled_spacing, scaled_spacing, loops_count, 0, params.layer_height, *this->print_object_config, *this->print_config); Arachne::WallToolPaths wall_tool_paths(polygons, scaled_spacing, scaled_spacing, loops_count, 0, params.layer_height,
*fill->print_object_config, *fill->print_config);
if (std::vector<Arachne::VariableWidthLines> loops = wall_tool_paths.getToolPaths(); !loops.empty()) { if (std::vector<Arachne::VariableWidthLines> loops = wall_tool_paths.getToolPaths(); !loops.empty()) {
std::vector<const Arachne::ExtrusionLine *> all_extrusions; std::vector<const Arachne::ExtrusionLine *> all_extrusions;
for (Arachne::VariableWidthLines &loop : loops) { for (Arachne::VariableWidthLines &loop : loops) {
@ -33,50 +308,166 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const
all_extrusions.emplace_back(&wall); all_extrusions.emplace_back(&wall);
} }
// Split paths using a nearest neighbor search.
size_t firts_poly_idx = thick_polylines_out.size();
Point last_pos(0, 0);
for (const Arachne::ExtrusionLine *extrusion : all_extrusions) { for (const Arachne::ExtrusionLine *extrusion : all_extrusions) {
if (extrusion->empty()) if (extrusion->junctions.size() < 2) {
continue; continue;
}
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion); ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
if (thick_polyline.length() == 0.) if (extrusion->is_closed) {
//FIXME this should not happen. thick_polyline.start_at_index(nearest_point_index(thick_polyline.points, ex_bb.min));
thick_polyline.clip_end(scaled_spacing * 0.5);
}
if (thick_polyline.is_valid() && thick_polyline.length() > 0 && thick_polyline.points.size() > 1) {
thick_polylines.push_back(thick_polyline);
}
}
}
}
std::sort(thick_polylines.begin(), thick_polylines.end(), [](const ThickPolyline &left, const ThickPolyline &right) {
BoundingBox lbb(left.points);
BoundingBox rbb(right.points);
if (lbb.min.x() == rbb.min.x())
return lbb.min.y() < rbb.min.y();
else
return lbb.min.x() < rbb.min.x();
});
// connect tiny gap fills to close colinear line
struct EndPoint
{
Vec2d position;
size_t polyline_idx;
size_t other_end_point_idx;
bool is_first;
bool used = false;
};
std::vector<EndPoint> connection_endpoints;
connection_endpoints.reserve(thick_polylines.size() * 2);
for (size_t pl_idx = 0; pl_idx < thick_polylines.size(); pl_idx++) {
size_t current_idx = connection_endpoints.size();
connection_endpoints.push_back({thick_polylines[pl_idx].first_point().cast<double>(), pl_idx, current_idx + 1, true});
connection_endpoints.push_back({thick_polylines[pl_idx].last_point().cast<double>(), pl_idx, current_idx, false});
}
std::vector<bool> linear_segment_flags(thick_polylines.size());
for (size_t i = 0;i < thick_polylines.size(); i++) {
const ThickPolyline& tp = thick_polylines[i];
linear_segment_flags[i] = tp.points.size() == 2 && tp.points.front().x() == tp.points.back().x() &&
tp.width.front() == scaled_spacing && tp.width.back() == scaled_spacing;
}
auto coord_fn = [&connection_endpoints](size_t idx, size_t dim) { return connection_endpoints[idx].position[dim]; };
KDTreeIndirect<2, double, decltype(coord_fn)> endpoints_tree{coord_fn, connection_endpoints.size()};
for (size_t ep_idx = 0; ep_idx < connection_endpoints.size(); ep_idx++) {
EndPoint &ep1 = connection_endpoints[ep_idx];
if (!ep1.used) {
std::vector<size_t> close_endpoints = find_nearby_points(endpoints_tree, ep1.position, double(scaled_spacing));
for (size_t close_endpoint_idx : close_endpoints) {
EndPoint &ep2 = connection_endpoints[close_endpoint_idx];
if (ep2.used || ep2.polyline_idx == ep1.polyline_idx ||
(linear_segment_flags[ep1.polyline_idx] && linear_segment_flags[ep2.polyline_idx])) {
continue; continue;
assert(thick_polyline.size() > 1);
assert(thick_polyline.length() > 0.);
//assert(thick_polyline.points.size() == thick_polyline.width.size());
if (extrusion->is_closed)
thick_polyline.start_at_index(nearest_point_index(thick_polyline.points, last_pos));
assert(thick_polyline.size() > 1);
//assert(thick_polyline.points.size() == thick_polyline.width.size());
thick_polylines_out.emplace_back(std::move(thick_polyline));
last_pos = thick_polylines_out.back().last_point();
} }
// clip the paths to prevent the extruder from getting exactly on the first point of the loop EndPoint &target_ep = ep1.polyline_idx > ep2.polyline_idx ? ep1 : ep2;
// Keep valid paths only. EndPoint &source_ep = ep1.polyline_idx > ep2.polyline_idx ? ep2 : ep1;
size_t j = firts_poly_idx;
for (size_t i = firts_poly_idx; i < thick_polylines_out.size(); ++i) { ThickPolyline &target_tp = thick_polylines[target_ep.polyline_idx];
assert(thick_polylines_out[i].size() > 1); ThickPolyline &source_tp = thick_polylines[source_ep.polyline_idx];
assert(thick_polylines_out[i].length() > 0.); linear_segment_flags[target_ep.polyline_idx] = linear_segment_flags[ep1.polyline_idx] ||
//assert(thick_polylines_out[i].points.size() == thick_polylines_out[i].width.size()); linear_segment_flags[ep2.polyline_idx];
thick_polylines_out[i].clip_end(this->loop_clipping);
assert(thick_polylines_out[i].size() > 1); Vec2d v1 = target_ep.is_first ?
if (thick_polylines_out[i].is_valid()) { (target_tp.points[0] - target_tp.points[1]).cast<double>() :
if (j < i) (target_tp.points.back() - target_tp.points[target_tp.points.size() - 1]).cast<double>();
thick_polylines_out[j] = std::move(thick_polylines_out[i]); Vec2d v2 = source_ep.is_first ?
++j; (source_tp.points[1] - source_tp.points[0]).cast<double>() :
(source_tp.points[source_tp.points.size() - 1] - source_tp.points.back()).cast<double>();
if (std::abs(Slic3r::angle(v1, v2)) > PI / 6.0) {
continue;
} }
// connect target_ep and source_ep, result is stored in target_tp, source_tp will be cleared
if (target_ep.is_first) {
target_tp.reverse();
target_ep.is_first = false;
connection_endpoints[target_ep.other_end_point_idx].is_first = true;
}
size_t new_start_idx = target_ep.other_end_point_idx;
if (!source_ep.is_first) {
source_tp.reverse();
source_ep.is_first = true;
connection_endpoints[source_ep.other_end_point_idx].is_first = false;
}
size_t new_end_idx = source_ep.other_end_point_idx;
target_tp.points.insert(target_tp.points.end(), source_tp.points.begin(), source_tp.points.end());
target_tp.width.push_back(target_tp.width.back());
target_tp.width.push_back(source_tp.width.front());
target_tp.width.insert(target_tp.width.end(), source_tp.width.begin(), source_tp.width.end());
target_ep.used = true;
source_ep.used = true;
connection_endpoints[new_start_idx].polyline_idx = target_ep.polyline_idx;
connection_endpoints[new_end_idx].polyline_idx = target_ep.polyline_idx;
connection_endpoints[new_start_idx].other_end_point_idx = new_end_idx;
connection_endpoints[new_end_idx].other_end_point_idx = new_start_idx;
source_tp.clear();
break;
} }
if (j < thick_polylines_out.size())
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
} }
} }
return thick_polylines_out; thick_polylines.erase(std::remove_if(thick_polylines.begin(), thick_polylines.end(),
[scaled_spacing](const ThickPolyline &tp) {
return tp.length() < scaled_spacing &&
std::all_of(tp.width.begin(), tp.width.end(),
[scaled_spacing](double w) { return w < scaled_spacing; });
}),
thick_polylines.end());
}
Algorithm::sort_paths(thick_polylines.begin(), thick_polylines.end(), bb.min, double(scaled_spacing) * 1.2, [](const ThickPolyline &tp) {
Lines ls;
Point prev = tp.first_point();
for (size_t i = 1; i < tp.points.size(); i++) {
ls.emplace_back(prev, tp.points[i]);
prev = ls.back().b;
}
return ls;
});
if (connect_extrusions) {
ThickPolylines connected_thick_polylines;
if (!thick_polylines.empty()) {
connected_thick_polylines.push_back(thick_polylines.front());
for (size_t tp_idx = 1; tp_idx < thick_polylines.size(); tp_idx++) {
ThickPolyline &tp = thick_polylines[tp_idx];
ThickPolyline &tail = connected_thick_polylines.back();
Point last = tail.last_point();
if ((last - tp.last_point()).cast<double>().squaredNorm() < (last - tp.first_point()).cast<double>().squaredNorm()) {
tp.reverse();
}
if ((last - tp.first_point()).cast<double>().squaredNorm() < squared_distance_limit_reconnection) {
tail.points.insert(tail.points.end(), tp.points.begin(), tp.points.end());
tail.width.push_back(scaled_spacing);
tail.width.push_back(scaled_spacing);
tail.width.insert(tail.width.end(), tp.width.begin(), tp.width.end());
} else {
connected_thick_polylines.push_back(tp);
}
}
}
thick_polylines = connected_thick_polylines;
}
rotate_thick_polylines(thick_polylines, cos(-aligning_angle), sin(-aligning_angle));
return thick_polylines;
} }
} // namespace Slic3r } // namespace Slic3r

View File

@ -6,13 +6,19 @@
namespace Slic3r { namespace Slic3r {
class FillEnsuring : public FillRectilinear ThickPolylines make_fill_polylines(
const Fill *fill, const Surface *surface, const FillParams &params, bool stop_vibrations, bool fill_gaps, bool connect_extrusions);
class FillEnsuring : public Fill
{ {
public: public:
Fill *clone() const override { return new FillEnsuring(*this); } Fill *clone() const override { return new FillEnsuring(*this); }
~FillEnsuring() override = default; ~FillEnsuring() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override { return {}; }; Polylines fill_surface(const Surface *surface, const FillParams &params) override { return {}; };
ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams &params) override; ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams &params) override
{
return make_fill_polylines(this, surface, params, true, true, true);
};
protected: protected:
void fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out); void fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out);

View File

@ -176,7 +176,7 @@ Flow Flow::with_cross_section(float area_new) const
return this->with_width(width_new); return this->with_width(width_new);
} else { } else {
// Create a rounded extrusion. // Create a rounded extrusion.
auto dmr = float(sqrt(area_new / M_PI)); auto dmr = 2.0 * float(sqrt(area_new / M_PI));
return Flow(dmr, dmr, m_spacing, m_nozzle_diameter, false); return Flow(dmr, dmr, m_spacing, m_nozzle_diameter, false);
} }
} else } else

View File

@ -879,9 +879,12 @@ namespace Slic3r {
IdToCutObjectInfoMap::iterator cut_object_info = m_cut_object_infos.find(object.second + 1); IdToCutObjectInfoMap::iterator cut_object_info = m_cut_object_infos.find(object.second + 1);
if (cut_object_info != m_cut_object_infos.end()) { if (cut_object_info != m_cut_object_infos.end()) {
model_object->cut_id = cut_object_info->second.id; model_object->cut_id = cut_object_info->second.id;
int vol_cnt = int(model_object->volumes.size());
for (auto connector : cut_object_info->second.connectors) { for (auto connector : cut_object_info->second.connectors) {
assert(0 <= connector.volume_id && connector.volume_id <= int(model_object->volumes.size())); if (connector.volume_id < 0 || connector.volume_id >= vol_cnt) {
add_error("Invalid connector is found");
continue;
}
model_object->volumes[connector.volume_id]->cut_info = model_object->volumes[connector.volume_id]->cut_info =
ModelVolume::CutInfo(CutConnectorType(connector.type), connector.r_tolerance, connector.h_tolerance, true); ModelVolume::CutInfo(CutConnectorType(connector.type), connector.r_tolerance, connector.h_tolerance, true);
} }
@ -2997,9 +3000,9 @@ namespace Slic3r {
unsigned int object_cnt = 0; unsigned int object_cnt = 0;
for (const ModelObject* object : model.objects) { for (const ModelObject* object : model.objects) {
object_cnt++;
if (!object->is_cut()) if (!object->is_cut())
continue; continue;
object_cnt++;
pt::ptree& obj_tree = tree.add("objects.object", ""); pt::ptree& obj_tree = tree.add("objects.object", "");
obj_tree.put("<xmlattr>.id", object_cnt); obj_tree.put("<xmlattr>.id", object_cnt);

View File

@ -4,44 +4,14 @@
#include <string> #include <string>
#include "SLAArchiveWriter.hpp" #include "SLAArchiveWriter.hpp"
#include "SLAArchiveFormatRegistry.hpp"
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
#define ANYCUBIC_SLA_FORMAT_VERSION_1 1 constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_1 = 1;
#define ANYCUBIC_SLA_FORMAT_VERSION_515 515 constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_515 = 515;
#define ANYCUBIC_SLA_FORMAT_VERSION_516 516 constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_516 = 516;
#define ANYCUBIC_SLA_FORMAT_VERSION_517 517 constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_517 = 517;
#define ANYCUBIC_SLA_FORMAT_VERSIONED(FILEFORMAT, NAME, VERSION) \
{ FILEFORMAT, { FILEFORMAT, [] (const auto &cfg) { return std::make_unique<AnycubicSLAArchive>(cfg, VERSION); } } }
#define ANYCUBIC_SLA_FORMAT(FILEFORMAT, NAME) \
ANYCUBIC_SLA_FORMAT_VERSIONED(FILEFORMAT, NAME, ANYCUBIC_SLA_FORMAT_VERSION_1)
/**
// Supports only ANYCUBIC_SLA_VERSION_1
ANYCUBIC_SLA_FORMAT_VERSIONED("pws", "Photon / Photon S", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pw0", "Photon Zero", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pwx", "Photon X", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_1 and ANYCUBIC_SLA_VERSION_515
ANYCUBIC_SLA_FORMAT_VERSIONED("pwmo", "Photon Mono", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pwms", "Photon Mono SE", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("dlp", "Photon Ultra", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pwmx", "Photon Mono X", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pmsq", "Photon Mono SQ", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516
ANYCUBIC_SLA_FORMAT_VERSIONED("pwma", "Photon Mono 4K", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pm3", "Photon M3", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pm3m", "Photon M3 Max", ANYCUBIC_SLA_VERSION_515),
// Supports NYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516 and ANYCUBIC_SLA_VERSION_517
ANYCUBIC_SLA_FORMAT_VERSIONED("pwmb", "Photon Mono X 6K / Photon M3 Plus", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("dl2p", "Photon Photon D2", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pmx2", "Photon Mono X2", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pm3r", "Photon M3 Premium", ANYCUBIC_SLA_VERSION_515),
*/
namespace Slic3r { namespace Slic3r {
@ -75,6 +45,21 @@ public:
const std::string &projectname = "") override; const std::string &projectname = "") override;
}; };
inline Slic3r::ArchiveEntry anycubic_sla_format_versioned(const char *fileformat, const char *desc, uint16_t version)
{
Slic3r::ArchiveEntry entry(fileformat);
entry.desc = desc;
entry.ext = fileformat;
entry.wrfactoryfn = [version] (const auto &cfg) { return std::make_unique<AnycubicSLAArchive>(cfg, version); };
return entry;
}
inline Slic3r::ArchiveEntry anycubic_sla_format(const char *fileformat, const char *desc)
{
return anycubic_sla_format_versioned(fileformat, desc, ANYCUBIC_SLA_FORMAT_VERSION_1);
}
} // namespace Slic3r::sla } // namespace Slic3r::sla

View File

@ -17,6 +17,7 @@
#include "libslic3r/GCode/ThumbnailData.hpp" #include "libslic3r/GCode/ThumbnailData.hpp"
#include "SLAArchiveReader.hpp" #include "SLAArchiveReader.hpp"
#include "SLAArchiveFormatRegistry.hpp"
#include "ZipperArchiveImport.hpp" #include "ZipperArchiveImport.hpp"
#include "libslic3r/MarchingSquares.hpp" #include "libslic3r/MarchingSquares.hpp"
@ -26,6 +27,7 @@
#include "libslic3r/SLA/RasterBase.hpp" #include "libslic3r/SLA/RasterBase.hpp"
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -436,7 +438,7 @@ ConfigSubstitutions SL1Reader::read(std::vector<ExPolygons> &slices,
ConfigSubstitutions SL1Reader::read(DynamicPrintConfig &out) ConfigSubstitutions SL1Reader::read(DynamicPrintConfig &out)
{ {
ZipperArchive arch = read_zipper_archive(m_fname, {}, {"png"}); ZipperArchive arch = read_zipper_archive(m_fname, {"ini"}, {"png", "thumbnail"});
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
} }

View File

@ -0,0 +1,148 @@
#include <set>
#include <mutex>
#include <memory>
#include "SL1.hpp"
#include "SL1_SVG.hpp"
#include "AnycubicSLA.hpp"
#include "I18N.hpp"
#include "SLAArchiveFormatRegistry.hpp"
namespace Slic3r {
static std::mutex arch_mtx;
class Registry {
static std::unique_ptr<Registry> registry;
std::set<ArchiveEntry> entries;
public:
Registry ()
{
entries = {
{
"SL1", // id
L("SL1 archive format"), // description
"sl1", // main extension
{"sl1s", "zip"}, // extension aliases
// Writer factory
[] (const auto &cfg) { return std::make_unique<SL1Archive>(cfg); },
// Reader factory
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) {
return std::make_unique<SL1Reader>(fname, quality, progr);
}
},
{
"SL1SVG",
L("SL1SVG archive files"),
"sl1_svg",
{},
[] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); },
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) {
return std::make_unique<SL1_SVGReader>(fname, quality, progr);
}
},
{
"SL2",
"",
"sl1_svg",
{},
[] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); },
nullptr
},
anycubic_sla_format("pwmo", "Photon Mono"),
anycubic_sla_format("pwmx", "Photon Mono X"),
anycubic_sla_format("pwms", "Photon Mono SE"),
/**
// Supports only ANYCUBIC_SLA_VERSION_1
anycubic_sla_format_versioned("pws", "Photon / Photon S", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pw0", "Photon Zero", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pwx", "Photon X", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_1 and ANYCUBIC_SLA_VERSION_515
anycubic_sla_format_versioned("pwmo", "Photon Mono", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pwms", "Photon Mono SE", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("dlp", "Photon Ultra", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pwmx", "Photon Mono X", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pmsq", "Photon Mono SQ", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516
anycubic_sla_format_versioned("pwma", "Photon Mono 4K", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pm3", "Photon M3", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pm3m", "Photon M3 Max", ANYCUBIC_SLA_VERSION_515),
// Supports NYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516 and ANYCUBIC_SLA_VERSION_517
anycubic_sla_format_versioned("pwmb", "Photon Mono X 6K / Photon M3 Plus", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("dl2p", "Photon Photon D2", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pmx2", "Photon Mono X2", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pm3r", "Photon M3 Premium", ANYCUBIC_SLA_VERSION_515),
*/
};
}
static Registry& get_instance()
{
if (!registry)
registry = std::make_unique<Registry>();
return *registry;
}
static std::set<ArchiveEntry>& get()
{
return get_instance().entries;
}
std::set<ArchiveEntry>& get_entries() { return entries; }
};
std::unique_ptr<Registry> Registry::registry = nullptr;
std::set<ArchiveEntry> registered_sla_archives()
{
std::lock_guard lk{arch_mtx};
return Registry::get();
}
std::vector<std::string> get_extensions(const ArchiveEntry &entry)
{
auto ret = reserve_vector<std::string>(entry.ext_aliases.size() + 1);
ret.emplace_back(entry.ext);
for (const char *alias : entry.ext_aliases)
ret.emplace_back(alias);
return ret;
}
ArchiveWriterFactory get_writer_factory(const char *formatid)
{
std::lock_guard lk{arch_mtx};
ArchiveWriterFactory ret;
auto entry = Registry::get().find(ArchiveEntry{formatid});
if (entry != Registry::get().end())
ret = entry->wrfactoryfn;
return ret;
}
ArchiveReaderFactory get_reader_factory(const char *formatid)
{
std::lock_guard lk{arch_mtx};
ArchiveReaderFactory ret;
auto entry = Registry::get().find(ArchiveEntry{formatid});
if (entry != Registry::get().end())
ret = entry->rdfactoryfn;
return ret;
}
} // namespace Slic3r::sla

View File

@ -0,0 +1,71 @@
#ifndef SLA_ARCHIVE_FORMAT_REGISTRY_HPP
#define SLA_ARCHIVE_FORMAT_REGISTRY_HPP
#include "SLAArchiveWriter.hpp"
#include "SLAArchiveReader.hpp"
#include <cstring>
namespace Slic3r {
// Factory function that returns an implementation of SLAArchiveWriter given
// a printer configuration.
using ArchiveWriterFactory = std::function<
std::unique_ptr<SLAArchiveWriter>(const SLAPrinterConfig &)
>;
// Factory function that returns an implementation of SLAArchiveReader
using ArchiveReaderFactory = std::function<
std::unique_ptr<SLAArchiveReader>(const std::string &fname,
SLAImportQuality quality,
const ProgrFn & progr)
>;
struct ArchiveEntry {
// Main ID for the format, for internal unique identification
const char *id;
// Generic description (usable in GUI) about an archive format. Should only
// be marked for localization (macro L).
const char *desc = "";
// Main extension of the format.
const char *ext = "zip";
ArchiveWriterFactory wrfactoryfn;
ArchiveReaderFactory rdfactoryfn;
// Secondary, alias extensions
std::vector<const char *> ext_aliases;
explicit ArchiveEntry(const char *formatid) : id{formatid} {}
ArchiveEntry(const char *formatid,
const char *description,
const char *extension,
std::initializer_list<const char *> extaliases,
const ArchiveWriterFactory &wrfn,
const ArchiveReaderFactory &rdfn)
: id{formatid}
, desc{description}
, ext{extension}
, ext_aliases{extaliases}
, wrfactoryfn{wrfn}
, rdfactoryfn{rdfn}
{}
bool operator <(const ArchiveEntry &other) const
{
return std::strcmp(id, other.id) < 0;
}
};
std::vector<std::string> get_extensions(const ArchiveEntry &entry);
std::set<ArchiveEntry> registered_sla_archives();
ArchiveWriterFactory get_writer_factory(const char *formatid);
ArchiveReaderFactory get_reader_factory(const char *formatid);
} // namespace Slic3r
#endif // ARCHIVEREGISTRY_HPP

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