Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_project_dirty_state

This commit is contained in:
enricoturri1966 2021-05-03 16:05:22 +02:00
commit ede14251b1
199 changed files with 11027 additions and 6477 deletions

View file

@ -268,8 +268,6 @@ set(LIBDIR_BIN ${CMAKE_CURRENT_BINARY_DIR}/src)
include_directories(${LIBDIR})
# For generated header files
include_directories(${LIBDIR_BIN}/platform)
# For libslic3r.h
include_directories(${LIBDIR}/clipper)
if(WIN32)
add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)

View file

@ -13,7 +13,7 @@ include("deps-unix-common.cmake")
ExternalProject_Add(dep_boost
EXCLUDE_FROM_ALL 1
URL "https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.gz"
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"
URL_HASH SHA256=aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./bootstrap.sh
@ -100,5 +100,5 @@ ExternalProject_Add(dep_libcurl
BUILD_COMMAND make "-j${NPROC}"
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
)
add_dependencies(dep_openvdb dep_boost)

View file

@ -18,7 +18,7 @@ include("deps-unix-common.cmake")
ExternalProject_Add(dep_boost
EXCLUDE_FROM_ALL 1
URL "https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.gz"
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"
URL_HASH SHA256=aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./bootstrap.sh
@ -87,5 +87,5 @@ ExternalProject_Add(dep_libcurl
BUILD_COMMAND make "-j${NPROC}"
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
)
add_dependencies(dep_openvdb dep_boost)

View file

@ -9,7 +9,7 @@ include("deps-unix-common.cmake")
ExternalProject_Add(dep_boost
EXCLUDE_FROM_ALL 1
URL "https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.gz"
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"
URL_HASH SHA256=aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND bootstrap.bat
@ -59,3 +59,4 @@ ExternalProject_Add(dep_libcurl
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
${DEP_CMAKE_OPTS}
)

View file

@ -55,7 +55,7 @@ endmacro()
ExternalProject_Add(dep_boost
EXCLUDE_FROM_ALL 1
URL "https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.gz"
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"
URL_HASH SHA256=aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND bootstrap.bat
@ -296,3 +296,4 @@ if (${DEP_DEBUG})
WORKING_DIRECTORY "${BINARY_DIR}"
)
endif ()

BIN
resources/icons/info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 232 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 221 KiB

Before After
Before After

View file

@ -1,3 +1,6 @@
min_slic3r_version = 2.3.1-beta
0.0.10 Various updates for Anycubic Mega. Added filament profiles.
0.0.9 Updated bed textures
min_slic3r_version = 2.3.0-beta2
0.0.8 Updated start and end g-code for Anycubic Mega.
0.0.7 Updated start g-code for Anycubic Mega.

View file

@ -5,7 +5,7 @@
name = Anycubic
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.8
config_version = 0.0.10
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -435,7 +435,7 @@ default_filament_profile = Generic PLA @AKOSSEL
inherits = *common_akossel*
printer_model = AKLP
printer_variant = 0.4
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AKLP\nPRINTER_HAS_BOWDEN\n
printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AKLP\nPRINTER_HAS_BOWDEN\n
bed_shape = 114.562x10.0229,113.253x19.9695,111.081x29.7642,108.065x39.3323,104.225x48.6011,99.5929x57.5,94.2025x65.9613,88.0951x73.9206,81.3173x81.3173,73.9206x88.0951,65.9613x94.2025,57.5x99.5929,48.6011x104.225,39.3323x108.065,29.7642x111.081,19.9695x113.253,10.0229x114.562,7.04172e-15x115,-10.0229x114.562,-19.9695x113.253,-29.7642x111.081,-39.3323x108.065,-48.6011x104.225,-57.5x99.5929,-65.9613x94.2025,-73.9206x88.0951,-81.3173x81.3173,-88.0951x73.9206,-94.2025x65.9613,-99.5929x57.5,-104.225x48.6011,-108.065x39.3323,-111.081x29.7642,-113.253x19.9695,-114.562x10.0229,-115x1.40834e-14,-114.562x-10.0229,-113.253x-19.9695,-111.081x-29.7642,-108.065x-39.3323,-104.225x-48.6011,-99.5929x-57.5,-94.2025x-65.9613,-88.0951x-73.9206,-81.3173x-81.3173,-73.9206x-88.0951,-65.9613x-94.2025,-57.5x-99.5929,-48.6011x-104.225,-39.3323x-108.065,-29.7642x-111.081,-19.9695x-113.253,-10.0229x-114.562,-2.11252e-14x-115,10.0229x-114.562,19.9695x-113.253,29.7642x-111.081,39.3323x-108.065,48.6011x-104.225,57.5x-99.5929,65.9613x-94.2025,73.9206x-88.0951,81.3173x-81.3173,88.0951x-73.9206,94.2025x-65.9613,99.5929x-57.5,104.225x-48.6011,108.065x-39.3323,111.081x-29.7642,113.253x-19.9695,114.562x-10.0229,115x-2.81669e-14
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-54.672 Y95.203 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-52.931 Y96.185 E0.300\nG1 X-50.985 Y97.231 E0.331\nG1 X-49.018 Y98.238 E0.331\nG1 X-47.032 Y99.205 E0.331\nG1 X-45.026 Y100.132 E0.331\nG1 X-43.003 Y101.019 E0.331\nG1 X-40.961 Y101.864 E0.331\nG1 X-38.904 Y102.668 E0.331\nG1 X-36.83 Y103.431 E0.331\nG1 X-34.742 Y104.152 E0.331\nG1 X-32.639 Y104.83 E0.331\nG1 X-30.523 Y105.466 E0.331\nG1 X-28.395 Y106.06 E0.331\nG1 X-26.255 Y106.61 E0.331\nG1 X-24.105 Y107.117 E0.331\nG1 X-21.945 Y107.581 E0.331\nG1 X-19.776 Y108.001 E0.331\nG1 X-17.599 Y108.377 E0.331\nG1 X-15.415 Y108.71 E0.331\nG1 X-13.224 Y108.998 E0.331\nG1 X-11.028 Y109.242 E0.331\nG1 X-8.828 Y109.442 E0.331\nG1 X-6.624 Y109.598 E0.331\nG1 X-4.418 Y109.709 E0.331\nG1 X-2.209 Y109.776 E0.332\nG1 X0 Y109.798 E0.331\nG1 X2.209 Y109.776 E0.690\nG1 X4.418 Y109.709 E0.691\nG1 X6.624 Y109.598 E0.690\nG1 X8.828 Y109.442 E0.690\nG1 X11.028 Y109.242 E0.690\nG1 X13.224 Y108.998 E0.690\nG1 X15.415 Y108.71 E0.691\nG1 X17.599 Y108.377 E0.690\nG1 X19.776 Y108.001 E0.690\nG1 X21.945 Y107.581 E0.690\nG1 X24.105 Y107.117 E0.690\nG1 X26.255 Y106.61 E0.690\nG1 X28.395 Y106.06 E0.690\nG1 X30.523 Y105.466 E0.690\nG1 X32.639 Y104.83 E0.690\nG1 X34.742 Y104.152 E0.690\nG1 X36.83 Y103.431 E0.690\nG1 X38.904 Y102.668 E0.691\nG1 X40.961 Y101.864 E0.690\nG1 X43.003 Y101.019 E0.691\nG1 X45.026 Y100.132 E0.690\nG1 X47.032 Y99.205 E0.691\nG1 X49.018 Y98.238 E0.690\nG1 X50.985 Y97.231 E0.691\nG1 X52.931 Y96.185 E0.690\nG1 X54.672 Y95.203 E0.625\nG92 E0.0\nG1 E-5 F3000 ; retract 5mm\nG1 X52.931 Y96.185 F1000 ; wipe\nG1 X50.985 Y97.231 F1000 ; wipe\nG1 X49.018 Y98.238 F1000 ; wipe\nG1 X0 Y109.798 F1000\nG1 E4.8 F1500; de-retract\nG92 E0.0 ; reset extrusion distance\nM221 S{if layer_height<0.075}100{else}95{endif}
@ -443,7 +443,7 @@ start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104
inherits = *common_akossel*
printer_model = AK
printer_variant = 0.4
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AK\nPRINTER_HAS_BOWDEN\n
printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AK\nPRINTER_HAS_BOWDEN\n
bed_shape = 89.6575x7.84402,88.6327x15.6283,86.9333x23.2937,84.5723x30.7818,81.5677x38.0356,77.9423x45,73.7237x51.6219,68.944x57.8509,63.6396x63.6396,57.8509x68.944,51.6219x73.7237,45x77.9423,38.0356x81.5677,30.7818x84.5723,23.2937x86.9333,15.6283x88.6327,7.84402x89.6575,5.51091e-15x90,-7.84402x89.6575,-15.6283x88.6327,-23.2937x86.9333,-30.7818x84.5723,-38.0356x81.5677,-45x77.9423,-51.6219x73.7237,-57.8509x68.944,-63.6396x63.6396,-68.944x57.8509,-73.7237x51.6219,-77.9423x45,-81.5677x38.0356,-84.5723x30.7818,-86.9333x23.2937,-88.6327x15.6283,-89.6575x7.84402,-90x1.10218e-14,-89.6575x-7.84402,-88.6327x-15.6283,-86.9333x-23.2937,-84.5723x-30.7818,-81.5677x-38.0356,-77.9423x-45,-73.7237x-51.6219,-68.944x-57.8509,-63.6396x-63.6396,-57.8509x-68.944,-51.6219x-73.7237,-45x-77.9423,-38.0356x-81.5677,-30.7818x-84.5723,-23.2937x-86.9333,-15.6283x-88.6327,-7.84402x-89.6575,-1.65327e-14x-90,7.84402x-89.6575,15.6283x-88.6327,23.2937x-86.9333,30.7818x-84.5723,38.0356x-81.5677,45x-77.9423,51.6219x-73.7237,57.8509x-68.944,63.6396x-63.6396,68.944x-57.8509,73.7237x-51.6219,77.9423x-45,81.5677x-38.0356,84.5723x-30.7818,86.9333x-23.2937,88.6327x-15.6283,89.6575x-7.84402,90x-2.20436e-14
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-39.672 Y69.712 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-38.457 Y70.397 E0.209\nG1 X-37.043 Y71.157 E0.241\nG1 X-35.614 Y71.889 E0.241\nG1 X-34.171 Y72.591 E0.241\nG1 X-32.714 Y73.265 E0.241\nG1 X-31.244 Y73.909 E0.241\nG1 X-29.761 Y74.523 E0.241\nG1 X-28.266 Y75.108 E0.241\nG1 X-26.759 Y75.662 E0.241\nG1 X-25.242 Y76.185 E0.241\nG1 X-23.714 Y76.678 E0.241\nG1 X-22.177 Y77.14 E0.241\nG1 X-20.63 Y77.571 E0.241\nG1 X-19.076 Y77.971 E0.241\nG1 X-17.514 Y78.34 E0.241\nG1 X-15.944 Y78.677 E0.241\nG1 X-14.368 Y78.982 E0.241\nG1 X-12.786 Y79.255 E0.241\nG1 X-11.199 Y79.497 E0.241\nG1 X-9.608 Y79.706 E0.241\nG1 X-8.013 Y79.884 E0.241\nG1 X-6.414 Y80.029 E0.241\nG1 X-4.813 Y80.142 E0.241\nG1 X-3.21 Y80.223 E0.241\nG1 X-1.605 Y80.271 E0.241\nG1 X0 Y80.287 E0.241\nG1 X1.605 Y80.271 E0.502\nG1 X3.21 Y80.223 E0.502\nG1 X4.813 Y80.142 E0.502\nG1 X6.414 Y80.029 E0.502\nG1 X8.013 Y79.884 E0.502\nG1 X9.608 Y79.706 E0.502\nG1 X11.199 Y79.497 E0.501\nG1 X12.786 Y79.255 E0.502\nG1 X14.368 Y78.982 E0.502\nG1 X15.944 Y78.677 E0.502\nG1 X17.514 Y78.34 E0.502\nG1 X19.076 Y77.971 E0.502\nG1 X20.63 Y77.571 E0.501\nG1 X22.177 Y77.14 E0.502\nG1 X23.714 Y76.678 E0.502\nG1 X25.242 Y76.185 E0.502\nG1 X26.759 Y75.662 E0.501\nG1 X28.266 Y75.108 E0.502\nG1 X29.761 Y74.523 E0.502\nG1 X31.244 Y73.909 E0.502\nG1 X32.714 Y73.265 E0.502\nG1 X34.171 Y72.591 E0.502\nG1 X35.614 Y71.889 E0.501\nG1 X37.043 Y71.157 E0.502\nG1 X38.457 Y70.397 E0.502\nG1 X39.672 Y69.712 E0.436\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
@ -784,7 +784,7 @@ printer_model = MEGA0
printer_variant = 0.4
max_layer_height = 0.3
min_layer_height = 0.1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_MEGA0
printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_MEGA0
bed_shape = 0x0,220x0,220x220,0x220
max_print_height = 250
machine_max_acceleration_e = 5000
@ -822,54 +822,61 @@ end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM107 ; Fan off\nM
[print:*common_mega*]
bottom_solid_min_thickness = 0.5
bridge_acceleration = 1800
bridge_flow_ratio = 0.8
bridge_acceleration = 1000
bridge_flow_ratio = 0.95
bridge_speed = 30
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ and nozzle_diameter[0]==0.4
default_acceleration = 1800
default_acceleration = 1000
ensure_vertical_shell_thickness = 1
external_perimeter_extrusion_width = 0.6
external_perimeter_speed = 40
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 25
extruder_clearance_height = 35
extruder_clearance_radius = 60
extrusion_width = 0.45
fill_density = 15%
fill_pattern = gyroid
first_layer_acceleration = 1800
first_layer_acceleration = 1000
first_layer_extrusion_width = 0.42
first_layer_height = 0.2
first_layer_speed = 20
gap_fill_speed = 40
gcode_comments = 1
infill_acceleration = 1800
infill_acceleration = 1000
infill_anchor = 2.5
infill_anchor_max = 12
infill_extrusion_width = 0.45
infill_speed = 60
max_print_speed = 200
min_skirt_length = 4
only_retract_when_crossing_perimeters = 0
output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
perimeter_acceleration = 1800
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
perimeter_acceleration = 800
perimeter_extrusion_width = 0.45
perimeter_speed = 45
perimeters = 2
seam_position = nearest
skirts = 0
slice_closing_radius = 0.05
small_perimeter_speed = 30
skirt_distance = 2
skirt_height = 3
skirts = 1
small_perimeter_speed = 25
solid_infill_below_area = 0
solid_infill_speed = 60
solid_infill_extrusion_width = 0.45
solid_infill_speed = 80
support_material_buildplate_only = 1
support_material_contact_distance = 0.1
support_material_extrusion_width = 0.35
support_material_interface_layers = 2
support_material_interface_spacing = 0.2
support_material_spacing = 2
support_material_speed = 50
support_material_threshold = 55
support_material_with_sheath = 0
thin_walls = 0
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 40
top_solid_layers = 5
top_solid_min_thickness = 0.6
travel_speed = 180
[print:*supported_mega*]
raft_layers = 2
support_material = 1
# XXXXXXXXXXXXXXXXXXXX
@ -911,7 +918,19 @@ inherits = *0.20mm_mega*;*supported_mega*
[print:*0.30mm_mega*]
inherits = *common_mega*
bottom_solid_layers = 4
bridge_flow_ratio = 0.95
external_perimeter_extrusion_width = 0.6
external_perimeter_speed = 35
extrusion_width = 0.5
fill_pattern = grid
infill_extrusion_width = 0.5
infill_speed = 85
layer_height = 0.3
perimeter_extrusion_width = 0.5
perimeter_speed = 50
small_perimeter_speed = 30
solid_infill_extrusion_width = 0.5
support_material_extrusion_width = 0.38
support_material_speed = 45
top_solid_layers = 4
[print:0.30mm DRAFT @MEGA]
@ -929,7 +948,6 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and
end_filament_gcode = "; Filament-specific end gcode"
fan_always_on = 1
fan_below_layer_time = 100
filament_colour = #FF8000
filament_vendor = Generic
min_print_speed = 15
slowdown_below_layer_time = 20
@ -941,13 +959,13 @@ slowdown_below_layer_time = 20
cooling = 0
fan_always_on = 0
fan_below_layer_time = 20
filament_colour = #FFF2EC
filament_colour = #3A80CA
filament_cost = 27.82
filament_density = 1.04
filament_max_volumetric_speed = 11
filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
filament_type = ABS
first_layer_bed_temperature = 100
first_layer_bed_temperature = 105
first_layer_temperature = 255
max_fan_speed = 30
min_fan_speed = 20
@ -970,7 +988,7 @@ filament_deretract_speed = 25
filament_max_volumetric_speed = 1.2
filament_retract_length = 0.8
filament_type = FLEX
first_layer_bed_temperature = 50
first_layer_bed_temperature = 55
first_layer_temperature = 240
max_fan_speed = 90
min_fan_speed = 70
@ -979,16 +997,41 @@ temperature = 240
[filament:Generic FLEX @MEGA]
inherits = *FLEX_mega*
[filament:SainSmart TPU @MEGA]
inherits = *FLEX_mega*
filament_vendor = SainSmart
bed_temperature = 50
bridge_fan_speed = 100
cooling = 1
disable_fan_first_layers = 4
filament_cost = 39.99
filament_density = 1.21
filament_deretract_speed = 15
filament_max_volumetric_speed = 1.8
filament_notes = "SainSmart TPU gains popularity among 3D Printing community for its balance of rigidity and flexibility. In addition, with a 95A Shore Hardness and improved bed adhesion, it is easier to print even with a stock elementary 3D Printer like the Creality Ender 3. SainSmart TPU will not disappoint if you are looking for flexible filament. From drone parts, phone cases, to small toys, all can be printed with ease.\n\nhttps://www.sainsmart.com/collections/tpu-filament/products/all-colors-tpu-flexible-filament-1-75mm-0-8kg-1-76lb"
filament_retract_before_travel = 5
filament_retract_length = 4
filament_retract_speed = 40
filament_unloading_speed = 90
first_layer_bed_temperature = 55
first_layer_temperature = 235
full_fan_speed_layer = 6
max_fan_speed = 80
min_fan_speed = 80
slowdown_below_layer_time = 10
temperature = 235
[filament:*PETG_mega*]
inherits = *common_mega*
bed_temperature = 90
bridge_fan_speed = 50
fan_below_layer_time = 20
filament_colour = #FF8000
filament_cost = 27.82
filament_density = 1.27
filament_max_volumetric_speed = 8
filament_type = PETG
first_layer_bed_temperature = 85
first_layer_bed_temperature = 90
first_layer_temperature = 230
max_fan_speed = 50
min_fan_speed = 30
@ -997,14 +1040,63 @@ temperature = 240
[filament:Generic PETG @MEGA]
inherits = *PETG_mega*
[filament:ColorFabb XT-CF20 @MEGA]
inherits = *PETG_mega*
compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
extrusion_multiplier = 1.05
filament_colour = #804040
filament_cost = 66.60
filament_density = 1.35
filament_deretract_speed = 25
filament_max_volumetric_speed = 2
filament_notes = "Based on colorFabb_XT, XT-CF20 is a carbon fiber composite material. Loaded with no less than 20% specially sourced carbon fibers we have developed a very stiff and tough 3D printing filament made for functional parts. It is truly a professional printers go-to material, especially for users looking for high melt strength, high melt viscosity and good dimensional accuracy and stability.\n\nhttps://colorfabb.com/xt-cf20"
filament_retract_before_travel = 1
filament_retract_length = 1.4
filament_retract_speed = 40
filament_spool_weight = 236
filament_vendor = ColorFabb
first_layer_temperature = 260
full_fan_speed_layer = 5
slowdown_below_layer_time = 15
temperature = 260
[filament:ERYONE PETG @MEGA]
inherits = *PETG_mega*
filament_vendor = ERYONE
filament_cost = 20.99
filament_notes = "https://eryone.com/petg/show/10.html"
[filament:FormFutura HDglass @MEGA]
inherits = *PETG_mega*
filament_vendor = FormFutura
filament_cost = 46.65
filament_notes = "HDglass is a high performance PETG type of 3D printer with unsurpassed 3D printing properties and improved mechanical strength, flexibility, toughness and heat resistance.\n\nhttps://www.formfutura.com/shop/product/hdglass-2812"
[filament:FormFutura ReForm rPET @MEGA]
inherits = *PETG_mega*
filament_vendor = FormFutura
filament_cost = 26.65
filament_notes = "ReForm rPET is a recycled PETG type of 3D printer filament that is made from post-industrial waste streams of a nearby located plastic bottle manufacturer.\n\nhttps://www.formfutura.com/shop/product/reform-rpet-2836"
filament_spool_weight = 176
[filament:Janbex transparent PETG @MEGA]
inherits = *PETG_mega*
filament_vendor = Janbex
filament_cost = 31.99
filament_spool_weight = 222
first_layer_temperature = 215
min_fan_speed = 100
temperature = 210
[filament:*PLA_mega*]
inherits = *common_mega*
bed_temperature = 60
disable_fan_first_layers = 1
filament_colour = #FF3232
filament_cost = 25.40
filament_density = 1.24
filament_max_volumetric_speed = 10
first_layer_bed_temperature = 60
first_layer_bed_temperature = 65
first_layer_temperature = 215
min_fan_speed = 100
temperature = 210
@ -1012,73 +1104,97 @@ temperature = 210
[filament:Generic PLA @MEGA]
inherits = *PLA_mega*
[filament:*3Dmensionals PLA_mega*]
[filament:3Dmensionals PLA @MEGA]
inherits = *PLA_mega*
filament_vendor = 3Dmensionals
filament_cost = 23.35
filament_cost = 22.90
filament_notes = "Das 3DFilaments - PLA von 3Dmensionals ist ein sehr leicht zu druckendes 3D-Drucker Filament. Dabei handelt es sich um ein etwas härteres PLA mit einer exzellenten thermischen Stabilität. Das Filament zeichnet sich vor allem durch verzugfreies 3D-Drucken aus und weist minimale bis keine Verformung nach dem Abkühlen auf. Daher ist es besonders gut für den Druck größerer Objekte geeignet. Zudem bietet 3DFilaments - PLA über die gesamte Fadenläge eine hervorragende Durchmesser- und Rundheitstoleranz.\n\nhttps://www.3dmensionals.de/3dfilaments?number=PSU3DM001V"
[filament:3Dmensionals PLA @MEGA]
inherits = *3Dmensionals PLA_mega*
[filament:3D Warhorse PLA @MEGA]
inherits = *PLA_mega*
filament_vendor = 3D Warhorse
filament_cost = 19.99
[filament:3Dmensionals PLA blue @MEGA]
inherits = *3Dmensionals PLA_mega*
filament_colour = #4155FB
[filament:AMOLEN wood PLA]
inherits = *PLA_mega*
filament_vendor = AMOLEN
compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
extrusion_multiplier = 1.1
filament_colour = #DFC287
filament_cost = 33.99
filament_density = 1.23
filament_max_volumetric_speed = 9
filament_notes = "https://amolen.com/collections/wood/products/amolen-pla-filament-1-75mm-wood-color-3d-printer-filament-1kg2-2lb"
[filament:3Dmensionals PLA silver @MEGA]
inherits = *3Dmensionals PLA_mega*
filament_colour = #B9B5B4
[filament:FormFutura EasyFil PLA @MEGA]
inherits = *PLA_mega*
filament_vendor = FormFutura
filament_cost = 39.93
filament_notes = "EasyFil PLA is an easy to print PLA type of 3D printer filament that is available in a wide variety of colors. Its improved flowing behavior make 3D printed layers flow more into each other.\n\nhttps://www.formfutura.com/shop/product/easyfil-pla-2801"
[filament:3Dmensionals PLA white @MEGA]
inherits = *3Dmensionals PLA_mega*
filament_colour = #FEFEFD
[filament:FormFutura ReForm rPLA @MEGA]
inherits = *PLA_mega*
filament_vendor = FormFutura
filament_cost = 26.65
filament_notes = "ReForm is a sustainable initiative within Formfutura to efficiently manage residual extrusion waste streams and re-use them into high-end upcycled filaments. The ideology behind ReForm is to a make 3D printing more sustainable without having to make compromises on material properties and yet keep it affordable.\n\nhttps://www.formfutura.com/shop/product/reform-rpla-2838"
[filament:*Verbatim PLA_mega*]
[filament:GIANTARM PLA @MEGA]
inherits = *PLA_mega*
filament_vendor = GIANTARM
filament_cost = 24.99
[filament:Prusament PLA @MEGA]
inherits = *PLA_mega*
filament_vendor = Prusa Polymers
filament_cost = 30.24
filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa"
filament_spool_weight = 201
temperature = 215
[filament:Verbatim PLA @MEGA]
inherits = *PLA_mega*
filament_vendor = Verbatim
filament_cost = 23.88
[filament:Verbatim PLA @MEGA]
inherits = *Verbatim PLA_mega*
[filament:Verbatim PLA black @MEGA]
inherits = *Verbatim PLA_mega*
filament_colour = #333333
[printer:*common_mega*]
printer_technology = FFF
bed_shape = 0x0,210x0,210x210,0x210
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]
default_filament_profile = Generic PLA @MEGA
default_print_profile = 0.15mm QUALITY @MEGA
deretract_speed = 50
end_gcode = G4 ; wait\nG92 E0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
deretract_speed = 40
end_gcode = G1 E-1.0 F2100 ; retract\nG92 E0.0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; move print head up\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y105 F3000 ; park print head\nM84 ; disable motors
extruder_colour = #808080
gcode_flavor = marlin
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
max_layer_height = 0.36
max_print_height = 205
remaining_times = 1
retract_before_travel = 1.5
retract_before_wipe = 60%
retract_layer_change = 1
retract_length = 6
retract_lift = 0.075
retract_length = 3.2
retract_lift = 0.2
retract_lift_below = 204
retract_speed = 70
silent_mode = 0
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y0 Z1 F100 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0\nG1 Z0.2 F360\nG1 X60 E9 F700 ; intro line\nG1 X100 E12.5 F700 ; intro line\nG92 E0
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y2.0 Z0.2 F1000 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0.0\nG1 X60.0 E9.0 F1000 ; intro line\nG1 X100.0 E12.5 F1000 ; intro line\nG92 E0.0
thumbnails = 16x16,220x124
use_relative_e_distances = 1
wipe = 1
machine_max_acceleration_e = 5000
machine_max_acceleration_e = 10000
machine_max_acceleration_extruding = 1250
machine_max_acceleration_retracting = 1250
machine_max_acceleration_x = 1000
machine_max_acceleration_y = 1000
machine_max_acceleration_z = 200
machine_max_acceleration_x = 3000
machine_max_acceleration_y = 2000
machine_max_acceleration_z = 60
machine_max_feedrate_e = 60
machine_max_feedrate_x = 200
machine_max_feedrate_y = 200
machine_max_feedrate_x = 500
machine_max_feedrate_y = 500
machine_max_feedrate_z = 6
machine_max_jerk_e = 5
machine_max_jerk_x = 8
machine_max_jerk_y = 8
machine_max_jerk_x = 10
machine_max_jerk_y = 10
machine_max_jerk_z = 0.4
[printer:Anycubic i3 Mega]
@ -1092,6 +1208,7 @@ inherits = *common_mega*
printer_model = I3MEGAS
printer_variant = 0.4
printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA_S\nPRINTER_HAS_BOWDEN
machine_max_feedrate_e = 30
machine_max_feedrate_z = 8
@ -1743,7 +1860,7 @@ machine_max_jerk_z = 5
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
printer_settings_id =
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PREDATOR\nPRINTER_HAS_BOWDEN\n
printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PREDATOR\nPRINTER_HAS_BOWDEN\n
default_filament_profile = Generic PLA @PREDATOR
[printer:Anycubic Predator 0.4 nozzle]
@ -1775,4 +1892,4 @@ default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR
#########################################
########## end printer presets ##########
#########################################
#########################################"do not" cause ' is bad for syntax highlighting

View file

@ -0,0 +1,561 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210.5mm"
height="210.5mm"
viewBox="0 0 210.5 210.5"
version="1.1"
id="svg886"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="ai3m.svg">
<defs
id="defs880" />
<sodipodi:namedview
id="base"
pagecolor="#7670ff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="466.73093"
inkscape:cy="380.93745"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:lockguides="false"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata883">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Layer 2"
transform="translate(0,-86.5)"
style="display:inline"
sodipodi:insensitive="true">
<path
id="path869"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.04216461;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 167.32704,288.75984 v -3.83255 h 1.45715 v 7.07119 l -6.06232,-5.36476 v -1.94915 z m -9.42165,-2.52278 1.54352,2.96287 h -0.60107 l -0.76147,1.4617 h 2.12401 l 0.6004,1.1525 h 1.65752 l -3.73414,-7.16792 z m 44.62362,4.25408 v 1.50745 c 0.98166,-0.11796 1.8734,-0.62934 2.47099,-1.41702 l -1.14996,-0.94952 c -0.31636,0.44259 -0.78818,0.74942 -1.32103,0.85909 z m -40.17486,-27.16603 11.53897,-20.77294 18.70747,18.05526 -17.35981,21.92818 z m -5.69662,28.48902 1.6624,-3.19108 -0.82877,-1.59087 L 155,291.81413 Z m 22.56867,-7.05936 c 0.97028,0.11659 1.8532,0.61761 2.4509,1.39077 l -1.16155,0.93258 c -0.31614,-0.41985 -0.77457,-0.70996 -1.28935,-0.81591 z m 3.41542,0.17252 h 1.46761 v 4.19716 c 0,0.59031 0.3725,1.11637 0.92932,1.3124 v 1.50898 c -1.38222,-0.22635 -2.39693,-1.42074 -2.39693,-2.82138 z m 8.44048,6.88684 v -6.88684 h -1.43359 v 6.88684 z m 1.73019,-4.18512 c 0.35459,0 0.64204,-0.28746 0.64204,-0.64204 0,-0.35459 -0.28745,-0.64204 -0.64204,-0.64204 h -0.8869 v -1.41764 h 0.8869 c 1.13753,0 2.05968,0.92215 2.05968,2.05968 0,1.13753 -0.92215,2.05968 -2.05968,2.05968 h -0.8869 l -0.004,-1.41764 z m -30.09042,4.18512 h 1.49929 v -2.7357 l -1.49929,-1.32677 z m 33.23702,0 h 1.43359 v -6.88684 h -1.43359 z m -6.61958,-43.20436 -15.24232,-6.09042 18.63476,17.98509 11.51531,1.11097 z m -18.15413,43.20436 v -3.62964 l 2.39506,-3.2572 h 1.87519 l -2.78508,3.78762 v 3.09922 z m 0.39556,-5.55407 -0.92997,1.26472 -1.81565,-2.59749 h 1.814 z m 21.17859,-25.58701 11.46398,1.10603 -13.7034,15.36187 -15.13578,5.47973 z m 7.21757,28.12689 c 0.17089,0.85467 0.83896,1.52274 1.69364,1.69363 v 1.50644 c -1.6794,-0.19619 -3.0039,-1.52068 -3.20008,-3.20007 -0.23374,-2.00112 1.19897,-3.81283 3.20008,-4.04658 v 1.50643 c -1.16914,0.23375 -1.92739,1.37102 -1.69364,2.54015 z m -5.04526,0.93674 c 0,-0.30809 -0.0685,-0.61233 -0.20062,-0.89067 -0.35104,0.36232 -0.79749,0.61783 -1.28769,0.73699 0.0131,0.0502 0.0197,0.10183 0.0197,0.15368 0,0.33625 -0.2726,0.60885 -0.60885,0.60885 h -0.92882 v 1.4686 l 0.92882,-10e-6 c 1.14733,0 2.07744,-0.9301 2.07744,-2.07744 z m -14.38439,-0.10463 1.14995,0.94952 c -0.5976,0.78768 -1.48934,1.29906 -2.471,1.41702 v -1.50745 c 0.53286,-0.10967 1.00468,-0.4165 1.32105,-0.85909 z m -2.17951,0.86152 c -0.85468,-0.17089 -1.52275,-0.83896 -1.69364,-1.69363 -0.23376,-1.16913 0.52451,-2.3064 1.69364,-2.54015 v -1.50643 c -2.00111,0.23375 -3.43383,2.04546 -3.20007,4.04658 0.19617,1.67939 1.52067,3.00388 3.20007,3.20007 z m 9.99181,-1.36912 v -4.19716 h -1.46761 v 4.19716 c 0,0.62159 -0.41231,1.16778 -1.01011,1.3381 v 1.49533 c 1.41883,-0.19091 2.47772,-1.40182 2.47772,-2.83343 z m 14.16946,-2.86224 v -1.50744 c 0.97027,0.11659 1.85319,0.61761 2.45089,1.39077 l -1.16154,0.93258 c -0.31614,-0.41985 -0.77458,-0.70996 -1.28935,-0.81591 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccsccccscccccccccccccccccccccccccccccccccccccccccccsccsccccscccccccccccccccccccccccc" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 1"
transform="translate(0,-86.5)"
style="display:none">
<path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.68079633,77.180801 H 219.81921"
id="path1596"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,77.180801 V 296.31918"
id="path1594"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,296.31918 H 0.68079633"
id="path1592"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.68079633,296.31918 V 77.180801"
id="rect1544"
inkscape:connector-curvature="0" />
<path
id="path5301"
d="M 9.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 19.681,296.31918 V 77.180801"
id="path5303" />
<path
id="path5305"
d="M 29.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 39.681,296.31918 V 77.180801"
id="path5307" />
<path
id="path5309"
d="M 49.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 59.681,296.31918 V 77.180801"
id="path5311" />
<path
id="path5313"
d="M 69.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 79.681,296.31918 V 77.180801"
id="path5315" />
<path
id="path5317"
d="M 89.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 99.681,296.31918 V 77.180801"
id="path5319" />
<path
id="path5321"
d="M 109.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 119.681,296.31918 V 77.180801"
id="path5323" />
<path
id="path5325"
d="M 129.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 139.681,296.31918 V 77.180801"
id="path5327" />
<path
id="path5329"
d="M 149.681,296.31918 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 159.681,296.31918 V 77.180801"
id="path5331" />
<path
id="path5333"
d="m 169.681,296.31918 v -3.0895 m 0,-10.12031 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 179.681,296.31918 v -2.82492 m 0,-10.18645 v -6.87917 m 0,-28.50885 V 77.180801"
id="path5335"
sodipodi:nodetypes="cccccc" />
<path
id="path5337"
d="m 189.681,296.31918 v -2.95721 m 0,-50.37005 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 199.681,296.31918 v -3.15564 m 0,-9.72344 v -4.69636 m 0,-30.8901 V 77.180801"
id="path5339"
sodipodi:nodetypes="cccccc" />
<path
id="path5341"
d="m 209.681,296.31918 v -2.89106 m 0,-10.25261 v -14.61822 m 0,-12.76615 V 77.180801"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
id="path5343"
d="m 219.81921,287.319 h -3.39004 m -51.52761,0 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 219.81921,277.319 h -18.00827 m -21.36511,0 H 0.68079633"
id="path5345"
sodipodi:nodetypes="cccc" />
<path
id="path5347"
d="m 219.81921,267.319 h -8.94629 m -36.90938,0 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 219.81921,257.319 h -8.74786 m -36.90937,0 H 0.68079633"
id="path5349"
sodipodi:nodetypes="cccc" />
<path
id="path5351"
d="m 219.81921,247.319 h -21.44786 m -18.12395,0 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,237.319 H 0.68079633"
id="path5353" />
<path
id="path5355"
d="M 219.81921,227.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,217.319 H 0.68079633"
id="path5357" />
<path
id="path5359"
d="M 219.81921,207.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,197.319 H 0.68079633"
id="path5361" />
<path
id="path5363"
d="M 219.81921,187.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,177.319 H 0.68079633"
id="path5365" />
<path
id="path5367"
d="M 219.81921,167.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,157.319 H 0.68079633"
id="path5369" />
<path
id="path5371"
d="M 219.81921,147.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,137.319 H 0.68079633"
id="path5373" />
<path
id="path5375"
d="M 219.81921,127.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,117.319 H 0.68079633"
id="path5377" />
<path
id="path5379"
d="M 219.81921,107.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 219.81921,97.319 H 0.68079633"
id="path5381" />
<path
id="path5383"
d="M 219.81921,87.319 H 0.68079633"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 3"
style="display:inline">
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.25,205.25001 h 152.88208 m 53.78799,0 h 3.32996"
id="path973"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 145.25002,210.25 V 0.25000128"
id="path971"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 205.25001,210.25 v -2.79018 m 0,-10.89792 V 0.25000128"
id="path969"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,15.250006 H 210.25003"
id="path967"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,155.25001 H 210.25003"
id="path965"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 55.249995,210.25 V 0.25000128"
id="path963"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.25,175.25 h 160.97366 m 43.87229,0 h 5.15408"
id="path961"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125.25003,210.25 V 0.25000128"
id="path959"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,35.250001 H 210.25003"
id="path957"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 195.25003,210.25 v -3.02405 m 0,-10.68744 0,-10.52373 m 0,-19.79114 0,-165.97363872"
id="path955"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 35.25,210.25 V 0.25000128"
id="path953"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.2500251,210.25 V 0.25000128"
id="path951"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,25.249986 H 210.25003"
id="path949"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,105.25 H 210.25003"
id="path947"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 105.25004,210.25 V 0.25000128"
id="path945"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,55.249996 H 210.25003"
id="path943"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 185.25001,210.25 v -3.02405 m 0,-10.73421 v -2.8531 m 0,-34.30738 V 0.25000128"
id="path941"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 175.25,210.25 v -3.11759 m 0,-51.39092 V 0.25000128"
id="path939"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 15.250005,210.25 V 0.25000128"
id="path937"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,125.25 H 210.25003"
id="path935"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 85.250005,210.25 V 0.25000128"
id="path933"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,75.249991 H 210.25003"
id="path931"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 155.25,210.25 v -3.02405 m 0,-7.39 V 0.25000128"
id="path929"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,0.25000128 V 210.25"
id="path927"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,5.2499912 H 210.25003"
id="path925"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,145.24999 H 210.25003"
id="path923"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 65.25001,210.25 V 0.25000128"
id="path921"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,95.250021 H 210.25003"
id="path919"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 165.25002,210.25 v -2.79018 m 0,-10.4302 v -13.18975 m 0,-14.82678 V 0.25000128"
id="path917"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 135.25001,210.25 V 0.25000128"
id="path915"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 210.25003,0.25000128 H 0.25"
id="path913"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.25,165.25002 h 166.9605 m 26.98754,0 h 16.05199"
id="path911"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 45.250015,210.25 V 0.25000128"
id="path909"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 115.25001,210.25 V 0.25000128"
id="path907"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,45.249981 H 210.25003"
id="path905"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 210.25003,210.25 V 0.25000128"
id="path903"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 25.25002,210.25 V 0.25000128"
id="path901"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.25,185.25002 h 166.25892 m 30.26159,0 h 13.47952"
id="path899"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,115.25002 H 210.25003"
id="path897"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 95.25002,210.25 V 0.25000128"
id="path895"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,65.250011 H 210.25003"
id="path893"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,210.25 H 210.25003"
id="path891"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,85.250006 H 210.25003"
id="path889"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.25,195.25 h 172.9694 m 6.46576,0 h 30.56487"
id="path887"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.25,135.25001 H 210.25003"
id="path885"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.250025,210.25 V 0.25000128"
id="path875"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

View file

@ -1,2 +1,2 @@
min_slic3r_version = 2.4.0-alpha0
min_slic3r_version = 2.3.1-beta
0.0.1 Initial Artillery bundle

View file

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Before After
Before After

View file

@ -1,3 +1,6 @@
min_slic3r_version = 2.3.1-beta
0.0.16 Updated CR6-SE start g-code. Added and updated filament profiles.
0.0.15 Added new printer models, filament profiles. Various improvements.
min_slic3r_version = 2.3.0-rc2
0.0.14 Optimized start g-code. Added filament profile. Various improvements.
0.0.13 Optimized start and end g-code. General improvements.

View file

@ -5,7 +5,7 @@
name = Creality
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.14
config_version = 0.0.16
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -21,7 +21,7 @@ technology = FFF
family = ENDER
bed_model = ender3_bed.stl
bed_texture = ender3.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER3BLTOUCH]
name = Creality Ender-3 BLTouch
@ -30,7 +30,7 @@ technology = FFF
family = ENDER
bed_model = ender3_bed.stl
bed_texture = ender3.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER3V2]
name = Creality Ender-3 V2
@ -39,7 +39,7 @@ technology = FFF
family = ENDER
bed_model = ender3v2_bed.stl
bed_texture = ender3v2.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER3MAX]
name = Creality Ender-3 Max
@ -48,7 +48,7 @@ technology = FFF
family = ENDER
bed_model = cr10v2_bed.stl
bed_texture = cr10spro.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER4]
name = Creality Ender-4
@ -57,7 +57,7 @@ technology = FFF
family = ENDER
bed_model = ender3v2_bed.stl
bed_texture = ender3v2.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER5]
name = Creality Ender-5
@ -66,7 +66,7 @@ technology = FFF
family = ENDER
bed_model = ender3_bed.stl
bed_texture = ender3.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER5PLUS]
name = Creality Ender-5 Plus
@ -75,7 +75,7 @@ technology = FFF
family = ENDER
bed_model = ender5plus_bed.stl
bed_texture = ender5plus.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER6]
name = Creality Ender-6
@ -84,7 +84,7 @@ technology = FFF
family = ENDER
bed_model = ender6_bed.stl
bed_texture = ender6.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER2]
name = Creality Ender-2
@ -93,7 +93,7 @@ technology = FFF
family = ENDER
bed_model = ender2_bed.stl
bed_texture = ender2.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR5PRO]
name = Creality CR-5 Pro
@ -102,7 +102,7 @@ technology = FFF
family = CR
bed_model = cr5pro_bed.stl
bed_texture = cr5pro.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR5PROH]
name = Creality CR-5 Pro H
@ -111,7 +111,7 @@ technology = FFF
family = CR
bed_model = cr5pro_bed.stl
bed_texture = cr5pro.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR6SE]
name = Creality CR-6 SE
@ -120,7 +120,7 @@ technology = FFF
family = CR
bed_model = cr6se_bed.stl
bed_texture = cr6se.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR6MAX]
name = Creality CR-6 Max
@ -129,7 +129,7 @@ technology = FFF
family = CR
bed_model = cr10s4_bed.stl
bed_texture = cr10s4.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10MINI]
name = Creality CR-10 Mini
@ -138,7 +138,7 @@ technology = FFF
family = CR
bed_model = cr10mini_bed.stl
bed_texture = cr10mini.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10MAX]
name = Creality CR-10 Max
@ -147,7 +147,7 @@ technology = FFF
family = CR
bed_model = cr10max_bed.stl
bed_texture = cr10max.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10]
name = Creality CR-10
@ -156,7 +156,7 @@ technology = FFF
family = CR
bed_model = cr10_bed.stl
bed_texture = cr10.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10V2]
name = Creality CR-10 V2
@ -165,7 +165,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10V3]
name = Creality CR-10 V3
@ -174,7 +174,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10S]
name = Creality CR-10 S
@ -183,7 +183,7 @@ technology = FFF
family = CR
bed_model = cr10_bed.stl
bed_texture = cr10.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10SPRO]
name = Creality CR-10 S Pro
@ -192,7 +192,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10spro.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10SPROV2]
name = Creality CR-10 S Pro V2
@ -201,7 +201,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10S4]
name = Creality CR-10 S4
@ -210,7 +210,7 @@ technology = FFF
family = CR
bed_model = cr10s4_bed.stl
bed_texture = cr10s4.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10S5]
name = Creality CR-10 S5
@ -219,7 +219,7 @@ technology = FFF
family = CR
bed_model = cr10s5_bed.stl
bed_texture = cr10s5.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR20]
name = Creality CR-20
@ -228,7 +228,7 @@ technology = FFF
family = CR
bed_model = ender3_bed.stl
bed_texture = cr20.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR20PRO]
name = Creality CR-20 Pro
@ -237,7 +237,7 @@ technology = FFF
family = CR
bed_model = ender3_bed.stl
bed_texture = cr20.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR200B]
name = Creality CR-200B
@ -246,7 +246,7 @@ technology = FFF
family = CR
bed_model = cr200b_bed.stl
bed_texture = cr200b.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR8]
name = Creality CR-8
@ -255,7 +255,7 @@ technology = FFF
family = CR
bed_model = cr8_bed.stl
bed_texture = cr8.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CRX]
#name = Creality CR-X
@ -264,7 +264,7 @@ default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @
#family = CR-X
#bed_model = cr10v2_bed.stl
#bed_texture = cr10spro.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CRXPRO]
#name = Creality CR-X Pro
@ -273,7 +273,7 @@ default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @
#family = CR-X
#bed_model = cr10v2_bed.stl
#bed_texture = cr10spro.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
# All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface.
@ -281,6 +281,7 @@ default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @
# Common print preset
[print:*common*]
avoid_crossing_perimeters = 0
bridge_acceleration = 250
bridge_angle = 0
bridge_flow_ratio = 0.95
bridge_speed = 25
@ -288,6 +289,7 @@ brim_width = 0
clip_multipart_objects = 1
compatible_printers =
complete_objects = 0
default_acceleration = 500
dont_support_bridges = 1
elefant_foot_compensation = 0.1
ensure_vertical_shell_thickness = 1
@ -383,6 +385,7 @@ layer_height = 0.08
perimeters = 3
bottom_solid_layers = 9
top_solid_layers = 11
bridge_flow_ratio = 0.70
[print:*0.10mm*]
inherits = *common*
@ -390,6 +393,7 @@ layer_height = 0.10
perimeters = 3
bottom_solid_layers = 7
top_solid_layers = 9
bridge_flow_ratio = 0.70
[print:*0.12mm*]
inherits = *common*
@ -397,12 +401,14 @@ layer_height = 0.12
perimeters = 3
bottom_solid_layers = 6
top_solid_layers = 7
bridge_flow_ratio = 0.70
[print:*0.16mm*]
inherits = *common*
layer_height = 0.16
bottom_solid_layers = 5
top_solid_layers = 7
bridge_flow_ratio = 0.85
[print:*0.20mm*]
inherits = *common*
@ -631,9 +637,11 @@ first_layer_bed_temperature = 60
filament_cost = 19.00
filament_density = 1.24
filament_colour = #FF0000
filament_spool_weight = 256
[filament:Devil Design PLA (Galaxy) @CREALITY]
[filament:Devil Design PLA Galaxy @CREALITY]
inherits = *PLA*
renamed_from = "Devil Design PLA (Galaxy) @CREALITY"
filament_vendor = Devil Design
temperature = 225
bed_temperature = 65
@ -642,6 +650,7 @@ first_layer_bed_temperature = 65
filament_cost = 19.00
filament_density = 1.24
filament_colour = #FF0000
filament_spool_weight = 256
[filament:Extrudr PLA NX2 @CREALITY]
inherits = *PLA*
@ -700,6 +709,40 @@ filament_density = 1.24
filament_colour = #125467
filament_spool_weight = 238
[filament:3DJAKE ecoPLA Matt @CREALITY]
inherits = *PLA*
filament_vendor = 3DJAKE
temperature = 195
bed_temperature = 60
first_layer_temperature = 195
first_layer_bed_temperature = 60
filament_cost = 24.99
filament_density = 1.38
filament_colour = #125467
filament_spool_weight = 238
[filament:3DJAKE ecoPLA Tough @CREALITY]
inherits = *PLA*
filament_vendor = 3DJAKE
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 29.99
filament_density = 1.21
filament_colour = #125467
[filament:FormFutura Tough PLA @CREALITY]
inherits = *PLA*
filament_vendor = FormFutura
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 46.65
filament_density = 1.21
filament_colour = #ed000e
[filament:123-3D Jupiter PLA @CREALITY]
inherits = *PLA*
filament_vendor = 123-3D
@ -926,7 +969,7 @@ printer_model = CR5PROH
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_CREALITY\nPRINTER_MODEL_CR5PROH\nPRINTER_HAS_BOWDEN
[printer:Creality CR-6 SE]
inherits = *common*; *fastabl*; *pauseprint*
inherits = *common*; *pauseprint*
bed_shape = 5x0,230x0,230x235,5x235
printer_model = CR6SE
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_CREALITY\nPRINTER_MODEL_CR6SE\nPRINTER_HAS_BOWDEN

View file

@ -1,2 +1,3 @@
min_slic3r_version = 2.4.0-alpha0
min_slic3r_version = 2.3.1-beta
0.0.1 Initial version
0.0.2 Improved start gcode, changed filename format

View file

@ -3,8 +3,8 @@
[vendor]
# Vendor name will be shown by the Config Wizard.
name = INAT
config_version = 0.0.1
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/
config_version = 0.0.2
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/
###
### PRINTER LIST
@ -133,7 +133,7 @@ extruder_clearance_radius = 85
extruder_clearance_height = 34
gcode_comments = 0
gcode_label_objects = 0
output_filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode
output_filename_format = {input_filename_base}_{filament_type[0]}.gcode
[print:0.2mm Standard @PROTON_X]
@ -193,7 +193,7 @@ use_firmware_retraction = 0
use_volumetric_e = 0
variable_layer_height = 1
#gcodes
start_gcode = G28 ;Home\nG0 Z0.3 F200 ;Move nozzle down\nM192 S50 ; Wait for probe temperature to settle\nG29\nG0 X0 Y0 Z30 F6000\nM84 E\nM0\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0\n
start_gcode = G28 ;Home\nG0 X-2 Y150 F6000 ;Move to the side\nG0 Z0.3 F200 ;Move nozzle down\nM192 ; Wait for probe temperature to settle\nG28 Z\nG29\nG0 X0 Y0 Z30 F6000\nM84 E\nM0\nG1 Z15.0 F6000 ;Move the platform down 15mm\n
end_gcode = M400\nM104 S0\nM140 S0\nM107\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X R5\nG0 Y300 F2000\nM84\n
color_change_gcode = M600
#limits

View file

@ -1,3 +1,5 @@
min_slic3r_version = 2.4.0-alpha0
1.3.0-alpha0 Disabled thick bridges, updated support settings.
min_slic3r_version = 2.3.0-rc1
1.2.4 Updated cost/density values in filament settings. Various changes in print settings.
1.2.3 Updated firmware version. Updated end g-code in MMU2 printer profiles.

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before After
Before After

View file

@ -1,4 +1,5 @@
min_slic3r_version = 2.3.0-alpha3
0.0.7 Added PLA, PETG profiles for 0.25 nozzle, fixed supports on 0.8 nozzle profile, fixed max volumetric speed, disabled elefant foot compensation
0.0.6 Added material TPU 93A (SMARTFIL)
0.0.5 Removed obsolete host keys.
0.0.4 Added PLA, PETG profiles for 0.8 nozzle, update print materials

View file

@ -6,7 +6,7 @@
name = TriLAB
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.6
config_version = 0.0.7
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -17,16 +17,16 @@ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/Prus
[printer_model:DQ2]
name = DeltiQ 2
variants = 0.4; 0.8
variants = 0.4; 0.25; 0.8
technology = FFF
family = DeltiQ 2
bed_model = dq2_bed.stl
bed_texture = dq2_bed_texture.svg
default_materials = DeltiQ - PLA - Generic; DeltiQ - PETG - Generic; DeltiQ - ABS - Generic; DeltiQ - PLA - ExtraFill (Fillamentum); DeltiQ - PETG (Devil Design); DeltiQ - ABS - ExtraFill (Fillamentum); DeltiQ - ASA - ExtraFill (Fillamentum); DeltiQ - CPE - HG100 (Fillamentum); DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 93A (SMARTFIL); DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle
default_materials = DeltiQ - PLA - Generic; DeltiQ - PETG - Generic; DeltiQ - ABS - Generic; DeltiQ - PLA - ExtraFill (Fillamentum); DeltiQ - PETG (Devil Design); DeltiQ - ABS - ExtraFill (Fillamentum); DeltiQ - ASA - ExtraFill (Fillamentum); DeltiQ - CPE - HG100 (Fillamentum); DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 93A (SMARTFIL); DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle; DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle
[printer_model:DQ2P]
name = DeltiQ 2 Plus
variants = 0.4; 0.8
variants = 0.4; 0.25; 0.8
technology = FFF
family = DeltiQ 2
bed_model = dq2_bed.stl
@ -110,7 +110,7 @@ complete_objects = 0
default_acceleration = 2000
dont_support_bridges = 0
draft_shield = 0
elefant_foot_compensation = 0.2
elefant_foot_compensation = 0.0
ensure_vertical_shell_thickness = 0
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 30
@ -150,7 +150,7 @@ min_skirt_length = 4
notes =
only_retract_when_crossing_perimeters = 1
ooze_prevention = 0
output_filename_format = {input_filename_base}_{printer_model}_{filament_type[0]}_{layer_height}mm_{print_time}.gcode
output_filename_format = {input_filename_base}_{printer_model}_{filament_type[0]}_{layer_height}mm_{print_time}_{timestamp}.gcode
overhangs = 1
perimeter_acceleration = 1500
perimeter_extruder = 1
@ -283,6 +283,37 @@ travel_speed = 200
max_print_speed = 40
complete_objects = 1
[print:DeltiQ 0.07mm Quality @0.25 nozzle]
inherits = DeltiQ 0.20mm Normal
bottom_solid_layers = 6
bottom_solid_min_thickness = 0.5
bridge_speed = 60
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and nozzle_diameter[0]==0.25
elefant_foot_compensation = 0.0
external_perimeter_extrusion_width = 0.27
extrusion_width = 0.25
first_layer_extrusion_width = 0.26
first_layer_height = 0.1
infill_extrusion_width = 0.27
infill_overlap = 50%
layer_height = 0.07
overhangs = 1
perimeter_extrusion_width = 0.27
perimeters = 5
solid_infill_extrusion_width = 0.27
skirts = 2
support_material_extrusion_width = 0.27
support_material_contact_distance = 0.1
top_infill_extrusion_width = 0.27
top_solid_layers = 6
top_solid_min_thickness = 0.5
thin_walls = 1
[print:DeltiQ 0.20mm Normal @0.25 nozzle]
inherits = DeltiQ 0.07mm Quality @0.25 nozzle
first_layer_height = 0.2
layer_height = 0.2
[print:DeltiQ 0.40mm Normal @0.8 nozzle]
inherits = DeltiQ 0.20mm Normal
bottom_solid_layers = 3
@ -290,7 +321,7 @@ bottom_solid_min_thickness = 1.2
bridge_flow_ratio = 0.90
bridge_speed = 20
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and nozzle_diameter[0]==0.8
elefant_foot_compensation = 0.2
elefant_foot_compensation = 0.0
external_perimeter_extrusion_width = 0.80
external_perimeter_speed = 30
extrusion_width = 0.80
@ -311,6 +342,8 @@ perimeters = 2
small_perimeter_speed = 20
solid_infill_extrusion_width = 0.8
solid_infill_speed = 60
support_material_extrusion_width = 0.8
support_material_contact_distance = 0.2
top_infill_extrusion_width = 0.8
top_solid_infill_speed = 40
top_solid_layers = 4
@ -412,7 +445,7 @@ fan_below_layer_time = 20
filament_vendor = Fillamentum
filament_cost = 774
filament_density = 1.08
filament_max_volumetric_speed = 4
filament_max_volumetric_speed = 8
filament_retract_before_travel = 3
filament_retract_before_wipe = 70%
filament_retract_layer_change = 1
@ -474,6 +507,19 @@ min_print_speed = 10
slowdown_below_layer_time = 5
temperature = 260
[filament:DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle]
inherits = DeltiQ - PLA - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.25
[filament:DeltiQ - PETG (Devil Design) @0.25 nozzle]
inherits = DeltiQ - PETG (Devil Design)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.25
first_layer_temperature = 225
temperature = 220
max_fan_speed = 65
min_fan_speed = 40
bridge_fan_speed = 100
[filament:DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle]
inherits = DeltiQ - PLA - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.8
@ -536,7 +582,7 @@ filament_vendor = Generic
filament_cost = 1870
filament_density = 1.22
filament_deretract_speed = nil
filament_max_volumetric_speed = 0.7
filament_max_volumetric_speed = 3.0
filament_retract_before_travel = 2
filament_retract_before_wipe = 70%
filament_retract_layer_change = 0
@ -634,7 +680,7 @@ filament_vendor = Fillamentum
filament_cost = 1870
filament_density = 1.22
filament_deretract_speed = nil
filament_max_volumetric_speed = 2.9
filament_max_volumetric_speed = 3.0
filament_retract_before_travel = 2
filament_retract_before_wipe = 70%
filament_retract_layer_change = 0
@ -665,7 +711,7 @@ filament_vendor = Fillamentum
filament_cost = 1870
filament_density = 1.22
filament_deretract_speed = nil
filament_max_volumetric_speed = 2.9
filament_max_volumetric_speed = 3.0
filament_retract_before_travel = 2
filament_retract_before_wipe = 70%
filament_retract_layer_change = 0
@ -689,7 +735,7 @@ extrusion_multiplier = 1.10
filament_cost = 1870
filament_density = 1.23
filament_deretract_speed = nil
filament_max_volumetric_speed = 2.9
filament_max_volumetric_speed = 3.0
filament_retract_before_wipe = 70%
filament_retract_length = 2.5
filament_retract_speed = 20
@ -822,6 +868,15 @@ printer_model = DQ2
printer_variant = 0.4
max_print_height = 320
[printer:DeltiQ 2 - 0.25 nozzle]
inherits = DeltiQ 2
printer_variant = 0.25
max_layer_height = 0.15
min_layer_height = 0.07
nozzle_diameter = 0.25
default_filament_profile = "DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle"
default_print_profile = DeltiQ 0.07mm Quality @0.25 nozzle
[printer:DeltiQ 2 - 0.8 nozzle]
inherits = DeltiQ 2
printer_variant = 0.8
@ -837,6 +892,15 @@ printer_model = DQ2P
printer_variant = 0.4
max_print_height = 500
[printer:DeltiQ 2 Plus - 0.25 nozzle]
inherits = DeltiQ 2 Plus
printer_variant = 0.25
max_layer_height = 0.15
min_layer_height = 0.07
nozzle_diameter = 0.25
default_filament_profile = "DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle"
default_print_profile = DeltiQ 0.07mm Quality @0.25 nozzle
[printer:DeltiQ 2 Plus - 0.8 nozzle]
inherits = DeltiQ 2 Plus
printer_variant = 0.8

View file

@ -217,6 +217,11 @@ int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */,
int wmain(int argc, wchar_t **argv)
{
#endif
// Allow the asserts to open message box, such message box allows to ignore the assert and continue with the application.
// Without this call, the seemingly same message box is being opened by the abort() function, but that is too late and
// the application will be killed even if "Ignore" button is pressed.
_set_error_mode(_OUT_TO_MSGBOX);
std::vector<wchar_t*> argv_extended;
argv_extended.emplace_back(argv[0]);

View file

@ -2,8 +2,9 @@ project(clipper)
cmake_minimum_required(VERSION 2.6)
add_library(clipper STATIC
clipper.cpp
clipper.hpp
# We are using ClipperLib compiled as part of the libslic3r project using Slic3r::Point as its base type.
# clipper.cpp
# clipper.hpp
clipper_z.cpp
clipper_z.hpp
)

File diff suppressed because it is too large Load diff

View file

@ -37,10 +37,12 @@
#include <inttypes.h>
#include <functional>
#include <Eigen/Geometry>
#define CLIPPER_VERSION "6.2.6"
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define use_xyz
//CLIPPERLIB_USE_XYZ: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define CLIPPERLIB_USE_XYZ
//use_lines: Enables line clipping. Adds a very minor cost to performance.
#define use_lines
@ -57,11 +59,15 @@
#include <functional>
#include <queue>
#ifdef use_xyz
#ifdef CLIPPERLIB_NAMESPACE_PREFIX
namespace CLIPPERLIB_NAMESPACE_PREFIX {
#endif // CLIPPERLIB_NAMESPACE_PREFIX
#ifdef CLIPPERLIB_USE_XYZ
namespace ClipperLib_Z {
#else /* use_xyz */
#else
namespace ClipperLib {
#endif /* use_xyz */
#endif
enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
enum PolyType { ptSubject, ptClip };
@ -71,32 +77,37 @@ enum PolyType { ptSubject, ptClip };
//see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
// If defined, Clipper will work with 32bit signed int coordinates to reduce memory
// consumption and to speed up exact orientation predicate calculation.
// In that case, coordinates and their differences (vectors of the coordinates) have to fit int32_t.
#define CLIPPERLIB_INT32
// Point coordinate type
#ifdef CLIPPERLIB_INT32
// Coordinates and their differences (vectors of the coordinates) have to fit int32_t.
typedef int32_t cInt;
#else
typedef int64_t cInt;
// Maximum cInt value to allow a cross product calculation using 32bit expressions.
static cInt const loRange = 0x3FFFFFFF;
static constexpr cInt const loRange = 0x3FFFFFFF; // 0x3FFFFFFF = 1 073 741 823
// Maximum allowed cInt value.
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
static constexpr cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
#endif // CLIPPERLIB_INT32
struct IntPoint {
cInt X;
cInt Y;
#ifdef use_xyz
cInt Z;
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
#else
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
#endif
#ifdef CLIPPERLIB_INTPOINT_TYPE
using IntPoint = CLIPPERLIB_INTPOINT_TYPE;
#else // CLIPPERLIB_INTPOINT_TYPE
using IntPoint = Eigen::Matrix<cInt,
#ifdef CLIPPERLIB_USE_XYZ
3
#else // CLIPPERLIB_USE_XYZ
2
#endif // CLIPPERLIB_USE_XYZ
, 1, Eigen::DontAlign>;
#endif // CLIPPERLIB_INTPOINT_TYPE
using DoublePoint = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
{
return a.X != b.X || a.Y != b.Y;
}
};
//------------------------------------------------------------------------------
typedef std::vector<IntPoint> Path;
@ -109,16 +120,9 @@ std::ostream& operator <<(std::ostream &s, const IntPoint &p);
std::ostream& operator <<(std::ostream &s, const Path &p);
std::ostream& operator <<(std::ostream &s, const Paths &p);
struct DoublePoint
{
double X;
double Y;
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
};
//------------------------------------------------------------------------------
#ifdef use_xyz
#ifdef CLIPPERLIB_USE_XYZ
typedef std::function<void(const IntPoint& e1bot, const IntPoint& e1top, const IntPoint& e2bot, const IntPoint& e2top, IntPoint& pt)> ZFillCallback;
#endif
@ -187,9 +191,7 @@ double Area(const Path &poly);
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
int PointInPolygon(const IntPoint &pt, const Path &path);
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType = pftEvenOdd);
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
void CleanPolygon(Path& poly, double distance = 1.415);
@ -259,11 +261,11 @@ enum EdgeSide { esLeft = 1, esRight = 2};
};
// Point of an output polygon.
// 36B on 64bit system without use_xyz.
// 36B on 64bit system without CLIPPERLIB_USE_XYZ.
struct OutPt {
// 4B
int Idx;
// 16B without use_xyz / 24B with use_xyz
// 16B without CLIPPERLIB_USE_XYZ / 24B with CLIPPERLIB_USE_XYZ
IntPoint Pt;
// 4B on 32bit system, 8B on 64bit system
OutPt *Next;
@ -289,10 +291,65 @@ enum EdgeSide { esLeft = 1, esRight = 2};
class ClipperBase
{
public:
ClipperBase() : m_UseFullRange(false), m_HasOpenPaths(false) {}
ClipperBase() :
#ifndef CLIPPERLIB_INT32
m_UseFullRange(false),
#endif // CLIPPERLIB_INT32
m_HasOpenPaths(false) {}
~ClipperBase() { Clear(); }
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
template<typename PathsProvider>
bool AddPaths(PathsProvider &&paths_provider, PolyType PolyTyp, bool Closed)
{
size_t num_paths = paths_provider.size();
if (num_paths == 0)
return false;
if (num_paths == 1)
return AddPath(*paths_provider.begin(), PolyTyp, Closed);
std::vector<int> num_edges(num_paths, 0);
int num_edges_total = 0;
size_t i = 0;
for (const Path &pg : paths_provider) {
// Remove duplicate end point from a closed input path.
// Remove duplicate points from the end of the input path.
int highI = (int)pg.size() -1;
if (Closed)
while (highI > 0 && (pg[highI] == pg[0]))
--highI;
while (highI > 0 && (pg[highI] == pg[highI -1]))
--highI;
if ((Closed && highI < 2) || (!Closed && highI < 1))
highI = -1;
num_edges[i ++] = highI + 1;
num_edges_total += highI + 1;
}
if (num_edges_total == 0)
return false;
// Allocate a new edge array.
std::vector<TEdge> edges(num_edges_total);
// Fill in the edge array.
bool result = false;
TEdge *p_edge = edges.data();
i = 0;
for (const Path &pg : paths_provider) {
if (num_edges[i]) {
bool res = AddPathInternal(pg, num_edges[i] - 1, PolyTyp, Closed, p_edge);
if (res) {
p_edge += num_edges[i];
result = true;
}
}
++ i;
}
if (result)
// At least some edges were generated. Remember the edge array.
m_edges.emplace_back(std::move(edges));
return result;
}
void Clear();
IntRect GetBounds();
// By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping.
@ -310,9 +367,14 @@ protected:
// Local minima (Y, left edge, right edge) sorted by ascending Y.
std::vector<LocalMinimum> m_MinimaList;
#ifdef CLIPPERLIB_INT32
static constexpr const bool m_UseFullRange = false;
#else // CLIPPERLIB_INT32
// True if the input polygons have abs values higher than loRange, but lower than hiRange.
// False if the input polygons have abs values lower or equal to loRange.
bool m_UseFullRange;
#endif // CLIPPERLIB_INT32
// A vector of edges per each input path.
std::vector<std::vector<TEdge>> m_edges;
// Don't remove intermediate vertices of a collinear sequence of points.
@ -349,7 +411,7 @@ public:
bool StrictlySimple() const {return m_StrictSimple;};
void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
#ifdef CLIPPERLIB_USE_XYZ
void ZFillFunction(ZFillCallback zFillFunc) { m_ZFill = zFillFunc; }
#endif
protected:
@ -382,7 +444,7 @@ private:
// Does the result go to a PolyTree or Paths?
bool m_UsingPolyTree;
bool m_StrictSimple;
#ifdef use_xyz
#ifdef CLIPPERLIB_USE_XYZ
ZFillCallback m_ZFill; //custom callback
#endif
void SetWindingCount(TEdge& edge) const;
@ -435,7 +497,7 @@ private:
void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const;
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const;
#ifdef use_xyz
#ifdef CLIPPERLIB_USE_XYZ
void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
#endif
};
@ -448,7 +510,11 @@ public:
MiterLimit(miterLimit), ArcTolerance(roundPrecision), ShortestEdgeLength(shortestEdgeLength), m_lowest(-1, 0) {}
~ClipperOffset() { Clear(); }
void AddPath(const Path& path, JoinType joinType, EndType endType);
void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
template<typename PathsProvider>
void AddPaths(PathsProvider &&paths, JoinType joinType, EndType endType) {
for (const Path &path : paths)
AddPath(path, joinType, endType);
}
void Execute(Paths& solution, double delta);
void Execute(PolyTree& solution, double delta);
void Clear();
@ -485,8 +551,20 @@ class clipperException : public std::exception
};
//------------------------------------------------------------------------------
template<typename PathsProvider>
inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftEvenOdd) {
Clipper c;
c.StrictlySimple(true);
c.AddPaths(std::forward<PathsProvider>(in_polys), ptSubject, true);
Paths out;
c.Execute(ctUnion, out, fillType, fillType);
return out;
}
} //ClipperLib namespace
#ifdef CLIPPERLIB_NAMESPACE_PREFIX
} // namespace CLIPPERLIB_NAMESPACE_PREFIX
#endif // CLIPPERLIB_NAMESPACE_PREFIX
#endif //clipper_hpp

View file

@ -1,7 +1,7 @@
// Hackish wrapper around the ClipperLib library to compile the Clipper library with the Z support.
// Enable the Z coordinate support.
#define use_xyz
#define CLIPPERLIB_USE_XYZ
// and let it compile
#include "clipper.cpp"

View file

@ -2,17 +2,17 @@
#ifndef clipper_z_hpp
#ifdef clipper_hpp
#error "You should include the clipper_z.hpp first"
#error "You should include clipper_z.hpp before clipper.hpp"
#endif
#define clipper_z_hpp
// Enable the Z coordinate support.
#define use_xyz
#define CLIPPERLIB_USE_XYZ
#include "clipper.hpp"
#undef clipper_hpp
#undef use_xyz
#undef CLIPPERLIB_USE_XYZ
#endif // clipper_z_hpp

View file

@ -12,11 +12,8 @@ set(LIBNEST2D_SRCFILES
include/libnest2d/placers/bottomleftplacer.hpp
include/libnest2d/placers/nfpplacer.hpp
include/libnest2d/selections/selection_boilerplate.hpp
#include/libnest2d/selections/filler.hpp
include/libnest2d/selections/firstfit.hpp
#include/libnest2d/selections/djd_heuristic.hpp
include/libnest2d/backends/clipper/geometries.hpp
include/libnest2d/backends/clipper/clipper_polygon.hpp
include/libnest2d/backends/libslic3r/geometries.hpp
include/libnest2d/optimizers/nlopt/nlopt_boilerplate.hpp
include/libnest2d/optimizers/nlopt/simplex.hpp
include/libnest2d/optimizers/nlopt/subplex.hpp
@ -27,5 +24,5 @@ set(LIBNEST2D_SRCFILES
add_library(libnest2d STATIC ${LIBNEST2D_SRCFILES})
target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(libnest2d PUBLIC clipper NLopt::nlopt TBB::tbb Boost::boost)
target_compile_definitions(libnest2d PUBLIC LIBNEST2D_THREADING_tbb LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_clipper)
target_link_libraries(libnest2d PUBLIC NLopt::nlopt TBB::tbb Boost::boost libslic3r)
target_compile_definitions(libnest2d PUBLIC LIBNEST2D_THREADING_tbb LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_libslic3r)

View file

@ -1,72 +0,0 @@
#ifndef CLIPPER_POLYGON_HPP
#define CLIPPER_POLYGON_HPP
#include <clipper.hpp>
namespace ClipperLib {
struct Polygon {
Path Contour;
Paths Holes;
inline Polygon() = default;
inline explicit Polygon(const Path& cont): Contour(cont) {}
// inline explicit Polygon(const Paths& holes):
// Holes(holes) {}
inline Polygon(const Path& cont, const Paths& holes):
Contour(cont), Holes(holes) {}
inline explicit Polygon(Path&& cont): Contour(std::move(cont)) {}
// inline explicit Polygon(Paths&& holes): Holes(std::move(holes)) {}
inline Polygon(Path&& cont, Paths&& holes):
Contour(std::move(cont)), Holes(std::move(holes)) {}
};
inline IntPoint& operator +=(IntPoint& p, const IntPoint& pa ) {
// This could be done with SIMD
p.X += pa.X;
p.Y += pa.Y;
return p;
}
inline IntPoint operator+(const IntPoint& p1, const IntPoint& p2) {
IntPoint ret = p1;
ret += p2;
return ret;
}
inline IntPoint& operator -=(IntPoint& p, const IntPoint& pa ) {
p.X -= pa.X;
p.Y -= pa.Y;
return p;
}
inline IntPoint operator -(const IntPoint& p ) {
IntPoint ret = p;
ret.X = -ret.X;
ret.Y = -ret.Y;
return ret;
}
inline IntPoint operator-(const IntPoint& p1, const IntPoint& p2) {
IntPoint ret = p1;
ret -= p2;
return ret;
}
inline IntPoint& operator *=(IntPoint& p, const IntPoint& pa ) {
p.X *= pa.X;
p.Y *= pa.Y;
return p;
}
inline IntPoint operator*(const IntPoint& p1, const IntPoint& p2) {
IntPoint ret = p1;
ret *= p2;
return ret;
}
}
#endif // CLIPPER_POLYGON_HPP

View file

@ -1,356 +0,0 @@
#ifndef CLIPPER_BACKEND_HPP
#define CLIPPER_BACKEND_HPP
#include <sstream>
#include <unordered_map>
#include <cassert>
#include <vector>
#include <iostream>
#include <libnest2d/geometry_traits.hpp>
#include <libnest2d/geometry_traits_nfp.hpp>
#include "clipper_polygon.hpp"
namespace libnest2d {
// Aliases for convinience
using PointImpl = ClipperLib::IntPoint;
using PathImpl = ClipperLib::Path;
using HoleStore = ClipperLib::Paths;
using PolygonImpl = ClipperLib::Polygon;
template<> struct ShapeTag<PolygonImpl> { using Type = PolygonTag; };
template<> struct ShapeTag<PathImpl> { using Type = PathTag; };
template<> struct ShapeTag<PointImpl> { using Type = PointTag; };
// Type of coordinate units used by Clipper. Enough to specialize for point,
// the rest of the types will work (Path, Polygon)
template<> struct CoordType<PointImpl> {
using Type = ClipperLib::cInt;
static const constexpr ClipperLib::cInt MM_IN_COORDS = 1000000;
};
// Enough to specialize for path, it will work for multishape and Polygon
template<> struct PointType<PathImpl> { using Type = PointImpl; };
// This is crucial. CountourType refers to itself by default, so we don't have
// to secialize for clipper Path. ContourType<PathImpl>::Type is PathImpl.
template<> struct ContourType<PolygonImpl> { using Type = PathImpl; };
// The holes are contained in Clipper::Paths
template<> struct HolesContainer<PolygonImpl> { using Type = ClipperLib::Paths; };
namespace pointlike {
// Tell libnest2d how to extract the X coord from a ClipperPoint object
template<> inline ClipperLib::cInt x(const PointImpl& p)
{
return p.X;
}
// Tell libnest2d how to extract the Y coord from a ClipperPoint object
template<> inline ClipperLib::cInt y(const PointImpl& p)
{
return p.Y;
}
// Tell libnest2d how to extract the X coord from a ClipperPoint object
template<> inline ClipperLib::cInt& x(PointImpl& p)
{
return p.X;
}
// Tell libnest2d how to extract the Y coord from a ClipperPoint object
template<> inline ClipperLib::cInt& y(PointImpl& p)
{
return p.Y;
}
}
// Using the libnest2d default area implementation
#define DISABLE_BOOST_AREA
namespace shapelike {
template<>
inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance, const PolygonTag&)
{
#define DISABLE_BOOST_OFFSET
using ClipperLib::ClipperOffset;
using ClipperLib::jtSquare;
using ClipperLib::etClosedPolygon;
using ClipperLib::Paths;
Paths result;
try {
ClipperOffset offs;
offs.AddPath(sh.Contour, jtSquare, etClosedPolygon);
offs.AddPaths(sh.Holes, jtSquare, etClosedPolygon);
offs.Execute(result, static_cast<double>(distance));
} catch (ClipperLib::clipperException &) {
throw GeometryException(GeomErr::OFFSET);
}
// Offsetting reverts the orientation and also removes the last vertex
// so boost will not have a closed polygon.
// we plan to replace contours
sh.Holes.clear();
bool found_the_contour = false;
for(auto& r : result) {
if(ClipperLib::Orientation(r)) {
// We don't like if the offsetting generates more than one contour
// but throwing would be an overkill. Instead, we should warn the
// caller about the inability to create correct geometries
if(!found_the_contour) {
sh.Contour = std::move(r);
ClipperLib::ReversePath(sh.Contour);
auto front_p = sh.Contour.front();
sh.Contour.emplace_back(std::move(front_p));
found_the_contour = true;
} else {
dout() << "Warning: offsetting result is invalid!";
/* TODO warning */
}
} else {
// TODO If there are multiple contours we can't be sure which hole
// belongs to the first contour. (But in this case the situation is
// bad enough to let it go...)
sh.Holes.emplace_back(std::move(r));
ClipperLib::ReversePath(sh.Holes.back());
auto front_p = sh.Holes.back().front();
sh.Holes.back().emplace_back(std::move(front_p));
}
}
}
template<>
inline void offset(PathImpl& sh, TCoord<PointImpl> distance, const PathTag&)
{
PolygonImpl p(std::move(sh));
offset(p, distance, PolygonTag());
sh = p.Contour;
}
// Tell libnest2d how to make string out of a ClipperPolygon object
template<> inline std::string toString(const PolygonImpl& sh)
{
std::stringstream ss;
ss << "Contour {\n";
for(auto p : sh.Contour) {
ss << "\t" << p.X << " " << p.Y << "\n";
}
ss << "}\n";
for(auto& h : sh.Holes) {
ss << "Holes {\n";
for(auto p : h) {
ss << "\t{\n";
ss << "\t\t" << p.X << " " << p.Y << "\n";
ss << "\t}\n";
}
ss << "}\n";
}
return ss.str();
}
template<>
inline PolygonImpl create(const PathImpl& path, const HoleStore& holes)
{
PolygonImpl p;
p.Contour = path;
p.Holes = holes;
return p;
}
template<> inline PolygonImpl create( PathImpl&& path, HoleStore&& holes) {
PolygonImpl p;
p.Contour.swap(path);
p.Holes.swap(holes);
return p;
}
template<>
inline const THolesContainer<PolygonImpl>& holes(const PolygonImpl& sh)
{
return sh.Holes;
}
template<> inline THolesContainer<PolygonImpl>& holes(PolygonImpl& sh)
{
return sh.Holes;
}
template<>
inline TContour<PolygonImpl>& hole(PolygonImpl& sh, unsigned long idx)
{
return sh.Holes[idx];
}
template<>
inline const TContour<PolygonImpl>& hole(const PolygonImpl& sh,
unsigned long idx)
{
return sh.Holes[idx];
}
template<> inline size_t holeCount(const PolygonImpl& sh)
{
return sh.Holes.size();
}
template<> inline PathImpl& contour(PolygonImpl& sh)
{
return sh.Contour;
}
template<>
inline const PathImpl& contour(const PolygonImpl& sh)
{
return sh.Contour;
}
#define DISABLE_BOOST_TRANSLATE
template<>
inline void translate(PolygonImpl& sh, const PointImpl& offs)
{
for(auto& p : sh.Contour) { p += offs; }
for(auto& hole : sh.Holes) for(auto& p : hole) { p += offs; }
}
#define DISABLE_BOOST_ROTATE
template<>
inline void rotate(PolygonImpl& sh, const Radians& rads)
{
using Coord = TCoord<PointImpl>;
auto cosa = rads.cos();
auto sina = rads.sin();
for(auto& p : sh.Contour) {
p = {
static_cast<Coord>(p.X * cosa - p.Y * sina),
static_cast<Coord>(p.X * sina + p.Y * cosa)
};
}
for(auto& hole : sh.Holes) for(auto& p : hole) {
p = {
static_cast<Coord>(p.X * cosa - p.Y * sina),
static_cast<Coord>(p.X * sina + p.Y * cosa)
};
}
}
} // namespace shapelike
#define DISABLE_BOOST_NFP_MERGE
inline TMultiShape<PolygonImpl> clipper_execute(
ClipperLib::Clipper& clipper,
ClipperLib::ClipType clipType,
ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd,
ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd)
{
TMultiShape<PolygonImpl> retv;
ClipperLib::PolyTree result;
clipper.Execute(clipType, result, subjFillType, clipFillType);
retv.reserve(static_cast<size_t>(result.Total()));
std::function<void(ClipperLib::PolyNode*, PolygonImpl&)> processHole;
auto processPoly = [&retv, &processHole](ClipperLib::PolyNode *pptr) {
PolygonImpl poly;
poly.Contour.swap(pptr->Contour);
assert(!pptr->IsHole());
if(!poly.Contour.empty() ) {
auto front_p = poly.Contour.front();
auto &back_p = poly.Contour.back();
if(front_p.X != back_p.X || front_p.Y != back_p.X)
poly.Contour.emplace_back(front_p);
}
for(auto h : pptr->Childs) { processHole(h, poly); }
retv.push_back(poly);
};
processHole = [&processPoly](ClipperLib::PolyNode *pptr, PolygonImpl& poly)
{
poly.Holes.emplace_back(std::move(pptr->Contour));
assert(pptr->IsHole());
if(!poly.Contour.empty() ) {
auto front_p = poly.Contour.front();
auto &back_p = poly.Contour.back();
if(front_p.X != back_p.X || front_p.Y != back_p.X)
poly.Contour.emplace_back(front_p);
}
for(auto c : pptr->Childs) processPoly(c);
};
auto traverse = [&processPoly] (ClipperLib::PolyNode *node)
{
for(auto ch : node->Childs) processPoly(ch);
};
traverse(&result);
return retv;
}
namespace nfp {
template<> inline TMultiShape<PolygonImpl>
merge(const TMultiShape<PolygonImpl>& shapes)
{
ClipperLib::Clipper clipper(ClipperLib::ioReverseSolution);
bool closed = true;
bool valid = true;
for(auto& path : shapes) {
valid &= clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
for(auto& h : path.Holes)
valid &= clipper.AddPath(h, ClipperLib::ptSubject, closed);
}
if(!valid) throw GeometryException(GeomErr::MERGE);
return clipper_execute(clipper, ClipperLib::ctUnion, ClipperLib::pftNegative);
}
}
}
#define DISABLE_BOOST_CONVEX_HULL
//#define DISABLE_BOOST_SERIALIZE
//#define DISABLE_BOOST_UNSERIALIZE
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4244)
#pragma warning(disable: 4267)
#endif
// All other operators and algorithms are implemented with boost
#include <libnest2d/utils/boost_alg.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // CLIPPER_BACKEND_HPP

View file

@ -0,0 +1,283 @@
#ifndef CLIPPER_BACKEND_HPP
#define CLIPPER_BACKEND_HPP
#include <sstream>
#include <unordered_map>
#include <cassert>
#include <vector>
#include <iostream>
#include <libnest2d/geometry_traits.hpp>
#include <libnest2d/geometry_traits_nfp.hpp>
#include <libslic3r/ExPolygon.hpp>
#include <libslic3r/ClipperUtils.hpp>
namespace Slic3r {
template<class T, class En = void> struct IsVec_ : public std::false_type {};
template<class T> struct IsVec_< Vec<2, T> >: public std::true_type {};
template<class T>
static constexpr const bool IsVec = IsVec_<libnest2d::remove_cvref_t<T>>::value;
template<class T, class O> using VecOnly = std::enable_if_t<IsVec<T>, O>;
inline Point operator+(const Point& p1, const Point& p2) {
Point ret = p1;
ret += p2;
return ret;
}
inline Point operator -(const Point& p ) {
Point ret = p;
ret.x() = -ret.x();
ret.y() = -ret.y();
return ret;
}
inline Point operator-(const Point& p1, const Point& p2) {
Point ret = p1;
ret -= p2;
return ret;
}
inline Point& operator *=(Point& p, const Point& pa ) {
p.x() *= pa.x();
p.y() *= pa.y();
return p;
}
inline Point operator*(const Point& p1, const Point& p2) {
Point ret = p1;
ret *= p2;
return ret;
}
} // namespace Slic3r
namespace libnest2d {
template<class T> using Vec = Slic3r::Vec<2, T>;
// Aliases for convinience
using PointImpl = Slic3r::Point;
using PathImpl = Slic3r::Polygon;
using HoleStore = Slic3r::Polygons;
using PolygonImpl = Slic3r::ExPolygon;
template<> struct ShapeTag<Slic3r::Vec2crd> { using Type = PointTag; };
template<> struct ShapeTag<Slic3r::Point> { using Type = PointTag; };
template<> struct ShapeTag<std::vector<Slic3r::Vec2crd>> { using Type = PathTag; };
template<> struct ShapeTag<Slic3r::Polygon> { using Type = PathTag; };
template<> struct ShapeTag<Slic3r::Points> { using Type = PathTag; };
template<> struct ShapeTag<Slic3r::ExPolygon> { using Type = PolygonTag; };
template<> struct ShapeTag<Slic3r::ExPolygons> { using Type = MultiPolygonTag; };
// Type of coordinate units used by Clipper. Enough to specialize for point,
// the rest of the types will work (Path, Polygon)
template<> struct CoordType<Slic3r::Point> {
using Type = coord_t;
static const constexpr coord_t MM_IN_COORDS = 1000000;
};
template<> struct CoordType<Slic3r::Vec2crd> {
using Type = coord_t;
static const constexpr coord_t MM_IN_COORDS = 1000000;
};
// Enough to specialize for path, it will work for multishape and Polygon
template<> struct PointType<std::vector<Slic3r::Vec2crd>> { using Type = Slic3r::Vec2crd; };
template<> struct PointType<Slic3r::Polygon> { using Type = Slic3r::Point; };
template<> struct PointType<Slic3r::Points> { using Type = Slic3r::Point; };
// This is crucial. CountourType refers to itself by default, so we don't have
// to secialize for clipper Path. ContourType<PathImpl>::Type is PathImpl.
template<> struct ContourType<Slic3r::ExPolygon> { using Type = Slic3r::Polygon; };
// The holes are contained in Clipper::Paths
template<> struct HolesContainer<Slic3r::ExPolygon> { using Type = Slic3r::Polygons; };
template<>
struct OrientationType<Slic3r::Polygon> {
static const constexpr Orientation Value = Orientation::COUNTER_CLOCKWISE;
};
template<>
struct OrientationType<Slic3r::Points> {
static const constexpr Orientation Value = Orientation::COUNTER_CLOCKWISE;
};
template<>
struct ClosureType<Slic3r::Polygon> {
static const constexpr Closure Value = Closure::OPEN;
};
template<>
struct ClosureType<Slic3r::Points> {
static const constexpr Closure Value = Closure::OPEN;
};
template<> struct MultiShape<Slic3r::ExPolygon> { using Type = Slic3r::ExPolygons; };
template<> struct ContourType<Slic3r::ExPolygons> { using Type = Slic3r::Polygon; };
// Using the libnest2d default area implementation
#define DISABLE_BOOST_AREA
namespace shapelike {
template<>
inline void offset(Slic3r::ExPolygon& sh, coord_t distance, const PolygonTag&)
{
#define DISABLE_BOOST_OFFSET
auto res = Slic3r::offset_ex(sh, distance, Slic3r::ClipperLib::jtSquare);
if (!res.empty()) sh = res.front();
}
template<>
inline void offset(Slic3r::Polygon& sh, coord_t distance, const PathTag&)
{
auto res = Slic3r::offset(sh, distance, Slic3r::ClipperLib::jtSquare);
if (!res.empty()) sh = res.front();
}
// Tell libnest2d how to make string out of a ClipperPolygon object
template<> inline std::string toString(const Slic3r::ExPolygon& sh)
{
std::stringstream ss;
ss << "Contour {\n";
for(auto &p : sh.contour.points) {
ss << "\t" << p.x() << " " << p.y() << "\n";
}
ss << "}\n";
for(auto& h : sh.holes) {
ss << "Holes {\n";
for(auto p : h.points) {
ss << "\t{\n";
ss << "\t\t" << p.x() << " " << p.y() << "\n";
ss << "\t}\n";
}
ss << "}\n";
}
return ss.str();
}
template<>
inline Slic3r::ExPolygon create(const Slic3r::Polygon& path, const Slic3r::Polygons& holes)
{
Slic3r::ExPolygon p;
p.contour = path;
p.holes = holes;
return p;
}
template<> inline Slic3r::ExPolygon create(Slic3r::Polygon&& path, Slic3r::Polygons&& holes) {
Slic3r::ExPolygon p;
p.contour.points.swap(path.points);
p.holes.swap(holes);
return p;
}
template<>
inline const THolesContainer<PolygonImpl>& holes(const Slic3r::ExPolygon& sh)
{
return sh.holes;
}
template<> inline THolesContainer<PolygonImpl>& holes(Slic3r::ExPolygon& sh)
{
return sh.holes;
}
template<>
inline Slic3r::Polygon& hole(Slic3r::ExPolygon& sh, unsigned long idx)
{
return sh.holes[idx];
}
template<>
inline const Slic3r::Polygon& hole(const Slic3r::ExPolygon& sh, unsigned long idx)
{
return sh.holes[idx];
}
template<> inline size_t holeCount(const Slic3r::ExPolygon& sh)
{
return sh.holes.size();
}
template<> inline Slic3r::Polygon& contour(Slic3r::ExPolygon& sh)
{
return sh.contour;
}
template<>
inline const Slic3r::Polygon& contour(const Slic3r::ExPolygon& sh)
{
return sh.contour;
}
template<>
inline void reserve(Slic3r::Polygon& p, size_t vertex_capacity, const PathTag&)
{
p.points.reserve(vertex_capacity);
}
template<>
inline void addVertex(Slic3r::Polygon& sh, const PathTag&, const Slic3r::Point &p)
{
sh.points.emplace_back(p);
}
#define DISABLE_BOOST_TRANSLATE
template<>
inline void translate(Slic3r::ExPolygon& sh, const Slic3r::Point& offs)
{
sh.translate(offs);
}
#define DISABLE_BOOST_ROTATE
template<>
inline void rotate(Slic3r::ExPolygon& sh, const Radians& rads)
{
sh.rotate(rads);
}
} // namespace shapelike
namespace nfp {
#define DISABLE_BOOST_NFP_MERGE
template<>
inline TMultiShape<PolygonImpl> merge(const TMultiShape<PolygonImpl>& shapes)
{
return Slic3r::union_ex(shapes);
}
} // namespace nfp
} // namespace libnest2d
#define DISABLE_BOOST_CONVEX_HULL
//#define DISABLE_BOOST_SERIALIZE
//#define DISABLE_BOOST_UNSERIALIZE
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4244)
#pragma warning(disable: 4267)
#endif
// All other operators and algorithms are implemented with boost
#include <libnest2d/utils/boost_alg.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // CLIPPER_BACKEND_HPP

View file

@ -128,22 +128,32 @@ template<class S> struct ContourType<DefaultMultiShape<S>> {
using Type = typename ContourType<S>::Type;
};
enum class Orientation {
CLOCKWISE,
COUNTER_CLOCKWISE
};
enum class Orientation { CLOCKWISE, COUNTER_CLOCKWISE };
template<class S>
struct OrientationType {
// Default Polygon orientation that the library expects
static const Orientation Value = Orientation::CLOCKWISE;
static const constexpr Orientation Value = Orientation::CLOCKWISE;
};
template<class T> inline /*constexpr*/ bool is_clockwise() {
template<class T> inline constexpr bool is_clockwise() {
return OrientationType<TContour<T>>::Value == Orientation::CLOCKWISE;
}
template<class T>
inline const constexpr Orientation OrientationTypeV =
OrientationType<TContour<T>>::Value;
enum class Closure { OPEN, CLOSED };
template<class S> struct ClosureType {
static const constexpr Closure Value = Closure::CLOSED;
};
template<class T>
inline const constexpr Closure ClosureTypeV =
ClosureType<TContour<T>>::Value;
/**
* \brief A point pair base class for other point pairs (segment, box, ...).
@ -474,8 +484,8 @@ inline _Box<P> _Box<P>::infinite(const P& center) {
// It is important for Mx and My to be strictly less than half of the
// range of type C. width(), height() and area() will not overflow this way.
C Mx = C((std::numeric_limits<C>::lowest() + 2 * getX(center)) / 2.01);
C My = C((std::numeric_limits<C>::lowest() + 2 * getY(center)) / 2.01);
C Mx = C((std::numeric_limits<C>::lowest() + 2 * getX(center)) / 4.01);
C My = C((std::numeric_limits<C>::lowest() + 2 * getY(center)) / 4.01);
ret.maxCorner() = center - P{Mx, My};
ret.minCorner() = center + P{Mx, My};
@ -587,9 +597,9 @@ inline void reserve(RawPath& p, size_t vertex_capacity, const PathTag&)
}
template<class S, class...Args>
inline void addVertex(S& sh, const PathTag&, Args...args)
inline void addVertex(S& sh, const PathTag&, const TPoint<S> &p)
{
sh.emplace_back(std::forward<Args>(args)...);
sh.emplace_back(p);
}
template<class S, class Fn>
@ -841,9 +851,9 @@ template<class P> auto rbegin(P& p) -> decltype(_backward(end(p)))
return _backward(end(p));
}
template<class P> auto rcbegin(const P& p) -> decltype(_backward(end(p)))
template<class P> auto rcbegin(const P& p) -> decltype(_backward(cend(p)))
{
return _backward(end(p));
return _backward(cend(p));
}
template<class P> auto rend(P& p) -> decltype(_backward(begin(p)))
@ -873,16 +883,16 @@ inline void reserve(T& sh, size_t vertex_capacity) {
reserve(sh, vertex_capacity, Tag<T>());
}
template<class S, class...Args>
inline void addVertex(S& sh, const PolygonTag&, Args...args)
template<class S>
inline void addVertex(S& sh, const PolygonTag&, const TPoint<S> &p)
{
addVertex(contour(sh), PathTag(), std::forward<Args>(args)...);
addVertex(contour(sh), PathTag(), p);
}
template<class S, class...Args> // Tag dispatcher
inline void addVertex(S& sh, Args...args)
template<class S> // Tag dispatcher
inline void addVertex(S& sh, const TPoint<S> &p)
{
addVertex(sh, Tag<S>(), std::forward<Args>(args)...);
addVertex(sh, Tag<S>(), p);
}
template<class S>

View file

@ -57,7 +57,6 @@ inline void buildPolygon(const EdgeList& edgelist,
tmp = std::next(tmp);
}
}
template<class Container, class Iterator = typename Container::iterator>
@ -214,15 +213,24 @@ inline NfpResult<RawShape> nfpConvexOnly(const RawShape& sh,
// Reserve the needed memory
edgelist.reserve(cap);
sl::reserve(rsh, static_cast<unsigned long>(cap));
auto add_edge = [&edgelist](const Vertex &v1, const Vertex &v2) {
Edge e{v1, v2};
if (e.sqlength() > 0)
edgelist.emplace_back(e);
};
{ // place all edges from sh into edgelist
auto first = sl::cbegin(sh);
auto next = std::next(first);
while(next != sl::cend(sh)) {
edgelist.emplace_back(*(first), *(next));
add_edge(*(first), *(next));
++first; ++next;
}
if constexpr (ClosureTypeV<RawShape> == Closure::OPEN)
add_edge(*sl::rcbegin(sh), *sl::cbegin(sh));
}
{ // place all edges from other into edgelist
@ -230,15 +238,19 @@ inline NfpResult<RawShape> nfpConvexOnly(const RawShape& sh,
auto next = std::next(first);
while(next != sl::cend(other)) {
edgelist.emplace_back(*(next), *(first));
add_edge(*(next), *(first));
++first; ++next;
}
if constexpr (ClosureTypeV<RawShape> == Closure::OPEN)
add_edge(*sl::cbegin(other), *sl::rcbegin(other));
}
std::sort(edgelist.begin(), edgelist.end(),
[](const Edge& e1, const Edge& e2)
{
Vertex ax(1, 0); // Unit vector for the X axis
const Vertex ax(1, 0); // Unit vector for the X axis
// get cectors from the edges
Vertex p1 = e1.second() - e1.first();
@ -285,11 +297,17 @@ inline NfpResult<RawShape> nfpConvexOnly(const RawShape& sh,
auto pcos1 = Ratio(lcos[0]) / lsq1 * sign * lcos[0];
auto pcos2 = Ratio(lcos[1]) / lsq2 * sign * lcos[1];
if constexpr (is_clockwise<RawShape>())
return q[0] < 2 ? pcos1 < pcos2 : pcos1 > pcos2;
else
return q[0] < 2 ? pcos1 > pcos2 : pcos1 < pcos2;
}
// If in different quadrants, compare the quadrant indices only.
if constexpr (is_clockwise<RawShape>())
return q[0] > q[1];
else
return q[0] < q[1];
});
__nfp::buildPolygon(edgelist, rsh, top_nfp);

View file

@ -7,6 +7,10 @@
#include <libnest2d/backends/clipper/geometries.hpp>
#endif
#ifdef LIBNEST2D_GEOMETRIES_libslic3r
#include <libnest2d/backends/libslic3r/geometries.hpp>
#endif
#ifdef LIBNEST2D_OPTIMIZER_nlopt
// We include the stock optimizers for local and global optimization
#include <libnest2d/optimizers/nlopt/subplex.hpp> // Local subplex for NfpPlacer

View file

@ -96,7 +96,7 @@ public:
* @return The orientation type identifier for the _Item type.
*/
static BP2D_CONSTEXPR Orientation orientation() {
return OrientationType<RawShape>::Value;
return OrientationType<TContour<RawShape>>::Value;
}
/**
@ -446,44 +446,32 @@ private:
}
};
template<class Sh> Sh create_rect(TCoord<Sh> width, TCoord<Sh> height)
{
auto sh = sl::create<Sh>(
{{0, 0}, {0, height}, {width, height}, {width, 0}});
if constexpr (ClosureTypeV<Sh> == Closure::CLOSED)
sl::addVertex(sh, {0, 0});
if constexpr (OrientationTypeV<Sh> == Orientation::COUNTER_CLOCKWISE)
std::reverse(sl::begin(sh), sl::end(sh));
return sh;
}
/**
* \brief Subclass of _Item for regular rectangle items.
*/
template<class RawShape>
class _Rectangle: public _Item<RawShape> {
using _Item<RawShape>::vertex;
template<class Sh>
class _Rectangle: public _Item<Sh> {
using _Item<Sh>::vertex;
using TO = Orientation;
public:
using Unit = TCoord<TPoint<RawShape>>;
using Unit = TCoord<Sh>;
template<TO o = OrientationType<RawShape>::Value>
inline _Rectangle(Unit width, Unit height,
// disable this ctor if o != CLOCKWISE
enable_if_t< o == TO::CLOCKWISE, int> = 0 ):
_Item<RawShape>( sl::create<RawShape>( {
{0, 0},
{0, height},
{width, height},
{width, 0},
{0, 0}
} ))
{
}
template<TO o = OrientationType<RawShape>::Value>
inline _Rectangle(Unit width, Unit height,
// disable this ctor if o != COUNTER_CLOCKWISE
enable_if_t< o == TO::COUNTER_CLOCKWISE, int> = 0 ):
_Item<RawShape>( sl::create<RawShape>( {
{0, 0},
{width, 0},
{width, height},
{0, height},
{0, 0}
} ))
{
}
inline _Rectangle(Unit w, Unit h): _Item<Sh>{create_rect<Sh>(w, h)} {}
inline Unit width() const BP2D_NOEXCEPT {
return getX(vertex(2));

View file

@ -365,45 +365,51 @@ protected:
// the additional vertices for maintaning min object distance
sl::reserve(rsh, finish-start+4);
/*auto addOthers = [&rsh, finish, start, &item](){
auto addOthers_ = [&rsh, finish, start, &item](){
for(size_t i = start+1; i < finish; i++)
sl::addVertex(rsh, item.vertex(i));
};*/
};
auto reverseAddOthers = [&rsh, finish, start, &item](){
auto reverseAddOthers_ = [&rsh, finish, start, &item](){
for(auto i = finish-1; i > start; i--)
sl::addVertex(rsh, item.vertex(
static_cast<unsigned long>(i)));
sl::addVertex(rsh, item.vertex(static_cast<unsigned long>(i)));
};
auto addOthers = [&addOthers_, &reverseAddOthers_]() {
if constexpr (!is_clockwise<RawShape>())
addOthers_();
else
reverseAddOthers_();
};
// Final polygon construction...
static_assert(OrientationType<RawShape>::Value ==
Orientation::CLOCKWISE,
"Counter clockwise toWallPoly() Unimplemented!");
// Clockwise polygon construction
sl::addVertex(rsh, topleft_vertex);
if(dir == Dir::LEFT) reverseAddOthers();
if(dir == Dir::LEFT) addOthers();
else {
sl::addVertex(rsh, getX(topleft_vertex), 0);
sl::addVertex(rsh, getX(bottomleft_vertex), 0);
sl::addVertex(rsh, {getX(topleft_vertex), 0});
sl::addVertex(rsh, {getX(bottomleft_vertex), 0});
}
sl::addVertex(rsh, bottomleft_vertex);
if(dir == Dir::LEFT) {
sl::addVertex(rsh, 0, getY(bottomleft_vertex));
sl::addVertex(rsh, 0, getY(topleft_vertex));
sl::addVertex(rsh, {0, getY(bottomleft_vertex)});
sl::addVertex(rsh, {0, getY(topleft_vertex)});
}
else reverseAddOthers();
else addOthers();
// Close the polygon
if constexpr (ClosureTypeV<RawShape> == Closure::CLOSED)
sl::addVertex(rsh, topleft_vertex);
if constexpr (!is_clockwise<RawShape>())
std::reverse(rsh.begin(), rsh.end());
return ret;
}

View file

@ -250,8 +250,8 @@ template<class RawShape> class EdgeCache {
Vertex ret = edge.first();
// Get the point on the edge which lies in ed distance from the start
ret += { static_cast<Coord>(std::round(ed*std::cos(angle))),
static_cast<Coord>(std::round(ed*std::sin(angle))) };
ret += Vertex(static_cast<Coord>(std::round(ed*std::cos(angle))),
static_cast<Coord>(std::round(ed*std::sin(angle))));
return ret;
}
@ -724,8 +724,7 @@ private:
auto rawobjfunc = [_objfunc, iv, startpos]
(Vertex v, Item& itm)
{
auto d = v - iv;
d += startpos;
auto d = (v - iv) + startpos;
itm.translation(d);
return _objfunc(itm);
};
@ -742,8 +741,7 @@ private:
&item, &bin, &iv, &startpos] (const Optimum& o)
{
auto v = getNfpPoint(o);
auto d = v - iv;
d += startpos;
auto d = (v - iv) + startpos;
item.translation(d);
merged_pile.emplace_back(item.transformedShape());
@ -877,8 +875,7 @@ private:
}
if( best_score < global_score ) {
auto d = getNfpPoint(optimum) - iv;
d += startpos;
auto d = (getNfpPoint(optimum) - iv) + startpos;
final_tr = d;
final_rot = initial_rot + rot;
can_pack = true;

View file

@ -19,7 +19,7 @@
#pragma warning(pop)
#endif
// this should be removed to not confuse the compiler
// #include <libnest2d.h>
// #include "../libnest2d.hpp"
namespace bp2d {
@ -30,6 +30,10 @@ using libnest2d::PolygonImpl;
using libnest2d::PathImpl;
using libnest2d::Orientation;
using libnest2d::OrientationType;
using libnest2d::OrientationTypeV;
using libnest2d::ClosureType;
using libnest2d::Closure;
using libnest2d::ClosureTypeV;
using libnest2d::getX;
using libnest2d::getY;
using libnest2d::setX;
@ -213,8 +217,15 @@ struct ToBoostOrienation<bp2d::Orientation::COUNTER_CLOCKWISE> {
static const order_selector Value = counterclockwise;
};
static const bp2d::Orientation RealOrientation =
bp2d::OrientationType<bp2d::PolygonImpl>::Value;
template<bp2d::Closure> struct ToBoostClosure {};
template<> struct ToBoostClosure<bp2d::Closure::OPEN> {
static const constexpr closure_selector Value = closure_selector::open;
};
template<> struct ToBoostClosure<bp2d::Closure::CLOSED> {
static const constexpr closure_selector Value = closure_selector::closed;
};
// Ring implementation /////////////////////////////////////////////////////////
@ -225,12 +236,13 @@ template<> struct tag<bp2d::PathImpl> {
template<> struct point_order<bp2d::PathImpl> {
static const order_selector value =
ToBoostOrienation<RealOrientation>::Value;
ToBoostOrienation<bp2d::OrientationTypeV<bp2d::PathImpl>>::Value;
};
// All our Paths should be closed for the bin packing application
template<> struct closure<bp2d::PathImpl> {
static const closure_selector value = closed;
static const constexpr closure_selector value =
ToBoostClosure< bp2d::ClosureTypeV<bp2d::PathImpl> >::Value;
};
// Polygon implementation //////////////////////////////////////////////////////

View file

@ -3,7 +3,7 @@
#include "BoundingBox.hpp"
#include <libnest2d/backends/clipper/geometries.hpp>
#include <libnest2d/backends/libslic3r/geometries.hpp>
#include <libnest2d/optimizers/nlopt/subplex.hpp>
#include <libnest2d/placers/nfpplacer.hpp>
#include <libnest2d/selections/firstfit.hpp>
@ -54,23 +54,22 @@ namespace Slic3r {
template<class Tout = double, class = FloatingOnly<Tout>, int...EigenArgs>
inline constexpr Eigen::Matrix<Tout, 2, EigenArgs...> unscaled(
const ClipperLib::IntPoint &v) noexcept
const Slic3r::ClipperLib::IntPoint &v) noexcept
{
return Eigen::Matrix<Tout, 2, EigenArgs...>{unscaled<Tout>(v.X),
unscaled<Tout>(v.Y)};
return Eigen::Matrix<Tout, 2, EigenArgs...>{unscaled<Tout>(v.x()),
unscaled<Tout>(v.y())};
}
namespace arrangement {
using namespace libnest2d;
namespace clppr = ClipperLib;
// Get the libnest2d types for clipper backend
using Item = _Item<clppr::Polygon>;
using Box = _Box<clppr::IntPoint>;
using Circle = _Circle<clppr::IntPoint>;
using Segment = _Segment<clppr::IntPoint>;
using MultiPolygon = TMultiShape<clppr::Polygon>;
using Item = _Item<ExPolygon>;
using Box = _Box<Point>;
using Circle = _Circle<Point>;
using Segment = _Segment<Point>;
using MultiPolygon = ExPolygons;
// Summon the spatial indexing facilities from boost
namespace bgi = boost::geometry::index;
@ -127,8 +126,8 @@ template<class TBin>
class AutoArranger {
public:
// Useful type shortcuts...
using Placer = typename placers::_NofitPolyPlacer<clppr::Polygon, TBin>;
using Selector = selections::_FirstFitSelection<clppr::Polygon>;
using Placer = typename placers::_NofitPolyPlacer<ExPolygon, TBin>;
using Selector = selections::_FirstFitSelection<ExPolygon>;
using Packer = _Nester<Placer, Selector>;
using PConfig = typename Packer::PlacementConfig;
using Distance = TCoord<PointImpl>;
@ -168,7 +167,7 @@ protected:
// as it possibly can be but at the same time, it has to provide
// reasonable results.
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
objfunc(const Item &item, const clppr::IntPoint &bincenter)
objfunc(const Item &item, const Point &bincenter)
{
const double bin_area = m_bin_area;
const SpatIndex& spatindex = m_rtree;
@ -220,12 +219,12 @@ protected:
switch (compute_case) {
case BIG_ITEM: {
const clppr::IntPoint& minc = ibb.minCorner(); // bottom left corner
const clppr::IntPoint& maxc = ibb.maxCorner(); // top right corner
const Point& minc = ibb.minCorner(); // bottom left corner
const Point& maxc = ibb.maxCorner(); // top right corner
// top left and bottom right corners
clppr::IntPoint top_left{getX(minc), getY(maxc)};
clppr::IntPoint bottom_right{getX(maxc), getY(minc)};
Point top_left{getX(minc), getY(maxc)};
Point bottom_right{getX(maxc), getY(minc)};
// Now the distance of the gravity center will be calculated to the
// five anchor points and the smallest will be chosen.
@ -452,7 +451,7 @@ template<> std::function<double(const Item&)> AutoArranger<Circle>::get_objfn()
// Specialization for a generalized polygon.
// Warning: this is unfinished business. It may or may not work.
template<>
std::function<double(const Item &)> AutoArranger<clppr::Polygon>::get_objfn()
std::function<double(const Item &)> AutoArranger<ExPolygon>::get_objfn()
{
auto bincenter = sl::boundingBox(m_bin).center();
return [this, bincenter](const Item &item) {
@ -521,7 +520,7 @@ void _arrange(
inline Box to_nestbin(const BoundingBox &bb) { return Box{{bb.min(X), bb.min(Y)}, {bb.max(X), bb.max(Y)}};}
inline Circle to_nestbin(const CircleBed &c) { return Circle({c.center()(0), c.center()(1)}, c.radius()); }
inline clppr::Polygon to_nestbin(const Polygon &p) { return sl::create<clppr::Polygon>(Slic3rMultiPoint_to_ClipperPath(p)); }
inline ExPolygon to_nestbin(const Polygon &p) { return ExPolygon{p}; }
inline Box to_nestbin(const InfiniteBed &bed) { return Box::infinite({bed.center.x(), bed.center.y()}); }
inline coord_t width(const BoundingBox& box) { return box.max.x() - box.min.x(); }
@ -568,19 +567,12 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
const Vec2crd &offs = arrpoly.translation;
double rotation = arrpoly.rotation;
if (p.is_counter_clockwise()) p.reverse();
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
// This fixes:
// https://github.com/prusa3d/PrusaSlicer/issues/2209
if (clpath.Contour.size() < 3)
if (p.points.size() < 3)
return;
auto firstp = clpath.Contour.front();
clpath.Contour.emplace_back(firstp);
outp.emplace_back(std::move(clpath));
outp.emplace_back(std::move(p));
outp.back().rotation(rotation);
outp.back().translation({offs.x(), offs.y()});
outp.back().binId(arrpoly.bed_idx);
@ -624,7 +616,7 @@ void arrange(ArrangePolygons & arrangables,
const BedT & bed,
const ArrangeParams & params)
{
namespace clppr = ClipperLib;
namespace clppr = Slic3r::ClipperLib;
std::vector<Item> items, fixeditems;
items.reserve(arrangables.size());
@ -643,8 +635,8 @@ void arrange(ArrangePolygons & arrangables,
_arrange(items, fixeditems, to_nestbin(bed), params, pri, cfn);
for(size_t i = 0; i < items.size(); ++i) {
clppr::IntPoint tr = items[i].translation();
arrangables[i].translation = {coord_t(tr.X), coord_t(tr.Y)};
Point tr = items[i].translation();
arrangables[i].translation = {coord_t(tr.x()), coord_t(tr.y())};
arrangables[i].rotation = items[i].rotation();
arrangables[i].bed_idx = items[i].binId();
}

View file

@ -225,24 +225,11 @@ BoundingBox3Base<PointClass>::max_size() const
template coordf_t BoundingBox3Base<Vec3f>::max_size() const;
template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
// Align a coordinate to a grid. The coordinate may be negative,
// the aligned value will never be bigger than the original one.
static inline coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {
// Current C++ standard defines the result of integer division to be rounded to zero,
// for both positive and negative numbers. Here we want to round down for negative
// numbers as well.
coord_t aligned = (coord < 0) ?
((coord - spacing + 1) / spacing) * spacing :
(coord / spacing) * spacing;
assert(aligned <= coord);
return aligned;
}
void BoundingBox::align_to_grid(const coord_t cell_size)
{
if (this->defined) {
min(0) = _align_to_grid(min(0), cell_size);
min(1) = _align_to_grid(min(1), cell_size);
min(0) = Slic3r::align_to_grid(min(0), cell_size);
min(1) = Slic3r::align_to_grid(min(1), cell_size);
}
}

View file

@ -40,7 +40,7 @@ void BridgeDetector::initialize()
this->angle = -1.;
// Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors.
Polygons grown = offset(to_polygons(this->expolygons), float(this->spacing));
Polygons grown = offset(this->expolygons, float(this->spacing));
// Detect possible anchoring edges of this bridging region.
// Detect what edges lie on lower slices by turning bridge contour and holes
@ -244,12 +244,16 @@ static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons)
std::sort(xx.begin(), xx.end());
// find trapezoids by looping from first to next-to-last coordinate
Polygons rectangle;
rectangle.emplace_back(Polygon());
for (std::vector<coord_t>::const_iterator x = xx.begin(); x != xx.end()-1; ++x) {
coord_t next_x = *(x + 1);
if (*x != next_x)
if (*x != next_x) {
// intersect with rectangle
// append results to return value
polygons_append(*polygons, intersection({ { { *x, bb.min.y() }, { next_x, bb.min.y() }, { next_x, bb.max.y() }, { *x, bb.max.y() } } }, src_polygons));
rectangle.front() = { { *x, bb.min.y() }, { next_x, bb.min.y() }, { next_x, bb.max.y() }, { *x, bb.max.y() } };
polygons_append(*polygons, intersection(rectangle, src_polygons));
}
}
}
@ -302,7 +306,7 @@ Polygons BridgeDetector::coverage(double angle) const
covered = union_(covered);
// Intersect trapezoids with actual bridge area to remove extra margins and append it to result.
polygons_rotate(covered, -(PI/2.0 - angle));
covered = intersection(covered, to_polygons(this->expolygons));
covered = intersection(this->expolygons, covered);
#if 0
{
my @lines = map @{$_->lines}, @$trapezoids;

View file

@ -78,7 +78,7 @@ static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
// Assign the maximum Z from four points. This values is valid index of the island
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot,
const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) {
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
pt.z() = std::max(std::max(e1bot.z(), e1top.z()), std::max(e2bot.z(), e2top.z()));
});
// Add islands
clipper.AddPaths(islands_clip, ClipperLib_Z::ptSubject, true);
@ -90,9 +90,9 @@ static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
ConstPrintObjectPtrs top_level_objects_with_brim;
for (int i = 0; i < islands_polytree.ChildCount(); ++i) {
for (const ClipperLib_Z::IntPoint &point : islands_polytree.Childs[i]->Contour) {
if (point.Z != 0 && processed_objects_idx.find(island_to_object[point.Z - 1]->id().id) == processed_objects_idx.end()) {
top_level_objects_with_brim.emplace_back(island_to_object[point.Z - 1]);
processed_objects_idx.insert(island_to_object[point.Z - 1]->id().id);
if (point.z() != 0 && processed_objects_idx.find(island_to_object[point.z() - 1]->id().id) == processed_objects_idx.end()) {
top_level_objects_with_brim.emplace_back(island_to_object[point.z() - 1]);
processed_objects_idx.insert(island_to_object[point.z() - 1]->id().id);
}
}
}
@ -139,7 +139,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrint
Polygons no_brim_area_object;
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim)
append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset), offset_ex(ex_poly.contour, brim_offset)));
append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset)));
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
append(no_brim_area_object, offset(ex_poly.holes, -no_brim_offset));
@ -156,7 +156,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrint
}
}
return diff_ex(to_polygons(std::move(brim_area)), no_brim_area);
return diff_ex(brim_area, no_brim_area);
}
static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
@ -183,14 +183,14 @@ static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs
if (top_outer_brim)
no_brim_area_object.emplace_back(ex_poly);
else
append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset), offset_ex(ex_poly.contour, brim_offset)));
append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset)));
}
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner)
append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset)));
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim)
append(no_brim_area_object, offset_ex(ex_poly.contour, no_brim_offset));
append(no_brim_area_object, to_expolygons(offset(ex_poly.contour, no_brim_offset)));
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset));
@ -317,7 +317,7 @@ static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_
islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), jtSquare);
}
loops = union_pt_chained_outside_in(loops, false);
loops = union_pt_chained_outside_in(loops);
std::reverse(loops.begin(), loops.end());
extrusion_entities_append_loops(brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()),
float(flow.width()), float(print.skirt_first_layer_height()));
@ -342,7 +342,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
poly.douglas_peucker(SCALED_RESOLUTION);
polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing())));
}
loops = union_pt_chained_outside_in(loops, false);
loops = union_pt_chained_outside_in(loops);
std::vector<Polylines> loops_pl_by_levels;
{
@ -456,7 +456,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot, const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
// Assign a valid input loop identifier. Such an identifier is strictly positive, the next line is safe even in case one side of a segment
// hat the Z coordinate not set to the contour coordinate.
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
pt.z() = std::max(std::max(e1bot.z(), e1top.z()), std::max(e2bot.z(), e2top.z()));
});
// add polygons
clipper.AddPaths(input_clip, ClipperLib_Z::ptSubject, false);
@ -474,8 +474,8 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
for (const ClipperLib_Z::Path &path : loops_trimmed) {
size_t input_idx = 0;
for (const ClipperLib_Z::IntPoint &pt : path)
if (pt.Z > 0) {
input_idx = (size_t)pt.Z;
if (pt.z() > 0) {
input_idx = (size_t)pt.z();
break;
}
assert(input_idx != 0);
@ -492,14 +492,14 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
size_t j = i + 1;
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ;
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
if (i + 1 == j && first_path.size() > 3 && first_path.front().x() == first_path.back().x() && first_path.front().y() == first_path.back().y()) {
auto *loop = new ExtrusionLoop();
brim.entities.emplace_back(loop);
loop->paths.emplace_back(erSkirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()));
Points &points = loop->paths.front().polyline.points;
points.reserve(first_path.size());
for (const ClipperLib_Z::IntPoint &pt : first_path)
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
points.emplace_back(coord_t(pt.x()), coord_t(pt.y()));
i = j;
} else {
//FIXME The path chaining here may not be optimal.
@ -511,7 +511,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
Points &points = static_cast<ExtrusionPath*>(this_loop_trimmed.entities.back())->polyline.points;
points.reserve(path.size());
for (const ClipperLib_Z::IntPoint &pt : path)
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
points.emplace_back(coord_t(pt.x()), coord_t(pt.y()));
}
chain_and_reorder_extrusion_entities(this_loop_trimmed.entities, &last_pt);
brim.entities.reserve(brim.entities.size() + this_loop_trimmed.entities.size());

View file

@ -23,6 +23,8 @@ add_library(libslic3r STATIC
BridgeDetector.hpp
Brim.cpp
Brim.hpp
clipper.cpp
clipper.hpp
ClipperUtils.cpp
ClipperUtils.hpp
Config.cpp
@ -219,6 +221,9 @@ add_library(libslic3r STATIC
SimplifyMeshImpl.hpp
SimplifyMesh.cpp
MarchingSquares.hpp
Execution/Execution.hpp
Execution/ExecutionSeq.hpp
Execution/ExecutionTBB.hpp
Optimize/Optimizer.hpp
Optimize/NLoptOptimizer.hpp
Optimize/BruteforceOptimizer.hpp

File diff suppressed because it is too large Load diff

View file

@ -8,218 +8,354 @@
#include "Surface.hpp"
// import these wherever we're included
using ClipperLib::jtMiter;
using ClipperLib::jtRound;
using ClipperLib::jtSquare;
using Slic3r::ClipperLib::jtMiter;
using Slic3r::ClipperLib::jtRound;
using Slic3r::ClipperLib::jtSquare;
// Factor to convert from coord_t (which is int32) to an int64 type used by the Clipper library
// for general offsetting (the offset(), offset2(), offset_ex() functions) and for the safety offset,
// which is optionally executed by other functions (union, intersection, diff).
// This scaling (cca 130t) is applied over the usual SCALING_FACTOR.
// By the way, is the scalling for offset needed at all?
// The reason to apply this scaling may be to match the resolution of the double mantissa.
#define CLIPPER_OFFSET_POWER_OF_2 17
// 2^17=131072
#define CLIPPER_OFFSET_SCALE (1 << CLIPPER_OFFSET_POWER_OF_2)
#define CLIPPER_OFFSET_SCALE_ROUNDING_DELTA ((1 << (CLIPPER_OFFSET_POWER_OF_2 - 1)) - 1)
#define CLIPPER_MAX_COORD_UNSCALED (ClipperLib::hiRange / CLIPPER_OFFSET_SCALE)
static constexpr const float ClipperSafetyOffset = 10.f;
#define CLIPPERUTILS_UNSAFE_OFFSET
namespace Slic3r {
//-----------------------------------------------------------
// legacy code from Clipper documentation
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons *expolygons);
Slic3r::ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree& polytree);
//-----------------------------------------------------------
namespace ClipperUtils {
class PathsProviderIteratorBase {
public:
using value_type = Points;
using difference_type = std::ptrdiff_t;
using pointer = const Points*;
using reference = const Points&;
using iterator_category = std::input_iterator_tag;
};
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input);
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polygons &input);
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const ExPolygons &input);
ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input);
Slic3r::Polygon ClipperPath_to_Slic3rPolygon(const ClipperLib::Path &input);
Slic3r::Polyline ClipperPath_to_Slic3rPolyline(const ClipperLib::Path &input);
Slic3r::Polygons ClipperPaths_to_Slic3rPolygons(const ClipperLib::Paths &input);
Slic3r::Polylines ClipperPaths_to_Slic3rPolylines(const ClipperLib::Paths &input);
Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
class EmptyPathsProvider {
public:
struct iterator : public PathsProviderIteratorBase {
public:
const Points& operator*() { assert(false); return s_empty_points; }
// all iterators point to end.
constexpr bool operator==(const iterator &rhs) const { return true; }
constexpr bool operator!=(const iterator &rhs) const { return false; }
const Points& operator++(int) { assert(false); return s_empty_points; }
constexpr iterator& operator++() { assert(false); return *this; }
};
constexpr EmptyPathsProvider() {}
static constexpr iterator cend() throw() { return iterator{}; }
static constexpr iterator end() throw() { return cend(); }
static constexpr iterator cbegin() throw() { return cend(); }
static constexpr iterator begin() throw() { return cend(); }
static constexpr size_t size() throw() { return 0; }
static Points s_empty_points;
};
class SinglePathProvider {
public:
SinglePathProvider(const Points &points) : m_points(points) {}
struct iterator : public PathsProviderIteratorBase {
public:
explicit iterator(const Points &points) : m_ptr(&points) {}
const Points& operator*() const { return *m_ptr; }
bool operator==(const iterator &rhs) const { return m_ptr == rhs.m_ptr; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
const Points& operator++(int) { auto out = m_ptr; m_ptr = &s_end; return *out; }
iterator& operator++() { m_ptr = &s_end; return *this; }
private:
const Points *m_ptr;
};
iterator cbegin() const { return iterator(m_points); }
iterator begin() const { return this->cbegin(); }
iterator cend() const { return iterator(s_end); }
iterator end() const { return this->cend(); }
size_t size() const { return 1; }
private:
const Points &m_points;
static Points s_end;
};
template<typename MultiPointType>
class MultiPointsProvider {
public:
MultiPointsProvider(const std::vector<MultiPointType> &multipoints) : m_multipoints(multipoints) {}
struct iterator : public PathsProviderIteratorBase {
public:
explicit iterator(typename std::vector<MultiPointType>::const_iterator it) : m_it(it) {}
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 !(*this == rhs); }
const Points& operator++(int) { return (m_it ++)->points; }
iterator& operator++() { ++ m_it; return *this; }
private:
typename std::vector<MultiPointType>::const_iterator m_it;
};
iterator cbegin() const { return iterator(m_multipoints.begin()); }
iterator begin() const { return this->cbegin(); }
iterator cend() const { return iterator(m_multipoints.end()); }
iterator end() const { return this->cend(); }
size_t size() const { return m_multipoints.size(); }
private:
const std::vector<MultiPointType> &m_multipoints;
};
using PolygonsProvider = MultiPointsProvider<Polygon>;
using PolylinesProvider = MultiPointsProvider<Polyline>;
struct ExPolygonProvider {
ExPolygonProvider(const ExPolygon &expoly) : m_expoly(expoly) {}
struct iterator : public PathsProviderIteratorBase {
public:
explicit iterator(const ExPolygon &expoly, int idx) : m_expoly(expoly), m_idx(idx) {}
const Points& operator*() const { return (m_idx == 0) ? m_expoly.contour.points : m_expoly.holes[m_idx - 1].points; }
bool operator==(const iterator &rhs) const { assert(m_expoly == rhs.m_expoly); return m_idx == rhs.m_idx; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
const Points& operator++(int) { const Points &out = **this; ++ m_idx; return out; }
iterator& operator++() { ++ m_idx; return *this; }
private:
const ExPolygon &m_expoly;
int m_idx;
};
iterator cbegin() const { return iterator(m_expoly, 0); }
iterator begin() const { return this->cbegin(); }
iterator cend() const { return iterator(m_expoly, m_expoly.holes.size() + 1); }
iterator end() const { return this->cend(); }
size_t size() const { return m_expoly.holes.size() + 1; }
private:
const ExPolygon &m_expoly;
};
struct ExPolygonsProvider {
ExPolygonsProvider(const ExPolygons &expolygons) : m_expolygons(expolygons) {
m_size = 0;
for (const ExPolygon &expoly : expolygons)
m_size += expoly.holes.size() + 1;
}
struct iterator : public PathsProviderIteratorBase {
public:
explicit iterator(ExPolygons::const_iterator it) : m_it_expolygon(it), m_idx_contour(0) {}
const Points& operator*() const { return (m_idx_contour == 0) ? m_it_expolygon->contour.points : m_it_expolygon->holes[m_idx_contour - 1].points; }
bool operator==(const iterator &rhs) const { return m_it_expolygon == rhs.m_it_expolygon && m_idx_contour == rhs.m_idx_contour; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
iterator& operator++() {
if (++ m_idx_contour == m_it_expolygon->holes.size() + 1) {
++ m_it_expolygon;
m_idx_contour = 0;
}
return *this;
}
const Points& operator++(int) {
const Points &out = **this;
++ (*this);
return out;
}
private:
ExPolygons::const_iterator m_it_expolygon;
size_t m_idx_contour;
};
iterator cbegin() const { return iterator(m_expolygons.cbegin()); }
iterator begin() const { return this->cbegin(); }
iterator cend() const { return iterator(m_expolygons.cend()); }
iterator end() const { return this->cend(); }
size_t size() const { return m_size; }
private:
const ExPolygons &m_expolygons;
size_t m_size;
};
struct SurfacesProvider {
SurfacesProvider(const Surfaces &surfaces) : m_surfaces(surfaces) {
m_size = 0;
for (const Surface &surface : surfaces)
m_size += surface.expolygon.holes.size() + 1;
}
struct iterator : public PathsProviderIteratorBase {
public:
explicit iterator(Surfaces::const_iterator it) : m_it_surface(it), m_idx_contour(0) {}
const Points& operator*() const { return (m_idx_contour == 0) ? m_it_surface->expolygon.contour.points : m_it_surface->expolygon.holes[m_idx_contour - 1].points; }
bool operator==(const iterator &rhs) const { return m_it_surface == rhs.m_it_surface && m_idx_contour == rhs.m_idx_contour; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
iterator& operator++() {
if (++ m_idx_contour == m_it_surface->expolygon.holes.size() + 1) {
++ m_it_surface;
m_idx_contour = 0;
}
return *this;
}
const Points& operator++(int) {
const Points &out = **this;
++ (*this);
return out;
}
private:
Surfaces::const_iterator m_it_surface;
size_t m_idx_contour;
};
iterator cbegin() const { return iterator(m_surfaces.cbegin()); }
iterator begin() const { return this->cbegin(); }
iterator cend() const { return iterator(m_surfaces.cend()); }
iterator end() const { return this->cend(); }
size_t size() const { return m_size; }
private:
const Surfaces &m_surfaces;
size_t m_size;
};
struct SurfacesPtrProvider {
SurfacesPtrProvider(const SurfacesPtr &surfaces) : m_surfaces(surfaces) {
m_size = 0;
for (const Surface *surface : surfaces)
m_size += surface->expolygon.holes.size() + 1;
}
struct iterator : public PathsProviderIteratorBase {
public:
explicit iterator(SurfacesPtr::const_iterator it) : m_it_surface(it), m_idx_contour(0) {}
const Points& operator*() const { return (m_idx_contour == 0) ? (*m_it_surface)->expolygon.contour.points : (*m_it_surface)->expolygon.holes[m_idx_contour - 1].points; }
bool operator==(const iterator &rhs) const { return m_it_surface == rhs.m_it_surface && m_idx_contour == rhs.m_idx_contour; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
iterator& operator++() {
if (++ m_idx_contour == (*m_it_surface)->expolygon.holes.size() + 1) {
++ m_it_surface;
m_idx_contour = 0;
}
return *this;
}
const Points& operator++(int) {
const Points &out = **this;
++ (*this);
return out;
}
private:
SurfacesPtr::const_iterator m_it_surface;
size_t m_idx_contour;
};
iterator cbegin() const { return iterator(m_surfaces.cbegin()); }
iterator begin() const { return this->cbegin(); }
iterator cend() const { return iterator(m_surfaces.cend()); }
iterator end() const { return this->cend(); }
size_t size() const { return m_size; }
private:
const SurfacesPtr &m_surfaces;
size_t m_size;
};
}
ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input);
// offset Polygons
ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
inline Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
#endif // CLIPPERUTILS_UNSAFE_OFFSET
// offset Polylines
inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polyline), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
inline Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polylines), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3);
Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3);
Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::Polygons offset(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::Polygons offset(const Slic3r::SurfacesPtr &surfaces, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::ExPolygons offset_ex(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
// offset expolygons and surfaces
ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit);
ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit);
inline Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
inline Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
{ return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
Slic3r::Polygons offset2(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1,
const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
double miterLimit = 3);
#ifdef CLIPPERUTILS_UNSAFE_OFFSET
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3);
#endif // CLIPPERUTILS_UNSAFE_OFFSET
Slic3r::Polygons _clipper(ClipperLib::ClipType clipType,
const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
Slic3r::ExPolygons _clipper_ex(ClipperLib::ClipType clipType,
const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType,
const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType,
const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType,
const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
// diff
inline Slic3r::Polygons
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polygons diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Polygon &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip, bool do_safety_offset = false);
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
{
return _clipper(ClipperLib::ctDifference, subject, clip, safety_offset_);
return _clipper_ln(ClipperLib::ctDifference, subject, clip, do_safety_offset);
}
inline Slic3r::ExPolygons
diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, bool do_safety_offset = false);
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::Polygons intersection(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polygons intersection(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygon &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, bool do_safety_offset = false);
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip, bool do_safety_offset = false);
Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false);
inline Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
{
return _clipper_ex(ClipperLib::ctDifference, subject, clip, safety_offset_);
return _clipper_ln(ClipperLib::ctIntersection, subject, clip, do_safety_offset);
}
inline Slic3r::ExPolygons
diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_);
}
inline Slic3r::Polygons
diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_);
}
inline Slic3r::Polylines
diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
inline Slic3r::Polylines
diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
inline Slic3r::Lines
diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_ln(ClipperLib::ctDifference, subject, clip, safety_offset_);
}
// intersection
inline Slic3r::Polygons
intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
inline Slic3r::ExPolygons
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
inline Slic3r::ExPolygons
intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctIntersection, to_polygons(subject), to_polygons(clip), safety_offset_);
}
inline Slic3r::Polygons
intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctIntersection, to_polygons(subject), to_polygons(clip), safety_offset_);
}
inline Slic3r::Polylines
intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
inline Slic3r::Polylines
intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
inline Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
{
return _clipper_ln(ClipperLib::ctIntersection, subject, clip, safety_offset_);
}
inline Slic3r::Lines intersection_ln(const Slic3r::Line &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false)
inline Slic3r::Lines intersection_ln(const Slic3r::Line &subject, const Slic3r::Polygons &clip, bool do_safety_offset = false)
{
Slic3r::Lines lines;
lines.emplace_back(subject);
return _clipper_ln(ClipperLib::ctIntersection, lines, clip, safety_offset_);
return _clipper_ln(ClipperLib::ctIntersection, lines, clip, do_safety_offset);
}
// union
inline Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
}
Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool do_safety_offset = false);
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject, bool do_safety_offset = false);
Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool do_safety_offset = false);
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool do_safety_offset = false);
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject);
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject);
inline Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false)
{
return _clipper(ClipperLib::ctUnion, subject, subject2, safety_offset_);
}
ClipperLib::PolyTree union_pt(const Slic3r::Polygons &subject);
ClipperLib::PolyTree union_pt(const Slic3r::ExPolygons &subject);
inline Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_);
}
inline Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctUnion, to_polygons(subject), Slic3r::Polygons(), safety_offset_);
}
inline Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset_ = false)
{
return _clipper_ex(ClipperLib::ctUnion, to_polygons(subject), Slic3r::Polygons(), safety_offset_);
}
ClipperLib::PolyTree union_pt(const Slic3r::Polygons &subject, bool safety_offset_ = false);
ClipperLib::PolyTree union_pt(const Slic3r::ExPolygons &subject, bool safety_offset_ = false);
ClipperLib::PolyTree union_pt(Slic3r::Polygons &&subject, bool safety_offset_ = false);
ClipperLib::PolyTree union_pt(Slic3r::ExPolygons &&subject, bool safety_offset_ = false);
Slic3r::Polygons union_pt_chained_outside_in(const Slic3r::Polygons &subject, bool safety_offset_ = false);
Slic3r::Polygons union_pt_chained_outside_in(const Slic3r::Polygons &subject);
ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes);
@ -267,7 +403,7 @@ void traverse_pt(const ClipperLib::PolyNode *tree, Polygons *out)
if (!tree) return; // terminates recursion
// Push the contour of the current level
out->emplace_back(ClipperPath_to_Slic3rPolygon(tree->Contour));
out->emplace_back(tree->Contour);
// Do the recursion for all the children.
traverse_pt<ordering>(tree->Childs, out);
@ -286,13 +422,13 @@ void traverse_pt(const ClipperLib::PolyNode *tree, ExPolygons *out)
}
ExPolygon level;
level.contour = ClipperPath_to_Slic3rPolygon(tree->Contour);
level.contour.points = tree->Contour;
foreach_node<ordering>(tree->Childs,
[out, &level] (const ClipperLib::PolyNode *node) {
// Holes are collected here.
level.holes.emplace_back(ClipperPath_to_Slic3rPolygon(node->Contour));
level.holes.emplace_back(node->Contour);
// By doing a recursion, a new level expoly is created with the contour
// and holes of the lower level. Doing this for all the childs.
@ -315,10 +451,9 @@ void traverse_pt(const ClipperLib::PolyNodes &nodes, ExOrJustPolygons *retval)
Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject, bool preserve_collinear = false);
Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject, bool preserve_collinear = false);
void safety_offset(ClipperLib::Paths* paths);
Polygons top_level_islands(const Slic3r::Polygons &polygons);
ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit);
Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);

View file

@ -471,8 +471,8 @@ bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src,
{
t_config_option_key opt_key = opt_key_src;
std::string value = value_src;
// Both opt_key and value may be modified by _handle_legacy().
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by _handle_legacy().
// Both opt_key and value may be modified by handle_legacy().
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
this->handle_legacy(opt_key, value);
if (opt_key.empty())
// Ignore the option.

View file

@ -18,11 +18,53 @@
#include <boost/algorithm/string/trim.hpp>
#include <boost/format/format_fwd.hpp>
#include <boost/functional/hash.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
#include <cereal/access.hpp>
#include <cereal/types/base_class.hpp>
namespace Slic3r {
struct FloatOrPercent
{
double value;
bool percent;
private:
friend class cereal::access;
template<class Archive> void serialize(Archive& ar) { ar(this->value); ar(this->percent); }
};
inline bool operator==(const FloatOrPercent& l, const FloatOrPercent& r) throw() { return l.value == r.value && l.percent == r.percent; }
inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) throw() { return !(l == r); }
}
namespace std {
template<> struct hash<Slic3r::FloatOrPercent> {
std::size_t operator()(const Slic3r::FloatOrPercent& v) const noexcept {
std::size_t seed = std::hash<double>{}(v.value);
return v.percent ? seed ^ 0x9e3779b9 : seed;
}
};
template<> struct hash<Slic3r::Vec2d> {
std::size_t operator()(const Slic3r::Vec2d& v) const noexcept {
std::size_t seed = std::hash<double>{}(v.x());
boost::hash_combine(seed, std::hash<double>{}(v.y()));
return seed;
}
};
template<> struct hash<Slic3r::Vec3d> {
std::size_t operator()(const Slic3r::Vec3d& v) const noexcept {
std::size_t seed = std::hash<double>{}(v.x());
boost::hash_combine(seed, std::hash<double>{}(v.y()));
boost::hash_combine(seed, std::hash<double>{}(v.z()));
return seed;
}
};
}
namespace Slic3r {
// Name of the configuration option.
@ -137,6 +179,7 @@ public:
virtual void setInt(int /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); }
virtual bool operator==(const ConfigOption &rhs) const = 0;
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
virtual size_t hash() const throw() = 0;
bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; }
bool is_vector() const { return ! this->is_scalar(); }
// If this option is nullable, then it may have its value or values set to nil.
@ -185,8 +228,10 @@ public:
return this->value == static_cast<const ConfigOptionSingle<T>*>(&rhs)->value;
}
bool operator==(const T &rhs) const { return this->value == rhs; }
bool operator!=(const T &rhs) const { return this->value != rhs; }
bool operator==(const T &rhs) const throw() { return this->value == rhs; }
bool operator!=(const T &rhs) const throw() { return this->value != rhs; }
size_t hash() const throw() override { return std::hash<T>{}(this->value); }
private:
friend class cereal::access;
@ -339,8 +384,16 @@ public:
return this->values == static_cast<const ConfigOptionVector<T>*>(&rhs)->values;
}
bool operator==(const std::vector<T> &rhs) const { return this->values == rhs; }
bool operator!=(const std::vector<T> &rhs) const { return this->values != rhs; }
bool operator==(const std::vector<T> &rhs) const throw() { return this->values == rhs; }
bool operator!=(const std::vector<T> &rhs) const throw() { return this->values != rhs; }
size_t hash() const throw() override {
std::hash<T> hasher;
size_t seed = 0;
for (const auto &v : this->values)
boost::hash_combine(seed, hasher(v));
return seed;
}
// Is this option overridden by another option?
// An option overrides another option if it is not nil and not equal.
@ -413,7 +466,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
double getFloat() const override { return this->value; }
ConfigOption* clone() const override { return new ConfigOptionFloat(*this); }
bool operator==(const ConfigOptionFloat &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionFloat &rhs) const throw() { return this->value == rhs.value; }
std::string serialize() const override
{
@ -454,7 +507,7 @@ public:
static ConfigOptionType static_type() { return coFloats; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionFloatsTempl(*this); }
bool operator==(const ConfigOptionFloatsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
bool operator==(const ConfigOptionFloatsTempl &rhs) const throw() { return vectors_equal(this->values, rhs.values); }
bool operator==(const ConfigOption &rhs) const override {
if (rhs.type() != this->type())
throw Slic3r::RuntimeError("ConfigOptionFloatsTempl: Comparing incompatible types");
@ -566,7 +619,7 @@ public:
int getInt() const override { return this->value; }
void setInt(int val) override { this->value = val; }
ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
bool operator==(const ConfigOptionInt &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionInt &rhs) const throw() { return this->value == rhs.value; }
std::string serialize() const override
{
@ -606,7 +659,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionIntsTempl(*this); }
ConfigOptionIntsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionIntsTempl &rhs) const { return this->values == rhs.values; }
bool operator==(const ConfigOptionIntsTempl &rhs) const throw() { return this->values == rhs.values; }
// Could a special "nil" value be stored inside the vector, indicating undefined value?
bool nullable() const override { return NULLABLE; }
// Special "nil" value to be stored into the vector if this->supports_nil().
@ -689,7 +742,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionString(*this); }
ConfigOptionString& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionString &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionString &rhs) const throw() { return this->value == rhs.value; }
bool empty() const { return this->value.empty(); }
std::string serialize() const override
@ -722,7 +775,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; }
bool operator==(const ConfigOptionStrings &rhs) const throw() { return this->values == rhs.values; }
bool is_nil(size_t) const override { return false; }
std::string serialize() const override
@ -757,7 +810,8 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPercent(*this); }
ConfigOptionPercent& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPercent &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionPercent &rhs) const throw() { return this->value == rhs.value; }
double get_abs_value(double ratio_over) const { return ratio_over * this->value / 100; }
std::string serialize() const override
@ -797,7 +851,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPercentsTempl(*this); }
ConfigOptionPercentsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPercentsTempl &rhs) const { return this->values == rhs.values; }
bool operator==(const ConfigOptionPercentsTempl &rhs) const throw() { return this->values == rhs.values; }
std::string serialize() const override
{
@ -856,8 +910,12 @@ public:
assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(&rhs));
return *this == *static_cast<const ConfigOptionFloatOrPercent*>(&rhs);
}
bool operator==(const ConfigOptionFloatOrPercent &rhs) const
bool operator==(const ConfigOptionFloatOrPercent &rhs) const throw()
{ return this->value == rhs.value && this->percent == rhs.percent; }
size_t hash() const throw() override {
size_t seed = std::hash<double>{}(this->value);
return this->percent ? seed ^ 0x9e3779b9 : seed;
}
double get_abs_value(double ratio_over) const
{ return this->percent ? (ratio_over * this->value / 100) : this->value; }
@ -891,27 +949,6 @@ private:
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionPercent>(this), percent); }
};
struct FloatOrPercent
{
double value;
bool percent;
private:
friend class cereal::access;
template<class Archive> void serialize(Archive & ar) { ar(this->value); ar(this->percent); }
};
inline bool operator==(const FloatOrPercent &l, const FloatOrPercent &r)
{
return l.value == r.value && l.percent == r.percent;
}
inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r)
{
return !(l == r);
}
template<bool NULLABLE>
class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector<FloatOrPercent>
{
@ -925,13 +962,14 @@ public:
static ConfigOptionType static_type() { return coFloatsOrPercents; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionFloatsOrPercentsTempl(*this); }
bool operator==(const ConfigOptionFloatsOrPercentsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
bool operator==(const ConfigOptionFloatsOrPercentsTempl &rhs) const throw() { return vectors_equal(this->values, rhs.values); }
bool operator==(const ConfigOption &rhs) const override {
if (rhs.type() != this->type())
throw Slic3r::RuntimeError("ConfigOptionFloatsOrPercentsTempl: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs));
return vectors_equal(this->values, static_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs)->values);
}
// Could a special "nil" value be stored inside the vector, indicating undefined value?
bool nullable() const override { return NULLABLE; }
// Special "nil" value to be stored into the vector if this->supports_nil().
@ -1038,7 +1076,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPoint(*this); }
ConfigOptionPoint& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoint &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionPoint &rhs) const throw() { return this->value == rhs.value; }
std::string serialize() const override
{
@ -1074,7 +1112,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; }
bool operator==(const ConfigOptionPoints &rhs) const throw() { return this->values == rhs.values; }
bool is_nil(size_t) const override { return false; }
std::string serialize() const override
@ -1146,7 +1184,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPoint3(*this); }
ConfigOptionPoint3& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoint3 &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionPoint3 &rhs) const throw() { return this->value == rhs.value; }
std::string serialize() const override
{
@ -1183,7 +1221,7 @@ public:
bool getBool() const override { return this->value; }
ConfigOption* clone() const override { return new ConfigOptionBool(*this); }
ConfigOptionBool& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionBool &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionBool &rhs) const throw() { return this->value == rhs.value; }
std::string serialize() const override
{
@ -1217,7 +1255,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionBoolsTempl(*this); }
ConfigOptionBoolsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionBoolsTempl &rhs) const { return this->values == rhs.values; }
bool operator==(const ConfigOptionBoolsTempl &rhs) const throw() { return this->values == rhs.values; }
// Could a special "nil" value be stored inside the vector, indicating undefined value?
bool nullable() const override { return NULLABLE; }
// Special "nil" value to be stored into the vector if this->supports_nil().
@ -1311,7 +1349,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnum<T>(*this); }
ConfigOptionEnum<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnum<T> &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionEnum<T> &rhs) const throw() { return this->value == rhs.value; }
int getInt() const override { return (int)this->value; }
void setInt(int val) override { this->value = T(val); }
@ -1397,7 +1435,7 @@ public:
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnumGeneric(*this); }
ConfigOptionEnumGeneric& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnumGeneric &rhs) const { return this->value == rhs.value; }
bool operator==(const ConfigOptionEnumGeneric &rhs) const throw() { return this->value == rhs.value; }
bool operator==(const ConfigOption &rhs) const override
{
@ -1967,8 +2005,9 @@ public:
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
// In ConfigManipulation::toggle_print_fff_options, it is called on option with type ConfigOptionEnumGeneric* and also ConfigOptionEnum*.
// Thus the virtual method getInt() is used to retrieve the enum value.
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return this->option<ConfigOptionEnum<ENUM>>(opt_key)->value; }
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }

View file

@ -83,8 +83,8 @@ inline bool operator!=(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.
inline size_t number_polygons(const ExPolygons &expolys)
{
size_t n_polygons = 0;
for (ExPolygons::const_iterator it = expolys.begin(); it != expolys.end(); ++ it)
n_polygons += it->holes.size() + 1;
for (const ExPolygon &ex : expolys)
n_polygons += ex.holes.size() + 1;
return n_polygons;
}
@ -217,6 +217,28 @@ inline Polygons to_polygons(const ExPolygons &src)
return polygons;
}
inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygon &src)
{
ConstPolygonPtrs polygons;
polygons.reserve(src.holes.size() + 1);
polygons.emplace_back(&src.contour);
for (const Polygon &hole : src.holes)
polygons.emplace_back(&hole);
return polygons;
}
inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygons &src)
{
ConstPolygonPtrs polygons;
polygons.reserve(number_polygons(src));
for (const ExPolygon &expoly : src) {
polygons.emplace_back(&expoly.contour);
for (const Polygon &hole : expoly.holes)
polygons.emplace_back(&hole);
}
return polygons;
}
inline Polygons to_polygons(ExPolygon &&src)
{
Polygons polygons;
@ -338,6 +360,8 @@ extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
extern bool remove_sticks(ExPolygon &poly);
extern void keep_largest_contour_only(ExPolygons &polygons);
inline double area(const ExPolygon &poly) { return poly.area(); }
inline double area(const ExPolygons &polys)
{
double s = 0.;

View file

@ -0,0 +1,128 @@
#ifndef EXECUTION_HPP
#define EXECUTION_HPP
#include <type_traits>
#include <utility>
#include <cstddef>
#include <iterator>
#include "libslic3r/libslic3r.h"
namespace Slic3r {
// Override for valid execution policies
template<class EP> struct IsExecutionPolicy_ : public std::false_type {};
template<class EP> constexpr bool IsExecutionPolicy =
IsExecutionPolicy_<remove_cvref_t<EP>>::value;
template<class EP, class T = void>
using ExecutionPolicyOnly = std::enable_if_t<IsExecutionPolicy<EP>, T>;
namespace execution {
// This struct needs to be specialized for each execution policy.
// See ExecutionSeq.hpp and ExecutionTBB.hpp for example.
template<class EP, class En = void> struct Traits {};
template<class EP> using AsTraits = Traits<remove_cvref_t<EP>>;
// Each execution policy should declare two types of mutexes. A a spin lock and
// a blocking mutex. These types should satisfy the BasicLockable concept.
template<class EP> using SpinningMutex = typename Traits<EP>::SpinningMutex;
template<class EP> using BlockingMutex = typename Traits<EP>::BlockingMutex;
// Query the available threads for concurrency.
template<class EP, class = ExecutionPolicyOnly<EP> >
size_t max_concurrency(const EP &ep)
{
return AsTraits<EP>::max_concurrency(ep);
}
// foreach loop with the execution policy passed as argument. Granularity can
// be specified explicitly. max_concurrency() can be used for optimal results.
template<class EP, class It, class Fn, class = ExecutionPolicyOnly<EP>>
void for_each(const EP &ep, It from, It to, Fn &&fn, size_t granularity = 1)
{
AsTraits<EP>::for_each(ep, from, to, std::forward<Fn>(fn), granularity);
}
// A reduce operation with the execution policy passed as argument.
// mergefn has T(const T&, const T&) signature
// accessfn has T(I) signature if I is an integral type and
// T(const I::value_type &) if I is an iterator type.
template<class EP,
class I,
class MergeFn,
class T,
class AccessFn,
class = ExecutionPolicyOnly<EP> >
T reduce(const EP & ep,
I from,
I to,
const T & init,
MergeFn && mergefn,
AccessFn &&accessfn,
size_t granularity = 1)
{
return AsTraits<EP>::reduce(ep, from, to, init,
std::forward<MergeFn>(mergefn),
std::forward<AccessFn>(accessfn),
granularity);
}
// An overload of reduce method to be used with iterators as 'from' and 'to'
// arguments. Access functor is omitted here.
template<class EP,
class I,
class MergeFn,
class T,
class = ExecutionPolicyOnly<EP> >
T reduce(const EP &ep,
I from,
I to,
const T & init,
MergeFn &&mergefn,
size_t granularity = 1)
{
return reduce(
ep, from, to, init, std::forward<MergeFn>(mergefn),
[](const auto &i) { return i; }, granularity);
}
template<class EP,
class I,
class T,
class AccessFn,
class = ExecutionPolicyOnly<EP>>
T accumulate(const EP & ep,
I from,
I to,
const T & init,
AccessFn &&accessfn,
size_t granularity = 1)
{
return reduce(ep, from, to, init, std::plus<T>{},
std::forward<AccessFn>(accessfn), granularity);
}
template<class EP,
class I,
class T,
class = ExecutionPolicyOnly<EP> >
T accumulate(const EP &ep,
I from,
I to,
const T & init,
size_t granularity = 1)
{
return reduce(
ep, from, to, init, std::plus<T>{}, [](const auto &i) { return i; },
granularity);
}
} // namespace execution_policy
} // namespace Slic3r
#endif // EXECUTION_HPP

View file

@ -0,0 +1,84 @@
#ifndef EXECUTIONSEQ_HPP
#define EXECUTIONSEQ_HPP
#ifdef PRUSASLICER_USE_EXECUTION_STD // Conflicts with our version of TBB
#include <execution>
#endif
#include "Execution.hpp"
namespace Slic3r {
// Execution policy implementing dummy sequential algorithms
struct ExecutionSeq {};
template<> struct IsExecutionPolicy_<ExecutionSeq> : public std::true_type {};
static constexpr ExecutionSeq ex_seq = {};
template<class EP> struct IsSequentialEP_ { static constexpr bool value = false; };
template<> struct IsSequentialEP_<ExecutionSeq>: public std::true_type {};
#ifdef PRUSASLICER_USE_EXECUTION_STD
template<> struct IsExecutionPolicy_<std::execution::sequenced_policy>: public std::true_type {};
template<> struct IsSequentialEP_<std::execution::sequenced_policy>: public std::true_type {};
#endif
template<class EP>
constexpr bool IsSequentialEP = IsSequentialEP_<remove_cvref_t<EP>>::value;
template<class EP, class R = EP>
using SequentialEPOnly = std::enable_if_t<IsSequentialEP<EP>, R>;
template<class EP>
struct execution::Traits<EP, SequentialEPOnly<EP, void>> {
private:
struct _Mtx { inline void lock() {} inline void unlock() {} };
template<class Fn, class It>
static IteratorOnly<It, void> loop_(It from, It to, Fn &&fn)
{
for (auto it = from; it != to; ++it) fn(*it);
}
template<class Fn, class I>
static IntegerOnly<I, void> loop_(I from, I to, Fn &&fn)
{
for (I i = from; i < to; ++i) fn(i);
}
public:
using SpinningMutex = _Mtx;
using BlockingMutex = _Mtx;
template<class It, class Fn>
static void for_each(const EP &,
It from,
It to,
Fn &&fn,
size_t /* ignore granularity */ = 1)
{
loop_(from, to, std::forward<Fn>(fn));
}
template<class I, class MergeFn, class T, class AccessFn>
static T reduce(const EP &,
I from,
I to,
const T & init,
MergeFn &&mergefn,
AccessFn &&access,
size_t /*granularity*/ = 1
)
{
T acc = init;
loop_(from, to, [&](auto &i) { acc = mergefn(acc, access(i)); });
return acc;
}
static size_t max_concurrency(const EP &) { return 1; }
};
} // namespace Slic3r
#endif // EXECUTIONSEQ_HPP

View file

@ -0,0 +1,77 @@
#ifndef EXECUTIONTBB_HPP
#define EXECUTIONTBB_HPP
#include <tbb/spin_mutex.h>
#include <tbb/mutex.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_reduce.h>
#include <tbb/task_arena.h>
#include "Execution.hpp"
namespace Slic3r {
struct ExecutionTBB {};
template<> struct IsExecutionPolicy_<ExecutionTBB> : public std::true_type {};
// Execution policy using Intel TBB library under the hood.
static constexpr ExecutionTBB ex_tbb = {};
template<> struct execution::Traits<ExecutionTBB> {
private:
template<class Fn, class It>
static IteratorOnly<It, void> loop_(const tbb::blocked_range<It> &range, Fn &&fn)
{
for (auto &el : range) fn(el);
}
template<class Fn, class I>
static IntegerOnly<I, void> loop_(const tbb::blocked_range<I> &range, Fn &&fn)
{
for (I i = range.begin(); i < range.end(); ++i) fn(i);
}
public:
using SpinningMutex = tbb::spin_mutex;
using BlockingMutex = tbb::mutex;
template<class It, class Fn>
static void for_each(const ExecutionTBB &,
It from, It to, Fn &&fn, size_t granularity)
{
tbb::parallel_for(tbb::blocked_range{from, to, granularity},
[&fn](const auto &range) {
loop_(range, std::forward<Fn>(fn));
});
}
template<class I, class MergeFn, class T, class AccessFn>
static T reduce(const ExecutionTBB &,
I from,
I to,
const T &init,
MergeFn &&mergefn,
AccessFn &&access,
size_t granularity = 1
)
{
return tbb::parallel_reduce(
tbb::blocked_range{from, to, granularity}, init,
[&](const auto &range, T subinit) {
T acc = subinit;
loop_(range, [&](auto &i) { acc = mergefn(acc, access(i)); });
return acc;
},
std::forward<MergeFn>(mergefn));
}
static size_t max_concurrency(const ExecutionTBB &)
{
return tbb::this_task_arena::max_concurrency();
}
};
}
#endif // EXECUTIONTBB_HPP

View file

@ -14,12 +14,12 @@ namespace Slic3r {
void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(intersection_pl((Polylines)polyline, to_polygons(collection.expolygons)), retval);
this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection.expolygons), retval);
}
void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(diff_pl((Polylines)this->polyline, to_polygons(collection.expolygons)), retval);
this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection.expolygons), retval);
}
void ExtrusionPath::clip_end(double distance)
@ -318,7 +318,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
case erIroning : return L("Ironing");
case erBridgeInfill : return L("Bridge infill");
case erGapFill : return L("Gap fill");
case erSkirt : return L("Skirt");
case erSkirt : return L("Skirt/Brim");
case erSupportMaterial : return L("Support material");
case erSupportMaterialInterface : return L("Support material interface");
case erWipeTower : return L("Wipe tower");
@ -349,7 +349,7 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
return erBridgeInfill;
else if (role == L("Gap fill"))
return erGapFill;
else if (role == L("Skirt"))
else if (role == L("Skirt") || role == L("Skirt/Brim")) // "Skirt" is for backward compatibility with 2.3.1 and earlier
return erSkirt;
else if (role == L("Support material"))
return erSupportMaterial;

View file

@ -203,6 +203,8 @@ public:
void reverse() override;
const Point& first_point() const override { return this->paths.front().polyline.points.front(); }
const Point& last_point() const override { return this->paths.back().polyline.points.back(); }
size_t size() const { return this->paths.size(); }
bool empty() const { return this->paths.empty(); }
double length() const override;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.

View file

@ -147,7 +147,7 @@ void Fill3DHoneycomb::_fill_surface_single(
// align bounding box to a multiple of our honeycomb grid module
// (a module is 2*$distance since one $distance half-module is
// growing while the other $distance half-module is shrinking)
bb.merge(_align_to_grid(bb.min, Point(2*distance, 2*distance)));
bb.merge(align_to_grid(bb.min, Point(2*distance, 2*distance)));
// generate pattern
Polylines polylines = makeGrid(
@ -162,7 +162,7 @@ void Fill3DHoneycomb::_fill_surface_single(
pl.translate(bb.min);
// clip pattern to boundaries, chain the clipped polylines
polylines = intersection_pl(polylines, to_polygons(expolygon));
polylines = intersection_pl(polylines, expolygon);
// connect lines if needed
if (params.dont_connect() || polylines.size() <= 1)

View file

@ -1368,7 +1368,7 @@ void Filler::_fill_surface_single(
all_polylines.reserve(lines.size());
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
// Crop all polylines
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
#endif
}

File diff suppressed because it is too large Load diff

View file

@ -133,26 +133,10 @@ public:
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 coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
static void connect_base_support(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams &params);
static void connect_base_support(Polylines &&infill_ordered, const Polygons &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams &params);
// Align a coordinate to a grid. The coordinate may be negative,
// the aligned value will never be bigger than the original one.
static coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {
// Current C++ standard defines the result of integer division to be rounded to zero,
// for both positive and negative numbers. Here we want to round down for negative
// numbers as well.
coord_t aligned = (coord < 0) ?
((coord - spacing + 1) / spacing) * spacing :
(coord / spacing) * spacing;
assert(aligned <= coord);
return aligned;
}
static Point _align_to_grid(Point coord, Point spacing)
{ return Point(_align_to_grid(coord(0), spacing(0)), _align_to_grid(coord(1), spacing(1))); }
static coord_t _align_to_grid(coord_t coord, coord_t spacing, coord_t base)
{ return base + _align_to_grid(coord - base, spacing); }
static Point _align_to_grid(Point coord, Point spacing, Point base)
{ return Point(_align_to_grid(coord(0), spacing(0), base(0)), _align_to_grid(coord(1), spacing(1), base(1))); }
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
};
} // namespace Slic3r

View file

@ -24,16 +24,16 @@ void FillConcentric::_fill_surface_single(
this->spacing = unscale<double>(distance);
}
Polygons loops = to_polygons(std::move(expolygon));
Polygons last = loops;
Polygons loops = to_polygons(expolygon);
ExPolygons last { std::move(expolygon) };
while (! last.empty()) {
last = offset2(last, -(distance + min_spacing/2), +min_spacing/2);
append(loops, last);
last = offset2_ex(last, -(distance + min_spacing/2), +min_spacing/2);
append(loops, to_polygons(last));
}
// generate paths from the outermost to the innermost, to avoid
// adhesion problems of the first central tiny loops
loops = union_pt_chained_outside_in(loops, false);
loops = union_pt_chained_outside_in(loops);
// split paths using a nearest neighbor search
size_t iPathFirst = polylines_out.size();

View file

@ -166,7 +166,7 @@ void FillGyroid::_fill_surface_single(
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
// align bounding box to a multiple of our grid module
bb.merge(_align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
bb.merge(align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
// generate pattern
Polylines polylines = make_gyroid_waves(
@ -180,7 +180,7 @@ void FillGyroid::_fill_surface_single(
for (Polyline &pl : polylines)
pl.translate(bb.min);
polylines = intersection_pl(polylines, to_polygons(expolygon));
polylines = intersection_pl(polylines, expolygon);
if (! polylines.empty()) {
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!

View file

@ -47,7 +47,7 @@ void FillHoneycomb::_fill_surface_single(
// extend bounding box so that our pattern will be aligned with other layers
// $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
// The infill is not aligned to the object bounding box, but to a world coordinate system. Supposedly good enough.
bounding_box.merge(_align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height)));
bounding_box.merge(align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height)));
}
coord_t x = bounding_box.min(0);
@ -73,7 +73,7 @@ void FillHoneycomb::_fill_surface_single(
}
}
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
all_polylines = intersection_pl(std::move(all_polylines), expolygon);
if (params.dont_connect() || all_polylines.size() <= 1)
append(polylines_out, chain_polylines(std::move(all_polylines)));
else

View file

@ -31,7 +31,7 @@ void FillLine::_fill_surface_single(
} else {
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.
bounding_box.merge(_align_to_grid(
bounding_box.merge(align_to_grid(
bounding_box.min,
Point(this->_line_spacing, this->_line_spacing),
direction.second.rotated(- direction.first)));
@ -58,7 +58,7 @@ void FillLine::_fill_surface_single(
pts.push_back(it->a);
pts.push_back(it->b);
}
Polylines polylines = intersection_pl(polylines_src, offset(to_polygons(expolygon), scale_(0.02)), false);
Polylines polylines = intersection_pl(polylines_src, offset(expolygon, scale_(0.02)), false);
// FIXME Vojtech: This is only performed for horizontal lines, not for the vertical lines!
const float INFILL_OVERLAP_OVER_SPACING = 0.3f;

View file

@ -44,7 +44,7 @@ void FillPlanePath::_fill_surface_single(
coord_t(floor(pt.x() * distance_between_lines + 0.5)),
coord_t(floor(pt.y() * distance_between_lines + 0.5))));
// intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines);
polylines = intersection_pl(std::move(polylines), to_polygons(expolygon));
polylines = intersection_pl(std::move(polylines), expolygon);
Polylines chained;
if (params.dont_connect() || params.density > 0.5 || polylines.size() <= 1)
chained = chain_polylines(std::move(polylines));

View file

@ -798,33 +798,44 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
assert(l <= this_x);
assert(r >= this_x);
// Calculate the intersection position in y axis. x is known.
if (p1(0) == this_x) {
if (p2(0) == this_x) {
if (p1.x() == this_x) {
if (p2.x() == this_x) {
// Ignore strictly vertical segments.
continue;
}
is.pos_p = p1(1);
const Point &p0 = prev_value_modulo(iPrev, contour);
if (int64_t(p0.x() - p1.x()) * int64_t(p2.x() - p1.x()) > 0) {
// Ignore points of a contour touching the infill line from one side.
continue;
}
is.pos_p = p1.y();
is.pos_q = 1;
} else if (p2(0) == this_x) {
is.pos_p = p2(1);
} else if (p2.x() == this_x) {
const Point &p3 = next_value_modulo(iSegment, contour);
if (int64_t(p3.x() - p2.x()) * int64_t(p1.x() - p2.x()) > 0) {
// Ignore points of a contour touching the infill line from one side.
continue;
}
is.pos_p = p2.y();
is.pos_q = 1;
} else {
// First calculate the intersection parameter 't' as a rational number with non negative denominator.
if (p2(0) > p1(0)) {
is.pos_p = this_x - p1(0);
is.pos_q = p2(0) - p1(0);
if (p2.x() > p1.x()) {
is.pos_p = this_x - p1.x();
is.pos_q = p2.x() - p1.x();
} else {
is.pos_p = p1(0) - this_x;
is.pos_q = p1(0) - p2(0);
is.pos_p = p1.x() - this_x;
is.pos_q = p1.x() - p2.x();
}
assert(is.pos_p >= 0 && is.pos_p <= is.pos_q);
assert(is.pos_q > 1);
assert(is.pos_p > 0 && is.pos_p < is.pos_q);
// Make an intersection point from the 't'.
is.pos_p *= int64_t(p2(1) - p1(1));
is.pos_p += p1(1) * int64_t(is.pos_q);
is.pos_p *= int64_t(p2.y() - p1.y());
is.pos_p += p1.y() * int64_t(is.pos_q);
}
// +-1 to take rounding into account.
assert(is.pos() + 1 >= std::min(p1(1), p2(1)));
assert(is.pos() <= std::max(p1(1), p2(1)) + 1);
assert(is.pos() + 1 >= std::min(p1.y(), p2.y()));
assert(is.pos() <= std::max(p1.y(), p2.y()) + 1);
segs[i].intersections.push_back(is);
}
}
@ -844,36 +855,31 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
size_t j = 0;
for (size_t i = 0; i < sil.intersections.size(); ++ i) {
// What is the orientation of the segment at the intersection point?
size_t iContour = sil.intersections[i].iContour;
SegmentIntersection &is = sil.intersections[i];
const size_t iContour = is.iContour;
const Points &contour = poly_with_offset.contour(iContour).points;
size_t iSegment = sil.intersections[i].iSegment;
size_t iPrev = ((iSegment == 0) ? contour.size() : iSegment) - 1;
coord_t dir = contour[iSegment](0) - contour[iPrev](0);
bool low = dir > 0;
sil.intersections[i].type = poly_with_offset.is_contour_outer(iContour) ?
const size_t iSegment = is.iSegment;
const size_t iPrev = prev_idx_modulo(iSegment, contour);
const coord_t dir = contour[iSegment].x() - contour[iPrev].x();
const bool low = dir > 0;
is.type = poly_with_offset.is_contour_outer(iContour) ?
(low ? SegmentIntersection::OUTER_LOW : SegmentIntersection::OUTER_HIGH) :
(low ? SegmentIntersection::INNER_LOW : SegmentIntersection::INNER_HIGH);
if (j > 0 && sil.intersections[i].iContour == sil.intersections[j-1].iContour) {
// Two successive intersection points on a vertical line with the same contour. This may be a special case.
if (sil.intersections[i].pos() == sil.intersections[j-1].pos()) {
bool take_next = true;
if (j > 0) {
SegmentIntersection &is2 = sil.intersections[j - 1];
if (iContour == is2.iContour && is.pos_q == 1 && is2.pos_q == 1) {
// Two successive intersection points on a vertical line with the same contour, both points are end points of their respective contour segments.
if (is.pos_p == is2.pos_p) {
// Two successive segments meet exactly at the vertical line.
#ifdef SLIC3R_DEBUG
// Verify that the segments of sil.intersections[i] and sil.intersections[j-1] are adjoint.
size_t iSegment2 = sil.intersections[j-1].iSegment;
size_t iPrev2 = ((iSegment2 == 0) ? contour.size() : iSegment2) - 1;
assert(iSegment == iPrev2 || iSegment2 == iPrev);
#endif /* SLIC3R_DEBUG */
if (sil.intersections[i].type == sil.intersections[j-1].type) {
assert(iSegment == prev_idx_modulo(is2.iSegment, contour) || is2.iSegment == iPrev);
assert(is.type == is2.type);
// Two successive segments of the same direction (both to the right or both to the left)
// meet exactly at the vertical line.
// Remove the second intersection point.
} else {
// This is a loop returning to the same point.
// It may as well be a vertex of a loop touching this vertical line.
// Remove both the lines.
-- j;
}
} else if (sil.intersections[i].type == sil.intersections[j-1].type) {
take_next = false;
} else if (is.type == is2.type) {
// Two non successive segments of the same direction (both to the right or both to the left)
// meet exactly at the vertical line. That means there is a Z shaped path, where the center segment
// of the Z shaped path is aligned with this vertical line.
@ -884,15 +890,11 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
// Remove the first intersection point, keep the second intersection point.
sil.intersections[j-1] = sil.intersections[i];
}
} else {
// Vertical line intersects a contour segment at a general position (not at one of its end points).
// or the contour just touches this vertical line with a vertical segment or a sequence of vertical segments.
// Keep both intersection points.
if (j < i)
sil.intersections[j] = sil.intersections[i];
++ j;
take_next = false;
}
} else {
}
}
if (take_next) {
// Vertical line intersects a contour segment at a general position (not at one of its end points).
if (j < i)
sil.intersections[j] = sil.intersections[i];
@ -905,7 +907,13 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
}
// Verify the segments. If something is wrong, give up.
#define ASSERT_THROW(CONDITION) do { assert(CONDITION); if (! (CONDITION)) throw InfillFailedException(); } while (0)
#ifdef INFILL_DEBUG_OUTPUT
#define INFILL_DEBUG_ASSERT(CONDITION)
try {
#else // INFILL_DEBUG_OUTPUT
#define INFILL_DEBUG_ASSERT(CONDITION) assert(CONDITION)
#endif // INFILL_DEBUG_OUTPUT
#define ASSERT_THROW(CONDITION) do { INFILL_DEBUG_ASSERT(CONDITION); if (! (CONDITION)) throw InfillFailedException(); } while (0)
for (size_t i_seg = 0; i_seg < segs.size(); ++ i_seg) {
SegmentedIntersectionLine &sil = segs[i_seg];
// The intersection points have to be even.
@ -925,6 +933,56 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
}
}
#undef ASSERT_THROW
#undef INFILL_DEBUG_ASSERT
#ifdef INFILL_DEBUG_OUTPUT
} catch (const InfillFailedException & /* ex */) {
// Export the buggy result into an SVG file.
static int iRun = 0;
BoundingBox bbox = get_extents(poly_with_offset.polygons_src);
bbox.offset(scale_(3.));
::Slic3r::SVG svg(debug_out_path("slice_region_by_vertical_lines-failed-%d.svg", iRun ++), bbox);
svg.draw(poly_with_offset.polygons_src);
svg.draw_outline(poly_with_offset.polygons_src, "green");
svg.draw_outline(poly_with_offset.polygons_outer, "green");
svg.draw_outline(poly_with_offset.polygons_inner, "green");
for (size_t i_seg = 0; i_seg < segs.size(); ++i_seg) {
SegmentedIntersectionLine &sil = segs[i_seg];
for (size_t i = 0; i < sil.intersections.size();) {
// An intersection segment crossing the bigger contour may cross the inner offsetted contour even number of times.
if (sil.intersections[i].type != SegmentIntersection::OUTER_LOW) {
svg.draw(Point(sil.pos, sil.intersections[i].pos()), "red");
break;
}
size_t j = i + 1;
if (j == sil.intersections.size()) {
svg.draw(Point(sil.pos, sil.intersections[i].pos()), "magenta");
break;
}
if (! (sil.intersections[j].type == SegmentIntersection::INNER_LOW || sil.intersections[j].type == SegmentIntersection::OUTER_HIGH)) {
svg.draw(Point(sil.pos, sil.intersections[j].pos()), "blue");
break;
}
for (; j < sil.intersections.size() && sil.intersections[j].is_inner(); ++j);
if (j == sil.intersections.size()) {
svg.draw(Point(sil.pos, sil.intersections[j - 1].pos()), "magenta");
break;
}
if ((j & 1) != 1 || sil.intersections[j].type != SegmentIntersection::OUTER_HIGH) {
svg.draw(Point(sil.pos, sil.intersections[j].pos()), "red");
break;
}
if (! (i + 1 == j || sil.intersections[j - 1].type == SegmentIntersection::INNER_HIGH)) {
svg.draw(Point(sil.pos, sil.intersections[j].pos()), "red");
break;
}
svg.draw(Line(Point(sil.pos, sil.intersections[i].pos()), Point(sil.pos, sil.intersections[j].pos())), "black");
i = j + 1;
}
}
assert(false);
throw;
}
#endif //INFILL_DEBUG_OUTPUT
return segs;
}
@ -2714,10 +2772,10 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.
Point refpt = rotate_vector.second.rotated(- rotate_vector.first);
// _align_to_grid will not work correctly with positive pattern_shift.
// align_to_grid will not work correctly with positive pattern_shift.
coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing;
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
bounding_box.merge(_align_to_grid(
bounding_box.merge(align_to_grid(
bounding_box.min,
Point(line_spacing, line_spacing),
refpt));
@ -2825,6 +2883,45 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
return true;
}
void make_fill_lines(const ExPolygonWithOffset &poly_with_offset, Point refpt, double angle, coord_t x_margin, coord_t line_spacing, coord_t pattern_shift, Polylines &fill_lines)
{
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
// Don't produce infill lines, which fully overlap with the infill perimeter.
coord_t x_min = bounding_box.min.x() + x_margin;
coord_t x_max = bounding_box.max.x() - x_margin;
// extend bounding box so that our pattern will be aligned with other layers
// align_to_grid will not work correctly with positive pattern_shift.
coord_t pattern_shift_scaled = pattern_shift % line_spacing;
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
bounding_box.merge(Slic3r::align_to_grid(bounding_box.min, Point(line_spacing, line_spacing), refpt));
// Intersect a set of euqally spaced vertical lines wiht expolygon.
// n_vlines = ceil(bbox_width / line_spacing)
const size_t n_vlines = (bounding_box.max.x() - bounding_box.min.x() + line_spacing - 1) / line_spacing;
const double cos_a = cos(angle);
const double sin_a = sin(angle);
for (const SegmentedIntersectionLine &vline : slice_region_by_vertical_lines(poly_with_offset, n_vlines, bounding_box.min.x(), line_spacing))
if (vline.pos >= x_min) {
if (vline.pos > x_max)
break;
for (auto it = vline.intersections.begin(); it != vline.intersections.end();) {
auto it_low = it ++;
assert(it_low->type == SegmentIntersection::OUTER_LOW);
if (it_low->type != SegmentIntersection::OUTER_LOW)
continue;
auto it_high = it;
assert(it_high->type == SegmentIntersection::OUTER_HIGH);
if (it_high->type == SegmentIntersection::OUTER_HIGH) {
if (angle == 0.)
fill_lines.emplace_back(Point(vline.pos, it_low->pos()), Point(vline.pos, it_high->pos()));
else
fill_lines.emplace_back(Point(vline.pos, it_low->pos()).rotated(cos_a, sin_a), Point(vline.pos, it_high->pos()).rotated(cos_a, sin_a));
++ it;
}
}
}
}
bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out)
{
assert(sweep_params.size() > 1);
@ -2843,42 +2940,8 @@ bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillPar
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
for (const SweepParams &sweep : sweep_params) {
// Rotate polygons so that we can work with vertical lines here
double angle = rotate_vector.first + sweep.angle_base;
ExPolygonWithOffset poly_with_offset(poly_with_offset_base, - angle);
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
// Don't produce infill lines, which fully overlap with the infill perimeter.
coord_t x_min = bounding_box.min.x() + line_width + coord_t(SCALED_EPSILON);
coord_t x_max = bounding_box.max.x() - line_width - coord_t(SCALED_EPSILON);
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.
Point refpt = rotate_vector.second.rotated(- angle);
// _align_to_grid will not work correctly with positive pattern_shift.
coord_t pattern_shift_scaled = coord_t(scale_(sweep.pattern_shift)) % line_spacing;
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
bounding_box.merge(_align_to_grid(bounding_box.min, Point(line_spacing, line_spacing), refpt));
// Intersect a set of euqally spaced vertical lines wiht expolygon.
// n_vlines = ceil(bbox_width / line_spacing)
const size_t n_vlines = (bounding_box.max.x() - bounding_box.min.x() + line_spacing - 1) / line_spacing;
const double cos_a = cos(angle);
const double sin_a = sin(angle);
for (const SegmentedIntersectionLine &vline : slice_region_by_vertical_lines(poly_with_offset, n_vlines, bounding_box.min.x(), line_spacing))
if (vline.pos > x_min) {
if (vline.pos >= x_max)
break;
for (auto it = vline.intersections.begin(); it != vline.intersections.end();) {
auto it_low = it ++;
assert(it_low->type == SegmentIntersection::OUTER_LOW);
if (it_low->type != SegmentIntersection::OUTER_LOW)
continue;
auto it_high = it;
assert(it_high->type == SegmentIntersection::OUTER_HIGH);
if (it_high->type == SegmentIntersection::OUTER_HIGH) {
fill_lines.emplace_back(Point(vline.pos, it_low->pos()).rotated(cos_a, sin_a), Point(vline.pos, it_high->pos()).rotated(cos_a, sin_a));
++ it;
}
}
}
float angle = rotate_vector.first + sweep.angle_base;
make_fill_lines(ExPolygonWithOffset(poly_with_offset_base, - angle), rotate_vector.second.rotated(-angle), angle, line_width + coord_t(SCALED_EPSILON), line_spacing, coord_t(scale_(sweep.pattern_shift)), fill_lines);
}
if (params.dont_connect() || fill_lines.size() <= 1) {
@ -2954,4 +3017,29 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams &para
return polylines_out;
}
Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams &params)
{
assert(! params.full_infill());
Polylines polylines_out;
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
ExPolygonWithOffset poly_with_offset(surface->expolygon, - rotate_vector.first, float(scale_(this->overlap - 0.5 * this->spacing)));
if (poly_with_offset.n_contours > 0) {
Polylines fill_lines;
coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
// Create infill lines, keep them vertical.
make_fill_lines(poly_with_offset, rotate_vector.second.rotated(- rotate_vector.first), 0, 0, line_spacing, 0, fill_lines);
// Both the poly_with_offset and polylines_out are rotated, so the infill lines are strictly vertical.
connect_base_support(std::move(fill_lines), poly_with_offset.polygons_outer, poly_with_offset.bounding_box_outer(), polylines_out, this->spacing, params);
// Rotate back by rotate_vector.first
const double cos_a = cos(rotate_vector.first);
const double sin_a = sin(rotate_vector.first);
for (Polyline &pl : polylines_out)
for (Point &pt : pl.points)
pt.rotate(cos_a, sin_a);
}
return polylines_out;
}
} // namespace Slic3r

View file

@ -97,6 +97,17 @@ protected:
float _layer_angle(size_t idx) const override { return 0.f; }
};
class FillSupportBase : public FillRectilinear
{
public:
Fill* clone() const override { return new FillSupportBase(*this); }
~FillSupportBase() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
float _layer_angle(size_t idx) const override { return 0.f; }
};
} // namespace Slic3r

View file

@ -92,15 +92,8 @@ double Flow::extrusion_width(const std::string& opt_key, const ConfigOptionFloat
auto opt_layer_height = config.option(opt_key_layer_height);
if (opt_layer_height == nullptr)
throw_on_missing_variable(opt_key, opt_key_layer_height);
double layer_height = opt_layer_height->getFloat();
if (first_layer && static_cast<const ConfigOptionFloatOrPercent*>(opt_layer_height)->percent) {
// first_layer_height depends on layer_height.
opt_layer_height = config.option("layer_height");
if (opt_layer_height == nullptr)
throw_on_missing_variable(opt_key, "layer_height");
layer_height *= 0.01 * opt_layer_height->getFloat();
}
return opt->get_abs_value(layer_height);
assert(! first_layer || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_layer_height)->percent);
return opt->get_abs_value(opt_layer_height->getFloat());
}
if (opt->value == 0.) {
@ -238,13 +231,14 @@ Flow support_material_flow(const PrintObject *object, float layer_height)
Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height)
{
const auto &width = (object->print()->config().first_layer_extrusion_width.value > 0) ? object->print()->config().first_layer_extrusion_width : object->config().support_material_extrusion_width;
const PrintConfig &print_config = object->print()->config();
const auto &width = (print_config.first_layer_extrusion_width.value > 0) ? print_config.first_layer_extrusion_width : object->config().support_material_extrusion_width;
return Flow::new_from_config_width(
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(width.value > 0) ? width : object->config().extrusion_width,
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder-1)),
(layer_height > 0.f) ? layer_height : float(object->config().first_layer_height.get_abs_value(object->config().layer_height.value)));
float(print_config.nozzle_diameter.get_at(object->config().support_material_extruder-1)),
(layer_height > 0.f) ? layer_height : float(print_config.first_layer_height.get_abs_value(object->config().layer_height.value)));
}
Flow support_material_interface_flow(const PrintObject *object, float layer_height)

View file

@ -248,7 +248,7 @@ std::vector<ExPolygons> extract_slices_from_sla_archive(
{
double incr, val, prev;
bool stop = false;
tbb::spin_mutex mutex;
tbb::spin_mutex mutex = {};
} st {100. / slices.size(), 0., 0.};
tbb::parallel_for(size_t(0), arch.images.size(),
@ -372,6 +372,13 @@ void fill_iniconf(ConfMap &m, const SLAPrint &print)
m["numFast"] = std::to_string(stats.fast_layers_count);
m["printTime"] = std::to_string(stats.estimated_print_time);
bool hollow_en = false;
auto it = print.objects().begin();
while (!hollow_en && it != print.objects().end())
hollow_en = (*it++)->config().hollowing_enable;
m["hollow"] = hollow_en ? "1" : "0";
m["action"] = "print";
}

View file

@ -435,19 +435,18 @@ namespace Slic3r {
{
std::string gcode;
assert(m_layer_idx >= 0);
if (!m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
if (m_layer_idx < (int)m_tool_changes.size()) {
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
// resulting in a wipe tower with sparse layers.
double wipe_tower_z = -1;
bool ignore_sparse = false;
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
wipe_tower_z = m_last_wipe_tower_print_z;
ignore_sparse = (m_brim_done && m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
if (m_tool_change_idx == 0 && !ignore_sparse)
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
}
@ -457,7 +456,6 @@ namespace Slic3r {
m_last_wipe_tower_print_z = wipe_tower_z;
}
}
m_brim_done = true;
}
return gcode;
}
@ -786,7 +784,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
namespace DoExport {
static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor, bool& silent_time_estimator_enabled)
{
silent_time_estimator_enabled = (config.gcode_flavor == gcfMarlin) && config.silent_mode;
silent_time_estimator_enabled = (config.gcode_flavor == gcfMarlinLegacy || config.gcode_flavor == gcfMarlinFirmware)
&& config.silent_mode;
processor.reset();
processor.apply_config(config);
processor.enable_stealth_time_estimator(silent_time_estimator_enabled);
@ -1112,7 +1111,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
// Write some terse information on the slicing parameters.
const PrintObject *first_object = print.objects().front();
const double layer_height = first_object->config().layer_height.value;
const double first_layer_height = first_object->config().first_layer_height.get_abs_value(layer_height);
assert(! print.config().first_layer_height.percent);
const double first_layer_height = print.config().first_layer_height.value;
for (const PrintRegion* region : print.regions()) {
_write_format(file, "; external perimeters extrusion width = %.2fmm\n", region->flow(*first_object, frExternalPerimeter, layer_height).width());
_write_format(file, "; perimeters extrusion width = %.2fmm\n", region->flow(*first_object, frPerimeter, layer_height).width());
@ -1357,7 +1357,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
bbox_prime.offset(0.5f);
bool overlap = bbox_prime.overlap(bbox_print);
if (print.config().gcode_flavor == gcfMarlin) {
if (print.config().gcode_flavor == gcfMarlinLegacy || print.config().gcode_flavor == gcfMarlinFirmware) {
_write(file, this->retract());
_write(file, "M300 S800 P500\n"); // Beep for 500ms, tone 800Hz.
if (overlap) {
@ -1560,7 +1560,8 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
// Do not process this piece of G-code by the time estimator, it already knows the values through another sources.
void GCode::print_machine_envelope(FILE *file, Print &print)
{
if (print.config().gcode_flavor.value == gcfMarlin && print.config().machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) {
if ((print.config().gcode_flavor.value == gcfMarlinLegacy || print.config().gcode_flavor.value == gcfMarlinFirmware)
&& print.config().machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) {
fprintf(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n",
int(print.config().machine_max_acceleration_x.values.front() + 0.5),
int(print.config().machine_max_acceleration_y.values.front() + 0.5),
@ -1571,10 +1572,20 @@ void GCode::print_machine_envelope(FILE *file, Print &print)
int(print.config().machine_max_feedrate_y.values.front() + 0.5),
int(print.config().machine_max_feedrate_z.values.front() + 0.5),
int(print.config().machine_max_feedrate_e.values.front() + 0.5));
// Now M204 - acceleration. This one is quite hairy thanks to how Marlin guys care about
// backwards compatibility: https://github.com/prusa3d/PrusaSlicer/issues/1089
// Legacy Marlin should export travel acceleration the same as printing acceleration.
// MarlinFirmware has the two separated.
int travel_acc = print.config().gcode_flavor == gcfMarlinLegacy
? int(print.config().machine_max_acceleration_extruding.values.front() + 0.5)
: int(print.config().machine_max_acceleration_travel.values.front() + 0.5);
fprintf(file, "M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
int(print.config().machine_max_acceleration_retracting.values.front() + 0.5),
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5));
travel_acc);
fprintf(file, "M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n",
print.config().machine_max_jerk_x.values.front(),
print.config().machine_max_jerk_y.values.front(),
@ -1768,6 +1779,10 @@ namespace ProcessLayer
else {
gcode += gcodegen.placeholder_parser_process("color_change_gcode", config.color_change_gcode, current_extruder_id);
gcode += "\n";
//FIXME Tell G-code writer that M600 filled the extruder, thus the G-code writer shall reset the extruder to unretracted state after
// return from M600. Thus the G-code generated by the following line is ignored.
// see GH issue #6362
gcodegen.writer().unretract();
}
}
else {

View file

@ -75,8 +75,8 @@ public:
m_tool_changes(tool_changes),
m_final_purge(final_purge),
m_layer_idx(-1),
m_tool_change_idx(0),
m_brim_done(false) {}
m_tool_change_idx(0)
{}
std::string prime(GCode &gcodegen);
void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; }
@ -105,8 +105,6 @@ private:
// Current layer index.
int m_layer_idx;
int m_tool_change_idx;
bool m_brim_done;
bool i_have_brim = false;
double m_last_wipe_tower_print_z = 0.f;
};

View file

@ -326,7 +326,7 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
PerExtruderAdjustments *adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
const char *line_start = gcode.c_str();
const char *line_end = line_start;
const char extrusion_axis = config.get_extrusion_axis()[0];
const char extrusion_axis = get_extrusion_axis(config)[0];
// Index of an existing CoolingLine of the current adjustment, which holds the feedrate setting command
// for a sequence of extrusion moves.
size_t active_speed_modifier = size_t(-1);

View file

@ -26,6 +26,7 @@
static const float INCHES_TO_MM = 25.4f;
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
static const float DEFAULT_TRAVEL_ACCELERATION = 1250.0f;
namespace Slic3r {
@ -190,6 +191,8 @@ void GCodeProcessor::TimeMachine::reset()
enabled = false;
acceleration = 0.0f;
max_acceleration = 0.0f;
travel_acceleration = 0.0f;
max_travel_acceleration = 0.0f;
extrude_factor_override_percentage = 1.0f;
time = 0.0f;
#if ENABLE_EXTENDED_M73_LINES
@ -823,8 +826,13 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]);
}
if (m_flavor == gcfMarlin && config.machine_limits_usage.value != MachineLimitsUsage::Ignore)
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) && config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
if (m_flavor == gcfMarlinLegacy) {
// Legacy Marlin does not have separate travel acceleration, it uses the 'extruding' value instead.
m_time_processor.machine_limits.machine_max_acceleration_travel = m_time_processor.machine_limits.machine_max_acceleration_extruding;
}
}
// Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
// As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
@ -842,10 +850,19 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
}
m_time_processor.export_remaining_time_enabled = config.remaining_times.value;
m_use_volumetric_e = config.use_volumetric_e;
#if ENABLE_START_GCODE_VISUALIZATION
const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
if (first_layer_height != nullptr)
m_first_layer_height = std::abs(first_layer_height->value);
#endif // ENABLE_START_GCODE_VISUALIZATION
}
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
@ -934,7 +951,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
}
}
if (m_flavor == gcfMarlin) {
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) {
const ConfigOptionFloats* machine_max_acceleration_x = config.option<ConfigOptionFloats>("machine_max_acceleration_x");
if (machine_max_acceleration_x != nullptr)
m_time_processor.machine_limits.machine_max_acceleration_x.values = machine_max_acceleration_x->values;
@ -991,6 +1008,15 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (machine_max_acceleration_retracting != nullptr)
m_time_processor.machine_limits.machine_max_acceleration_retracting.values = machine_max_acceleration_retracting->values;
// Legacy Marlin does not have separate travel acceleration, it uses the 'extruding' value instead.
const ConfigOptionFloats* machine_max_acceleration_travel = config.option<ConfigOptionFloats>(m_flavor == gcfMarlinLegacy
? "machine_max_acceleration_extruding"
: "machine_max_acceleration_travel");
if (machine_max_acceleration_travel != nullptr)
m_time_processor.machine_limits.machine_max_acceleration_travel.values = machine_max_acceleration_travel->values;
const ConfigOptionFloats* machine_min_extruding_rate = config.option<ConfigOptionFloats>("machine_min_extruding_rate");
if (machine_min_extruding_rate != nullptr)
m_time_processor.machine_limits.machine_min_extruding_rate.values = machine_min_extruding_rate->values;
@ -1004,6 +1030,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
}
if (m_time_processor.machine_limits.machine_max_acceleration_x.values.size() > 1)
@ -1012,6 +1041,12 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
const ConfigOptionBool* use_volumetric_e = config.option<ConfigOptionBool>("use_volumetric_e");
if (use_volumetric_e != nullptr)
m_use_volumetric_e = use_volumetric_e->value;
#if ENABLE_START_GCODE_VISUALIZATION
const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
if (first_layer_height != nullptr)
m_first_layer_height = std::abs(first_layer_height->value);
#endif // ENABLE_START_GCODE_VISUALIZATION
}
void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
@ -1037,6 +1072,9 @@ void GCodeProcessor::reset()
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
m_line_id = 0;
#if ENABLE_SEAMS_VISUALIZATION
m_last_line_id = 0;
#endif // ENABLE_SEAMS_VISUALIZATION
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
m_feedrate = 0.0f;
m_width = 0.0f;
@ -1059,6 +1097,10 @@ void GCodeProcessor::reset()
m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f);
m_extruded_last_z = 0.0f;
#if ENABLE_START_GCODE_VISUALIZATION
m_first_layer_height = 0.0f;
m_processing_start_custom_gcode = false;
#endif // ENABLE_START_GCODE_VISUALIZATION
m_g1_line_id = 0;
m_layer_id = 0;
m_cp_color.reset();
@ -1420,6 +1462,13 @@ void GCodeProcessor::process_tags(const std::string_view comment)
// extrusion role tag
if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()));
#if ENABLE_SEAMS_VISUALIZATION
if (m_extrusion_role == erExternalPerimeter)
m_seams_detector.activate(true);
#endif // ENABLE_SEAMS_VISUALIZATION
#if ENABLE_START_GCODE_VISUALIZATION
m_processing_start_custom_gcode = (m_extrusion_role == erCustom && m_g1_line_id == 0);
#endif // ENABLE_START_GCODE_VISUALIZATION
return;
}
@ -1646,23 +1695,23 @@ bool GCodeProcessor::process_cura_tags(const std::string_view comment)
if (pos != comment.npos) {
const std::string_view flavor = comment.substr(pos + tag.length());
if (flavor == "BFB")
m_flavor = gcfMarlin; // << ???????????????????????
m_flavor = gcfMarlinLegacy; // is this correct ?
else if (flavor == "Mach3")
m_flavor = gcfMach3;
else if (flavor == "Makerbot")
m_flavor = gcfMakerWare;
else if (flavor == "UltiGCode")
m_flavor = gcfMarlin; // << ???????????????????????
m_flavor = gcfMarlinLegacy; // is this correct ?
else if (flavor == "Marlin(Volumetric)")
m_flavor = gcfMarlin; // << ???????????????????????
m_flavor = gcfMarlinLegacy; // is this correct ?
else if (flavor == "Griffin")
m_flavor = gcfMarlin; // << ???????????????????????
m_flavor = gcfMarlinLegacy; // is this correct ?
else if (flavor == "Repetier")
m_flavor = gcfRepetier;
else if (flavor == "RepRap")
m_flavor = gcfRepRapFirmware;
else if (flavor == "Marlin")
m_flavor = gcfMarlin;
m_flavor = gcfMarlinLegacy;
else
BOOST_LOG_TRIVIAL(warning) << "GCodeProcessor found unknown flavor: " << flavor;
@ -2164,7 +2213,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
}
#if ENABLE_START_GCODE_VISUALIZATION
if (type == EMoveType::Extrude && (m_width == 0.0f || m_height == 0.0f))
#else
if (type == EMoveType::Extrude && (m_extrusion_role == erCustom || m_width == 0.0f || m_height == 0.0f))
#endif // ENABLE_START_GCODE_VISUALIZATION
type = EMoveType::Travel;
// time estimate section
@ -2226,9 +2279,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
}
// calculates block acceleration
float acceleration = is_extrusion_only_move(delta_pos) ?
float acceleration =
(type == EMoveType::Travel) ? get_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)) :
(is_extrusion_only_move(delta_pos) ?
get_retract_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)) :
get_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i));
get_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)));
for (unsigned char a = X; a <= E; ++a) {
float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), static_cast<Axis>(a));
@ -2278,13 +2333,13 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
float jerk =
(v_exit > v_entry) ?
(((v_entry > 0.0f) || (v_exit < 0.0f)) ?
((v_entry > 0.0f || v_exit < 0.0f) ?
// coasting
(v_exit - v_entry) :
// axis reversal
std::max(v_exit, -v_entry)) :
// v_exit <= v_entry
(((v_entry < 0.0f) || (v_exit > 0.0f)) ?
((v_entry < 0.0f || v_exit > 0.0f) ?
// coasting
(v_entry - v_exit) :
// axis reversal
@ -2305,7 +2360,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
float vmax_junction_threshold = vmax_junction * 0.99f;
// Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
if ((prev.safe_feedrate > vmax_junction_threshold) && (curr.safe_feedrate > vmax_junction_threshold))
if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
vmax_junction = curr.safe_feedrate;
}
@ -2329,6 +2384,31 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
machine.calculate_time(TimeProcessor::Planner::queue_size);
}
#if ENABLE_SEAMS_VISUALIZATION
// check for seam starting vertex
if (type == EMoveType::Extrude && m_extrusion_role == erExternalPerimeter && m_seams_detector.is_active() && !m_seams_detector.has_first_vertex())
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
// check for seam ending vertex and store the resulting move
else if ((type != EMoveType::Extrude || m_extrusion_role != erExternalPerimeter) && m_seams_detector.is_active()) {
auto set_end_position = [this](const Vec3f& pos) {
m_end_position[X] = pos.x(); m_end_position[Y] = pos.y(); m_end_position[Z] = pos.z();
};
assert(m_seams_detector.has_first_vertex());
const Vec3f curr_pos(m_end_position[X], m_end_position[Y], m_end_position[Z]);
const Vec3f new_pos = m_result.moves.back().position - m_extruder_offsets[m_extruder_id];
const std::optional<Vec3f> first_vertex = m_seams_detector.get_first_vertex();
// the threshold value = 0.25 is arbitrary, we may find some smarter condition later
if ((new_pos - *first_vertex).norm() < 0.25f) {
set_end_position(0.5f * (new_pos + *first_vertex));
store_move_vertex(EMoveType::Seam);
set_end_position(curr_pos);
}
m_seams_detector.activate(false);
}
#endif // ENABLE_SEAMS_VISUALIZATION
// store move
store_move_vertex(type);
}
@ -2575,7 +2655,7 @@ void GCodeProcessor::process_M203(const GCodeReader::GCodeLine& line)
// see http://reprap.org/wiki/G-code#M203:_Set_maximum_feedrate
// http://smoothieware.org/supported-g-codes
float factor = (m_flavor == gcfMarlin || m_flavor == gcfSmoothie) ? 1.0f : MMMIN_TO_MMSEC;
float factor = (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfSmoothie) ? 1.0f : MMMIN_TO_MMSEC;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal ||
@ -2602,10 +2682,11 @@ void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line)
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal ||
m_time_processor.machine_envelope_processing_enabled) {
if (line.has_value('S', value)) {
// Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware,
// and it is also generated by Slic3r to control acceleration per extrusion type
// (there is a separate acceleration settings in Slicer for perimeter, first layer etc).
// Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware
// It is also generated by PrusaSlicer to control acceleration per extrusion type
// (perimeters, first layer etc) when 'Marlin (legacy)' flavor is used.
set_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value);
set_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value);
if (line.has_value('T', value))
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
}
@ -2615,11 +2696,9 @@ void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line)
set_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value);
if (line.has_value('R', value))
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
if (line.has_value('T', value)) {
if (line.has_value('T', value))
// Interpret the T value as the travel acceleration in the new Marlin format.
//FIXME Prusa3D firmware currently does not support travel acceleration value independent from the extruding acceleration value.
// set_travel_acceleration(value);
}
set_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value);
}
}
}
@ -2749,7 +2828,7 @@ void GCodeProcessor::process_T(const std::string_view command)
int eid = 0;
if (! parse_number(command.substr(1), eid) || eid < 0 || eid > 255) {
// Specific to the MMU2 V2 (see https://www.help.prusa3d.com/en/article/prusa-specific-g-codes_112173):
if (m_flavor == gcfMarlin && (command == "Tx" || command == "Tc" || command == "T?"))
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) && (command == "Tx" || command == "Tc" || command == "T?"))
return;
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
@ -2783,15 +2862,29 @@ void GCodeProcessor::process_T(const std::string_view command)
void GCodeProcessor::store_move_vertex(EMoveType type)
{
#if ENABLE_SEAMS_VISUALIZATION
m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ?
m_line_id + 1 :
((type == EMoveType::Seam) ? m_last_line_id : m_line_id);
#endif // ENABLE_SEAMS_VISUALIZATION
MoveVertex vertex = {
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
#if ENABLE_SEAMS_VISUALIZATION
m_last_line_id,
#else
(type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ? m_line_id + 1 : m_line_id,
#endif // ENABLE_SEAMS_VISUALIZATION
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
type,
m_extrusion_role,
m_extruder_id,
m_cp_color.current,
#if ENABLE_START_GCODE_VISUALIZATION
Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
#else
Vec3f(m_end_position[X], m_end_position[Y], m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
#endif // ENABLE_START_GCODE_VISUALIZATION
m_end_position[E] - m_start_position[E],
m_feedrate,
m_width,
@ -2890,6 +2983,22 @@ void GCodeProcessor::set_acceleration(PrintEstimatedTimeStatistics::ETimeMode mo
}
}
float GCodeProcessor::get_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const
{
size_t id = static_cast<size_t>(mode);
return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
}
void GCodeProcessor::set_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value)
{
size_t id = static_cast<size_t>(mode);
if (id < m_time_processor.machines.size()) {
m_time_processor.machines[id].travel_acceleration = (m_time_processor.machines[id].max_travel_acceleration == 0.0f) ? value :
// Clamp the acceleration with the maximum.
std::min(value, m_time_processor.machines[id].max_travel_acceleration);
}
}
float GCodeProcessor::get_filament_load_time(size_t extruder_id)
{
return (m_time_processor.filament_load_times.empty() || m_time_processor.extruder_unloaded) ?

View file

@ -12,6 +12,9 @@
#include <vector>
#include <string>
#include <string_view>
#if ENABLE_SEAMS_VISUALIZATION
#include <optional>
#endif // ENABLE_SEAMS_VISUALIZATION
namespace Slic3r {
@ -20,6 +23,9 @@ namespace Slic3r {
Noop,
Retract,
Unretract,
#if ENABLE_SEAMS_VISUALIZATION
Seam,
#endif // ENABLE_SEAMS_VISUALIZATION
Tool_change,
Color_change,
Pause_Print,
@ -251,6 +257,9 @@ namespace Slic3r {
float acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
float max_acceleration; // mm/s^2
float travel_acceleration; // mm/s^2
// hard limit for the travel acceleration, to which the firmware will clamp.
float max_travel_acceleration; // mm/s^2
float extrude_factor_override_percentage;
float time; // s
#if ENABLE_EXTENDED_M73_LINES
@ -367,8 +376,7 @@ namespace Slic3r {
#if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 };
void reset()
{
void reset() {
time = 0;
moves = std::vector<MoveVertex>();
bed_shape = Pointfs();
@ -377,8 +385,7 @@ namespace Slic3r {
settings_ids.reset();
}
#else
void reset()
{
void reset() {
moves = std::vector<MoveVertex>();
bed_shape = Pointfs();
extruder_colors = std::vector<std::string>();
@ -388,6 +395,29 @@ namespace Slic3r {
#endif // ENABLE_GCODE_VIEWER_STATISTICS
};
#if ENABLE_SEAMS_VISUALIZATION
class SeamsDetector
{
bool m_active{ false };
std::optional<Vec3f> m_first_vertex;
public:
void activate(bool active) {
if (m_active != active) {
m_active = active;
if (m_active)
m_first_vertex.reset();
}
}
std::optional<Vec3f> get_first_vertex() const { return m_first_vertex; }
void set_first_vertex(const Vec3f& vertex) { m_first_vertex = vertex; }
bool is_active() const { return m_active; }
bool has_first_vertex() const { return m_first_vertex.has_value(); }
};
#endif // ENABLE_SEAMS_VISUALIZATION
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
struct DataChecker
{
@ -473,6 +503,9 @@ namespace Slic3r {
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
unsigned int m_line_id;
#if ENABLE_SEAMS_VISUALIZATION
unsigned int m_last_line_id;
#endif // ENABLE_SEAMS_VISUALIZATION
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
float m_feedrate; // mm/s
float m_width; // mm
@ -487,10 +520,17 @@ namespace Slic3r {
ExtruderTemps m_extruder_temps;
std::vector<float> m_filament_diameters;
float m_extruded_last_z;
#if ENABLE_START_GCODE_VISUALIZATION
float m_first_layer_height; // mm
bool m_processing_start_custom_gcode;
#endif // ENABLE_START_GCODE_VISUALIZATION
unsigned int m_g1_line_id;
unsigned int m_layer_id;
CpColor m_cp_color;
bool m_use_volumetric_e;
#if ENABLE_SEAMS_VISUALIZATION
SeamsDetector m_seams_detector;
#endif // ENABLE_SEAMS_VISUALIZATION
enum class EProducer
{
@ -669,6 +709,8 @@ namespace Slic3r {
float get_retract_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const;
float get_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const;
void set_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value);
float get_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const;
void set_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value);
float get_filament_load_time(size_t extruder_id);
float get_filament_unload_time(size_t extruder_id);

View file

@ -329,6 +329,16 @@ void ToolOrdering::reorder_extruders(unsigned int last_extruder_id)
lt.extruders.front() = last_extruder_id;
break;
}
// On first layer with wipe tower, prefer a soluble extruder
// at the beginning, so it is not wiped on the first layer.
if (lt == m_layer_tools[0] && m_print_config_ptr && m_print_config_ptr->wipe_tower) {
for (size_t i = 0; i<lt.extruders.size(); ++i)
if (m_print_config_ptr->filament_soluble.get_at(lt.extruders[i]-1)) { // 1-based...
std::swap(lt.extruders[i], lt.extruders.front());
break;
}
}
}
last_extruder_id = lt.extruders.back();
}

View file

@ -9,17 +9,6 @@
#include "BoundingBox.hpp"
// Experimental "Peter's wipe tower" feature was partially implemented, inspired by
// PJR's idea of alternating two perpendicular wiping directions on a square tower.
// It is probably never going to be finished, there are multiple remaining issues
// and there is probably no need to go down this way. m_peters_wipe_tower variable
// turns this on, maybe it should just be removed. Anyway, the issues are
// - layer's are not exactly square
// - variable width for higher levels
// - make sure it is not too sparse (apply max_bridge_distance and make last wipe longer)
// - enable enhanced first layer adhesion
namespace Slic3r
{
@ -122,8 +111,10 @@ public:
WipeTowerWriter& feedrate(float f)
{
if (f != m_current_feedrate)
if (f != m_current_feedrate) {
m_gcode += "G1" + set_format_F(f) + "\n";
m_current_feedrate = f;
}
return *this;
}
@ -242,6 +233,14 @@ public:
return (*this);
}
WipeTowerWriter& rectangle(const WipeTower::box_coordinates& box, const float f = 0.f)
{
rectangle(Vec2f(box.ld.x(), box.ld.y()),
box.ru.x() - box.lu.x(),
box.ru.y() - box.rd.y(), f);
return (*this);
}
WipeTowerWriter& load(float e, float f = 0.f)
{
if (e == 0.f && (f == 0.f || f == m_current_feedrate))
@ -343,7 +342,7 @@ public:
WipeTowerWriter& speed_override_backup()
{
// This is only supported by Prusa at this point (https://github.com/prusa3d/PrusaSlicer/issues/3114)
if (m_gcode_flavor == gcfMarlin)
if (m_gcode_flavor == gcfMarlinLegacy || m_gcode_flavor == gcfMarlinFirmware)
m_gcode += "M220 B\n";
return *this;
}
@ -351,7 +350,7 @@ public:
// Let the firmware restore the active speed override value.
WipeTowerWriter& speed_override_restore()
{
if (m_gcode_flavor == gcfMarlin)
if (m_gcode_flavor == gcfMarlinLegacy || m_gcode_flavor == gcfMarlinFirmware)
m_gcode += "M220 R\n";
return *this;
}
@ -523,13 +522,21 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
m_wipe_tower_brim_width(float(config.wipe_tower_brim_width)),
m_y_shift(0.f),
m_z_pos(0.f),
m_is_first_layer(false),
m_bridging(float(config.wipe_tower_bridging)),
m_no_sparse_layers(config.wipe_tower_no_sparse_layers),
m_gcode_flavor(config.gcode_flavor),
m_travel_speed(config.travel_speed),
m_current_tool(initial_tool),
wipe_volumes(wiping_matrix)
{
// Read absolute value of first layer speed, if given as percentage,
// it is taken over following default. Speeds from config are not
// easily accessible here.
const float default_speed = 60.f;
m_first_layer_speed = config.get_abs_value("first_layer_speed", default_speed);
if (m_first_layer_speed == 0.f) // just to make sure autospeed doesn't break it.
m_first_layer_speed = default_speed / 2.f;
// If this is a single extruder MM printer, we will use all the SE-specific config values.
// Otherwise, the defaults will be used to turn off the SE stuff.
if (m_semm) {
@ -539,10 +546,24 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
m_extra_loading_move = float(config.extra_loading_move);
m_set_extruder_trimpot = config.high_current_on_filament_swap;
}
// Calculate where the priming lines should be - very naive test not detecting parallelograms or custom shapes
// Calculate where the priming lines should be - very naive test not detecting parallelograms etc.
const std::vector<Vec2d>& bed_points = config.bed_shape.values;
BoundingBoxf bb(bed_points);
m_bed_width = float(bb.size().x());
m_bed_shape = (bed_points.size() == 4 ? RectangularBed : CircularBed);
m_bed_width = float(BoundingBoxf(bed_points).size().x());
if (m_bed_shape == CircularBed) {
// this may still be a custom bed, check that the points are roughly on a circle
double r2 = std::pow(m_bed_width/2., 2.);
double lim2 = std::pow(m_bed_width/10., 2.);
Vec2d center = bb.center();
for (const Vec2d& pt : bed_points)
if (std::abs(std::pow(pt.x()-center.x(), 2.) + std::pow(pt.y()-center.y(), 2.) - r2) > lim2) {
m_bed_shape = CustomBed;
break;
}
}
m_bed_bottom_left = m_bed_shape == RectangularBed
? Vec2f(bed_points.front().x(), bed_points.front().y())
: Vec2f::Zero();
@ -556,6 +577,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
m_filpar.push_back(FilamentParameters());
m_filpar[idx].material = config.filament_type.get_at(idx);
m_filpar[idx].is_soluble = config.filament_soluble.get_at(idx);
m_filpar[idx].temperature = config.temperature.get_at(idx);
m_filpar[idx].first_layer_temperature = config.first_layer_temperature.get_at(idx);
@ -617,10 +639,12 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
float prime_section_width = std::min(0.9f * m_bed_width / tools.size(), 60.f);
box_coordinates cleaning_box(Vec2f(0.02f * m_bed_width, 0.01f + m_perimeter_width/2.f), prime_section_width, 100.f);
// In case of a circular bed, place it so it goes across the diameter and hope it will fit
if (m_bed_shape == CircularBed)
cleaning_box.translate(-m_bed_width/2 + m_bed_width * 0.03f, -m_bed_width * 0.12f);
if (m_bed_shape == RectangularBed)
if (m_bed_shape == CircularBed) {
cleaning_box = box_coordinates(Vec2f(0.f, 0.f), prime_section_width, 100.f);
float total_width_half = tools.size() * prime_section_width / 2.f;
cleaning_box.translate(-total_width_half, -std::sqrt(std::max(0.f, std::pow(m_bed_width/2, 2.f) - std::pow(1.05f * total_width_half, 2.f))));
}
else
cleaning_box.translate(m_bed_bottom_left);
std::vector<ToolChangeResult> results;
@ -680,7 +704,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
if (m_set_extruder_trimpot)
writer.set_extruder_trimpot(550);
writer.speed_override_restore()
.feedrate(6000)
.feedrate(m_travel_speed * 60.f)
.flush_planner_queue()
.reset_extruder()
.append("; CP PRIMING END\n"
@ -694,21 +718,14 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
m_old_temperature = -1; // If the priming is turned off in config, the temperature changing commands will not actually appear
// in the output gcode - we should not remember emitting them (we will output them twice in the worst case)
// so that tool_change() will know to extrude the wipe tower brim:
m_print_brim = true;
return results;
}
WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
{
if ( m_print_brim )
return toolchange_Brim();
size_t old_tool = m_current_tool;
float wipe_area = 0.f;
bool last_change_in_layer = false;
float wipe_volume = 0.f;
// Finds this toolchange info
@ -717,8 +734,6 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
for (const auto &b : m_layer_info->tool_changes)
if ( b.new_tool == tool ) {
wipe_volume = b.wipe_volume;
if (tool == m_layer_info->tool_changes.back().new_tool)
last_change_in_layer = true;
wipe_area = b.required_depth * m_layer_info->extra_spacing;
break;
}
@ -730,14 +745,14 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
box_coordinates cleaning_box(
Vec2f(m_perimeter_width / 2.f, m_perimeter_width / 2.f),
m_wipe_tower_width - m_perimeter_width,
(tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5f*m_perimeter_width
(tool != (unsigned int)(-1) ? wipe_area+m_depth_traversed-0.5f*m_perimeter_width
: m_wipe_tower_depth-m_perimeter_width));
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow)
.set_z(m_z_pos)
.set_initial_tool(m_current_tool)
.set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f))
.set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f))
.append(";--------------------\n"
"; CP TOOLCHANGE START\n")
.comment_with_value(" toolchange #", m_num_tool_changes + 1); // the number is zero-based
@ -759,7 +774,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
// Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
if (tool != (unsigned int)-1){ // This is not the last change.
toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material,
m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
is_first_layer() ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
toolchange_Load(writer, cleaning_box);
writer.travel(writer.x(), writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
@ -770,24 +785,10 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
m_depth_traversed += wipe_area;
if (last_change_in_layer) {// draw perimeter line
writer.set_y_shift(m_y_shift);
if (m_peters_wipe_tower)
writer.rectangle(Vec2f::Zero(), m_layer_info->depth + 3*m_perimeter_width, m_wipe_tower_depth);
else {
writer.rectangle(Vec2f::Zero(), m_wipe_tower_width, m_layer_info->depth + m_perimeter_width);
if (layer_finished()) { // no finish_layer will be called, we must wipe the nozzle
writer.add_wipe_point(writer.x(), writer.y())
.add_wipe_point(writer.x()> m_wipe_tower_width / 2.f ? 0.f : m_wipe_tower_width, writer.y());
}
}
}
if (m_set_extruder_trimpot)
writer.set_extruder_trimpot(550); // Reset the extruder current to a normal value.
writer.speed_override_restore();
writer.feedrate(6000)
writer.feedrate(m_travel_speed * 60.f)
.flush_planner_queue()
.reset_extruder()
.append("; CP TOOLCHANGE END\n"
@ -801,66 +802,6 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
return construct_tcr(writer, false, old_tool);
}
WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_offset)
{
size_t old_tool = m_current_tool;
const box_coordinates wipeTower_box(
Vec2f::Zero(),
m_wipe_tower_width,
m_wipe_tower_depth);
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow * 1.1f)
.set_z(m_z_pos) // Let the writer know the current Z position as a base for Z-hop.
.set_initial_tool(m_current_tool)
.append(";-------------------------------------\n"
"; CP WIPE TOWER FIRST LAYER BRIM START\n");
Vec2f initial_position = wipeTower_box.lu - Vec2f(m_wipe_tower_brim_width + 2*m_perimeter_width, 0);
writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
// Prime the extruder left of the wipe tower.
writer.extrude_explicit(wipeTower_box.ld - Vec2f(m_wipe_tower_brim_width + 2*m_perimeter_width, 0),
1.5f * m_extrusion_flow * (wipeTower_box.lu.y() - wipeTower_box.ld.y()), 2400);
// The tool is supposed to be active and primed at the time when the wipe tower brim is extruded.
// Extrude brim around the future wipe tower ('normal' spacing with no extra void space).
box_coordinates box(wipeTower_box);
float spacing = m_perimeter_width - m_layer_height*float(1.-M_PI_4);
// How many perimeters shall the brim have?
size_t loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
for (size_t i = 0; i < loops_num; ++ i) {
box.expand(spacing);
writer.travel (box.ld, 7000)
.extrude(box.lu, 2100).extrude(box.ru)
.extrude(box.rd ).extrude(box.ld);
}
// Save actual brim width to be later passed to the Print object, which will use it
// for skirt calculation and pass it to GLCanvas for precise preview box
m_wipe_tower_brim_width_real = wipeTower_box.ld.x() - box.ld.x() + spacing/2.f;
box.expand(-spacing);
writer.add_wipe_point(writer.x(), writer.y())
.add_wipe_point(box.ld)
.add_wipe_point(box.rd);
writer.append("; CP WIPE TOWER FIRST LAYER BRIM END\n"
";-----------------------------------\n");
m_print_brim = false; // Mark the brim as extruded
// Ask our writer about how much material was consumed:
if (m_current_tool < m_used_filament_length.size())
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
return construct_tcr(writer, false, old_tool);
}
// Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
void WipeTower::toolchange_Unload(
@ -957,7 +898,7 @@ void WipeTower::toolchange_Unload(
// be already set and there is no need to change anything. Also, the temperature could be changed
// for wrong extruder.
if (m_semm) {
if (new_temperature != 0 && (new_temperature != m_old_temperature || m_is_first_layer) ) { // Set the extruder temperature, but don't wait.
if (new_temperature != 0 && (new_temperature != m_old_temperature || is_first_layer()) ) { // Set the extruder temperature, but don't wait.
// If the required temperature is the same as last time, don't emit the M104 again (if user adjusted the value, it would be reset)
// However, always change temperatures on the first layer (this is to avoid issues with priming lines turned off).
writer.set_extruder_temp(new_temperature, false);
@ -1017,7 +958,10 @@ void WipeTower::toolchange_Change(
// gcode could have left the extruder somewhere, we cannot just start extruding. We should also inform the
// postprocessor that we absolutely want to have this in the gcode, even if it thought it is the same as before.
Vec2f current_pos = writer.pos_rotated();
writer.append(std::string("G1 X") + std::to_string(current_pos.x()) + " Y" + std::to_string(current_pos.y()) + never_skip_tag() + "\n");
writer.feedrate(m_travel_speed * 60.f) // see https://github.com/prusa3d/PrusaSlicer/issues/5483
.append(std::string("G1 X") + std::to_string(current_pos.x())
+ " Y" + std::to_string(current_pos.y())
+ never_skip_tag() + "\n");
// The toolchange Tn command will be inserted later, only in case that the user does
// not provide a custom toolchange gcode.
@ -1063,9 +1007,8 @@ void WipeTower::toolchange_Wipe(
float wipe_volume)
{
// Increase flow on first layer, slow down print.
writer.set_extrusion_flow(m_extrusion_flow * (m_is_first_layer ? 1.18f : 1.f))
writer.set_extrusion_flow(m_extrusion_flow * (is_first_layer() ? 1.18f : 1.f))
.append("; CP TOOLCHANGE WIPE\n");
float wipe_coeff = m_is_first_layer ? 0.5f : 1.f;
const float& xl = cleaning_box.ld.x();
const float& xr = cleaning_box.rd.x();
@ -1075,7 +1018,9 @@ void WipeTower::toolchange_Wipe(
float x_to_wipe = volume_to_length(wipe_volume, m_perimeter_width, m_layer_height);
float dy = m_extra_spacing*m_perimeter_width;
float wipe_speed = 1600.f;
const float target_speed = is_first_layer() ? m_first_layer_speed * 60.f : 4800.f;
float wipe_speed = 0.33f * target_speed;
// if there is less than 2.5*m_perimeter_width to the edge, advance straightaway (there is likely a blob anyway)
if ((m_left_to_right ? xr-writer.x() : writer.x()-xl) < 2.5f*m_perimeter_width) {
@ -1086,17 +1031,17 @@ void WipeTower::toolchange_Wipe(
// now the wiping itself:
for (int i = 0; true; ++i) {
if (i!=0) {
if (wipe_speed < 1610.f) wipe_speed = 1800.f;
else if (wipe_speed < 1810.f) wipe_speed = 2200.f;
else if (wipe_speed < 2210.f) wipe_speed = 4200.f;
else wipe_speed = std::min(4800.f, wipe_speed + 50.f);
if (wipe_speed < 0.34f * target_speed) wipe_speed = 0.375f * target_speed;
else if (wipe_speed < 0.377 * target_speed) wipe_speed = 0.458f * target_speed;
else if (wipe_speed < 0.46f * target_speed) wipe_speed = 0.875f * target_speed;
else wipe_speed = std::min(target_speed, wipe_speed + 50.f);
}
float traversed_x = writer.x();
if (m_left_to_right)
writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed);
else
writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed);
if (writer.y()+float(EPSILON) > cleaning_box.lu.y()-0.5f*m_perimeter_width)
break; // in case next line would not fit
@ -1112,15 +1057,14 @@ void WipeTower::toolchange_Wipe(
m_left_to_right = !m_left_to_right;
}
// this is neither priming nor not the last toolchange on this layer - we are
// going back to the model - wipe the nozzle.
if (m_layer_info != m_plan.end() && m_current_tool != m_layer_info->tool_changes.back().new_tool) {
m_left_to_right = !m_left_to_right;
// We may be going back to the model - wipe the nozzle. If this is followed
// by finish_layer, this wipe path will be overwritten.
writer.add_wipe_point(writer.x(), writer.y())
.add_wipe_point(writer.x(), writer.y() - dy)
.add_wipe_point(m_left_to_right ? m_wipe_tower_width : 0.f, writer.y() - dy);
.add_wipe_point(! m_left_to_right ? m_wipe_tower_width : 0.f, writer.y() - dy);
}
if (m_layer_info != m_plan.end() && m_current_tool != m_layer_info->tool_changes.back().new_tool)
m_left_to_right = !m_left_to_right;
writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow.
}
@ -1130,9 +1074,8 @@ void WipeTower::toolchange_Wipe(
WipeTower::ToolChangeResult WipeTower::finish_layer()
{
// This should only be called if the layer is not finished yet.
// Otherwise the caller would likely travel to the wipe tower in vain.
assert(! this->layer_finished());
m_current_layer_finished = true;
size_t old_tool = m_current_tool;
@ -1140,15 +1083,14 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
writer.set_extrusion_flow(m_extrusion_flow)
.set_z(m_z_pos)
.set_initial_tool(m_current_tool)
.set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f))
.append(";--------------------\n"
"; CP EMPTY GRID START\n")
.comment_with_value(" layer #", m_num_layer_changes + 1);
.set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f));
// Slow down on the 1st layer.
float speed_factor = m_is_first_layer ? 0.5f : 1.f;
bool first_layer = is_first_layer();
float feedrate = first_layer ? m_first_layer_speed * 60.f : 2900.f;
float current_depth = m_layer_info->depth - m_layer_info->toolchanges_depth();
box_coordinates fill_box(Vec2f(m_perimeter_width, m_depth_traversed + m_perimeter_width),
box_coordinates fill_box(Vec2f(m_perimeter_width, m_layer_info->depth-(current_depth-m_perimeter_width)),
m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width);
@ -1156,45 +1098,60 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON;
box_coordinates box = fill_box;
for (int i=0;i<2;++i) {
if (! toolchanges_on_layer) {
if (i==0) box.expand(m_perimeter_width);
else box.expand(-m_perimeter_width);
}
else i=2; // only draw the inner perimeter, outer has been already drawn by tool_change(...)
writer.rectangle(box.ld, box.rd.x()-box.ld.x(), box.ru.y()-box.rd.y(), 2900*speed_factor);
}
box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)),
m_wipe_tower_width, m_layer_info->depth + m_perimeter_width);
// inner perimeter of the sparse section, if there is space for it:
if (fill_box.ru.y() - fill_box.rd.y() > m_perimeter_width - WT_EPSILON)
writer.rectangle(fill_box.ld, fill_box.rd.x()-fill_box.ld.x(), fill_box.ru.y()-fill_box.rd.y(), feedrate);
// we are in one of the corners, travel to ld along the perimeter:
if (writer.x() > fill_box.ld.x()+EPSILON) writer.travel(fill_box.ld.x(),writer.y());
if (writer.y() > fill_box.ld.y()+EPSILON) writer.travel(writer.x(),fill_box.ld.y());
if (m_is_first_layer && m_adhesion) {
// Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower.
box.expand(-m_perimeter_width/2.f);
int nsteps = int(floor((box.lu.y() - box.ld.y()) / (2*m_perimeter_width)));
float step = (box.lu.y() - box.ld.y()) / nsteps;
writer.travel(box.ld - Vec2f(m_perimeter_width/2.f, m_perimeter_width/2.f));
if (nsteps >= 0)
for (int i = 0; i < nsteps; ++i) {
writer.extrude(box.ld.x()+m_perimeter_width/2.f, writer.y() + 0.5f * step);
writer.extrude(box.rd.x() - m_perimeter_width / 2.f, writer.y());
writer.extrude(box.rd.x() - m_perimeter_width / 2.f, writer.y() + 0.5f * step);
writer.extrude(box.ld.x() + m_perimeter_width / 2.f, writer.y());
}
writer.add_wipe_point(writer.x(), writer.y())
.add_wipe_point(box.rd.x()-m_perimeter_width/2.f,writer.y());
}
else { // Extrude a sparse infill to support the material to be printed above.
// Extrude infill to support the material to be printed above.
const float dy = (fill_box.lu.y() - fill_box.ld.y() - m_perimeter_width);
const float left = fill_box.lu.x() + 2*m_perimeter_width;
const float right = fill_box.ru.x() - 2 * m_perimeter_width;
float left = fill_box.lu.x() + 2*m_perimeter_width;
float right = fill_box.ru.x() - 2 * m_perimeter_width;
if (dy > m_perimeter_width)
{
// Extrude an inverse U at the left of the region.
writer.travel(fill_box.ld + Vec2f(m_perimeter_width * 2, 0.f))
.extrude(fill_box.lu + Vec2f(m_perimeter_width * 2, 0.f), 2900 * speed_factor);
.append(";--------------------\n"
"; CP EMPTY GRID START\n")
.comment_with_value(" layer #", m_num_layer_changes + 1);
// Is there a soluble filament wiped/rammed at the next layer?
// If so, the infill should not be sparse.
bool solid_infill = m_layer_info+1 == m_plan.end()
? false
: std::any_of((m_layer_info+1)->tool_changes.begin(),
(m_layer_info+1)->tool_changes.end(),
[this](const WipeTowerInfo::ToolChange& tch) {
return m_filpar[tch.new_tool].is_soluble
|| m_filpar[tch.old_tool].is_soluble;
});
solid_infill |= first_layer && m_adhesion;
if (solid_infill) {
float sparse_factor = 1.5f; // 1=solid, 2=every other line, etc.
if (first_layer) { // the infill should touch perimeters
left -= m_perimeter_width;
right += m_perimeter_width;
sparse_factor = 1.f;
}
float y = fill_box.ld.y() + m_perimeter_width;
int n = dy / (m_perimeter_width * sparse_factor);
float spacing = (dy-m_perimeter_width)/(n-1);
int i=0;
for (i=0; i<n; ++i) {
writer.extrude(writer.x(), y, feedrate)
.extrude(i%2 ? left : right, y);
y = y + spacing;
}
writer.extrude(writer.x(), fill_box.lu.y());
} else {
// Extrude an inverse U at the left of the region and the sparse infill.
writer.extrude(fill_box.lu + Vec2f(m_perimeter_width * 2, 0.f), feedrate);
const int n = 1+int((right-left)/m_bridging);
const float dx = (right-left)/n;
@ -1203,18 +1160,40 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
writer.travel(x,writer.y());
writer.extrude(x,i%2 ? fill_box.rd.y() : fill_box.ru.y());
}
writer.add_wipe_point(Vec2f(writer.x(), writer.y()))
.add_wipe_point(Vec2f(left, writer.y()));
}
else {
writer.add_wipe_point(Vec2f(writer.x(), writer.y()))
.add_wipe_point(Vec2f(right, writer.y()));
}
}
writer.append("; CP EMPTY GRID END\n"
";------------------\n\n\n\n\n\n\n");
}
m_depth_traversed = m_wipe_tower_depth-m_perimeter_width;
// outer perimeter (always):
writer.rectangle(wt_box, feedrate);
// brim (first layer only)
if (first_layer) {
box_coordinates box = wt_box;
float spacing = m_perimeter_width - m_layer_height*float(1.-M_PI_4);
// How many perimeters shall the brim have?
size_t loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
for (size_t i = 0; i < loops_num; ++ i) {
box.expand(spacing);
writer.rectangle(box);
}
// Save actual brim width to be later passed to the Print object, which will use it
// for skirt calculation and pass it to GLCanvas for precise preview box
m_wipe_tower_brim_width_real = wt_box.ld.x() - box.ld.x() + spacing/2.f;
wt_box = box;
}
// Now prepare future wipe. box contains rectangle that was extruded last (ccw).
Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd :
(writer.pos() == wt_box.rd ? wt_box.ru :
(writer.pos() == wt_box.ru ? wt_box.lu :
wt_box.ld)));
writer.add_wipe_point(writer.pos())
.add_wipe_point(target);
// Ask our writer about how much material was consumed.
@ -1227,17 +1206,16 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
}
// Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box
void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim, float wipe_volume)
void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool,
unsigned int new_tool, float wipe_volume)
{
assert(m_plan.empty() || m_plan.back().z <= z_par + WT_EPSILON); // refuses to add a layer below the last one
if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan first
m_plan.push_back(WipeTowerInfo(z_par, layer_height_par));
if (brim) { // this toolchange prints brim - we must add it to m_plan, but not to count its depth
m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool));
return;
}
if (m_first_layer_idx == size_t(-1) && (! m_no_sparse_layers || old_tool != new_tool))
m_first_layer_idx = m_plan.size() - 1;
if (old_tool == new_tool) // new layer without toolchanges - we are done
return;
@ -1293,28 +1271,65 @@ void WipeTower::save_on_last_wipe()
if (m_layer_info->tool_changes.size()==0) // we have no way to save anything on an empty layer
continue;
for (const auto &toolchange : m_layer_info->tool_changes)
// Which toolchange will finish_layer extrusions be subtracted from?
int idx = first_toolchange_to_nonsoluble(m_layer_info->tool_changes);
for (int i=0; i<int(m_layer_info->tool_changes.size()); ++i) {
auto& toolchange = m_layer_info->tool_changes[i];
tool_change(toolchange.new_tool);
if (i == idx) {
float width = m_wipe_tower_width - 3*m_perimeter_width; // width we draw into
float length_to_save = 2*(m_wipe_tower_width+m_wipe_tower_depth) + (!layer_finished() ? finish_layer().total_extrusion_length_in_plane() : 0.f);
float length_to_wipe = volume_to_length(m_layer_info->tool_changes.back().wipe_volume,
m_perimeter_width,m_layer_info->height) - m_layer_info->tool_changes.back().first_wipe_line - length_to_save;
float length_to_save = finish_layer().total_extrusion_length_in_plane();
float length_to_wipe = volume_to_length(toolchange.wipe_volume,
m_perimeter_width, m_layer_info->height) - toolchange.first_wipe_line - length_to_save;
length_to_wipe = std::max(length_to_wipe,0.f);
float depth_to_wipe = m_perimeter_width * (std::floor(length_to_wipe/width) + ( length_to_wipe > 0.f ? 1.f : 0.f ) ) * m_extra_spacing;
//depth += (int(length_to_extrude / width) + 1) * m_perimeter_width;
m_layer_info->tool_changes.back().required_depth = m_layer_info->tool_changes.back().ramming_depth + depth_to_wipe;
toolchange.required_depth = toolchange.ramming_depth + depth_to_wipe;
}
}
}
}
// Return index of first toolchange that switches to non-soluble extruder
// ot -1 if there is no such toolchange.
int WipeTower::first_toolchange_to_nonsoluble(
const std::vector<WipeTowerInfo::ToolChange>& tool_changes) const
{
for (size_t idx=0; idx<tool_changes.size(); ++idx)
if (! m_filpar[tool_changes[idx].new_tool].is_soluble)
return idx;
return -1;
}
static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first,
WipeTower::ToolChangeResult& second)
{
assert(first.new_tool == second.initial_tool);
WipeTower::ToolChangeResult out = first;
if (first.end_pos != second.start_pos) {
char buf[2048]; // Add a travel move from tc1.end_pos to tc2.start_pos.
sprintf(buf, "G1 X%.3f Y%.3f F7200\n", second.start_pos.x(), second.start_pos.y());
out.gcode += buf;
}
out.gcode += second.gcode;
out.extrusions.insert(out.extrusions.end(), second.extrusions.begin(), second.extrusions.end());
out.end_pos = second.end_pos;
out.wipe_path = second.wipe_path;
out.initial_tool = first.initial_tool;
out.new_tool = second.new_tool;
return out;
}
// Processes vector m_plan and calls respective functions to generate G-code for the wipe tower
// Resulting ToolChangeResults are appended into vector "result"
void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result)
{
if (m_plan.empty())
return;
m_extra_spacing = 1.f;
@ -1325,9 +1340,6 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
plan_tower();
}
if (m_peters_wipe_tower)
make_wipe_tower_square();
m_layer_info = m_plan.begin();
// we don't know which extruder to start with - we'll set it according to the first toolchange
@ -1346,65 +1358,41 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
std::vector<WipeTower::ToolChangeResult> layer_result;
for (auto layer : m_plan)
{
set_layer(layer.z,layer.height,0,layer.z == m_plan.front().z,layer.z == m_plan.back().z);
if (m_peters_wipe_tower)
m_internal_rotation += 90.f;
else
set_layer(layer.z, layer.height, 0, false/*layer.z == m_plan.front().z*/, layer.z == m_plan.back().z);
m_internal_rotation += 180.f;
if (!m_peters_wipe_tower && m_layer_info->depth < m_wipe_tower_depth - m_perimeter_width)
if (m_layer_info->depth < m_wipe_tower_depth - m_perimeter_width)
m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f;
for (const auto &toolchange : layer.tool_changes)
layer_result.emplace_back(tool_change(toolchange.new_tool));
int idx = first_toolchange_to_nonsoluble(layer.tool_changes);
ToolChangeResult finish_layer_tcr;
if (! layer_finished()) {
auto finish_layer_toolchange = finish_layer();
if ( ! layer.tool_changes.empty() ) { // we will merge it to the last toolchange
auto& last_toolchange = layer_result.back();
if (last_toolchange.end_pos != finish_layer_toolchange.start_pos) {
char buf[2048]; // Add a travel move from tc1.end_pos to tc2.start_pos.
sprintf(buf, "G1 X%.3f Y%.3f F7200\n", finish_layer_toolchange.start_pos.x(), finish_layer_toolchange.start_pos.y());
last_toolchange.gcode += buf;
if (idx == -1) {
// if there is no toolchange switching to non-soluble, finish layer
// will be called at the very beginning. That's the last possibility
// where a nonsoluble tool can be.
finish_layer_tcr = finish_layer();
}
last_toolchange.gcode += finish_layer_toolchange.gcode;
last_toolchange.extrusions.insert(last_toolchange.extrusions.end(), finish_layer_toolchange.extrusions.begin(), finish_layer_toolchange.extrusions.end());
last_toolchange.end_pos = finish_layer_toolchange.end_pos;
last_toolchange.wipe_path = finish_layer_toolchange.wipe_path;
for (int i=0; i<int(layer.tool_changes.size()); ++i) {
layer_result.emplace_back(tool_change(layer.tool_changes[i].new_tool));
if (i == idx) // finish_layer will be called after this toolchange
finish_layer_tcr = finish_layer();
}
if (layer_result.empty()) {
// there is nothing to merge finish_layer with
layer_result.emplace_back(std::move(finish_layer_tcr));
}
else {
if (idx == -1)
layer_result[0] = merge_tcr(finish_layer_tcr, layer_result[0]);
else
layer_result.emplace_back(std::move(finish_layer_toolchange));
layer_result[idx] = merge_tcr(layer_result[idx], finish_layer_tcr);
}
result.emplace_back(std::move(layer_result));
m_is_first_layer = false;
}
}
void WipeTower::make_wipe_tower_square()
{
const float width = m_wipe_tower_width - 3 * m_perimeter_width;
const float depth = m_wipe_tower_depth - m_perimeter_width;
// area that we actually print into is width*depth
float side = sqrt(depth * width);
m_wipe_tower_width = side + 3 * m_perimeter_width;
m_wipe_tower_depth = side + 2 * m_perimeter_width;
// For all layers, find how depth changed and update all toolchange depths
for (auto &lay : m_plan)
{
side = sqrt(lay.depth * width);
float width_ratio = width / side;
//lay.extra_spacing = width_ratio;
for (auto &tch : lay.tool_changes)
tch.required_depth *= width_ratio;
}
plan_tower(); // propagates depth downwards again (width has changed)
for (auto& lay : m_plan) // depths set, now the spacing
lay.extra_spacing = lay.depth / lay.toolchanges_depth();
}
} // namespace Slic3r

View file

@ -84,6 +84,37 @@ public:
}
};
struct box_coordinates
{
box_coordinates(float left, float bottom, float width, float height) :
ld(left , bottom ),
lu(left , bottom + height),
rd(left + width, bottom ),
ru(left + width, bottom + height) {}
box_coordinates(const Vec2f &pos, float width, float height) : box_coordinates(pos(0), pos(1), width, height) {}
void translate(const Vec2f &shift) {
ld += shift; lu += shift;
rd += shift; ru += shift;
}
void translate(const float dx, const float dy) { translate(Vec2f(dx, dy)); }
void expand(const float offset) {
ld += Vec2f(- offset, - offset);
lu += Vec2f(- offset, offset);
rd += Vec2f( offset, - offset);
ru += Vec2f( offset, offset);
}
void expand(const float offset_x, const float offset_y) {
ld += Vec2f(- offset_x, - offset_y);
lu += Vec2f(- offset_x, offset_y);
rd += Vec2f( offset_x, - offset_y);
ru += Vec2f( offset_x, offset_y);
}
Vec2f ld; // left down
Vec2f lu; // left upper
Vec2f rd; // right lower
Vec2f ru; // right upper
};
// Construct ToolChangeResult from current state of WipeTower and WipeTowerWriter.
// WipeTowerWriter is moved from !
ToolChangeResult construct_tcr(WipeTowerWriter& writer,
@ -102,7 +133,7 @@ public:
// Appends into internal structure m_plan containing info about the future wipe tower
// to be used before building begins. The entries must be added ordered in z.
void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim, float wipe_volume = 0.f);
void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, float wipe_volume = 0.f);
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
void generate(std::vector<std::vector<ToolChangeResult>> &result);
@ -129,9 +160,8 @@ public:
{
m_z_pos = print_z;
m_layer_height = layer_height;
m_is_first_layer = is_first_layer;
m_print_brim = is_first_layer;
m_depth_traversed = 0.f;
m_current_layer_finished = false;
m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
if (is_first_layer) {
this->m_num_layer_changes = 0;
@ -175,7 +205,7 @@ public:
// Is the current layer finished?
bool layer_finished() const {
return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed);
return m_current_layer_finished;
}
std::vector<float> get_used_filament() const { return m_used_filament_length; }
@ -183,6 +213,7 @@ public:
struct FilamentParameters {
std::string material = "PLA";
bool is_soluble = false;
int temperature = 0;
int first_layer_temperature = 0;
float loading_speed = 0.f;
@ -208,7 +239,6 @@ private:
SHAPE_REVERSED = -1
};
const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet
const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
const float WT_EPSILON = 1e-3f;
float filament_area() const {
@ -228,8 +258,10 @@ private:
float m_z_pos = 0.f; // Current Z position.
float m_layer_height = 0.f; // Current layer height.
size_t m_max_color_changes = 0; // Maximum number of color changes per layer.
bool m_is_first_layer = false;// Is this the 1st layer of the print? If so, print the brim around the waste tower.
int m_old_temperature = -1; // To keep track of what was the last temp that we set (so we don't issue the command when not neccessary)
float m_travel_speed = 0.f;
float m_first_layer_speed = 0.f;
size_t m_first_layer_idx = size_t(-1);
// G-code generator parameters.
float m_cooling_tube_retraction = 0.f;
@ -245,7 +277,8 @@ private:
// Bed properties
enum {
RectangularBed,
CircularBed
CircularBed,
CustomBed
} m_bed_shape;
float m_bed_width; // width of the bed bounding box
Vec2f m_bed_bottom_left; // bottom-left corner coordinates (for rectangular beds)
@ -268,9 +301,12 @@ private:
const std::vector<std::vector<float>> wipe_volumes;
float m_depth_traversed = 0.f; // Current y position at the wipe tower.
bool m_current_layer_finished = false;
bool m_left_to_right = true;
float m_extra_spacing = 1.f;
bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; }
// Calculates extrusion flow needed to produce required line width for given layer height
float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow
{
@ -294,38 +330,6 @@ private:
void save_on_last_wipe();
struct box_coordinates
{
box_coordinates(float left, float bottom, float width, float height) :
ld(left , bottom ),
lu(left , bottom + height),
rd(left + width, bottom ),
ru(left + width, bottom + height) {}
box_coordinates(const Vec2f &pos, float width, float height) : box_coordinates(pos(0), pos(1), width, height) {}
void translate(const Vec2f &shift) {
ld += shift; lu += shift;
rd += shift; ru += shift;
}
void translate(const float dx, const float dy) { translate(Vec2f(dx, dy)); }
void expand(const float offset) {
ld += Vec2f(- offset, - offset);
lu += Vec2f(- offset, offset);
rd += Vec2f( offset, - offset);
ru += Vec2f( offset, offset);
}
void expand(const float offset_x, const float offset_y) {
ld += Vec2f(- offset_x, - offset_y);
lu += Vec2f(- offset_x, offset_y);
rd += Vec2f( offset_x, - offset_y);
ru += Vec2f( offset_x, offset_y);
}
Vec2f ld; // left down
Vec2f lu; // left upper
Vec2f rd; // right lower
Vec2f ru; // right upper
};
// to store information about tool changes for a given layer
struct WipeTowerInfo{
struct ToolChange {
@ -356,11 +360,10 @@ private:
// Stores information about used filament length per extruder:
std::vector<float> m_used_filament_length;
// Returns gcode for wipe tower brim
// sideOnly -- set to false -- experimental, draw brim on sides of wipe tower
// offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower
ToolChangeResult toolchange_Brim(bool sideOnly = false, float y_offset = 0.f);
// Return index of first toolchange that switches to non-soluble extruder
// ot -1 if there is no such toolchange.
int first_toolchange_to_nonsoluble(
const std::vector<WipeTowerInfo::ToolChange>& tool_changes) const;
void toolchange_Unload(
WipeTowerWriter &writer,
@ -386,6 +389,6 @@ private:
}; // namespace Slic3r
} // namespace Slic3r
#endif // WipeTowerPrusaMM_hpp_

View file

@ -13,13 +13,13 @@ namespace Slic3r {
void GCodeReader::apply_config(const GCodeConfig &config)
{
m_config = config;
m_extrusion_axis = m_config.get_extrusion_axis()[0];
m_extrusion_axis = get_extrusion_axis(m_config)[0];
}
void GCodeReader::apply_config(const DynamicPrintConfig &config)
{
m_config.apply(config, true);
m_extrusion_axis = m_config.get_extrusion_axis()[0];
m_extrusion_axis = get_extrusion_axis(m_config)[0];
}
const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline, std::pair<const char*, const char*> &command)

View file

@ -18,9 +18,10 @@ namespace Slic3r {
void GCodeWriter::apply_print_config(const PrintConfig &print_config)
{
this->config.apply(print_config, true);
m_extrusion_axis = this->config.get_extrusion_axis();
m_extrusion_axis = get_extrusion_axis(this->config);
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin && print_config.machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) ?
bool is_marlin = print_config.gcode_flavor.value == gcfMarlinLegacy || print_config.gcode_flavor.value == gcfMarlinFirmware;
m_max_acceleration = std::lrint((is_marlin && print_config.machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) ?
print_config.machine_max_acceleration_extruding.values.front() : 0);
}
@ -48,7 +49,8 @@ std::string GCodeWriter::preamble()
}
if (FLAVOR_IS(gcfRepRapSprinter) ||
FLAVOR_IS(gcfRepRapFirmware) ||
FLAVOR_IS(gcfMarlin) ||
FLAVOR_IS(gcfMarlinLegacy) ||
FLAVOR_IS(gcfMarlinFirmware) ||
FLAVOR_IS(gcfTeacup) ||
FLAVOR_IS(gcfRepetier) ||
FLAVOR_IS(gcfSmoothie))
@ -207,6 +209,10 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
} else if (FLAVOR_IS(gcfRepRapFirmware)) {
// M204: Set default acceleration
gcode << "M204 P" << acceleration;
} else if (FLAVOR_IS(gcfMarlinFirmware)) {
// This is new MarlinFirmware with separated print/retraction/travel acceleration.
// Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway).
gcode << "M204 P" << acceleration;
} else {
// M204: Set default acceleration
gcode << "M204 S" << acceleration;

View file

@ -1087,11 +1087,13 @@ bool
MedialAxis::validate_edge(const VD::edge_type* edge)
{
// prevent overflows and detect almost-infinite edges
#ifndef CLIPPERLIB_INT32
if (std::abs(edge->vertex0()->x()) > double(CLIPPER_MAX_COORD_UNSCALED) ||
std::abs(edge->vertex0()->y()) > double(CLIPPER_MAX_COORD_UNSCALED) ||
std::abs(edge->vertex1()->x()) > double(CLIPPER_MAX_COORD_UNSCALED) ||
std::abs(edge->vertex1()->y()) > double(CLIPPER_MAX_COORD_UNSCALED))
return false;
#endif // CLIPPERLIB_INT32
// construct the line representing this edge of the Voronoi diagram
const Line line(

View file

@ -22,12 +22,14 @@
#pragma warning(pop)
#endif // _MSC_VER
namespace Slic3r {
namespace ClipperLib {
class PolyNode;
using PolyNodes = std::vector<PolyNode*>;
}
namespace Slic3r { namespace Geometry {
namespace Geometry {
// Generic result of an orientation predicate.
enum Orientation
@ -299,20 +301,23 @@ bool liang_barsky_line_clipping(
// Ugly named variant, that accepts the squared line
// Don't call me with a nearly zero length vector!
// sympy:
// factor(solve([a * x + b * y + c, x**2 + y**2 - r**2], [x, y])[0])
// factor(solve([a * x + b * y + c, x**2 + y**2 - r**2], [x, y])[1])
template<typename T>
int ray_circle_intersections_r2_lv2_c(T r2, T a, T b, T lv2, T c, std::pair<Eigen::Matrix<T, 2, 1, Eigen::DontAlign>, Eigen::Matrix<T, 2, 1, Eigen::DontAlign>> &out)
{
T x0 = - a * c / lv2;
T y0 = - b * c / lv2;
T d = r2 - c * c / lv2;
if (d < T(0))
T x0 = - a * c;
T y0 = - b * c;
T d2 = r2 * lv2 - c * c;
if (d2 < T(0))
return 0;
T mult = sqrt(d / lv2);
out.first.x() = x0 + b * mult;
out.first.y() = y0 - a * mult;
out.second.x() = x0 - b * mult;
out.second.y() = y0 + a * mult;
return mult == T(0) ? 1 : 2;
T d = sqrt(d2);
out.first.x() = (x0 + b * d) / lv2;
out.first.y() = (y0 - a * d) / lv2;
out.second.x() = (x0 - b * d) / lv2;
out.second.y() = (y0 + a * d) / lv2;
return d == T(0) ? 1 : 2;
}
template<typename T>
int ray_circle_intersections(T r, T a, T b, T c, std::pair<Eigen::Matrix<T, 2, 1, Eigen::DontAlign>, Eigen::Matrix<T, 2, 1, Eigen::DontAlign>> &out)
@ -527,6 +532,6 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation)
return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z());
}
} }
} } // namespace Slicer::Geometry
#endif

View file

@ -39,11 +39,11 @@ void Layer::make_slices()
ExPolygons slices;
if (m_regions.size() == 1) {
// optimization: if we only have one region, take its slices
slices = m_regions.front()->slices;
slices = to_expolygons(m_regions.front()->slices.surfaces);
} else {
Polygons slices_p;
for (LayerRegion *layerm : m_regions)
polygons_append(slices_p, to_polygons(layerm->slices));
polygons_append(slices_p, to_polygons(layerm->slices.surfaces));
slices = union_ex(slices_p);
}
@ -105,7 +105,7 @@ ExPolygons Layer::merged(float offset_scaled) const
const PrintRegionConfig &config = layerm->region()->config();
// Our users learned to bend Slic3r to produce empty volumes to act as subtracters. Only add the region if it is non-empty.
if (config.bottom_solid_layers > 0 || config.top_solid_layers > 0 || config.fill_density > 0. || config.perimeters > 0)
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
append(polygons, offset(layerm->slices.surfaces, offset_scaled));
}
ExPolygons out = union_ex(polygons);
if (offset_scaled2 != 0.f)
@ -185,7 +185,7 @@ void Layer::make_perimeters()
}
// merge the surfaces assigned to each group
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), surfaces_with_extra_perimeters.second.front());
}
// make perimeters
@ -196,7 +196,7 @@ void Layer::make_perimeters()
if (!fill_surfaces.surfaces.empty()) {
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
// Separate the fill surfaces.
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
ExPolygons expp = intersection_ex(fill_surfaces.surfaces, (*l)->slices.surfaces);
(*l)->fill_expolygons = expp;
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
}

View file

@ -196,7 +196,7 @@ protected:
// between the raft and the object first layer.
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
Layer(id, object, height, print_z, slice_z) {}
virtual ~SupportLayer() {}
virtual ~SupportLayer() = default;
};
}

View file

@ -49,19 +49,17 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
// in place. However we're now only using its boundaries (which are invariant)
// so we're safe. This guarantees idempotence of prepare_infill() also in case
// that combine_infill() turns some fill_surface into VOID surfaces.
// Polygons fill_boundaries = to_polygons(std::move(this->fill_surfaces));
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
// Collect polygons per surface type.
std::vector<Polygons> polygons_by_surface;
polygons_by_surface.assign(size_t(stCount), Polygons());
std::vector<SurfacesPtr> by_surface;
by_surface.assign(size_t(stCount), SurfacesPtr());
for (Surface &surface : this->slices.surfaces)
polygons_append(polygons_by_surface[(size_t)surface.surface_type], surface.expolygon);
by_surface[size_t(surface.surface_type)].emplace_back(&surface);
// Trim surfaces by the fill_boundaries.
this->fill_surfaces.surfaces.clear();
for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) {
const Polygons &polygons = polygons_by_surface[surface_type];
if (! polygons.empty())
this->fill_surfaces.append(intersection_ex(polygons, fill_boundaries), SurfaceType(surface_type));
const SurfacesPtr &this_surfaces = by_surface[surface_type];
if (! this_surfaces.empty())
this->fill_surfaces.append(intersection_ex(this_surfaces, this->fill_expolygons), SurfaceType(surface_type));
}
}
@ -216,12 +214,12 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
break;
}
// Grown by 3mm.
Polygons polys = offset(to_polygons(bridges[i].expolygon), margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
Polygons polys = offset(bridges[i].expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
if (idx_island == -1) {
BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
} else {
// Found an island, to which this bridge region belongs. Trim it,
polys = intersection(polys, to_polygons(fill_boundaries_ex[idx_island]));
polys = intersection(polys, fill_boundaries_ex[idx_island]);
}
bridge_bboxes.push_back(get_extents(polys));
bridges_grown.push_back(std::move(polys));
@ -325,11 +323,11 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
if (s1.empty())
continue;
Polygons polys;
polygons_append(polys, std::move(s1));
polygons_append(polys, to_polygons(std::move(s1)));
for (size_t j = i + 1; j < top.size(); ++ j) {
Surface &s2 = top[j];
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
polygons_append(polys, std::move(s2));
polygons_append(polys, to_polygons(std::move(s2)));
s2.clear();
}
}
@ -351,11 +349,11 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
if (s1.empty())
continue;
Polygons polys;
polygons_append(polys, std::move(s1));
polygons_append(polys, to_polygons(std::move(s1)));
for (size_t j = i + 1; j < internal.size(); ++ j) {
Surface &s2 = internal[j];
if (! s2.empty() && surfaces_could_merge(s1, s2)) {
polygons_append(polys, std::move(s2));
polygons_append(polys, to_polygons(std::move(s2)));
s2.clear();
}
}
@ -423,7 +421,7 @@ void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
for (const Surface &surface : this->slices.surfaces)
assert(surface.surface_type == stInternal);
#endif /* NDEBUG */
this->slices.set(intersection_ex(to_polygons(std::move(this->slices.surfaces)), trimming_polygons, false), stInternal);
this->slices.set(intersection_ex(this->slices.surfaces, trimming_polygons), stInternal);
}
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
@ -432,10 +430,9 @@ void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_comp
for (const Surface &surface : this->slices.surfaces)
assert(surface.surface_type == stInternal);
#endif /* NDEBUG */
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces));
Polygons slices_polygons = to_polygons(slices_expolygons);
Polygons tmp = intersection(slices_polygons, trimming_polygons, false);
append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
ExPolygons surfaces = to_expolygons(std::move(this->slices.surfaces));
Polygons tmp = intersection(surfaces, trimming_polygons);
append(tmp, diff(surfaces, offset(offset_ex(surfaces, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
this->slices.set(union_ex(tmp), stInternal);
}

View file

@ -4,6 +4,8 @@
#include "libslic3r.h"
#include "Point.hpp"
#include <type_traits>
namespace Slic3r {
class BoundingBox;
@ -20,12 +22,28 @@ Linef3 transform(const Linef3& line, const Transform3d& t);
namespace line_alg {
template<class L, class En = void> struct Traits {
static constexpr int Dim = L::Dim;
using Scalar = typename L::Scalar;
static Vec<Dim, Scalar>& get_a(L &l) { return l.a; }
static Vec<Dim, Scalar>& get_b(L &l) { return l.b; }
static const Vec<Dim, Scalar>& get_a(const L &l) { return l.a; }
static const Vec<Dim, Scalar>& get_b(const L &l) { return l.b; }
};
template<class L> const constexpr int Dim = Traits<remove_cvref_t<L>>::Dim;
template<class L> using Scalar = typename Traits<remove_cvref_t<L>>::Scalar;
template<class L> auto get_a(L &&l) { return Traits<remove_cvref_t<L>>::get_a(l); }
template<class L> auto get_b(L &&l) { return Traits<remove_cvref_t<L>>::get_b(l); }
// Distance to the closest point of line.
template<class L, class T, int N>
double distance_to_squared(const L &line, const Vec<N, T> &point)
template<class L>
double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point)
{
const Vec<N, double> v = (line.b - line.a).template cast<double>();
const Vec<N, double> va = (point - line.a).template cast<double>();
const Vec<Dim<L>, double> v = (get_b(line) - get_a(line)).template cast<double>();
const Vec<Dim<L>, double> va = (point - get_a(line)).template cast<double>();
const double l2 = v.squaredNorm(); // avoid a sqrt
if (l2 == 0.0)
// a == b case
@ -35,12 +53,12 @@ double distance_to_squared(const L &line, const Vec<N, T> &point)
// It falls where t = [(this-a) . (b-a)] / |b-a|^2
const double t = va.dot(v) / l2;
if (t < 0.0) return va.squaredNorm(); // beyond the 'a' end of the segment
else if (t > 1.0) return (point - line.b).template cast<double>().squaredNorm(); // beyond the 'b' end of the segment
else if (t > 1.0) return (point - get_b(line)).template cast<double>().squaredNorm(); // beyond the 'b' end of the segment
return (t * v - va).squaredNorm();
}
template<class L, class T, int N>
double distance_to(const L &line, const Vec<N, T> &point)
template<class L>
double distance_to(const L &line, const Vec<Dim<L>, Scalar<L>> &point)
{
return std::sqrt(distance_to_squared(line, point));
}
@ -84,6 +102,9 @@ public:
Point a;
Point b;
static const constexpr int Dim = 2;
using Scalar = Point::Scalar;
};
class ThickLine : public Line
@ -107,6 +128,9 @@ public:
Vec3crd a;
Vec3crd b;
static const constexpr int Dim = 3;
using Scalar = Vec3crd::Scalar;
};
class Linef
@ -117,6 +141,9 @@ public:
Vec2d a;
Vec2d b;
static const constexpr int Dim = 2;
using Scalar = Vec2d::Scalar;
};
class Linef3
@ -133,6 +160,9 @@ public:
Vec3d a;
Vec3d b;
static const constexpr int Dim = 3;
using Scalar = Vec3d::Scalar;
};
BoundingBox get_extents(const Lines &lines);

View file

@ -106,13 +106,8 @@ template<class C> bool all_of(const C &container)
});
}
template<class T> struct remove_cvref
{
using type =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
};
template<class T> using remove_cvref_t = typename remove_cvref<T>::type;
//template<class T>
//using remove_cvref_t = std::remove_reference_t<std::remove_cv_t<T>>;
/// Exactly like Matlab https://www.mathworks.com/help/matlab/ref/linspace.html
template<class T, class I, class = IntegerOnly<I>>

View file

@ -14,55 +14,9 @@
#include <boost/multiprecision/integer.hpp>
#endif
#include <libnest2d/geometry_traits.hpp>
#include <libnest2d/backends/libslic3r/geometries.hpp>
#include <libnest2d/utils/rotcalipers.hpp>
namespace libnest2d {
template<> struct PointType<Slic3r::Points> { using Type = Slic3r::Point; };
template<> struct CoordType<Slic3r::Point> { using Type = coord_t; };
template<> struct ShapeTag<Slic3r::ExPolygon> { using Type = PolygonTag; };
template<> struct ShapeTag<Slic3r::Polygon> { using Type = PolygonTag; };
template<> struct ShapeTag<Slic3r::Points> { using Type = PathTag; };
template<> struct ShapeTag<Slic3r::Point> { using Type = PointTag; };
template<> struct ContourType<Slic3r::ExPolygon> { using Type = Slic3r::Points; };
template<> struct ContourType<Slic3r::Polygon> { using Type = Slic3r::Points; };
namespace pointlike {
template<> inline coord_t x(const Slic3r::Point& p) { return p.x(); }
template<> inline coord_t y(const Slic3r::Point& p) { return p.y(); }
template<> inline coord_t& x(Slic3r::Point& p) { return p.x(); }
template<> inline coord_t& y(Slic3r::Point& p) { return p.y(); }
} // pointlike
namespace shapelike {
template<> inline Slic3r::Points& contour(Slic3r::ExPolygon& sh) { return sh.contour.points; }
template<> inline const Slic3r::Points& contour(const Slic3r::ExPolygon& sh) { return sh.contour.points; }
template<> inline Slic3r::Points& contour(Slic3r::Polygon& sh) { return sh.points; }
template<> inline const Slic3r::Points& contour(const Slic3r::Polygon& sh) { return sh.points; }
template<> Slic3r::Points::iterator begin(Slic3r::Points& pts, const PathTag&) { return pts.begin();}
template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.cbegin(); }
template<> Slic3r::Points::iterator end(Slic3r::Points& pts, const PathTag&) { return pts.end();}
template<> Slic3r::Points::const_iterator cend(const Slic3r::Points& pts, const PathTag&) { return pts.cend(); }
template<> inline Slic3r::ExPolygon create<Slic3r::ExPolygon>(Slic3r::Points&& contour)
{
Slic3r::ExPolygon expoly; expoly.contour.points.swap(contour);
return expoly;
}
template<> inline Slic3r::Polygon create<Slic3r::Polygon>(Slic3r::Points&& contour)
{
Slic3r::Polygon poly; poly.points.swap(contour);
return poly;
}
} // shapelike
} // libnest2d
namespace Slic3r {
// Used as compute type.
@ -74,13 +28,22 @@ using Rational = boost::rational<boost::multiprecision::int128_t>;
using Rational = boost::rational<__int128>;
#endif
MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
template<class P>
libnest2d::RotatedBox<Point, Unit> minAreaBoundigBox_(
const P &p, MinAreaBoundigBox::PolygonLevel lvl)
{
const Polygon &chull = pc == pcConvex ? p :
P chull = lvl == MinAreaBoundigBox::pcConvex ?
p :
libnest2d::sl::convexHull(p);
libnest2d::RotatedBox<Point, Unit> box =
libnest2d::minAreaBoundingBox<Polygon, Unit, Rational>(chull);
libnest2d::removeCollinearPoints(chull);
return libnest2d::minAreaBoundingBox<P, Unit, Rational>(chull);
}
MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
{
libnest2d::RotatedBox<Point, Unit> box = minAreaBoundigBox_(p, pc);
m_right = libnest2d::cast<long double>(box.right_extent());
m_bottom = libnest2d::cast<long double>(box.bottom_extent());
@ -89,11 +52,7 @@ MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc)
{
const ExPolygon &chull = pc == pcConvex ? p :
libnest2d::sl::convexHull(p);
libnest2d::RotatedBox<Point, Unit> box =
libnest2d::minAreaBoundingBox<ExPolygon, Unit, Rational>(chull);
libnest2d::RotatedBox<Point, Unit> box = minAreaBoundigBox_(p, pc);
m_right = libnest2d::cast<long double>(box.right_extent());
m_bottom = libnest2d::cast<long double>(box.bottom_extent());
@ -102,11 +61,7 @@ MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc)
MinAreaBoundigBox::MinAreaBoundigBox(const Points &pts, PolygonLevel pc)
{
const Points &chull = pc == pcConvex ? pts :
libnest2d::sl::convexHull(pts);
libnest2d::RotatedBox<Point, Unit> box =
libnest2d::minAreaBoundingBox<Points, Unit, Rational>(chull);
libnest2d::RotatedBox<Point, Unit> box = minAreaBoundigBox_(pts, pc);
m_right = libnest2d::cast<long double>(box.right_extent());
m_bottom = libnest2d::cast<long double>(box.bottom_extent());

View file

@ -27,11 +27,7 @@ public:
// Constructors with various types of geometry data used in Slic3r.
// If the convexity is known apriory, pcConvex can be used to skip
// convex hull calculation. It is very important that the input polygons
// do NOT have any collinear points (except for the first and the last
// vertex being the same -- meaning a closed polygon for boost)
// To make sure this constraint is satisfied, you can call
// remove_collinear_points on the input polygon before handing over here)
// convex hull calculation.
explicit MinAreaBoundigBox(const Polygon&, PolygonLevel = pcSimple);
explicit MinAreaBoundigBox(const ExPolygon&, PolygonLevel = pcSimple);
explicit MinAreaBoundigBox(const Points&, PolygonLevel = pcSimple);

View file

@ -833,18 +833,6 @@ indexed_triangle_set ModelObject::raw_indexed_triangle_set() const
return out;
}
// Non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
TriangleMesh ModelObject::full_raw_mesh() const
{
TriangleMesh mesh;
for (const ModelVolume *v : this->volumes)
{
TriangleMesh vol_mesh(v->mesh());
vol_mesh.transform(v->get_matrix());
mesh.merge(vol_mesh);
}
return mesh;
}
const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const
{

View file

@ -289,8 +289,6 @@ public:
TriangleMesh raw_mesh() const;
// The same as above, but producing a lightweight indexed_triangle_set.
indexed_triangle_set raw_indexed_triangle_set() const;
// Non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
TriangleMesh full_raw_mesh() const;
// A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
// This bounding box is only used for the actual slicing.
const BoundingBoxf3& raw_bounding_box() const;

View file

@ -64,6 +64,7 @@ public:
bool has_duplicate_points() const;
// Remove exact duplicates, return true if any duplicate has been removed.
bool remove_duplicate_points();
void clear() { this->points.clear(); }
void append(const Point &point) { this->points.push_back(point); }
void append(const Points &src) { this->append(src.begin(), src.end()); }
void append(const Points::const_iterator &begin, const Points::const_iterator &end) { this->points.insert(this->points.end(), begin, end); }
@ -83,6 +84,13 @@ public:
static Points _douglas_peucker(const Points &points, const double tolerance);
static Points visivalingam(const Points& pts, const double& tolerance);
inline auto begin() { return points.begin(); }
inline auto begin() const { return points.begin(); }
inline auto end() { return points.end(); }
inline auto end() const { return points.end(); }
inline auto cbegin() const { return points.begin(); }
inline auto cend() const { return points.end(); }
};
class MultiPoint3

View file

@ -8,6 +8,7 @@
#include <functional>
#include <limits>
#include <cassert>
#include <optional>
namespace Slic3r { namespace opt {

View file

@ -349,9 +349,7 @@ void PerimeterGenerator::process()
coord_t min_width = coord_t(scale_(this->ext_perimeter_flow.nozzle_diameter() / 3));
ExPolygons expp = offset2_ex(
// medial axis requires non-overlapping geometry
diff_ex(to_polygons(last),
offset(offsets, float(ext_perimeter_width / 2.)),
true),
diff_ex(last, offset(offsets, float(ext_perimeter_width / 2.)), true),
- float(min_width / 2.), float(min_width / 2.));
// the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop
for (ExPolygon &ex : expp)
@ -514,7 +512,7 @@ void PerimeterGenerator::process()
and use zigzag). */
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
// therefore it may cover the area, but no the volume.
last = diff_ex(to_polygons(last), gap_fill.polygons_covered_by_width(10.f));
last = diff_ex(last, gap_fill.polygons_covered_by_width(10.f));
this->gap_fill->append(std::move(gap_fill.entities));
}
}

View file

@ -17,42 +17,42 @@ class BoundingBox;
class Line;
class MultiPoint;
class Point;
typedef Point Vector;
using Vector = Point;
// Eigen types, to replace the Slic3r's own types in the future.
// Vector types with a fixed point coordinate base type.
typedef Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign> Vec2crd;
typedef Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign> Vec3crd;
typedef Eigen::Matrix<int, 2, 1, Eigen::DontAlign> Vec2i;
typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> Vec3i;
typedef Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign> Vec2i32;
typedef Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign> Vec2i64;
typedef Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign> Vec3i32;
typedef Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign> Vec3i64;
using Vec2crd = Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign>;
using Vec3crd = Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign>;
using Vec2i = Eigen::Matrix<int, 2, 1, Eigen::DontAlign>;
using Vec3i = Eigen::Matrix<int, 3, 1, Eigen::DontAlign>;
using Vec2i32 = Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign>;
using Vec2i64 = Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign>;
using Vec3i32 = Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign>;
using Vec3i64 = Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign>;
// Vector types with a double coordinate base type.
typedef Eigen::Matrix<float, 2, 1, Eigen::DontAlign> Vec2f;
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> Vec3f;
typedef Eigen::Matrix<double, 2, 1, Eigen::DontAlign> Vec2d;
typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vec3d;
using Vec2f = Eigen::Matrix<float, 2, 1, Eigen::DontAlign>;
using Vec3f = Eigen::Matrix<float, 3, 1, Eigen::DontAlign>;
using Vec2d = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
using Vec3d = Eigen::Matrix<double, 3, 1, Eigen::DontAlign>;
typedef std::vector<Point> Points;
typedef std::vector<Point*> PointPtrs;
typedef std::vector<const Point*> PointConstPtrs;
typedef std::vector<Vec3crd> Points3;
typedef std::vector<Vec2d> Pointfs;
typedef std::vector<Vec2d> Vec2ds;
typedef std::vector<Vec3d> Pointf3s;
using Points = std::vector<Point>;
using PointPtrs = std::vector<Point*>;
using PointConstPtrs = std::vector<const Point*>;
using Points3 = std::vector<Vec3crd>;
using Pointfs = std::vector<Vec2d>;
using Vec2ds = std::vector<Vec2d>;
using Pointf3s = std::vector<Vec3d>;
typedef Eigen::Matrix<float, 2, 2, Eigen::DontAlign> Matrix2f;
typedef Eigen::Matrix<double, 2, 2, Eigen::DontAlign> Matrix2d;
typedef Eigen::Matrix<float, 3, 3, Eigen::DontAlign> Matrix3f;
typedef Eigen::Matrix<double, 3, 3, Eigen::DontAlign> Matrix3d;
using Matrix2f = Eigen::Matrix<float, 2, 2, Eigen::DontAlign>;
using Matrix2d = Eigen::Matrix<double, 2, 2, Eigen::DontAlign>;
using Matrix3f = Eigen::Matrix<float, 3, 3, Eigen::DontAlign>;
using Matrix3d = Eigen::Matrix<double, 3, 3, Eigen::DontAlign>;
typedef Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign> Transform2f;
typedef Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign> Transform2d;
typedef Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign> Transform3f;
typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d;
using Transform2f = Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign>;
using Transform2d = Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign>;
using Transform3f = Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign>;
using Transform3d = Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign>;
inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); }
@ -101,7 +101,7 @@ template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N
class Point : public Vec2crd
{
public:
typedef coord_t coord_type;
using coord_type = coord_t;
Point() : Vec2crd(0, 0) {}
Point(int32_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
@ -337,7 +337,7 @@ public:
}
private:
typedef typename std::unordered_multimap<Vec2crd, ValueType, PointHash> map_type;
using map_type = typename std::unordered_multimap<Vec2crd, ValueType, PointHash>;
PointAccessor m_point_accessor;
map_type m_map;
coord_t m_search_radius;
@ -413,6 +413,25 @@ unscaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v) noexcept
return v.template cast<Tout>() * SCALING_FACTOR;
}
// Align a coordinate to a grid. The coordinate may be negative,
// the aligned value will never be bigger than the original one.
inline coord_t align_to_grid(const coord_t coord, const coord_t spacing) {
// Current C++ standard defines the result of integer division to be rounded to zero,
// for both positive and negative numbers. Here we want to round down for negative
// numbers as well.
coord_t aligned = (coord < 0) ?
((coord - spacing + 1) / spacing) * spacing :
(coord / spacing) * spacing;
assert(aligned <= coord);
return aligned;
}
inline Point align_to_grid(Point coord, Point spacing)
{ return Point(align_to_grid(coord.x(), spacing.x()), align_to_grid(coord.y(), spacing.y())); }
inline coord_t align_to_grid(coord_t coord, coord_t spacing, coord_t base)
{ return base + align_to_grid(coord - base, spacing); }
inline Point align_to_grid(Point coord, Point spacing, Point base)
{ return Point(align_to_grid(coord.x(), spacing.x(), base.x()), align_to_grid(coord.y(), spacing.y(), base.y())); }
} // namespace Slic3r
// start Boost
@ -420,11 +439,11 @@ unscaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v) noexcept
#include <boost/polygon/polygon.hpp>
namespace boost { namespace polygon {
template <>
struct geometry_concept<Slic3r::Point> { typedef point_concept type; };
struct geometry_concept<Slic3r::Point> { using type = point_concept; };
template <>
struct point_traits<Slic3r::Point> {
typedef coord_t coordinate_type;
using coordinate_type = coord_t;
static inline coordinate_type get(const Slic3r::Point& point, orientation_2d orient) {
return static_cast<coordinate_type>(point((orient == HORIZONTAL) ? 0 : 1));
@ -433,7 +452,7 @@ namespace boost { namespace polygon {
template <>
struct point_mutable_traits<Slic3r::Point> {
typedef coord_t coordinate_type;
using coordinate_type = coord_t;
static inline void set(Slic3r::Point& point, orientation_2d orient, coord_t value) {
point((orient == HORIZONTAL) ? 0 : 1) = value;
}

View file

@ -70,7 +70,7 @@ double Polygon::area() const
bool Polygon::is_counter_clockwise() const
{
return ClipperLib::Orientation(Slic3rMultiPoint_to_ClipperPath(*this));
return ClipperLib::Orientation(this->points);
}
bool Polygon::is_clockwise() const

View file

@ -11,7 +11,9 @@
namespace Slic3r {
class Polygon;
typedef std::vector<Polygon> Polygons;
using Polygons = std::vector<Polygon>;
using PolygonPtrs = std::vector<Polygon*>;
using ConstPolygonPtrs = std::vector<const Polygon*>;
class Polygon : public MultiPoint
{
@ -70,6 +72,9 @@ public:
// Projection of a point onto the polygon.
Point point_projection(const Point &point) const;
std::vector<float> parameter_by_length() const;
using iterator = Points::iterator;
using const_iterator = Points::const_iterator;
};
inline bool operator==(const Polygon &lhs, const Polygon &rhs) { return lhs.points == rhs.points; }
@ -88,6 +93,8 @@ inline double total_length(const Polygons &polylines) {
return total;
}
inline double area(const Polygon &poly) { return poly.area(); }
inline double area(const Polygons &polys)
{
double s = 0.;
@ -215,6 +222,24 @@ inline Polylines to_polylines(Polygons &&polys)
return polylines;
}
inline Polygons to_polygons(const std::vector<Points> &paths)
{
Polygons out;
out.reserve(paths.size());
for (const Points &path : paths)
out.emplace_back(path);
return out;
}
inline Polygons to_polygons(std::vector<Points> &&paths)
{
Polygons out;
out.reserve(paths.size());
for (const Points &path : paths)
out.emplace_back(std::move(path));
return out;
}
} // Slic3r
// start Boost

View file

@ -124,6 +124,24 @@ inline Lines to_lines(const Polylines &polys)
return lines;
}
inline Polylines to_polylines(const std::vector<Points> &paths)
{
Polylines out;
out.reserve(paths.size());
for (const Points &path : paths)
out.emplace_back(path);
return out;
}
inline Polylines to_polylines(std::vector<Points> &&paths)
{
Polylines out;
out.reserve(paths.size());
for (const Points &path : paths)
out.emplace_back(std::move(path));
return out;
}
inline void polylines_append(Polylines &dst, const Polylines &src)
{
dst.insert(dst.end(), src.begin(), src.end());

View file

@ -296,6 +296,13 @@ void Preset::normalize(DynamicPrintConfig &config)
if (auto *gap_fill_enabled = config.option<ConfigOptionBool>("gap_fill_enabled", false); gap_fill_enabled)
gap_fill_enabled->value = false;
}
if (auto *first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height", false); first_layer_height && first_layer_height->percent)
if (const auto *layer_height = config.option<ConfigOptionFloat>("layer_height", false); layer_height) {
// Legacy conversion - first_layer_height moved from PrintObject setting to a Print setting, thus we are getting rid of the dependency
// of first_layer_height on PrintObject specific layer_height. Covert the first layer heigth to an absolute value.
first_layer_height->value = first_layer_height->get_abs_value(layer_height->value);
first_layer_height->percent = false;
}
}
std::string Preset::remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config)
@ -427,7 +434,7 @@ const std::vector<std::string>& Preset::print_options()
"bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield",
"min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
"support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_style",
"support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style",
"support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers",
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops",
"support_material_contact_distance", "support_material_bottom_contact_distance",
@ -468,7 +475,7 @@ const std::vector<std::string>& Preset::machine_limits_options()
static std::vector<std::string> s_opts;
if (s_opts.empty()) {
s_opts = {
"machine_max_acceleration_extruding", "machine_max_acceleration_retracting",
"machine_max_acceleration_extruding", "machine_max_acceleration_retracting", "machine_max_acceleration_travel",
"machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e",
"machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e",
"machine_min_extruding_rate", "machine_min_travel_rate",

View file

@ -100,7 +100,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"filament_spool_weight",
"first_layer_acceleration",
"first_layer_bed_temperature",
"first_layer_speed",
"gcode_comments",
"gcode_label_objects",
"infill_acceleration",
@ -139,7 +138,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"start_filament_gcode",
"toolchange_gcode",
"threads",
"travel_speed",
"use_firmware_retraction",
"use_relative_e_distances",
"use_volumetric_e",
@ -182,7 +180,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
} else if (
opt_key == "complete_objects"
|| opt_key == "filament_type"
|| opt_key == "filament_soluble"
|| opt_key == "first_layer_temperature"
|| opt_key == "filament_loading_speed"
|| opt_key == "filament_loading_speed_start"
@ -210,9 +207,17 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "cooling_tube_retraction"
|| opt_key == "cooling_tube_length"
|| opt_key == "extra_loading_move"
|| opt_key == "travel_speed"
|| opt_key == "first_layer_speed"
|| opt_key == "z_offset") {
steps.emplace_back(psWipeTower);
steps.emplace_back(psSkirt);
} else if (opt_key == "filament_soluble") {
steps.emplace_back(psWipeTower);
// Soluble support interface / non-soluble base interface produces non-soluble interface layers below soluble interface layers.
// Thus switching between soluble / non-soluble interface layer material may require recalculation of supports.
//FIXME Killing supports on any change of "filament_soluble" is rough. We should check for each object whether that is necessary.
osteps.emplace_back(posSupportMaterial);
} else if (
opt_key == "first_layer_extrusion_width"
|| opt_key == "min_layer_height"
@ -1293,7 +1298,7 @@ std::string Print::validate(std::string* warning) const
}
if (m_config.gcode_flavor != gcfRepRapSprinter && m_config.gcode_flavor != gcfRepRapFirmware &&
m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlin)
m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlinLegacy && m_config.gcode_flavor != gcfMarlinFirmware)
return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.");
if (! m_config.use_relative_e_distances)
return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
@ -1459,7 +1464,8 @@ std::string Print::validate(std::string* warning) const
}
// validate first_layer_height
double first_layer_height = object->config().get_abs_value("first_layer_height");
assert(! m_config.first_layer_height.percent);
double first_layer_height = m_config.first_layer_height.value;
double first_layer_min_nozzle_diameter;
if (object->has_raft()) {
// if we have raft layers, only support material extruder is used on first layer
@ -1556,9 +1562,8 @@ BoundingBox Print::total_bounding_box() const
double Print::skirt_first_layer_height() const
{
if (m_objects.empty())
throw Slic3r::InvalidArgument("skirt_first_layer_height() can't be called without PrintObjects");
return m_objects.front()->config().get_abs_value("first_layer_height");
assert(! m_config.first_layer_height.percent);
return m_config.first_layer_height.value;
}
Flow Print::brim_flow() const
@ -1987,9 +1992,7 @@ void Print::_make_wipe_tower()
// Set the extruder & material properties at the wipe tower object.
for (size_t i = 0; i < number_of_extruders; ++ i)
wipe_tower.set_extruder(
i, m_config);
wipe_tower.set_extruder(i, m_config);
m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));
@ -2015,8 +2018,8 @@ void Print::_make_wipe_tower()
volume_to_wipe += (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
// request a toolchange at the wipe tower with at least volume_to_wipe purging amount
wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id,
first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back(), volume_to_wipe);
wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height,
current_extruder_id, extruder_id, volume_to_wipe);
current_extruder_id = extruder_id;
}
}

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