diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9a5fc8387..c6f295150 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm
index 0c35c93d9..b7a7da772 100644
--- a/lib/Slic3r/Geometry/Clipper.pm
+++ b/lib/Slic3r/Geometry/Clipper.pm
@@ -5,7 +5,7 @@ use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
- offset offset2
+ offset
offset_ex offset2_ex
diff_ex diff union_ex intersection_ex
JT_ROUND JT_MITER JT_SQUARE
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index 7370881ea..0385f88b8 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -7,7 +7,7 @@ use List::Util qw(min max sum first);
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(scale epsilon);
use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex
- offset offset2 offset_ex offset2_ex JT_MITER);
+ offset offset_ex offset2_ex JT_MITER);
use Slic3r::Print::State ':steps';
use Slic3r::Surface ':types';
diff --git a/resources/icons/splashscreen-gcodepreview.jpg b/resources/icons/splashscreen-gcodepreview.jpg
index 3bae38493..481c4a6e1 100644
Binary files a/resources/icons/splashscreen-gcodepreview.jpg and b/resources/icons/splashscreen-gcodepreview.jpg differ
diff --git a/resources/icons/splashscreen.jpg b/resources/icons/splashscreen.jpg
index 754e24588..08236bccc 100644
Binary files a/resources/icons/splashscreen.jpg and b/resources/icons/splashscreen.jpg differ
diff --git a/resources/profiles/Anycubic.idx b/resources/profiles/Anycubic.idx
index 24a881f30..cc3b55ef4 100644
--- a/resources/profiles/Anycubic.idx
+++ b/resources/profiles/Anycubic.idx
@@ -1,13 +1,14 @@
-min_slic3r_version = 2.3.1-beta
-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.
-0.0.6 Reduced max print height for Predator. Updated end g-code, before layer change g-code and output filename format for Kossel.
-0.0.5 Updated end g-code.
-min_slic3r_version = 2.3.0-alpha2
-0.0.4 Fixed predator output filename format, infill overlap, start gcode adjustments.
-0.0.3 Fixed infill_overlap, start_gcode, end_gcode for Anycubic Predator
-0.0.2 Added Anycubic Predator
-min_slic3r_version = 2.3.0-alpha0
-0.0.1 Initial Version
+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.
+0.0.6 Reduced max print height for Predator. Updated end g-code, before layer change g-code and output filename format for Kossel.
+0.0.5 Updated end g-code.
+min_slic3r_version = 2.3.0-alpha2
+0.0.4 Fixed predator output filename format, infill overlap, start gcode adjustments.
+0.0.3 Fixed infill_overlap, start_gcode, end_gcode for Anycubic Predator
+0.0.2 Added Anycubic Predator
+min_slic3r_version = 2.3.0-alpha0
+0.0.1 Initial Version
diff --git a/resources/profiles/Anycubic.ini b/resources/profiles/Anycubic.ini
index 44308abc8..c1b763879 100644
--- a/resources/profiles/Anycubic.ini
+++ b/resources/profiles/Anycubic.ini
@@ -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.9
+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%
@@ -76,7 +76,7 @@ bridge_flow_ratio = 0.8
bridge_speed = 30
brim_width = 0
clip_multipart_objects = 1
-compatible_printers =
+compatible_printers =
complete_objects = 0
dont_support_bridges = 1
elefant_foot_compensation = 0
@@ -108,7 +108,7 @@ max_volumetric_extrusion_rate_slope_negative = 0
max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0
min_skirt_length = 4
-notes =
+notes =
overhangs = 0
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
@@ -117,8 +117,8 @@ perimeters = 2
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
perimeter_speed = 45
-post_process =
-print_settings_id =
+post_process =
+print_settings_id =
raft_layers = 0
resolution = 0
seam_position = nearest
@@ -290,7 +290,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and n
# Common filament preset
[filament:*common_akossel*]
cooling = 0
-compatible_printers =
+compatible_printers =
extrusion_multiplier = 1
filament_cost = 0
filament_density = 0
@@ -375,9 +375,9 @@ filament_vendor = Generic
# Common printer preset
[printer:*common_akossel*]
printer_technology = FFF
-bed_shape =
+bed_shape =
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]
-between_objects_gcode =
+between_objects_gcode =
deretract_speed = 40
extruder_colour = #FFFF00
extruder_offset = 0x0
@@ -405,8 +405,8 @@ max_layer_height = 0.3
min_layer_height = 0.08
max_print_height = 300
nozzle_diameter = 0.4
-printer_notes =
-printer_settings_id =
+printer_notes =
+printer_settings_id =
retract_before_travel = 2
retract_before_wipe = 70%
retract_layer_change = 1
@@ -419,9 +419,9 @@ retract_restart_extra = 0
retract_restart_extra_toolchange = 0
retract_speed = 60
single_extruder_multi_material = 0
-start_gcode =
+start_gcode =
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG28 ; home\nM84 ; disable motors
-toolchange_gcode =
+toolchange_gcode =
use_firmware_retraction = 0
use_relative_e_distances = 1
use_volumetric_e = 0
@@ -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
@@ -955,14 +973,14 @@ slowdown_below_layer_time = 20
[filament:Generic ABS @MEGA]
inherits = *ABS_mega*
-
+
[filament:*FLEX_mega*]
inherits = *common_mega*
bed_temperature = 50
bridge_fan_speed = 80
cooling = 0
extrusion_multiplier = 1.15
-fan_always_on = 0
+fan_always_on = 0
filament_colour = #008000
filament_cost = 82.00
filament_density = 1.22
@@ -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} E-34.0 F720 ; move print head up & retract filament\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 Y1.0 Z0.3 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\n; initial load\nG1 X205.0 E19 F1000\nG1 Y1.6\nG1 X5.0 E19 F1000\nG92 E0.0\n; intro line\nG1 Y2.0 Z0.2 F1000\nG1 X65.0 E9.0 F1000\nG1 X105.0 E12.5 F1000\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]
diff --git a/resources/profiles/Anycubic/i3megas.svg b/resources/profiles/Anycubic/i3megas.svg
new file mode 100644
index 000000000..dfb4ae496
--- /dev/null
+++ b/resources/profiles/Anycubic/i3megas.svg
@@ -0,0 +1,561 @@
+
+
+
+
diff --git a/resources/profiles/Anycubic/i3megas_bed.stl b/resources/profiles/Anycubic/i3megas_bed.stl
new file mode 100644
index 000000000..49ff8c5b3
Binary files /dev/null and b/resources/profiles/Anycubic/i3megas_bed.stl differ
diff --git a/resources/profiles/Creality.ini b/resources/profiles/Creality.ini
index 524815525..717b49558 100644
--- a/resources/profiles/Creality.ini
+++ b/resources/profiles/Creality.ini
@@ -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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @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 Matt @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.
@@ -326,7 +326,7 @@ notes =
overhangs = 0
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
-output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
+output_filename_format = {input_filename_base}_{print_time}_{layer_height}mm_{temperature[0]}C_{filament_type[0]}_{printer_model}.gcode
perimeters = 2
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
@@ -639,6 +639,18 @@ filament_density = 1.24
filament_colour = #FF0000
filament_spool_weight = 256
+[filament:Devil Design PLA Matt @CREALITY]
+inherits = *PLA*
+filament_vendor = Devil Design
+temperature = 205
+bed_temperature = 60
+first_layer_temperature = 205
+first_layer_bed_temperature = 60
+filament_cost = 20.00
+filament_density = 1.38
+filament_colour = #FF0000
+filament_spool_weight = 256
+
[filament:Devil Design PLA Galaxy @CREALITY]
inherits = *PLA*
renamed_from = "Devil Design PLA (Galaxy) @CREALITY"
diff --git a/resources/profiles/PrusaResearch/mk2.svg b/resources/profiles/PrusaResearch/mk2.svg
index b8fa8d0cd..1fe5b4c57 100644
--- a/resources/profiles/PrusaResearch/mk2.svg
+++ b/resources/profiles/PrusaResearch/mk2.svg
@@ -1 +1,927 @@
-
\ No newline at end of file
+
+
diff --git a/resources/profiles/PrusaResearch/mk3.svg b/resources/profiles/PrusaResearch/mk3.svg
index c8f53373b..678213ac5 100644
--- a/resources/profiles/PrusaResearch/mk3.svg
+++ b/resources/profiles/PrusaResearch/mk3.svg
@@ -1 +1,930 @@
-
\ No newline at end of file
+
+
diff --git a/src/clipper/CMakeLists.txt b/src/clipper/CMakeLists.txt
index 8a4e92852..0362a4d84 100644
--- a/src/clipper/CMakeLists.txt
+++ b/src/clipper/CMakeLists.txt
@@ -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
)
diff --git a/src/clipper/clipper.cpp b/src/clipper/clipper.cpp
index cbe54a064..0285d9167 100644
--- a/src/clipper/clipper.cpp
+++ b/src/clipper/clipper.cpp
@@ -61,11 +61,15 @@
#define CLIPPERLIB_PROFILE_BLOCK(name)
#endif
-#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 /* CLIPPERLIB_USE_XYZ */
namespace ClipperLib {
-#endif /* use_xyz */
+#endif /* CLIPPERLIB_USE_XYZ */
static double const pi = 3.141592653589793238;
static double const two_pi = pi *2;
@@ -156,7 +160,7 @@ double Area(const Path &poly)
double a = 0;
for (int i = 0, j = size -1; i < size; ++i)
{
- a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y);
+ a += ((double)poly[j].x() + poly[i].x()) * ((double)poly[j].y() - poly[i].y());
j = i;
}
return -a * 0.5;
@@ -169,7 +173,7 @@ double Area(const OutRec &outRec)
if (!op) return 0;
double a = 0;
do {
- a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y);
+ a += (double)(op->Prev->Pt.x() + op->Pt.x()) * (double)(op->Prev->Pt.y() - op->Pt.y());
op = op->Next;
} while (op != outRec.Pts);
return a * 0.5;
@@ -201,26 +205,26 @@ int PointInPolygon(const IntPoint &pt, const Path &path)
for(size_t i = 1; i <= cnt; ++i)
{
IntPoint ipNext = (i == cnt ? path[0] : path[i]);
- if (ipNext.Y == pt.Y && ((ipNext.X == pt.X) || (ip.Y == pt.Y && ((ipNext.X > pt.X) == (ip.X < pt.X)))))
+ if (ipNext.y() == pt.y() && ((ipNext.x() == pt.x()) || (ip.y() == pt.y() && ((ipNext.x() > pt.x()) == (ip.x() < pt.x())))))
return -1;
- if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y))
+ if ((ip.y() < pt.y()) != (ipNext.y() < pt.y()))
{
- if (ip.X >= pt.X)
+ if (ip.x() >= pt.x())
{
- if (ipNext.X > pt.X) result = 1 - result;
+ if (ipNext.x() > pt.x()) result = 1 - result;
else
{
- double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y);
+ double d = (double)(ip.x() - pt.x()) * (ipNext.y() - pt.y()) - (double)(ipNext.x() - pt.x()) * (ip.y() - pt.y());
if (!d) return -1;
- if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
+ if ((d > 0) == (ipNext.y() > ip.y())) result = 1 - result;
}
} else
{
- if (ipNext.X > pt.X)
+ if (ipNext.x() > pt.x())
{
- double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y);
+ double d = (double)(ip.x() - pt.x()) * (ipNext.y() - pt.y()) - (double)(ipNext.x() - pt.x()) * (ip.y() - pt.y());
if (!d) return -1;
- if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
+ if ((d > 0) == (ipNext.y() > ip.y())) result = 1 - result;
}
}
}
@@ -238,29 +242,29 @@ int PointInPolygon (const IntPoint &pt, OutPt *op)
OutPt* startOp = op;
do
{
- if (op->Next->Pt.Y == pt.Y)
+ if (op->Next->Pt.y() == pt.y())
{
- if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y &&
- ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1;
+ if ((op->Next->Pt.x() == pt.x()) || (op->Pt.y() == pt.y() &&
+ ((op->Next->Pt.x() > pt.x()) == (op->Pt.x() < pt.x())))) return -1;
}
- if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y))
+ if ((op->Pt.y() < pt.y()) != (op->Next->Pt.y() < pt.y()))
{
- if (op->Pt.X >= pt.X)
+ if (op->Pt.x() >= pt.x())
{
- if (op->Next->Pt.X > pt.X) result = 1 - result;
+ if (op->Next->Pt.x() > pt.x()) result = 1 - result;
else
{
- double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y);
+ double d = (double)(op->Pt.x() - pt.x()) * (op->Next->Pt.y() - pt.y()) - (double)(op->Next->Pt.x() - pt.x()) * (op->Pt.y() - pt.y());
if (!d) return -1;
- if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result;
+ if ((d > 0) == (op->Next->Pt.y() > op->Pt.y())) result = 1 - result;
}
} else
{
- if (op->Next->Pt.X > pt.X)
+ if (op->Next->Pt.x() > pt.x())
{
- double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y);
+ double d = (double)(op->Pt.x() - pt.x()) * (op->Next->Pt.y() - pt.y()) - (double)(op->Next->Pt.x() - pt.x()) * (op->Pt.y() - pt.y());
if (!d) return -1;
- if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result;
+ if ((d > 0) == (op->Next->Pt.y() > op->Pt.y())) result = 1 - result;
}
}
}
@@ -304,100 +308,100 @@ inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cI
#endif
inline bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range)
- { return SlopesEqual(e1.Delta.X, e1.Delta.Y, e2.Delta.X, e2.Delta.Y, UseFullInt64Range); }
+ { return SlopesEqual(e1.Delta.x(), e1.Delta.y(), e2.Delta.x(), e2.Delta.y(), UseFullInt64Range); }
inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, bool UseFullInt64Range)
- { return SlopesEqual(pt1.X-pt2.X, pt1.Y-pt2.Y, pt2.X-pt3.X, pt2.Y-pt3.Y, UseFullInt64Range); }
+ { return SlopesEqual(pt1.x()-pt2.x(), pt1.y()-pt2.y(), pt2.x()-pt3.x(), pt2.y()-pt3.y(), UseFullInt64Range); }
inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, const IntPoint &pt4, bool UseFullInt64Range)
- { return SlopesEqual(pt1.X-pt2.X, pt1.Y-pt2.Y, pt3.X-pt4.X, pt3.Y-pt4.Y, UseFullInt64Range); }
+ { return SlopesEqual(pt1.x()-pt2.x(), pt1.y()-pt2.y(), pt3.x()-pt4.x(), pt3.y()-pt4.y(), UseFullInt64Range); }
//------------------------------------------------------------------------------
inline bool IsHorizontal(TEdge &e)
{
- return e.Delta.Y == 0;
+ return e.Delta.y() == 0;
}
//------------------------------------------------------------------------------
inline double GetDx(const IntPoint &pt1, const IntPoint &pt2)
{
- return (pt1.Y == pt2.Y) ?
- HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y);
+ return (pt1.y() == pt2.y()) ?
+ HORIZONTAL : (double)(pt2.x() - pt1.x()) / (pt2.y() - pt1.y());
}
//---------------------------------------------------------------------------
inline cInt TopX(TEdge &edge, const cInt currentY)
{
- return (currentY == edge.Top.Y) ?
- edge.Top.X :
- edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y));
+ return (currentY == edge.Top.y()) ?
+ edge.Top.x() :
+ edge.Bot.x() + Round(edge.Dx *(currentY - edge.Bot.y()));
}
//------------------------------------------------------------------------------
void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
{
-#ifdef use_xyz
- ip.Z = 0;
+#ifdef CLIPPERLIB_USE_XYZ
+ ip.z() = 0;
#endif
double b1, b2;
if (Edge1.Dx == Edge2.Dx)
{
- ip.Y = Edge1.Curr.Y;
- ip.X = TopX(Edge1, ip.Y);
+ ip.y() = Edge1.Curr.y();
+ ip.x() = TopX(Edge1, ip.y());
return;
}
- else if (Edge1.Delta.X == 0)
+ else if (Edge1.Delta.x() == 0)
{
- ip.X = Edge1.Bot.X;
+ ip.x() = Edge1.Bot.x();
if (IsHorizontal(Edge2))
- ip.Y = Edge2.Bot.Y;
+ ip.y() = Edge2.Bot.y();
else
{
- b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx);
- ip.Y = Round(ip.X / Edge2.Dx + b2);
+ b2 = Edge2.Bot.y() - (Edge2.Bot.x() / Edge2.Dx);
+ ip.y() = Round(ip.x() / Edge2.Dx + b2);
}
}
- else if (Edge2.Delta.X == 0)
+ else if (Edge2.Delta.x() == 0)
{
- ip.X = Edge2.Bot.X;
+ ip.x() = Edge2.Bot.x();
if (IsHorizontal(Edge1))
- ip.Y = Edge1.Bot.Y;
+ ip.y() = Edge1.Bot.y();
else
{
- b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx);
- ip.Y = Round(ip.X / Edge1.Dx + b1);
+ b1 = Edge1.Bot.y() - (Edge1.Bot.x() / Edge1.Dx);
+ ip.y() = Round(ip.x() / Edge1.Dx + b1);
}
}
else
{
- b1 = double(Edge1.Bot.X) - double(Edge1.Bot.Y) * Edge1.Dx;
- b2 = double(Edge2.Bot.X) - double(Edge2.Bot.Y) * Edge2.Dx;
+ b1 = double(Edge1.Bot.x()) - double(Edge1.Bot.y()) * Edge1.Dx;
+ b2 = double(Edge2.Bot.x()) - double(Edge2.Bot.y()) * Edge2.Dx;
double q = (b2-b1) / (Edge1.Dx - Edge2.Dx);
- ip.Y = Round(q);
- ip.X = (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ?
+ ip.y() = Round(q);
+ ip.x() = (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ?
Round(Edge1.Dx * q + b1) :
Round(Edge2.Dx * q + b2);
}
- if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y)
+ if (ip.y() < Edge1.Top.y() || ip.y() < Edge2.Top.y())
{
- if (Edge1.Top.Y > Edge2.Top.Y)
- ip.Y = Edge1.Top.Y;
+ if (Edge1.Top.y() > Edge2.Top.y())
+ ip.y() = Edge1.Top.y();
else
- ip.Y = Edge2.Top.Y;
+ ip.y() = Edge2.Top.y();
if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx))
- ip.X = TopX(Edge1, ip.Y);
+ ip.x() = TopX(Edge1, ip.y());
else
- ip.X = TopX(Edge2, ip.Y);
+ ip.x() = TopX(Edge2, ip.y());
}
- //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ...
- if (ip.Y > Edge1.Curr.Y)
+ //finally, don't allow 'ip' to be BELOW curr.y() (ie bottom of scanbeam) ...
+ if (ip.y() > Edge1.Curr.y())
{
- ip.Y = Edge1.Curr.Y;
+ ip.y() = Edge1.Curr.y();
//use the more vertical edge to derive X ...
if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx))
- ip.X = TopX(Edge2, ip.Y); else
- ip.X = TopX(Edge1, ip.Y);
+ ip.x() = TopX(Edge2, ip.y()); else
+ ip.x() = TopX(Edge1, ip.y());
}
}
//------------------------------------------------------------------------------
@@ -429,7 +433,7 @@ inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt)
void InitEdge2(TEdge& e, PolyType Pt)
{
- if (e.Curr.Y >= e.Next->Curr.Y)
+ if (e.Curr.y() >= e.Next->Curr.y())
{
e.Bot = e.Curr;
e.Top = e.Next->Curr;
@@ -439,11 +443,11 @@ void InitEdge2(TEdge& e, PolyType Pt)
e.Bot = e.Next->Curr;
}
- e.Delta.X = (e.Top.X - e.Bot.X);
- e.Delta.Y = (e.Top.Y - e.Bot.Y);
+ e.Delta.x() = (e.Top.x() - e.Bot.x());
+ e.Delta.y() = (e.Top.y() - e.Bot.y());
- if (e.Delta.Y == 0) e.Dx = HORIZONTAL;
- else e.Dx = (double)(e.Delta.X) / e.Delta.Y;
+ if (e.Delta.y() == 0) e.Dx = HORIZONTAL;
+ else e.Dx = (double)(e.Delta.x()) / e.Delta.y();
e.PolyTyp = Pt;
}
@@ -466,9 +470,9 @@ inline void ReverseHorizontal(TEdge &e)
//swap horizontal edges' Top and Bottom x's so they follow the natural
//progression of the bounds - ie so their xbots will align with the
//adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
- std::swap(e.Top.X, e.Bot.X);
-#ifdef use_xyz
- std::swap(e.Top.Z, e.Bot.Z);
+ std::swap(e.Top.x(), e.Bot.x());
+#ifdef CLIPPERLIB_USE_XYZ
+ std::swap(e.Top.z(), e.Bot.z());
#endif
}
//------------------------------------------------------------------------------
@@ -477,20 +481,20 @@ bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a,
IntPoint pt2b, IntPoint &pt1, IntPoint &pt2)
{
//precondition: segments are Collinear.
- if (std::abs(pt1a.X - pt1b.X) > std::abs(pt1a.Y - pt1b.Y))
+ if (std::abs(pt1a.x() - pt1b.x()) > std::abs(pt1a.y() - pt1b.y()))
{
- if (pt1a.X > pt1b.X) std::swap(pt1a, pt1b);
- if (pt2a.X > pt2b.X) std::swap(pt2a, pt2b);
- if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a;
- if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b;
- return pt1.X < pt2.X;
+ if (pt1a.x() > pt1b.x()) std::swap(pt1a, pt1b);
+ if (pt2a.x() > pt2b.x()) std::swap(pt2a, pt2b);
+ if (pt1a.x() > pt2a.x()) pt1 = pt1a; else pt1 = pt2a;
+ if (pt1b.x() < pt2b.x()) pt2 = pt1b; else pt2 = pt2b;
+ return pt1.x() < pt2.x();
} else
{
- if (pt1a.Y < pt1b.Y) std::swap(pt1a, pt1b);
- if (pt2a.Y < pt2b.Y) std::swap(pt2a, pt2b);
- if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a;
- if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b;
- return pt1.Y > pt2.Y;
+ if (pt1a.y() < pt1b.y()) std::swap(pt1a, pt1b);
+ if (pt2a.y() < pt2b.y()) std::swap(pt2a, pt2b);
+ if (pt1a.y() < pt2a.y()) pt1 = pt1a; else pt1 = pt2a;
+ if (pt1b.y() > pt2b.y()) pt2 = pt1b; else pt2 = pt2b;
+ return pt1.y() > pt2.y();
}
}
//------------------------------------------------------------------------------
@@ -521,14 +525,14 @@ OutPt* GetBottomPt(OutPt *pp)
OutPt* p = pp->Next;
while (p != pp)
{
- if (p->Pt.Y > pp->Pt.Y)
+ if (p->Pt.y() > pp->Pt.y())
{
pp = p;
dups = 0;
}
- else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X)
+ else if (p->Pt.y() == pp->Pt.y() && p->Pt.x() <= pp->Pt.x())
{
- if (p->Pt.X < pp->Pt.X)
+ if (p->Pt.x() < pp->Pt.x())
{
dups = 0;
pp = p;
@@ -558,10 +562,10 @@ bool Pt2IsBetweenPt1AndPt3(const IntPoint &pt1,
{
if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2))
return false;
- else if (pt1.X != pt3.X)
- return (pt2.X > pt1.X) == (pt2.X < pt3.X);
+ else if (pt1.x() != pt3.x())
+ return (pt2.x() > pt1.x()) == (pt2.x() < pt3.x());
else
- return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y);
+ return (pt2.y() > pt1.y()) == (pt2.y() < pt3.y());
}
//------------------------------------------------------------------------------
@@ -582,10 +586,10 @@ inline void RangeTest(const IntPoint& Pt, bool& useFullRange)
{
if (useFullRange)
{
- if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange)
+ if (Pt.x() > hiRange || Pt.y() > hiRange || -Pt.x() > hiRange || -Pt.y() > hiRange)
throw clipperException("Coordinate outside allowed range");
}
- else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange)
+ else if (Pt.x() > loRange|| Pt.y() > loRange || -Pt.x() > loRange || -Pt.y() > loRange)
{
useFullRange = true;
RangeTest(Pt, useFullRange);
@@ -605,8 +609,8 @@ inline TEdge* FindNextLocMin(TEdge* E)
while (IsHorizontal(*E->Prev)) E = E->Prev;
TEdge* E2 = E;
while (IsHorizontal(*E)) E = E->Next;
- if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz.
- if (E2->Prev->Bot.X < E->Bot.X) E = E2;
+ if (E->Top.y() == E->Prev->Bot.y()) continue; //ie just an intermediate horz.
+ if (E2->Prev->Bot.x() < E->Bot.x()) E = E2;
break;
}
return E;
@@ -625,14 +629,14 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
//create another LocMin and call ProcessBound once more
if (NextIsForward)
{
- while (E->Top.Y == E->Next->Bot.Y) E = E->Next;
+ while (E->Top.y() == E->Next->Bot.y()) E = E->Next;
//don't include top horizontals when parsing a bound a second time,
//they will be contained in the opposite bound ...
while (E != Result && IsHorizontal(*E)) E = E->Prev;
}
else
{
- while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev;
+ while (E->Top.y() == E->Prev->Bot.y()) E = E->Prev;
while (E != Result && IsHorizontal(*E)) E = E->Next;
}
@@ -649,7 +653,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
else
E = Result->Prev;
LocalMinimum locMin;
- locMin.Y = E->Bot.Y;
+ locMin.Y = E->Bot.y();
locMin.LeftBound = 0;
locMin.RightBound = E;
E->WindDelta = 0;
@@ -672,17 +676,17 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
EStart = E->Next;
if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge
{
- if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X)
+ if (EStart->Bot.x() != E->Bot.x() && EStart->Top.x() != E->Bot.x())
ReverseHorizontal(*E);
}
- else if (EStart->Bot.X != E->Bot.X)
+ else if (EStart->Bot.x() != E->Bot.x())
ReverseHorizontal(*E);
}
EStart = E;
if (NextIsForward)
{
- while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip)
+ while (Result->Top.y() == Result->Next->Bot.y() && Result->Next->OutIdx != Skip)
Result = Result->Next;
if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip)
{
@@ -691,38 +695,38 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
//unless a Skip edge is encountered when that becomes the top divide
Horz = Result;
while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev;
- if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev;
+ if (Horz->Prev->Top.x() > Result->Next->Top.x()) Result = Horz->Prev;
}
while (E != Result)
{
E->NextInLML = E->Next;
if (IsHorizontal(*E) && E != EStart &&
- E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
+ E->Bot.x() != E->Prev->Top.x()) ReverseHorizontal(*E);
E = E->Next;
}
- if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X)
+ if (IsHorizontal(*E) && E != EStart && E->Bot.x() != E->Prev->Top.x())
ReverseHorizontal(*E);
Result = Result->Next; //move to the edge just beyond current bound
} else
{
- while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip)
+ while (Result->Top.y() == Result->Prev->Bot.y() && Result->Prev->OutIdx != Skip)
Result = Result->Prev;
if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip)
{
Horz = Result;
while (IsHorizontal(*Horz->Next)) Horz = Horz->Next;
- if (Horz->Next->Top.X == Result->Prev->Top.X ||
- Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next;
+ if (Horz->Next->Top.x() == Result->Prev->Top.x() ||
+ Horz->Next->Top.x() > Result->Prev->Top.x()) Result = Horz->Next;
}
while (E != Result)
{
E->NextInLML = E->Prev;
- if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
+ if (IsHorizontal(*E) && E != EStart && E->Bot.x() != E->Next->Top.x())
ReverseHorizontal(*E);
E = E->Prev;
}
- if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
+ if (IsHorizontal(*E) && E != EStart && E->Bot.x() != E->Next->Top.x())
ReverseHorizontal(*E);
Result = Result->Prev; //move to the edge just beyond current bound
}
@@ -755,48 +759,6 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
return result;
}
-bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
-{
- CLIPPERLIB_PROFILE_FUNC();
- std::vector num_edges(ppg.size(), 0);
- int num_edges_total = 0;
- for (size_t i = 0; i < ppg.size(); ++ i) {
- const Path &pg = ppg[i];
- // 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 edges(num_edges_total);
- // Fill in the edge array.
- bool result = false;
- TEdge *p_edge = edges.data();
- for (Paths::size_type i = 0; i < ppg.size(); ++i)
- if (num_edges[i]) {
- bool res = AddPathInternal(ppg[i], num_edges[i] - 1, PolyTyp, Closed, p_edge);
- if (res) {
- p_edge += num_edges[i];
- result = true;
- }
- }
- if (result)
- // At least some edges were generated. Remember the edge array.
- m_edges.emplace_back(std::move(edges));
- return result;
-}
-
bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges)
{
CLIPPERLIB_PROFILE_FUNC();
@@ -887,7 +849,7 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
{
InitEdge2(*E, PolyTyp);
E = E->Next;
- if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false;
+ if (IsFlat && E->Curr.y() != eStart->Curr.y()) IsFlat = false;
}
while (E != eStart);
@@ -903,14 +865,14 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
}
E->Prev->OutIdx = Skip;
LocalMinimum locMin;
- locMin.Y = E->Bot.Y;
+ locMin.Y = E->Bot.y();
locMin.LeftBound = 0;
locMin.RightBound = E;
locMin.RightBound->Side = esRight;
locMin.RightBound->WindDelta = 0;
for (;;)
{
- if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
+ if (E->Bot.x() != E->Prev->Top.x()) ReverseHorizontal(*E);
if (E->Next->OutIdx == Skip) break;
E->NextInLML = E->Next;
E = E->Next;
@@ -937,7 +899,7 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
//E and E.Prev now share a local minima (left aligned if horizontal).
//Compare their slopes to find which starts which bound ...
LocalMinimum locMin;
- locMin.Y = E->Bot.Y;
+ locMin.Y = E->Bot.y();
if (E->Dx < E->Prev->Dx)
{
locMin.LeftBound = E->Prev;
@@ -1028,27 +990,27 @@ IntRect ClipperBase::GetBounds()
result.left = result.top = result.right = result.bottom = 0;
return result;
}
- result.left = lm->LeftBound->Bot.X;
- result.top = lm->LeftBound->Bot.Y;
- result.right = lm->LeftBound->Bot.X;
- result.bottom = lm->LeftBound->Bot.Y;
+ result.left = lm->LeftBound->Bot.x();
+ result.top = lm->LeftBound->Bot.y();
+ result.right = lm->LeftBound->Bot.x();
+ result.bottom = lm->LeftBound->Bot.y();
while (lm != m_MinimaList.end())
{
- result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y);
+ result.bottom = std::max(result.bottom, lm->LeftBound->Bot.y());
TEdge* e = lm->LeftBound;
for (;;) {
TEdge* bottomE = e;
while (e->NextInLML)
{
- if (e->Bot.X < result.left) result.left = e->Bot.X;
- if (e->Bot.X > result.right) result.right = e->Bot.X;
+ if (e->Bot.x() < result.left) result.left = e->Bot.x();
+ if (e->Bot.x() > result.right) result.right = e->Bot.x();
e = e->NextInLML;
}
- result.left = std::min(result.left, e->Bot.X);
- result.right = std::max(result.right, e->Bot.X);
- result.left = std::min(result.left, e->Top.X);
- result.right = std::max(result.right, e->Top.X);
- result.top = std::min(result.top, e->Top.Y);
+ result.left = std::min(result.left, e->Bot.x());
+ result.right = std::max(result.right, e->Bot.x());
+ result.left = std::min(result.left, e->Top.x());
+ result.right = std::max(result.right, e->Top.x());
+ result.top = std::min(result.top, e->Top.y());
if (bottomE == lm->LeftBound) e = lm->RightBound;
else break;
}
@@ -1073,7 +1035,7 @@ Clipper::Clipper(int initOptions) :
m_StrictSimple = ((initOptions & ioStrictlySimple) != 0);
m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0);
m_HasOpenPaths = false;
-#ifdef use_xyz
+#ifdef CLIPPERLIB_USE_XYZ
m_ZFill = 0;
#endif
}
@@ -1099,7 +1061,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
CLIPPERLIB_PROFILE_FUNC();
if (m_HasOpenPaths)
throw clipperException("Error: PolyTree struct is needed for open path clipping.");
- solution.resize(0);
+ solution.clear();
m_SubjFillType = subjFillType;
m_ClipFillType = clipFillType;
m_ClipType = clipType;
@@ -1454,7 +1416,7 @@ OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt)
}
if (prevE && prevE->OutIdx >= 0 &&
- (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) &&
+ (TopX(*prevE, Pt.y()) == TopX(*e, Pt.y())) &&
SlopesEqual(*e, *prevE, m_UseFullRange) &&
(e->WindDelta != 0) && (prevE->WindDelta != 0))
{
@@ -1540,7 +1502,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
SetWindingCount(*lb);
if (IsContributing(*lb))
Op1 = AddOutPt(lb, lb->Bot);
- m_Scanbeam.push(lb->Top.Y);
+ m_Scanbeam.push(lb->Top.y());
}
else
{
@@ -1551,13 +1513,13 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
rb->WindCnt2 = lb->WindCnt2;
if (IsContributing(*lb))
Op1 = AddLocalMinPoly(lb, rb, lb->Bot);
- m_Scanbeam.push(lb->Top.Y);
+ m_Scanbeam.push(lb->Top.y());
}
if (rb)
{
if(IsHorizontal(*rb)) AddEdgeToSEL(rb);
- else m_Scanbeam.push(rb->Top.Y);
+ else m_Scanbeam.push(rb->Top.y());
}
if (!lb || !rb) continue;
@@ -1569,12 +1531,12 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
for (Join &jr : m_GhostJoins)
//if the horizontal Rb and a 'ghost' horizontal overlap, then convert
//the 'ghost' join to a real join ready for later ...
- if (HorzSegmentsOverlap(jr.OutPt1->Pt.X, jr.OffPt.X, rb->Bot.X, rb->Top.X))
+ if (HorzSegmentsOverlap(jr.OutPt1->Pt.x(), jr.OffPt.x(), rb->Bot.x(), rb->Top.x()))
m_Joins.emplace_back(Join(jr.OutPt1, Op1, jr.OffPt));
}
if (lb->OutIdx >= 0 && lb->PrevInAEL &&
- lb->PrevInAEL->Curr.X == lb->Bot.X &&
+ lb->PrevInAEL->Curr.x() == lb->Bot.x() &&
lb->PrevInAEL->OutIdx >= 0 &&
SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) &&
(lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0))
@@ -1637,14 +1599,14 @@ void Clipper::DeleteFromSEL(TEdge *e)
}
//------------------------------------------------------------------------------
-#ifdef use_xyz
+#ifdef CLIPPERLIB_USE_XYZ
void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2)
{
- if (pt.Z != 0 || !m_ZFill) return;
- else if (pt == e1.Bot) pt.Z = e1.Bot.Z;
- else if (pt == e1.Top) pt.Z = e1.Top.Z;
- else if (pt == e2.Bot) pt.Z = e2.Bot.Z;
- else if (pt == e2.Top) pt.Z = e2.Top.Z;
+ if (pt.z() != 0 || !m_ZFill) return;
+ else if (pt == e1.Bot) pt.z() = e1.Bot.z();
+ else if (pt == e1.Top) pt.z() = e1.Top.z();
+ else if (pt == e2.Bot) pt.z() = e2.Bot.z();
+ else if (pt == e2.Top) pt.z() = e2.Top.z();
else m_ZFill(e1.Bot, e1.Top, e2.Bot, e2.Top, pt);
}
//------------------------------------------------------------------------------
@@ -1655,7 +1617,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt)
bool e1Contributing = ( e1->OutIdx >= 0 );
bool e2Contributing = ( e2->OutIdx >= 0 );
-#ifdef use_xyz
+#ifdef CLIPPERLIB_USE_XYZ
SetZ(Pt, *e1, *e2);
#endif
@@ -1872,10 +1834,10 @@ OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
outRec2->BottomPt = GetBottomPt(outRec2->Pts);
OutPt *OutPt1 = outRec1->BottomPt;
OutPt *OutPt2 = outRec2->BottomPt;
- if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1;
- else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2;
- else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1;
- else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2;
+ if (OutPt1->Pt.y() > OutPt2->Pt.y()) return outRec1;
+ else if (OutPt1->Pt.y() < OutPt2->Pt.y()) return outRec2;
+ else if (OutPt1->Pt.x() < OutPt2->Pt.x()) return outRec1;
+ else if (OutPt1->Pt.x() > OutPt2->Pt.x()) return outRec2;
else if (OutPt1->Next == OutPt1) return outRec2;
else if (OutPt2->Next == OutPt2) return outRec1;
else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1;
@@ -2081,13 +2043,13 @@ void Clipper::ProcessHorizontals()
inline bool IsMaxima(TEdge *e, const cInt Y)
{
- return e && e->Top.Y == Y && !e->NextInLML;
+ return e && e->Top.y() == Y && !e->NextInLML;
}
//------------------------------------------------------------------------------
inline bool IsIntermediate(TEdge *e, const cInt Y)
{
- return e->Top.Y == Y && e->NextInLML;
+ return e->Top.y() == Y && e->NextInLML;
}
//------------------------------------------------------------------------------
@@ -2202,15 +2164,15 @@ void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2)
inline void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right)
{
- if (HorzEdge.Bot.X < HorzEdge.Top.X)
+ if (HorzEdge.Bot.x() < HorzEdge.Top.x())
{
- Left = HorzEdge.Bot.X;
- Right = HorzEdge.Top.X;
+ Left = HorzEdge.Bot.x();
+ Right = HorzEdge.Top.x();
Dir = dLeftToRight;
} else
{
- Left = HorzEdge.Top.X;
- Right = HorzEdge.Bot.X;
+ Left = HorzEdge.Top.x();
+ Right = HorzEdge.Bot.x();
Dir = dRightToLeft;
}
}
@@ -2219,8 +2181,8 @@ inline void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt&
/*******************************************************************************
* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or *
* Bottom of a scanbeam) are processed as if layered. The order in which HEs *
-* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] *
-* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), *
+* are processed doesn't matter. HEs intersect with other HE Bot.x()s only [#] *
+* (or they could intersect with Top.x()s only, ie EITHER Bot.x()s OR Top.x()s), *
* and with other non-horizontal edges [*]. Once these intersections are *
* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into *
* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. *
@@ -2248,15 +2210,15 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
if (dir == dLeftToRight)
{
maxIt = m_Maxima.begin();
- while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) ++maxIt;
- if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X)
+ while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.x()) ++maxIt;
+ if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.x())
maxIt = m_Maxima.end();
}
else
{
maxRit = m_Maxima.rbegin();
- while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) ++maxRit;
- if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X)
+ while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.x()) ++maxRit;
+ if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.x())
maxRit = m_Maxima.rend();
}
}
@@ -2278,30 +2240,30 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
{
if (dir == dLeftToRight)
{
- while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X)
+ while (maxIt != m_Maxima.end() && *maxIt < e->Curr.x())
{
if (horzEdge->OutIdx >= 0 && !IsOpen)
- AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y));
+ AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.y()));
++maxIt;
}
}
else
{
- while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X)
+ while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.x())
{
if (horzEdge->OutIdx >= 0 && !IsOpen)
- AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y));
+ AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.y()));
++maxRit;
}
}
};
- if ((dir == dLeftToRight && e->Curr.X > horzRight) ||
- (dir == dRightToLeft && e->Curr.X < horzLeft)) break;
+ if ((dir == dLeftToRight && e->Curr.x() > horzRight) ||
+ (dir == dRightToLeft && e->Curr.x() < horzLeft)) break;
//Also break if we've got to the end of an intermediate horizontal edge ...
//nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
- if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML &&
+ if (e->Curr.x() == horzEdge->Top.x() && horzEdge->NextInLML &&
e->Dx < horzEdge->NextInLML->Dx) break;
if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times
@@ -2311,8 +2273,8 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
while (eNextHorz)
{
if (eNextHorz->OutIdx >= 0 &&
- HorzSegmentsOverlap(horzEdge->Bot.X,
- horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
+ HorzSegmentsOverlap(horzEdge->Bot.x(),
+ horzEdge->Top.x(), eNextHorz->Bot.x(), eNextHorz->Top.x()))
{
OutPt* op2 = GetLastOutPt(eNextHorz);
m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top));
@@ -2335,12 +2297,12 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
if(dir == dLeftToRight)
{
- IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
+ IntPoint Pt = IntPoint(e->Curr.x(), horzEdge->Curr.y());
IntersectEdges(horzEdge, e, Pt);
}
else
{
- IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
+ IntPoint Pt = IntPoint(e->Curr.x(), horzEdge->Curr.y());
IntersectEdges( e, horzEdge, Pt);
}
TEdge* eNext = (dir == dLeftToRight) ? e->NextInAEL : e->PrevInAEL;
@@ -2364,8 +2326,8 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
while (eNextHorz)
{
if (eNextHorz->OutIdx >= 0 &&
- HorzSegmentsOverlap(horzEdge->Bot.X,
- horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
+ HorzSegmentsOverlap(horzEdge->Bot.x(),
+ horzEdge->Top.x(), eNextHorz->Bot.x(), eNextHorz->Top.x()))
{
OutPt* op2 = GetLastOutPt(eNextHorz);
m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top));
@@ -2385,17 +2347,17 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
//nb: HorzEdge is no longer horizontal here
TEdge* ePrev = horzEdge->PrevInAEL;
TEdge* eNext = horzEdge->NextInAEL;
- if (ePrev && ePrev->Curr.X == horzEdge->Bot.X &&
- ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 &&
- (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y &&
+ if (ePrev && ePrev->Curr.x() == horzEdge->Bot.x() &&
+ ePrev->Curr.y() == horzEdge->Bot.y() && ePrev->WindDelta != 0 &&
+ (ePrev->OutIdx >= 0 && ePrev->Curr.y() > ePrev->Top.y() &&
SlopesEqual(*horzEdge, *ePrev, m_UseFullRange)))
{
OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot);
m_Joins.emplace_back(Join(op1, op2, horzEdge->Top));
}
- else if (eNext && eNext->Curr.X == horzEdge->Bot.X &&
- eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 &&
- eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y &&
+ else if (eNext && eNext->Curr.x() == horzEdge->Bot.x() &&
+ eNext->Curr.y() == horzEdge->Bot.y() && eNext->WindDelta != 0 &&
+ eNext->OutIdx >= 0 && eNext->Curr.y() > eNext->Top.y() &&
SlopesEqual(*horzEdge, *eNext, m_UseFullRange))
{
OutPt* op2 = AddOutPt(eNext, horzEdge->Bot);
@@ -2433,7 +2395,7 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e)
e->PrevInAEL = AelPrev;
e->NextInAEL = AelNext;
if (!IsHorizontal(*e))
- m_Scanbeam.push(e->Top.Y);
+ m_Scanbeam.push(e->Top.y());
}
//------------------------------------------------------------------------------
@@ -2476,7 +2438,7 @@ void Clipper::BuildIntersectList(const cInt topY)
{
e->PrevInSEL = e->PrevInAEL;
e->NextInSEL = e->NextInAEL;
- e->Curr.X = TopX( *e, topY );
+ e->Curr.x() = TopX( *e, topY );
e = e->NextInAEL;
}
@@ -2490,7 +2452,7 @@ void Clipper::BuildIntersectList(const cInt topY)
{
TEdge *eNext = e->NextInSEL;
IntPoint Pt;
- if(e->Curr.X > eNext->Curr.X)
+ if(e->Curr.x() > eNext->Curr.x())
{
IntersectPoint(*e, *eNext, Pt);
m_IntersectList.emplace_back(IntersectNode(e, eNext, Pt));
@@ -2522,7 +2484,7 @@ bool Clipper::FixupIntersectionOrder()
//Now it's crucial that intersections are made only between adjacent edges,
//so to ensure this the order of intersections may need adjusting ...
CopyAELToSEL();
- std::sort(m_IntersectList.begin(), m_IntersectList.end(), [](const IntersectNode &node1, const IntersectNode &node2) { return node2.Pt.Y < node1.Pt.Y; });
+ std::sort(m_IntersectList.begin(), m_IntersectList.end(), [](const IntersectNode &node1, const IntersectNode &node2) { return node2.Pt.y() < node1.Pt.y(); });
size_t cnt = m_IntersectList.size();
for (size_t i = 0; i < cnt; ++i)
@@ -2610,7 +2572,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
if(IsMaximaEdge)
{
- if (m_StrictSimple) m_Maxima.push_back(e->Top.X);
+ if (m_StrictSimple) m_Maxima.push_back(e->Top.x());
TEdge* ePrev = e->PrevInAEL;
DoMaxima(e);
if( !ePrev ) e = m_ActiveEdges;
@@ -2618,7 +2580,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
}
else
{
- //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ...
+ //2. promote horizontal edges, otherwise update Curr.x() and Curr.y() ...
if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML))
{
UpdateEdgeIntoAEL(e);
@@ -2628,8 +2590,8 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
}
else
{
- e->Curr.X = TopX( *e, topY );
- e->Curr.Y = topY;
+ e->Curr.x() = TopX( *e, topY );
+ e->Curr.y() = topY;
}
//When StrictlySimple and 'e' is being touched by another edge, then
@@ -2638,10 +2600,10 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
{
TEdge* ePrev = e->PrevInAEL;
if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
- (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0))
+ (ePrev->Curr.x() == e->Curr.x()) && (ePrev->WindDelta != 0))
{
IntPoint pt = e->Curr;
-#ifdef use_xyz
+#ifdef CLIPPERLIB_USE_XYZ
SetZ(pt, *ePrev, *e);
#endif
OutPt* op = AddOutPt(ePrev, pt);
@@ -2673,18 +2635,18 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
//if output polygons share an edge, they'll need joining later ...
TEdge* ePrev = e->PrevInAEL;
TEdge* eNext = e->NextInAEL;
- if (ePrev && ePrev->Curr.X == e->Bot.X &&
- ePrev->Curr.Y == e->Bot.Y && op &&
- ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y &&
+ if (ePrev && ePrev->Curr.x() == e->Bot.x() &&
+ ePrev->Curr.y() == e->Bot.y() && op &&
+ ePrev->OutIdx >= 0 && ePrev->Curr.y() > ePrev->Top.y() &&
SlopesEqual(*e, *ePrev, m_UseFullRange) &&
(e->WindDelta != 0) && (ePrev->WindDelta != 0))
{
OutPt* op2 = AddOutPt(ePrev, e->Bot);
m_Joins.emplace_back(Join(op, op2, e->Top));
}
- else if (eNext && eNext->Curr.X == e->Bot.X &&
- eNext->Curr.Y == e->Bot.Y && op &&
- eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y &&
+ else if (eNext && eNext->Curr.x() == e->Bot.x() &&
+ eNext->Curr.y() == e->Bot.y() && op &&
+ eNext->OutIdx >= 0 && eNext->Curr.y() > eNext->Top.y() &&
SlopesEqual(*e, *eNext, m_UseFullRange) &&
(e->WindDelta != 0) && (eNext->WindDelta != 0))
{
@@ -2861,13 +2823,13 @@ void Clipper::BuildResult2(PolyTree& polytree)
inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2)
{
- if (e2.Curr.X == e1.Curr.X)
+ if (e2.Curr.x() == e1.Curr.x())
{
- if (e2.Top.Y > e1.Top.Y)
- return e2.Top.X < TopX(e1, e2.Top.Y);
- else return e1.Top.X > TopX(e2, e1.Top.Y);
+ if (e2.Top.y() > e1.Top.y())
+ return e2.Top.x() < TopX(e1, e2.Top.y());
+ else return e1.Top.x() > TopX(e2, e1.Top.y());
}
- else return e2.Curr.X < e1.Curr.X;
+ else return e2.Curr.x() < e1.Curr.x();
}
//------------------------------------------------------------------------------
@@ -2956,8 +2918,8 @@ OutPt* Clipper::DupOutPt(OutPt* outPt, bool InsertAfter)
bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b,
const IntPoint &Pt, bool DiscardLeft)
{
- Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight);
- Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight);
+ Direction Dir1 = (op1->Pt.x() > op1b->Pt.x() ? dRightToLeft : dLeftToRight);
+ Direction Dir2 = (op2->Pt.x() > op2b->Pt.x() ? dRightToLeft : dLeftToRight);
if (Dir1 == Dir2) return false;
//When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we
@@ -2967,10 +2929,10 @@ bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b,
//otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.)
if (Dir1 == dLeftToRight)
{
- while (op1->Next->Pt.X <= Pt.X &&
- op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y)
+ while (op1->Next->Pt.x() <= Pt.x() &&
+ op1->Next->Pt.x() >= op1->Pt.x() && op1->Next->Pt.y() == Pt.y())
op1 = op1->Next;
- if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next;
+ if (DiscardLeft && (op1->Pt.x() != Pt.x())) op1 = op1->Next;
op1b = this->DupOutPt(op1, !DiscardLeft);
if (op1b->Pt != Pt)
{
@@ -2981,10 +2943,10 @@ bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b,
}
else
{
- while (op1->Next->Pt.X >= Pt.X &&
- op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y)
+ while (op1->Next->Pt.x() >= Pt.x() &&
+ op1->Next->Pt.x() <= op1->Pt.x() && op1->Next->Pt.y() == Pt.y())
op1 = op1->Next;
- if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next;
+ if (!DiscardLeft && (op1->Pt.x() != Pt.x())) op1 = op1->Next;
op1b = this->DupOutPt(op1, DiscardLeft);
if (op1b->Pt != Pt)
{
@@ -2996,10 +2958,10 @@ bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b,
if (Dir2 == dLeftToRight)
{
- while (op2->Next->Pt.X <= Pt.X &&
- op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y)
+ while (op2->Next->Pt.x() <= Pt.x() &&
+ op2->Next->Pt.x() >= op2->Pt.x() && op2->Next->Pt.y() == Pt.y())
op2 = op2->Next;
- if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next;
+ if (DiscardLeft && (op2->Pt.x() != Pt.x())) op2 = op2->Next;
op2b = this->DupOutPt(op2, !DiscardLeft);
if (op2b->Pt != Pt)
{
@@ -3009,10 +2971,10 @@ bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b,
};
} else
{
- while (op2->Next->Pt.X >= Pt.X &&
- op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y)
+ while (op2->Next->Pt.x() >= Pt.x() &&
+ op2->Next->Pt.x() <= op2->Pt.x() && op2->Next->Pt.y() == Pt.y())
op2 = op2->Next;
- if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next;
+ if (!DiscardLeft && (op2->Pt.x() != Pt.x())) op2 = op2->Next;
op2b = this->DupOutPt(op2, DiscardLeft);
if (op2b->Pt != Pt)
{
@@ -3052,7 +3014,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
//location at the Bottom of the overlapping segment (& Join.OffPt is above).
//3. StrictSimple joins where edges touch but are not collinear and where
//Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point.
- bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y);
+ bool isHorizontal = (j->OutPt1->Pt.y() == j->OffPt.y());
if (isHorizontal && (j->OffPt == j->OutPt1->Pt) &&
(j->OffPt == j->OutPt2->Pt))
@@ -3062,11 +3024,11 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
op1b = j->OutPt1->Next;
while (op1b != op1 && (op1b->Pt == j->OffPt))
op1b = op1b->Next;
- bool reverse1 = (op1b->Pt.Y > j->OffPt.Y);
+ bool reverse1 = (op1b->Pt.y() > j->OffPt.y());
op2b = j->OutPt2->Next;
while (op2b != op2 && (op2b->Pt == j->OffPt))
op2b = op2b->Next;
- bool reverse2 = (op2b->Pt.Y > j->OffPt.Y);
+ bool reverse2 = (op2b->Pt.y() > j->OffPt.y());
if (reverse1 == reverse2) return false;
if (reverse1)
{
@@ -3098,22 +3060,22 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
//them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt
//may be anywhere along the horizontal edge.
op1b = op1;
- while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2)
+ while (op1->Prev->Pt.y() == op1->Pt.y() && op1->Prev != op1b && op1->Prev != op2)
op1 = op1->Prev;
- while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2)
+ while (op1b->Next->Pt.y() == op1b->Pt.y() && op1b->Next != op1 && op1b->Next != op2)
op1b = op1b->Next;
if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon'
op2b = op2;
- while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b)
+ while (op2->Prev->Pt.y() == op2->Pt.y() && op2->Prev != op2b && op2->Prev != op1b)
op2 = op2->Prev;
- while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1)
+ while (op2b->Next->Pt.y() == op2b->Pt.y() && op2b->Next != op2 && op2b->Next != op1)
op2b = op2b->Next;
if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon'
cInt Left, Right;
//Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges
- if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right))
+ if (!GetOverlap(op1->Pt.x(), op1b->Pt.x(), op2->Pt.x(), op2b->Pt.x(), Left, Right))
return false;
//DiscardLeftSide: when overlapping edges are joined, a spike will created
@@ -3121,51 +3083,51 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
//on the discard Side as either may still be needed for other joins ...
IntPoint Pt;
bool DiscardLeftSide;
- if (op1->Pt.X >= Left && op1->Pt.X <= Right)
+ if (op1->Pt.x() >= Left && op1->Pt.x() <= Right)
{
- Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X);
+ Pt = op1->Pt; DiscardLeftSide = (op1->Pt.x() > op1b->Pt.x());
}
- else if (op2->Pt.X >= Left&& op2->Pt.X <= Right)
+ else if (op2->Pt.x() >= Left&& op2->Pt.x() <= Right)
{
- Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X);
+ Pt = op2->Pt; DiscardLeftSide = (op2->Pt.x() > op2b->Pt.x());
}
- else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right)
+ else if (op1b->Pt.x() >= Left && op1b->Pt.x() <= Right)
{
- Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X;
+ Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.x() > op1->Pt.x();
}
else
{
- Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X);
+ Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.x() > op2->Pt.x());
}
j->OutPt1 = op1; j->OutPt2 = op2;
return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide);
} else
{
//nb: For non-horizontal joins ...
- // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y
- // 2. Jr.OutPt1.Pt > Jr.OffPt.Y
+ // 1. Jr.OutPt1.Pt.y() == Jr.OutPt2.Pt.y()
+ // 2. Jr.OutPt1.Pt > Jr.OffPt.y()
//make sure the polygons are correctly oriented ...
op1b = op1->Next;
while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next;
- bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) ||
+ bool Reverse1 = ((op1b->Pt.y() > op1->Pt.y()) ||
!SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange));
if (Reverse1)
{
op1b = op1->Prev;
while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev;
- if ((op1b->Pt.Y > op1->Pt.Y) ||
+ if ((op1b->Pt.y() > op1->Pt.y()) ||
!SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false;
};
op2b = op2->Next;
while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next;
- bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) ||
+ bool Reverse2 = ((op2b->Pt.y() > op2->Pt.y()) ||
!SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange));
if (Reverse2)
{
op2b = op2->Prev;
while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev;
- if ((op2b->Pt.Y > op2->Pt.Y) ||
+ if ((op2b->Pt.y() > op2->Pt.y()) ||
!SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false;
}
@@ -3334,11 +3296,11 @@ void Clipper::JoinCommonEdges()
DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2)
{
- if(pt2.X == pt1.X && pt2.Y == pt1.Y)
+ if(pt2.x() == pt1.x() && pt2.y() == pt1.y())
return DoublePoint(0, 0);
- double Dx = double(pt2.X - pt1.X);
- double dy = double(pt2.Y - pt1.Y);
+ double Dx = double(pt2.x() - pt1.x());
+ double dy = double(pt2.y() - pt1.y());
double f = 1.0 / std::sqrt( Dx*Dx + dy*dy );
Dx *= f;
dy *= f;
@@ -3354,7 +3316,7 @@ void ClipperOffset::Clear()
for (int i = 0; i < m_polyNodes.ChildCount(); ++i)
delete m_polyNodes.Childs[i];
m_polyNodes.Childs.clear();
- m_lowest.X = -1;
+ m_lowest.x() = -1;
}
//------------------------------------------------------------------------------
@@ -3373,8 +3335,8 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
for (; highI > 0; -- highI) {
bool same = false;
if (has_shortest_edge_length) {
- double dx = double(path[highI].X - path[0].X);
- double dy = double(path[highI].Y - path[0].Y);
+ double dx = double(path[highI].x() - path[0].x());
+ double dy = double(path[highI].y() - path[0].y());
same = dx*dx + dy*dy < shortest_edge_length2;
} else
same = path[0] == path[highI];
@@ -3387,8 +3349,8 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
for (int i = 1; i <= highI; i++) {
bool same = false;
if (has_shortest_edge_length) {
- double dx = double(path[i].X - newNode->Contour[j].X);
- double dy = double(path[i].Y - newNode->Contour[j].Y);
+ double dx = double(path[i].x() - newNode->Contour[j].x());
+ double dy = double(path[i].y() - newNode->Contour[j].y());
same = dx*dx + dy*dy < shortest_edge_length2;
} else
same = newNode->Contour[j] == path[i];
@@ -3396,9 +3358,9 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
continue;
j++;
newNode->Contour.push_back(path[i]);
- if (path[i].Y > newNode->Contour[k].Y ||
- (path[i].Y == newNode->Contour[k].Y &&
- path[i].X < newNode->Contour[k].X)) k = j;
+ if (path[i].y() > newNode->Contour[k].y() ||
+ (path[i].y() == newNode->Contour[k].y() &&
+ path[i].x() < newNode->Contour[k].x())) k = j;
}
if (endType == etClosedPolygon && j < 2)
{
@@ -3409,32 +3371,25 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
//if this path's lowest pt is lower than all the others then update m_lowest
if (endType != etClosedPolygon) return;
- if (m_lowest.X < 0)
+ if (m_lowest.x() < 0)
m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k);
else
{
- IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y];
- if (newNode->Contour[k].Y > ip.Y ||
- (newNode->Contour[k].Y == ip.Y &&
- newNode->Contour[k].X < ip.X))
+ IntPoint ip = m_polyNodes.Childs[(int)m_lowest.x()]->Contour[(int)m_lowest.y()];
+ if (newNode->Contour[k].y() > ip.y() ||
+ (newNode->Contour[k].y() == ip.y() &&
+ newNode->Contour[k].x() < ip.x()))
m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k);
}
}
//------------------------------------------------------------------------------
-void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType)
-{
- for (const Path &path : paths)
- AddPath(path, joinType, endType);
-}
-//------------------------------------------------------------------------------
-
void ClipperOffset::FixOrientations()
{
//fixup orientations of all closed paths if the orientation of the
//closed path with the lowermost vertex is wrong ...
- if (m_lowest.X >= 0 &&
- !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour))
+ if (m_lowest.x() >= 0 &&
+ !Orientation(m_polyNodes.Childs[(int)m_lowest.x()]->Contour))
{
for (int i = 0; i < m_polyNodes.ChildCount(); ++i)
{
@@ -3582,8 +3537,8 @@ void ClipperOffset::DoOffset(double delta)
for (cInt j = 1; j <= steps; j++)
{
m_destPoly.push_back(IntPoint(
- Round(m_srcPoly[0].X + X * delta),
- Round(m_srcPoly[0].Y + Y * delta)));
+ Round(m_srcPoly[0].x() + X * delta),
+ Round(m_srcPoly[0].y() + Y * delta)));
double X2 = X;
X = X * m_cos - m_sin * Y;
Y = X2 * m_sin + Y * m_cos;
@@ -3595,8 +3550,8 @@ void ClipperOffset::DoOffset(double delta)
for (int j = 0; j < 4; ++j)
{
m_destPoly.push_back(IntPoint(
- Round(m_srcPoly[0].X + X * delta),
- Round(m_srcPoly[0].Y + Y * delta)));
+ Round(m_srcPoly[0].x() + X * delta),
+ Round(m_srcPoly[0].y() + Y * delta)));
if (X < 0) X = 1;
else if (Y < 0) Y = 1;
else X = -1;
@@ -3632,8 +3587,8 @@ void ClipperOffset::DoOffset(double delta)
//re-build m_normals ...
DoublePoint n = m_normals[len -1];
for (int j = len - 1; j > 0; j--)
- m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y);
- m_normals[0] = DoublePoint(-n.X, -n.Y);
+ m_normals[j] = DoublePoint(-m_normals[j - 1].x(), -m_normals[j - 1].y());
+ m_normals[0] = DoublePoint(-n.x(), -n.y());
k = 0;
for (int j = len - 1; j >= 0; j--)
OffsetPoint(j, k, node.m_jointype);
@@ -3649,9 +3604,9 @@ void ClipperOffset::DoOffset(double delta)
if (node.m_endtype == etOpenButt)
{
int j = len - 1;
- pt1 = IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * delta), Round(m_srcPoly[j].Y + m_normals[j].Y * delta));
+ pt1 = IntPoint(Round(m_srcPoly[j].x() + m_normals[j].x() * delta), Round(m_srcPoly[j].y() + m_normals[j].y() * delta));
m_destPoly.push_back(pt1);
- pt1 = IntPoint(Round(m_srcPoly[j].X - m_normals[j].X * delta), Round(m_srcPoly[j].Y - m_normals[j].Y * delta));
+ pt1 = IntPoint(Round(m_srcPoly[j].x() - m_normals[j].x() * delta), Round(m_srcPoly[j].y() - m_normals[j].y() * delta));
m_destPoly.push_back(pt1);
}
else
@@ -3659,7 +3614,7 @@ void ClipperOffset::DoOffset(double delta)
int j = len - 1;
k = len - 2;
m_sinA = 0;
- m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y);
+ m_normals[j] = DoublePoint(-m_normals[j].x(), -m_normals[j].y());
if (node.m_endtype == etOpenSquare)
DoSquare(j, k);
else
@@ -3668,17 +3623,17 @@ void ClipperOffset::DoOffset(double delta)
//re-build m_normals ...
for (int j = len - 1; j > 0; j--)
- m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y);
- m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y);
+ m_normals[j] = DoublePoint(-m_normals[j - 1].x(), -m_normals[j - 1].y());
+ m_normals[0] = DoublePoint(-m_normals[1].x(), -m_normals[1].y());
k = len - 1;
for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype);
if (node.m_endtype == etOpenButt)
{
- pt1 = IntPoint(Round(m_srcPoly[0].X - m_normals[0].X * delta), Round(m_srcPoly[0].Y - m_normals[0].Y * delta));
+ pt1 = IntPoint(Round(m_srcPoly[0].x() - m_normals[0].x() * delta), Round(m_srcPoly[0].y() - m_normals[0].y() * delta));
m_destPoly.push_back(pt1);
- pt1 = IntPoint(Round(m_srcPoly[0].X + m_normals[0].X * delta), Round(m_srcPoly[0].Y + m_normals[0].Y * delta));
+ pt1 = IntPoint(Round(m_srcPoly[0].x() + m_normals[0].x() * delta), Round(m_srcPoly[0].y() + m_normals[0].y() * delta));
m_destPoly.push_back(pt1);
}
else
@@ -3699,15 +3654,15 @@ void ClipperOffset::DoOffset(double delta)
void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
{
//cross product ...
- m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y);
+ m_sinA = (m_normals[k].x() * m_normals[j].y() - m_normals[j].x() * m_normals[k].y());
if (std::fabs(m_sinA * m_delta) < 1.0)
{
//dot product ...
- double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y );
+ double cosA = (m_normals[k].x() * m_normals[j].x() + m_normals[j].y() * m_normals[k].y() );
if (cosA > 0) // angle => 0 degrees
{
- m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta),
- Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta)));
+ m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
+ Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
return;
}
//else angle => 180 degrees
@@ -3717,19 +3672,19 @@ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
if (m_sinA * m_delta < 0)
{
- m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta),
- Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta)));
+ m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
+ Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
m_destPoly.push_back(m_srcPoly[j]);
- m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta),
- Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta)));
+ m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
+ Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
}
else
switch (jointype)
{
case jtMiter:
{
- double r = 1 + (m_normals[j].X * m_normals[k].X +
- m_normals[j].Y * m_normals[k].Y);
+ double r = 1 + (m_normals[j].x() * m_normals[k].x() +
+ m_normals[j].y() * m_normals[k].y());
if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k);
break;
}
@@ -3743,43 +3698,43 @@ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
void ClipperOffset::DoSquare(int j, int k)
{
double dx = std::tan(std::atan2(m_sinA,
- m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4);
+ m_normals[k].x() * m_normals[j].x() + m_normals[k].y() * m_normals[j].y()) / 4);
m_destPoly.push_back(IntPoint(
- Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)),
- Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx))));
+ Round(m_srcPoly[j].x() + m_delta * (m_normals[k].x() - m_normals[k].y() * dx)),
+ Round(m_srcPoly[j].y() + m_delta * (m_normals[k].y() + m_normals[k].x() * dx))));
m_destPoly.push_back(IntPoint(
- Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)),
- Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx))));
+ Round(m_srcPoly[j].x() + m_delta * (m_normals[j].x() + m_normals[j].y() * dx)),
+ Round(m_srcPoly[j].y() + m_delta * (m_normals[j].y() - m_normals[j].x() * dx))));
}
//------------------------------------------------------------------------------
void ClipperOffset::DoMiter(int j, int k, double r)
{
double q = m_delta / r;
- m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q),
- Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q)));
+ m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].x() + (m_normals[k].x() + m_normals[j].x()) * q),
+ Round(m_srcPoly[j].y() + (m_normals[k].y() + m_normals[j].y()) * q)));
}
//------------------------------------------------------------------------------
void ClipperOffset::DoRound(int j, int k)
{
double a = std::atan2(m_sinA,
- m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y);
+ m_normals[k].x() * m_normals[j].x() + m_normals[k].y() * m_normals[j].y());
auto steps = std::max(Round(m_StepsPerRad * std::fabs(a)), 1);
- double X = m_normals[k].X, Y = m_normals[k].Y, X2;
+ double X = m_normals[k].x(), Y = m_normals[k].y(), X2;
for (int i = 0; i < steps; ++i)
{
m_destPoly.push_back(IntPoint(
- Round(m_srcPoly[j].X + X * m_delta),
- Round(m_srcPoly[j].Y + Y * m_delta)));
+ Round(m_srcPoly[j].x() + X * m_delta),
+ Round(m_srcPoly[j].y() + Y * m_delta)));
X2 = X;
X = X * m_cos - m_sin * Y;
Y = X2 * m_sin + Y * m_cos;
}
m_destPoly.push_back(IntPoint(
- Round(m_srcPoly[j].X + m_normals[j].X * m_delta),
- Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta)));
+ Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
+ Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
}
//------------------------------------------------------------------------------
@@ -3871,34 +3826,22 @@ void ReversePaths(Paths& p)
}
//------------------------------------------------------------------------------
-void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType)
+Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType)
{
Clipper c;
c.StrictlySimple(true);
c.AddPath(in_poly, ptSubject, true);
- c.Execute(ctUnion, out_polys, fillType, fillType);
+ Paths out;
+ c.Execute(ctUnion, out, fillType, fillType);
+ return out;
}
-//------------------------------------------------------------------------------
-void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType)
-{
- Clipper c;
- c.StrictlySimple(true);
- c.AddPaths(in_polys, ptSubject, true);
- c.Execute(ctUnion, out_polys, fillType, fillType);
-}
-//------------------------------------------------------------------------------
-
-void SimplifyPolygons(Paths &polys, PolyFillType fillType)
-{
- SimplifyPolygons(polys, polys, fillType);
-}
//------------------------------------------------------------------------------
inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2)
{
- auto Dx = double(pt1.X - pt2.X);
- auto dy = double(pt1.Y - pt2.Y);
+ auto Dx = double(pt1.x() - pt2.x());
+ auto dy = double(pt1.y() - pt2.y());
return (Dx*Dx + dy*dy);
}
//------------------------------------------------------------------------------
@@ -3912,10 +3855,10 @@ double DistanceFromLineSqrd(
//A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
//perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
//see http://en.wikipedia.org/wiki/Perpendicular_distance
- double A = double(ln1.Y - ln2.Y);
- double B = double(ln2.X - ln1.X);
- double C = A * ln1.X + B * ln1.Y;
- C = A * pt.X + B * pt.Y - C;
+ double A = double(ln1.y() - ln2.y());
+ double B = double(ln2.x() - ln1.x());
+ double C = A * ln1.x() + B * ln1.y();
+ C = A * pt.x() + B * pt.y() - C;
return (C * C) / (A * A + B * B);
}
//---------------------------------------------------------------------------
@@ -3926,20 +3869,20 @@ bool SlopesNearCollinear(const IntPoint& pt1,
//this function is more accurate when the point that's geometrically
//between the other 2 points is the one that's tested for distance.
//ie makes it more likely to pick up 'spikes' ...
- if (std::abs(pt1.X - pt2.X) > std::abs(pt1.Y - pt2.Y))
+ if (std::abs(pt1.x() - pt2.x()) > std::abs(pt1.y() - pt2.y()))
{
- if ((pt1.X > pt2.X) == (pt1.X < pt3.X))
+ if ((pt1.x() > pt2.x()) == (pt1.x() < pt3.x()))
return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
- else if ((pt2.X > pt1.X) == (pt2.X < pt3.X))
+ else if ((pt2.x() > pt1.x()) == (pt2.x() < pt3.x()))
return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
else
return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
}
else
{
- if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y))
+ if ((pt1.y() > pt2.y()) == (pt1.y() < pt3.y()))
return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
- else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y))
+ else if ((pt2.y() > pt1.y()) == (pt2.y() < pt3.y()))
return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
else
return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
@@ -3949,8 +3892,8 @@ bool SlopesNearCollinear(const IntPoint& pt1,
bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd)
{
- auto Dx = double(pt1.X - pt2.X);
- auto dy = double(pt1.Y - pt2.Y);
+ auto Dx = double(pt1.x() - pt2.x());
+ auto dy = double(pt1.y() - pt2.y());
return ((Dx * Dx) + (dy * dy) <= distSqrd);
}
//------------------------------------------------------------------------------
@@ -4058,7 +4001,7 @@ void Minkowski(const Path& poly, const Path& path,
Path p;
p.reserve(polyCnt);
for (size_t j = 0; j < poly.size(); ++j)
- p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y));
+ p.push_back(IntPoint(path[i].x() + poly[j].x(), path[i].y() + poly[j].y()));
pp.push_back(p);
}
else
@@ -4067,7 +4010,7 @@ void Minkowski(const Path& poly, const Path& path,
Path p;
p.reserve(polyCnt);
for (size_t j = 0; j < poly.size(); ++j)
- p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y));
+ p.push_back(IntPoint(path[i].x() - poly[j].x(), path[i].y() - poly[j].y()));
pp.push_back(p);
}
@@ -4102,7 +4045,7 @@ void TranslatePath(const Path& input, Path& output, const IntPoint& delta)
//precondition: input != output
output.resize(input.size());
for (size_t i = 0; i < input.size(); ++i)
- output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y);
+ output[i] = IntPoint(input[i].x() + delta.x(), input[i].y() + delta.y());
}
//------------------------------------------------------------------------------
@@ -4178,7 +4121,7 @@ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths)
std::ostream& operator <<(std::ostream &s, const IntPoint &p)
{
- s << "(" << p.X << "," << p.Y << ")";
+ s << "(" << p.x() << "," << p.y() << ")";
return s;
}
//------------------------------------------------------------------------------
@@ -4188,8 +4131,8 @@ std::ostream& operator <<(std::ostream &s, const Path &p)
if (p.empty()) return s;
Path::size_type last = p.size() -1;
for (Path::size_type i = 0; i < last; i++)
- s << "(" << p[i].X << "," << p[i].Y << "), ";
- s << "(" << p[last].X << "," << p[last].Y << ")\n";
+ s << "(" << p[i].x() << "," << p[i].y() << "), ";
+ s << "(" << p[last].x() << "," << p[last].y() << ")\n";
return s;
}
//------------------------------------------------------------------------------
@@ -4204,3 +4147,7 @@ std::ostream& operator <<(std::ostream &s, const Paths &p)
//------------------------------------------------------------------------------
} //ClipperLib namespace
+
+#ifdef CLIPPERLIB_NAMESPACE_PREFIX
+} // namespace CLIPPERLIB_NAMESPACE_PREFIX
+#endif // CLIPPERLIB_NAMESPACE_PREFIX
diff --git a/src/clipper/clipper.hpp b/src/clipper/clipper.hpp
index 48e83d046..74e6601f9 100644
--- a/src/clipper/clipper.hpp
+++ b/src/clipper/clipper.hpp
@@ -37,10 +37,12 @@
#include
#include
+#include
+
#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
#include
-#ifdef use_xyz
-namespace ClipperLib_Z {
-#else /* use_xyz */
-namespace ClipperLib {
-#endif /* use_xyz */
+#ifdef CLIPPERLIB_NAMESPACE_PREFIX
+ namespace CLIPPERLIB_NAMESPACE_PREFIX {
+#endif // CLIPPERLIB_NAMESPACE_PREFIX
+
+#ifdef CLIPPERLIB_USE_XYZ
+ namespace ClipperLib_Z {
+#else
+ namespace ClipperLib {
+#endif
enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
enum PolyType { ptSubject, ptClip };
@@ -88,29 +94,24 @@ enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
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;
+#endif // CLIPPERLIB_INTPOINT_TYPE
+
+using DoublePoint = Eigen::Matrix;
- 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;
-typedef std::vector< Path > Paths;
+typedef std::vector Path;
+typedef std::vector Paths;
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
@@ -119,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 ZFillCallback;
#endif
@@ -197,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);
@@ -269,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;
@@ -306,7 +298,58 @@ public:
m_HasOpenPaths(false) {}
~ClipperBase() { Clear(); }
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
- bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
+
+ template
+ 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 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 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.
@@ -368,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:
@@ -401,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;
@@ -454,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
};
@@ -467,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
+ 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();
@@ -504,8 +551,20 @@ class clipperException : public std::exception
};
//------------------------------------------------------------------------------
+template
+inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftEvenOdd) {
+ Clipper c;
+ c.StrictlySimple(true);
+ c.AddPaths(std::forward(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
-
-
diff --git a/src/clipper/clipper_z.cpp b/src/clipper/clipper_z.cpp
index 4a54ef346..f26be7089 100644
--- a/src/clipper/clipper_z.cpp
+++ b/src/clipper/clipper_z.cpp
@@ -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"
diff --git a/src/clipper/clipper_z.hpp b/src/clipper/clipper_z.hpp
index e5e7d48ce..20596d8e1 100644
--- a/src/clipper/clipper_z.hpp
+++ b/src/clipper/clipper_z.hpp
@@ -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
diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt
index 3892ed30b..c18dc31cb 100644
--- a/src/libnest2d/CMakeLists.txt
+++ b/src/libnest2d/CMakeLists.txt
@@ -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)
diff --git a/src/libnest2d/include/libnest2d/backends/clipper/clipper_polygon.hpp b/src/libnest2d/include/libnest2d/backends/clipper/clipper_polygon.hpp
deleted file mode 100644
index 6511fbb72..000000000
--- a/src/libnest2d/include/libnest2d/backends/clipper/clipper_polygon.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef CLIPPER_POLYGON_HPP
-#define CLIPPER_POLYGON_HPP
-
-#include
-
-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
diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp
deleted file mode 100644
index 9586db35c..000000000
--- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp
+++ /dev/null
@@ -1,356 +0,0 @@
-#ifndef CLIPPER_BACKEND_HPP
-#define CLIPPER_BACKEND_HPP
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#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 { using Type = PolygonTag; };
-template<> struct ShapeTag { using Type = PathTag; };
-template<> struct ShapeTag { 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 {
- 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 { using Type = PointImpl; };
-
-// This is crucial. CountourType refers to itself by default, so we don't have
-// to secialize for clipper Path. ContourType::Type is PathImpl.
-template<> struct ContourType { using Type = PathImpl; };
-
-// The holes are contained in Clipper::Paths
-template<> struct HolesContainer { 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 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(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 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& holes(const PolygonImpl& sh)
-{
- return sh.Holes;
-}
-
-template<> inline THolesContainer& holes(PolygonImpl& sh)
-{
- return sh.Holes;
-}
-
-template<>
-inline TContour& hole(PolygonImpl& sh, unsigned long idx)
-{
- return sh.Holes[idx];
-}
-
-template<>
-inline const TContour& 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;
-
- auto cosa = rads.cos();
- auto sina = rads.sin();
-
- for(auto& p : sh.Contour) {
- p = {
- static_cast(p.X * cosa - p.Y * sina),
- static_cast(p.X * sina + p.Y * cosa)
- };
- }
- for(auto& hole : sh.Holes) for(auto& p : hole) {
- p = {
- static_cast(p.X * cosa - p.Y * sina),
- static_cast(p.X * sina + p.Y * cosa)
- };
- }
-}
-
-} // namespace shapelike
-
-#define DISABLE_BOOST_NFP_MERGE
-inline TMultiShape clipper_execute(
- ClipperLib::Clipper& clipper,
- ClipperLib::ClipType clipType,
- ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd,
- ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd)
-{
- TMultiShape retv;
-
- ClipperLib::PolyTree result;
- clipper.Execute(clipType, result, subjFillType, clipFillType);
-
- retv.reserve(static_cast(result.Total()));
-
- std::function 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
-merge(const TMultiShape& 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
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#endif // CLIPPER_BACKEND_HPP
diff --git a/src/libnest2d/include/libnest2d/backends/libslic3r/geometries.hpp b/src/libnest2d/include/libnest2d/backends/libslic3r/geometries.hpp
new file mode 100644
index 000000000..14b075b19
--- /dev/null
+++ b/src/libnest2d/include/libnest2d/backends/libslic3r/geometries.hpp
@@ -0,0 +1,283 @@
+#ifndef CLIPPER_BACKEND_HPP
+#define CLIPPER_BACKEND_HPP
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+namespace Slic3r {
+
+template struct IsVec_ : public std::false_type {};
+
+template struct IsVec_< Vec<2, T> >: public std::true_type {};
+
+template
+static constexpr const bool IsVec = IsVec_>::value;
+
+template using VecOnly = std::enable_if_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 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 { using Type = PointTag; };
+template<> struct ShapeTag { using Type = PointTag; };
+
+template<> struct ShapeTag> { using Type = PathTag; };
+template<> struct ShapeTag { using Type = PathTag; };
+template<> struct ShapeTag { using Type = PathTag; };
+template<> struct ShapeTag { using Type = PolygonTag; };
+template<> struct ShapeTag { 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 {
+ using Type = coord_t;
+ static const constexpr coord_t MM_IN_COORDS = 1000000;
+};
+
+template<> struct CoordType {
+ 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> { using Type = Slic3r::Vec2crd; };
+template<> struct PointType { using Type = Slic3r::Point; };
+template<> struct PointType { using Type = Slic3r::Point; };
+
+// This is crucial. CountourType refers to itself by default, so we don't have
+// to secialize for clipper Path. ContourType::Type is PathImpl.
+template<> struct ContourType { using Type = Slic3r::Polygon; };
+
+// The holes are contained in Clipper::Paths
+template<> struct HolesContainer { using Type = Slic3r::Polygons; };
+
+template<>
+struct OrientationType {
+ static const constexpr Orientation Value = Orientation::COUNTER_CLOCKWISE;
+};
+
+template<>
+struct OrientationType {
+ static const constexpr Orientation Value = Orientation::COUNTER_CLOCKWISE;
+};
+
+template<>
+struct ClosureType {
+ static const constexpr Closure Value = Closure::OPEN;
+};
+
+template<>
+struct ClosureType {
+ static const constexpr Closure Value = Closure::OPEN;
+};
+
+template<> struct MultiShape { using Type = Slic3r::ExPolygons; };
+template<> struct ContourType { 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& holes(const Slic3r::ExPolygon& sh)
+{
+ return sh.holes;
+}
+
+template<> inline THolesContainer& 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 merge(const TMultiShape& 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
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // CLIPPER_BACKEND_HPP
diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp
index 3095c717d..7ea437339 100644
--- a/src/libnest2d/include/libnest2d/geometry_traits.hpp
+++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp
@@ -128,22 +128,32 @@ template struct ContourType> {
using Type = typename ContourType::Type;
};
-enum class Orientation {
- CLOCKWISE,
- COUNTER_CLOCKWISE
-};
+enum class Orientation { CLOCKWISE, COUNTER_CLOCKWISE };
template
struct OrientationType {
// Default Polygon orientation that the library expects
- static const Orientation Value = Orientation::CLOCKWISE;
+ static const constexpr Orientation Value = Orientation::CLOCKWISE;
};
-template inline /*constexpr*/ bool is_clockwise() {
+template inline constexpr bool is_clockwise() {
return OrientationType>::Value == Orientation::CLOCKWISE;
}
+template
+inline const constexpr Orientation OrientationTypeV =
+ OrientationType>::Value;
+
+enum class Closure { OPEN, CLOSED };
+
+template struct ClosureType {
+ static const constexpr Closure Value = Closure::CLOSED;
+};
+
+template
+inline const constexpr Closure ClosureTypeV =
+ ClosureType>::Value;
/**
* \brief A point pair base class for other point pairs (segment, box, ...).
@@ -587,9 +597,9 @@ inline void reserve(RawPath& p, size_t vertex_capacity, const PathTag&)
}
template
-inline void addVertex(S& sh, const PathTag&, Args...args)
+inline void addVertex(S& sh, const PathTag&, const TPoint &p)
{
- sh.emplace_back(std::forward(args)...);
+ sh.emplace_back(p);
}
template
@@ -841,9 +851,9 @@ template auto rbegin(P& p) -> decltype(_backward(end(p)))
return _backward(end(p));
}
-template auto rcbegin(const P& p) -> decltype(_backward(end(p)))
+template auto rcbegin(const P& p) -> decltype(_backward(cend(p)))
{
- return _backward(end(p));
+ return _backward(cend(p));
}
template 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());
}
-template
-inline void addVertex(S& sh, const PolygonTag&, Args...args)
+template
+inline void addVertex(S& sh, const PolygonTag&, const TPoint &p)
{
- addVertex(contour(sh), PathTag(), std::forward(args)...);
+ addVertex(contour(sh), PathTag(), p);
}
-template // Tag dispatcher
-inline void addVertex(S& sh, Args...args)
+template // Tag dispatcher
+inline void addVertex(S& sh, const TPoint &p)
{
- addVertex(sh, Tag(), std::forward(args)...);
+ addVertex(sh, Tag(), p);
}
template
diff --git a/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp
index 6b3ff60c1..d9f947802 100644
--- a/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp
+++ b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp
@@ -28,7 +28,7 @@ inline void buildPolygon(const EdgeList& edgelist,
auto& rsh = sl::contour(rpoly);
- sl::reserve(rsh, 2*edgelist.size());
+ sl::reserve(rsh, 2 * edgelist.size());
// Add the two vertices from the first edge into the final polygon.
sl::addVertex(rsh, edgelist.front().first());
@@ -57,7 +57,6 @@ inline void buildPolygon(const EdgeList& edgelist,
tmp = std::next(tmp);
}
-
}
template
@@ -214,17 +213,24 @@ inline NfpResult nfpConvexOnly(const RawShape& sh,
// Reserve the needed memory
edgelist.reserve(cap);
sl::reserve(rsh, static_cast(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)) {
- if (pl::magnsq(*next - *first) > 0)
- edgelist.emplace_back(*(first), *(next));
+ add_edge(*(first), *(next));
++first; ++next;
}
+
+ if constexpr (ClosureTypeV == Closure::OPEN)
+ add_edge(*sl::rcbegin(sh), *sl::cbegin(sh));
}
{ // place all edges from other into edgelist
@@ -232,17 +238,19 @@ inline NfpResult nfpConvexOnly(const RawShape& sh,
auto next = std::next(first);
while(next != sl::cend(other)) {
- if (pl::magnsq(*next - *first) > 0)
- edgelist.emplace_back(*(next), *(first));
+ add_edge(*(next), *(first));
++first; ++next;
}
+
+ if constexpr (ClosureTypeV == Closure::OPEN)
+ add_edge(*sl::cbegin(other), *sl::rcbegin(other));
}
- std::sort(edgelist.begin(), edgelist.end(),
- [](const Edge& e1, const Edge& e2)
+ 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();
@@ -288,12 +296,18 @@ inline NfpResult nfpConvexOnly(const RawShape& sh,
// If Ratio is an actual rational type, there is no precision loss
auto pcos1 = Ratio(lcos[0]) / lsq1 * sign * lcos[0];
auto pcos2 = Ratio(lcos[1]) / lsq2 * sign * lcos[1];
-
- return q[0] < 2 ? pcos1 < pcos2 : pcos1 > pcos2;
+
+ if constexpr (is_clockwise())
+ 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.
- return q[0] > q[1];
+ if constexpr (is_clockwise())
+ return q[0] > q[1];
+ else
+ return q[0] < q[1];
});
__nfp::buildPolygon(edgelist, rsh, top_nfp);
diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp
index 9d24a2569..a4cf7dc56 100644
--- a/src/libnest2d/include/libnest2d/libnest2d.hpp
+++ b/src/libnest2d/include/libnest2d/libnest2d.hpp
@@ -7,6 +7,10 @@
#include
#endif
+#ifdef LIBNEST2D_GEOMETRIES_libslic3r
+#include
+#endif
+
#ifdef LIBNEST2D_OPTIMIZER_nlopt
// We include the stock optimizers for local and global optimization
#include // Local subplex for NfpPlacer
diff --git a/src/libnest2d/include/libnest2d/nester.hpp b/src/libnest2d/include/libnest2d/nester.hpp
index 20da9b9a1..52c738a4c 100644
--- a/src/libnest2d/include/libnest2d/nester.hpp
+++ b/src/libnest2d/include/libnest2d/nester.hpp
@@ -96,7 +96,7 @@ public:
* @return The orientation type identifier for the _Item type.
*/
static BP2D_CONSTEXPR Orientation orientation() {
- return OrientationType::Value;
+ return OrientationType>::Value;
}
/**
@@ -446,44 +446,32 @@ private:
}
};
+template Sh create_rect(TCoord width, TCoord height)
+{
+ auto sh = sl::create(
+ {{0, 0}, {0, height}, {width, height}, {width, 0}});
+
+ if constexpr (ClosureTypeV == Closure::CLOSED)
+ sl::addVertex(sh, {0, 0});
+
+ if constexpr (OrientationTypeV == Orientation::COUNTER_CLOCKWISE)
+ std::reverse(sl::begin(sh), sl::end(sh));
+
+ return sh;
+}
+
/**
* \brief Subclass of _Item for regular rectangle items.
*/
-template
-class _Rectangle: public _Item {
- using _Item::vertex;
+template
+class _Rectangle: public _Item {
+ using _Item::vertex;
using TO = Orientation;
public:
- using Unit = TCoord>;
+ using Unit = TCoord;
- template::Value>
- inline _Rectangle(Unit width, Unit height,
- // disable this ctor if o != CLOCKWISE
- enable_if_t< o == TO::CLOCKWISE, int> = 0 ):
- _Item( sl::create( {
- {0, 0},
- {0, height},
- {width, height},
- {width, 0},
- {0, 0}
- } ))
- {
- }
-
- template::Value>
- inline _Rectangle(Unit width, Unit height,
- // disable this ctor if o != COUNTER_CLOCKWISE
- enable_if_t< o == TO::COUNTER_CLOCKWISE, int> = 0 ):
- _Item( sl::create( {
- {0, 0},
- {width, 0},
- {width, height},
- {0, height},
- {0, 0}
- } ))
- {
- }
+ inline _Rectangle(Unit w, Unit h): _Item{create_rect(w, h)} {}
inline Unit width() const BP2D_NOEXCEPT {
return getX(vertex(2));
diff --git a/src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp b/src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp
index e1a4ffbd9..a067194dc 100644
--- a/src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp
+++ b/src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp
@@ -365,44 +365,50 @@ 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(i)));
+ sl::addVertex(rsh, item.vertex(static_cast(i)));
+ };
+
+ auto addOthers = [&addOthers_, &reverseAddOthers_]() {
+ if constexpr (!is_clockwise())
+ addOthers_();
+ else
+ reverseAddOthers_();
};
// Final polygon construction...
- static_assert(OrientationType::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
- sl::addVertex(rsh, topleft_vertex);
+ if constexpr (ClosureTypeV == Closure::CLOSED)
+ sl::addVertex(rsh, topleft_vertex);
+
+ if constexpr (!is_clockwise())
+ std::reverse(rsh.begin(), rsh.end());
return ret;
}
diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp
index bd9c60355..47ba7bbdc 100644
--- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp
+++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp
@@ -250,8 +250,8 @@ template class EdgeCache {
Vertex ret = edge.first();
// Get the point on the edge which lies in ed distance from the start
- ret += { static_cast(std::round(ed*std::cos(angle))),
- static_cast(std::round(ed*std::sin(angle))) };
+ ret += Vertex(static_cast(std::round(ed*std::cos(angle))),
+ static_cast(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;
diff --git a/src/libnest2d/include/libnest2d/utils/boost_alg.hpp b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp
index 16dee513b..d6213d0ed 100644
--- a/src/libnest2d/include/libnest2d/utils/boost_alg.hpp
+++ b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp
@@ -19,7 +19,7 @@
#pragma warning(pop)
#endif
// this should be removed to not confuse the compiler
-// #include
+// #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 {
static const order_selector Value = counterclockwise;
};
-static const bp2d::Orientation RealOrientation =
- bp2d::OrientationType::Value;
+template struct ToBoostClosure {};
+
+template<> struct ToBoostClosure {
+ static const constexpr closure_selector Value = closure_selector::open;
+};
+
+template<> struct ToBoostClosure {
+ static const constexpr closure_selector Value = closure_selector::closed;
+};
// Ring implementation /////////////////////////////////////////////////////////
@@ -225,12 +236,13 @@ template<> struct tag {
template<> struct point_order {
static const order_selector value =
- ToBoostOrienation::Value;
+ ToBoostOrienation>::Value;
};
// All our Paths should be closed for the bin packing application
template<> struct closure {
- static const closure_selector value = closed;
+ static const constexpr closure_selector value =
+ ToBoostClosure< bp2d::ClosureTypeV >::Value;
};
// Polygon implementation //////////////////////////////////////////////////////
diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp
index 3800d49e3..61a32678b 100644
--- a/src/libslic3r/Arrange.cpp
+++ b/src/libslic3r/Arrange.cpp
@@ -3,7 +3,7 @@
#include "BoundingBox.hpp"
-#include
+#include
#include
#include
#include
@@ -54,23 +54,22 @@ namespace Slic3r {
template, int...EigenArgs>
inline constexpr Eigen::Matrix unscaled(
- const ClipperLib::IntPoint &v) noexcept
+ const Slic3r::ClipperLib::IntPoint &v) noexcept
{
- return Eigen::Matrix{unscaled(v.X),
- unscaled(v.Y)};
+ return Eigen::Matrix{unscaled(v.x()),
+ unscaled(v.y())};
}
namespace arrangement {
using namespace libnest2d;
-namespace clppr = ClipperLib;
// Get the libnest2d types for clipper backend
-using Item = _Item;
-using Box = _Box;
-using Circle = _Circle;
-using Segment = _Segment;
-using MultiPolygon = TMultiShape;
+using Item = _Item;
+using Box = _Box;
+using Circle = _Circle;
+using Segment = _Segment;
+using MultiPolygon = ExPolygons;
// Summon the spatial indexing facilities from boost
namespace bgi = boost::geometry::index;
@@ -127,8 +126,8 @@ template
class AutoArranger {
public:
// Useful type shortcuts...
- using Placer = typename placers::_NofitPolyPlacer;
- using Selector = selections::_FirstFitSelection;
+ using Placer = typename placers::_NofitPolyPlacer;
+ using Selector = selections::_FirstFitSelection;
using Packer = _Nester;
using PConfig = typename Packer::PlacementConfig;
using Distance = TCoord;
@@ -168,7 +167,7 @@ protected:
// as it possibly can be but at the same time, it has to provide
// reasonable results.
std::tuple
- 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 AutoArranger::get_objfn()
// Specialization for a generalized polygon.
// Warning: this is unfinished business. It may or may not work.
template<>
-std::function AutoArranger::get_objfn()
+std::function AutoArranger::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(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- 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();
}
diff --git a/src/libslic3r/BridgeDetector.cpp b/src/libslic3r/BridgeDetector.cpp
index 671ebbdaa..03d671db4 100644
--- a/src/libslic3r/BridgeDetector.cpp
+++ b/src/libslic3r/BridgeDetector.cpp
@@ -58,7 +58,7 @@ void BridgeDetector::initialize()
// detect anchors as intersection between our bridge expolygon and the lower slices
// safety offset required to avoid Clipper from detecting empty intersection while Boost actually found some edges
- this->_anchor_regions = intersection_ex(grown, to_polygons(this->lower_slices), true);
+ this->_anchor_regions = intersection_ex(grown, union_safety_offset(this->lower_slices));
/*
if (0) {
@@ -227,29 +227,33 @@ void ExPolygon::get_trapezoids(ExPolygon clone, Polygons* polygons, double angle
// This algorithm may return more trapezoids than necessary
// (i.e. it may break a single trapezoid in several because
// other parts of the object have x coordinates in the middle)
-static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons)
+static void get_trapezoids2(const ExPolygon& expoly, Polygons* polygons)
{
Polygons src_polygons = to_polygons(expoly);
// get all points of this ExPolygon
- const Points pp = to_points(src_polygons);
-
+ const Points pp = to_points(src_polygons);
+
// build our bounding box
BoundingBox bb(pp);
-
+
// get all x coordinates
std::vector xx;
xx.reserve(pp.size());
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p)
xx.push_back(p->x());
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::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;
diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp
index 08bedc5c0..68851e051 100644
--- a/src/libslic3r/Brim.cpp
+++ b/src/libslic3r/Brim.cpp
@@ -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 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(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());
diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt
index 2abe94656..0cf67597a 100644
--- a/src/libslic3r/CMakeLists.txt
+++ b/src/libslic3r/CMakeLists.txt
@@ -23,6 +23,8 @@ add_library(libslic3r STATIC
BridgeDetector.hpp
Brim.cpp
Brim.hpp
+ clipper.cpp
+ clipper.hpp
ClipperUtils.cpp
ClipperUtils.hpp
Config.cpp
@@ -161,6 +163,7 @@ add_library(libslic3r STATIC
AppConfig.hpp
Print.cpp
Print.hpp
+ PrintApply.cpp
PrintBase.cpp
PrintBase.hpp
PrintConfig.cpp
diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp
index cd243dfb1..724224604 100644
--- a/src/libslic3r/ClipperUtils.cpp
+++ b/src/libslic3r/ClipperUtils.cpp
@@ -24,7 +24,6 @@
namespace Slic3r {
#ifdef CLIPPER_UTILS_DEBUG
-bool clipper_export_enabled = false;
// For debugging the Clipper library, for providing bug reports to the Clipper author.
bool export_clipper_input_polygons_bin(const char *path, const ClipperLib::Paths &input_subject, const ClipperLib::Paths &input_clip)
{
@@ -57,425 +56,284 @@ err:
}
#endif /* CLIPPER_UTILS_DEBUG */
-#ifdef CLIPPERUTILS_OFFSET_SCALE
-void scaleClipperPolygon(ClipperLib::Path &polygon)
-{
- CLIPPERUTILS_PROFILE_FUNC();
- for (ClipperLib::Path::iterator pit = polygon.begin(); pit != polygon.end(); ++pit) {
- pit->X <<= CLIPPER_OFFSET_POWER_OF_2;
- pit->Y <<= CLIPPER_OFFSET_POWER_OF_2;
- }
+namespace ClipperUtils {
+ Points EmptyPathsProvider::s_empty_points;
+ Points SinglePathProvider::s_end;
}
-void scaleClipperPolygons(ClipperLib::Paths &polygons)
+static ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree &&polytree)
{
- CLIPPERUTILS_PROFILE_FUNC();
- for (ClipperLib::Paths::iterator it = polygons.begin(); it != polygons.end(); ++it)
- for (ClipperLib::Path::iterator pit = (*it).begin(); pit != (*it).end(); ++pit) {
- pit->X <<= CLIPPER_OFFSET_POWER_OF_2;
- pit->Y <<= CLIPPER_OFFSET_POWER_OF_2;
+ struct Inner {
+ static void PolyTreeToExPolygonsRecursive(ClipperLib::PolyNode &&polynode, ExPolygons *expolygons)
+ {
+ size_t cnt = expolygons->size();
+ expolygons->resize(cnt + 1);
+ (*expolygons)[cnt].contour.points = std::move(polynode.Contour);
+ (*expolygons)[cnt].holes.resize(polynode.ChildCount());
+ for (int i = 0; i < polynode.ChildCount(); ++ i) {
+ (*expolygons)[cnt].holes[i].points = std::move(polynode.Childs[i]->Contour);
+ // Add outer polygons contained by (nested within) holes.
+ for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++ j)
+ PolyTreeToExPolygonsRecursive(std::move(*polynode.Childs[i]->Childs[j]), expolygons);
+ }
}
-}
-void unscaleClipperPolygon(ClipperLib::Path &polygon)
-{
- CLIPPERUTILS_PROFILE_FUNC();
- for (ClipperLib::Path::iterator pit = polygon.begin(); pit != polygon.end(); ++pit) {
- pit->X += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
- pit->Y += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
- pit->X >>= CLIPPER_OFFSET_POWER_OF_2;
- pit->Y >>= CLIPPER_OFFSET_POWER_OF_2;
- }
-}
-
-void unscaleClipperPolygons(ClipperLib::Paths &polygons)
-{
- CLIPPERUTILS_PROFILE_FUNC();
- for (ClipperLib::Paths::iterator it = polygons.begin(); it != polygons.end(); ++it)
- for (ClipperLib::Path::iterator pit = (*it).begin(); pit != (*it).end(); ++pit) {
- pit->X += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
- pit->Y += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
- pit->X >>= CLIPPER_OFFSET_POWER_OF_2;
- pit->Y >>= CLIPPER_OFFSET_POWER_OF_2;
+ static size_t PolyTreeCountExPolygons(const ClipperLib::PolyNode &polynode)
+ {
+ size_t cnt = 1;
+ for (int i = 0; i < polynode.ChildCount(); ++ i) {
+ for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++ j)
+ cnt += PolyTreeCountExPolygons(*polynode.Childs[i]->Childs[j]);
+ }
+ return cnt;
}
-}
-#endif // CLIPPERUTILS_OFFSET_SCALE
+ };
-//-----------------------------------------------------------
-// legacy code from Clipper documentation
-void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, ExPolygons* expolygons)
-{
- size_t cnt = expolygons->size();
- expolygons->resize(cnt + 1);
- (*expolygons)[cnt].contour = ClipperPath_to_Slic3rPolygon(polynode.Contour);
- (*expolygons)[cnt].holes.resize(polynode.ChildCount());
- for (int i = 0; i < polynode.ChildCount(); ++i)
- {
- (*expolygons)[cnt].holes[i] = ClipperPath_to_Slic3rPolygon(polynode.Childs[i]->Contour);
- //Add outer polygons contained by (nested within) holes ...
- for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++j)
- AddOuterPolyNodeToExPolygons(*polynode.Childs[i]->Childs[j], expolygons);
- }
-}
-
-ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree& polytree)
-{
ExPolygons retval;
- for (int i = 0; i < polytree.ChildCount(); ++i)
- AddOuterPolyNodeToExPolygons(*polytree.Childs[i], &retval);
- return retval;
-}
-//-----------------------------------------------------------
-
-Slic3r::Polygon ClipperPath_to_Slic3rPolygon(const ClipperLib::Path &input)
-{
- Polygon retval;
- for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
- retval.points.emplace_back(pit->X, pit->Y);
+ size_t cnt = 0;
+ for (int i = 0; i < polytree.ChildCount(); ++ i)
+ cnt += Inner::PolyTreeCountExPolygons(*polytree.Childs[i]);
+ retval.reserve(cnt);
+ for (int i = 0; i < polytree.ChildCount(); ++ i)
+ Inner::PolyTreeToExPolygonsRecursive(std::move(*polytree.Childs[i]), &retval);
return retval;
}
-Slic3r::Polyline ClipperPath_to_Slic3rPolyline(const ClipperLib::Path &input)
+Polylines PolyTreeToPolylines(ClipperLib::PolyTree &&polytree)
{
- Polyline retval;
- for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
- retval.points.emplace_back(pit->X, pit->Y);
- return retval;
-}
+ struct Inner {
+ static void AddPolyNodeToPaths(ClipperLib::PolyNode &polynode, Polylines &out)
+ {
+ if (! polynode.Contour.empty())
+ out.emplace_back(std::move(polynode.Contour));
+ for (ClipperLib::PolyNode *child : polynode.Childs)
+ AddPolyNodeToPaths(*child, out);
+ }
+ };
-Slic3r::Polygons ClipperPaths_to_Slic3rPolygons(const ClipperLib::Paths &input)
-{
- Slic3r::Polygons retval;
- retval.reserve(input.size());
- for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
- retval.emplace_back(ClipperPath_to_Slic3rPolygon(*it));
- return retval;
-}
-
-Slic3r::Polylines ClipperPaths_to_Slic3rPolylines(const ClipperLib::Paths &input)
-{
- Slic3r::Polylines retval;
- retval.reserve(input.size());
- for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
- retval.emplace_back(ClipperPath_to_Slic3rPolyline(*it));
- return retval;
+ Polylines out;
+ out.reserve(polytree.Total());
+ Inner::AddPolyNodeToPaths(polytree, out);
+ return out;
}
ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input)
{
- // init Clipper
ClipperLib::Clipper clipper;
- clipper.Clear();
-
- // perform union
clipper.AddPaths(input, ClipperLib::ptSubject, true);
ClipperLib::PolyTree polytree;
clipper.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // offset results work with both EvenOdd and NonZero
-
- // write to ExPolygons object
- return PolyTreeToExPolygons(polytree);
+ return PolyTreeToExPolygons(std::move(polytree));
}
-ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
+// Offset outside by 10um, one by one.
+template
+static ClipperLib::Paths safety_offset(PathsProvider &&paths)
{
- ClipperLib::Path retval;
- for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
- retval.emplace_back((*pit)(0), (*pit)(1));
- return retval;
-}
-
-ClipperLib::Path Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input)
-{
- ClipperLib::Path output;
- output.reserve(input.points.size());
- for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit)
- output.emplace_back((*pit)(0), (*pit)(1));
- return output;
-}
-
-ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polygons &input)
-{
- ClipperLib::Paths retval;
- for (Polygons::const_iterator it = input.begin(); it != input.end(); ++it)
- retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(*it));
- return retval;
-}
-
-ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const ExPolygons &input)
-{
- ClipperLib::Paths retval;
- for (auto &ep : input) {
- retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(ep.contour));
-
- for (auto &h : ep.holes)
- retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(h));
+ ClipperLib::ClipperOffset co;
+ ClipperLib::Paths out;
+ out.reserve(paths.size());
+ ClipperLib::Paths out_this;
+ for (const ClipperLib::Path &path : paths) {
+ co.Clear();
+ co.MiterLimit = 2.;
+ // Execute reorients the contours so that the outer most contour has a positive area. Thus the output
+ // contours will be CCW oriented even though the input paths are CW oriented.
+ // Offset is applied after contour reorientation, thus the signum of the offset value is reversed.
+ co.AddPath(path, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
+ bool ccw = ClipperLib::Orientation(path);
+ co.Execute(out_this, ccw ? ClipperSafetyOffset : - ClipperSafetyOffset);
+ if (! ccw) {
+ // Reverse the resulting contours.
+ for (ClipperLib::Path &path : out_this)
+ std::reverse(path.begin(), path.end());
+ }
+ append(out, std::move(out_this));
}
-
- return retval;
+ return out;
}
-ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input)
+// Only safe for a single path.
+template
+ClipperLib::Paths _offset(PathsProvider &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit)
{
- ClipperLib::Paths retval;
- for (Polylines::const_iterator it = input.begin(); it != input.end(); ++it)
- retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(*it));
- return retval;
-}
-
-ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit)
-{
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- // scale input
- scaleClipperPolygons(input);
-#endif // CLIPPERUTILS_OFFSET_SCALE
-
// perform offset
ClipperLib::ClipperOffset co;
if (joinType == jtRound)
co.ArcTolerance = miterLimit;
else
co.MiterLimit = miterLimit;
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
float delta_scaled = delta;
-#endif // CLIPPERUTILS_OFFSET_SCALE
co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
- co.AddPaths(input, joinType, endType);
+ co.AddPaths(std::forward(input), joinType, endType);
ClipperLib::Paths retval;
co.Execute(retval, delta_scaled);
-
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- // unscale output
- unscaleClipperPolygons(retval);
-#endif // CLIPPERUTILS_OFFSET_SCALE
return retval;
}
-ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit)
-{
- ClipperLib::Paths paths;
- paths.emplace_back(std::move(input));
- return _offset(std::move(paths), endType, delta, joinType, miterLimit);
-}
+Slic3r::Polygons offset(const Slic3r::Polygon& polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(ClipperUtils::SinglePathProvider(polygon.points), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
-// This is a safe variant of the polygon offset, tailored for a single ExPolygon:
-// a single polygon with multiple non-overlapping holes.
-// Each contour and hole is offsetted separately, then the holes are subtracted from the outer contours.
-ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
- ClipperLib::JoinType joinType, double miterLimit)
+#ifdef CLIPPERUTILS_UNSAFE_OFFSET
+Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(ClipperUtils::PolygonsProvider(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
+Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return ClipperPaths_to_Slic3rExPolygons(_offset(ClipperUtils::PolygonsProvider(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
+#endif // CLIPPERUTILS_UNSAFE_OFFSET
+
+Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(ClipperUtils::SinglePathProvider(polyline.points), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
+Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(ClipperUtils::PolylinesProvider(polylines), ClipperLib::etOpenButt, delta, joinType, miterLimit)); }
+
+// returns number of expolygons collected (0 or 1).
+static int offset_expolygon_inner(const Slic3r::ExPolygon &expoly, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
{
-// printf("new ExPolygon offset\n");
// 1) Offset the outer contour.
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
- float delta_scaled = delta;
-#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::Paths contours;
{
- ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(expolygon.contour);
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- scaleClipperPolygon(input);
-#endif // CLIPPERUTILS_OFFSET_SCALE
ClipperLib::ClipperOffset co;
if (joinType == jtRound)
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
co.ArcTolerance = miterLimit;
-#endif // CLIPPERUTILS_OFFSET_SCALE
else
co.MiterLimit = miterLimit;
- co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
- co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
- co.Execute(contours, delta_scaled);
+ co.ShortestEdgeLength = double(std::abs(delta * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
+ co.AddPath(expoly.contour.points, joinType, ClipperLib::etClosedPolygon);
+ co.Execute(contours, delta);
}
+ if (contours.empty())
+ // No need to try to offset the holes.
+ return 0;
- // 2) Offset the holes one by one, collect the results.
- ClipperLib::Paths holes;
- {
- holes.reserve(expolygon.holes.size());
- for (Polygons::const_iterator it_hole = expolygon.holes.begin(); it_hole != expolygon.holes.end(); ++ it_hole) {
- ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole);
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- scaleClipperPolygon(input);
-#endif // CLIPPERUTILS_OFFSET_SCALE
- ClipperLib::ClipperOffset co;
- if (joinType == jtRound)
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit;
-#endif // CLIPPERUTILS_OFFSET_SCALE
- else
- co.MiterLimit = miterLimit;
- co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
- co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
- ClipperLib::Paths out;
- co.Execute(out, - delta_scaled);
- append(holes, std::move(out));
+ if (expoly.holes.empty()) {
+ // No need to subtract holes from the offsetted expolygon, we are done.
+ append(out, std::move(contours));
+ } else {
+ // 2) Offset the holes one by one, collect the offsetted holes.
+ ClipperLib::Paths holes;
+ {
+ for (const Polygon &hole : expoly.holes) {
+ ClipperLib::ClipperOffset co;
+ if (joinType == jtRound)
+ co.ArcTolerance = miterLimit;
+ else
+ co.MiterLimit = miterLimit;
+ co.ShortestEdgeLength = double(std::abs(delta * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
+ co.AddPath(hole.points, joinType, ClipperLib::etClosedPolygon);
+ ClipperLib::Paths out2;
+ // Execute reorients the contours so that the outer most contour has a positive area. Thus the output
+ // contours will be CCW oriented even though the input paths are CW oriented.
+ // Offset is applied after contour reorientation, thus the signum of the offset value is reversed.
+ co.Execute(out2, - delta);
+ append(holes, std::move(out2));
+ }
+ }
+
+ // 3) Subtract holes from the contours.
+ if (holes.empty()) {
+ // No hole remaining after an offset. Just copy the outer contour.
+ append(out, std::move(contours));
+ } else if (delta < 0) {
+ // Negative offset. There is a chance, that the offsetted hole intersects the outer contour.
+ // Subtract the offsetted holes from the offsetted contours.
+ ClipperLib::Clipper clipper;
+ clipper.Clear();
+ clipper.AddPaths(contours, ClipperLib::ptSubject, true);
+ clipper.AddPaths(holes, ClipperLib::ptClip, true);
+ ClipperLib::Paths output;
+ clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
+ if (! output.empty()) {
+ append(out, std::move(output));
+ } else {
+ // The offsetted holes have eaten up the offsetted outer contour.
+ return 0;
+ }
+ } else {
+ // Positive offset. As long as the Clipper offset does what one expects it to do, the offsetted hole will have a smaller
+ // area than the original hole or even disappear, therefore there will be no new intersections.
+ // Just collect the reversed holes.
+ out.reserve(contours.size() + holes.size());
+ append(out, std::move(contours));
+ // Reverse the holes in place.
+ for (size_t i = 0; i < holes.size(); ++ i)
+ std::reverse(holes[i].begin(), holes[i].end());
+ append(out, std::move(holes));
}
}
- // 3) Subtract holes from the contours.
- ClipperLib::Paths output;
- if (holes.empty()) {
- output = std::move(contours);
- } else {
- ClipperLib::Clipper clipper;
- clipper.Clear();
- clipper.AddPaths(contours, ClipperLib::ptSubject, true);
- clipper.AddPaths(holes, ClipperLib::ptClip, true);
- clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
- }
-
- // 4) Unscale the output.
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- unscaleClipperPolygons(output);
-#endif // CLIPPERUTILS_OFFSET_SCALE
- return output;
+ return 1;
+}
+
+static int offset_expolygon_inner(const Slic3r::Surface &surface, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
+ { return offset_expolygon_inner(surface.expolygon, delta, joinType, miterLimit, out); }
+static int offset_expolygon_inner(const Slic3r::Surface *surface, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out)
+ { return offset_expolygon_inner(surface->expolygon, delta, joinType, miterLimit, out); }
+
+ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+{
+ ClipperLib::Paths out;
+ offset_expolygon_inner(expolygon, delta, joinType, miterLimit, out);
+ return out;
}
// This is a safe variant of the polygons offset, tailored for multiple ExPolygons.
// It is required, that the input expolygons do not overlap and that the holes of each ExPolygon don't intersect with their respective outer contours.
// Each ExPolygon is offsetted separately, then the offsetted ExPolygons are united.
-ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta,
- ClipperLib::JoinType joinType, double miterLimit)
+template
+ClipperLib::Paths _offset(const ExPolygonVector &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
{
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
- float delta_scaled = delta;
-#endif // CLIPPERUTILS_OFFSET_SCALE
// Offsetted ExPolygons before they are united.
- ClipperLib::Paths contours_cummulative;
- contours_cummulative.reserve(expolygons.size());
- // How many non-empty offsetted expolygons were actually collected into contours_cummulative?
+ ClipperLib::Paths output;
+ output.reserve(expolygons.size());
+ // How many non-empty offsetted expolygons were actually collected into output?
// If only one, then there is no need to do a final union.
size_t expolygons_collected = 0;
- for (Slic3r::ExPolygons::const_iterator it_expoly = expolygons.begin(); it_expoly != expolygons.end(); ++ it_expoly) {
- // 1) Offset the outer contour.
- ClipperLib::Paths contours;
- {
- ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(it_expoly->contour);
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- scaleClipperPolygon(input);
-#endif // CLIPPERUTILS_OFFSET_SCALE
- ClipperLib::ClipperOffset co;
- if (joinType == jtRound)
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit;
-#endif // CLIPPERUTILS_OFFSET_SCALE
- else
- co.MiterLimit = miterLimit;
- co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
- co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
- co.Execute(contours, delta_scaled);
- }
- if (contours.empty())
- // No need to try to offset the holes.
- continue;
-
- if (it_expoly->holes.empty()) {
- // No need to subtract holes from the offsetted expolygon, we are done.
- contours_cummulative.insert(contours_cummulative.end(), contours.begin(), contours.end());
- ++ expolygons_collected;
- } else {
- // 2) Offset the holes one by one, collect the offsetted holes.
- ClipperLib::Paths holes;
- {
- for (Polygons::const_iterator it_hole = it_expoly->holes.begin(); it_hole != it_expoly->holes.end(); ++ it_hole) {
- ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole);
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- scaleClipperPolygon(input);
-#endif // CLIPPERUTILS_OFFSET_SCALE
- ClipperLib::ClipperOffset co;
- if (joinType == jtRound)
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
- co.ArcTolerance = miterLimit;
-#endif // CLIPPERUTILS_OFFSET_SCALE
- else
- co.MiterLimit = miterLimit;
- co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
- co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
- ClipperLib::Paths out;
- co.Execute(out, - delta_scaled);
- holes.insert(holes.end(), out.begin(), out.end());
- }
- }
-
- // 3) Subtract holes from the contours.
- if (holes.empty()) {
- // No hole remaining after an offset. Just copy the outer contour.
- contours_cummulative.insert(contours_cummulative.end(), contours.begin(), contours.end());
- ++ expolygons_collected;
- } else if (delta < 0) {
- // Negative offset. There is a chance, that the offsetted hole intersects the outer contour.
- // Subtract the offsetted holes from the offsetted contours.
- ClipperLib::Clipper clipper;
- clipper.Clear();
- clipper.AddPaths(contours, ClipperLib::ptSubject, true);
- clipper.AddPaths(holes, ClipperLib::ptClip, true);
- ClipperLib::Paths output;
- clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
- if (! output.empty()) {
- contours_cummulative.insert(contours_cummulative.end(), output.begin(), output.end());
- ++ expolygons_collected;
- } else {
- // The offsetted holes have eaten up the offsetted outer contour.
- }
- } else {
- // Positive offset. As long as the Clipper offset does what one expects it to do, the offsetted hole will have a smaller
- // area than the original hole or even disappear, therefore there will be no new intersections.
- // Just collect the reversed holes.
- contours_cummulative.reserve(contours.size() + holes.size());
- contours_cummulative.insert(contours_cummulative.end(), contours.begin(), contours.end());
- // Reverse the holes in place.
- for (size_t i = 0; i < holes.size(); ++ i)
- std::reverse(holes[i].begin(), holes[i].end());
- contours_cummulative.insert(contours_cummulative.end(), holes.begin(), holes.end());
- ++ expolygons_collected;
- }
- }
- }
+ for (const auto &expoly : expolygons)
+ expolygons_collected += offset_expolygon_inner(expoly, delta, joinType, miterLimit, output);
// 4) Unite the offsetted expolygons.
- ClipperLib::Paths output;
if (expolygons_collected > 1 && delta > 0) {
// There is a chance that the outwards offsetted expolygons may intersect. Perform a union.
ClipperLib::Clipper clipper;
clipper.Clear();
- clipper.AddPaths(contours_cummulative, ClipperLib::ptSubject, true);
+ clipper.AddPaths(output, ClipperLib::ptSubject, true);
clipper.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
} else {
// Negative offset. The shrunk expolygons shall not mutually intersect. Just copy the output.
- output = std::move(contours_cummulative);
}
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- // 4) Unscale the output.
- unscaleClipperPolygons(output);
-#endif // CLIPPERUTILS_OFFSET_SCALE
return output;
}
-ClipperLib::Paths
-_offset2(const Polygons &polygons, const float delta1, const float delta2,
- const ClipperLib::JoinType joinType, const double miterLimit)
+Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(expolygon, delta, joinType, miterLimit)); }
+Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(expolygons, delta, joinType, miterLimit)); }
+Slic3r::Polygons offset(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(surfaces, delta, joinType, miterLimit)); }
+Slic3r::Polygons offset(const Slic3r::SurfacesPtr &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return to_polygons(_offset(surfaces, delta, joinType, miterLimit)); }
+Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
+Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
+Slic3r::ExPolygons offset_ex(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
+ { return ClipperPaths_to_Slic3rExPolygons(_offset(surfaces, delta, joinType, miterLimit)); }
+
+#ifdef CLIPPERUTILS_UNSAFE_OFFSET
+Slic3r::Polygons union_safety_offset(const Slic3r::Polygons &polygons)
+ { return offset(polygons, ClipperSafetyOffset); }
+Slic3r::ExPolygons union_safety_offset_ex(const Slic3r::Polygons &polygons)
+ { return offset_ex(polygons, ClipperSafetyOffset); }
+#endif // CLIPPERUTILS_UNSAFE_OFFSET
+
+Slic3r::Polygons union_safety_offset(const Slic3r::ExPolygons &expolygons)
+ { return offset(expolygons, ClipperSafetyOffset); }
+Slic3r::ExPolygons union_safety_offset_ex(const Slic3r::ExPolygons &expolygons)
+ { return offset_ex(expolygons, ClipperSafetyOffset); }
+
+ClipperLib::Paths _offset2(const Polygons &polygons, const float delta1, const float delta2, const ClipperLib::JoinType joinType, const double miterLimit)
{
- // read input
- ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons);
-
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- // scale input
- scaleClipperPolygons(input);
-#endif // CLIPPERUTILS_OFFSET_SCALE
-
// prepare ClipperOffset object
ClipperLib::ClipperOffset co;
if (joinType == jtRound) {
@@ -483,18 +341,13 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2,
} else {
co.MiterLimit = miterLimit;
}
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- float delta_scaled1 = delta1 * float(CLIPPER_OFFSET_SCALE);
- float delta_scaled2 = delta2 * float(CLIPPER_OFFSET_SCALE);
-#else // CLIPPERUTILS_OFFSET_SCALE
float delta_scaled1 = delta1;
float delta_scaled2 = delta2;
-#endif // CLIPPERUTILS_OFFSET_SCALE
co.ShortestEdgeLength = double(std::max(std::abs(delta_scaled1), std::abs(delta_scaled2)) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR);
// perform first offset
ClipperLib::Paths output1;
- co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
+ co.AddPaths(ClipperUtils::PolygonsProvider(polygons), joinType, ClipperLib::etClosedPolygon);
co.Execute(output1, delta_scaled1);
// perform second offset
@@ -503,106 +356,81 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2,
ClipperLib::Paths retval;
co.Execute(retval, delta_scaled2);
-#ifdef CLIPPERUTILS_OFFSET_SCALE
- // unscale output
- unscaleClipperPolygons(retval);
-#endif // CLIPPERUTILS_OFFSET_SCALE
return retval;
}
-Polygons
-offset2(const Polygons &polygons, const float delta1, const float delta2,
- const ClipperLib::JoinType joinType, const double miterLimit)
+Polygons offset2(const Polygons &polygons, const float delta1, const float delta2, const ClipperLib::JoinType joinType, const double miterLimit)
{
- // perform offset
- ClipperLib::Paths output = _offset2(polygons, delta1, delta2, joinType, miterLimit);
-
- // convert into ExPolygons
- return ClipperPaths_to_Slic3rPolygons(output);
+ return to_polygons(_offset2(polygons, delta1, delta2, joinType, miterLimit));
}
-ExPolygons
-offset2_ex(const Polygons &polygons, const float delta1, const float delta2,
- const ClipperLib::JoinType joinType, const double miterLimit)
+ExPolygons offset2_ex(const Polygons &polygons, const float delta1, const float delta2, const ClipperLib::JoinType joinType, const double miterLimit)
{
- // perform offset
- ClipperLib::Paths output = _offset2(polygons, delta1, delta2, joinType, miterLimit);
-
- // convert into ExPolygons
- return ClipperPaths_to_Slic3rExPolygons(output);
+ return ClipperPaths_to_Slic3rExPolygons(_offset2(polygons, delta1, delta2, joinType, miterLimit));
}
//FIXME Vojtech: This functon may likely be optimized to avoid some of the Slic3r to Clipper
-// conversions and unnecessary Clipper calls.
-ExPolygons offset2_ex(const ExPolygons &expolygons, const float delta1,
- const float delta2, ClipperLib::JoinType joinType, double miterLimit)
+// conversions and unnecessary Clipper calls. It is not that bad now as Clipper uses Slic3r's own Point / Polygon types directly.
+Polygons offset2(const ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType, double miterLimit)
{
- Polygons polys;
- for (const ExPolygon &expoly : expolygons)
- append(polys,
- offset(offset_ex(expoly, delta1, joinType, miterLimit),
- delta2, joinType, miterLimit));
- return union_ex(polys);
+ return offset(offset_ex(expolygons, delta1, joinType, miterLimit), delta2, joinType, miterLimit);
+}
+ExPolygons offset2_ex(const ExPolygons &expolygons, const float delta1, const float delta2, ClipperLib::JoinType joinType, double miterLimit)
+{
+ return offset_ex(offset_ex(expolygons, delta1, joinType, miterLimit), delta2, joinType, miterLimit);
}
-template
-T _clipper_do(const ClipperLib::ClipType clipType,
- TSubj && subject,
- TClip && clip,
- const ClipperLib::PolyFillType fillType,
- const bool safety_offset_)
+template
+TResult _clipper_do(
+ const ClipperLib::ClipType clipType,
+ TSubj && subject,
+ TClip && clip,
+ const ClipperLib::PolyFillType fillType)
{
- // read input
- ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(std::forward(subject));
- ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(std::forward(clip));
-
- // perform safety offset
- if (safety_offset_) {
- if (clipType == ClipperLib::ctUnion) {
- safety_offset(&input_subject);
- } else {
- safety_offset(&input_clip);
- }
- }
-
- // init Clipper
ClipperLib::Clipper clipper;
- clipper.Clear();
-
- // add polygons
- clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
- clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
-
- // perform operation
- T retval;
+ clipper.AddPaths(std::forward(subject), ClipperLib::ptSubject, true);
+ clipper.AddPaths(std::forward(clip), ClipperLib::ptClip, true);
+ TResult retval;
clipper.Execute(clipType, retval, fillType, fillType);
return retval;
}
+template
+TResult _clipper_do(
+ const ClipperLib::ClipType clipType,
+ TSubj && subject,
+ TClip && clip,
+ const ClipperLib::PolyFillType fillType,
+ const ApplySafetyOffset do_safety_offset)
+{
+ // Safety offset only allowed on intersection and difference.
+ assert(do_safety_offset == ApplySafetyOffset::No || clipType != ClipperLib::ctUnion);
+ return do_safety_offset == ApplySafetyOffset::Yes ?
+ _clipper_do(clipType, std::forward(subject), safety_offset(std::forward(clip)), fillType) :
+ _clipper_do(clipType, std::forward(subject), std::forward(clip), fillType);
+}
+
// Fix of #117: A large fractal pyramid takes ages to slice
// The Clipper library has difficulties processing overlapping polygons.
// Namely, the function ClipperLib::JoinCommonEdges() has potentially a terrible time complexity if the output
// of the operation is of the PolyTree type.
-// This function implmenets a following workaround:
+// This function implemenets a following workaround:
// 1) Peform the Clipper operation with the output to Paths. This method handles overlaps in a reasonable time.
// 2) Run Clipper Union once again to extract the PolyTree from the result of 1).
-inline ClipperLib::PolyTree _clipper_do_polytree2(const ClipperLib::ClipType clipType, const Polygons &subject,
- const Polygons &clip, const ClipperLib::PolyFillType fillType, const bool safety_offset_)
+template
+inline ClipperLib::PolyTree _clipper_do_polytree2(
+ const ClipperLib::ClipType clipType,
+ PathProvider1 &&subject,
+ PathProvider2 &&clip,
+ const ClipperLib::PolyFillType fillType)
{
- // read input
- ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject);
- ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip);
-
- // perform safety offset
- if (safety_offset_)
- safety_offset((clipType == ClipperLib::ctUnion) ? &input_subject : &input_clip);
-
ClipperLib::Clipper clipper;
- clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
- clipper.AddPaths(input_clip, ClipperLib::ptClip, true);
+ clipper.AddPaths(std::forward(subject), ClipperLib::ptSubject, true);
+ clipper.AddPaths(std::forward(clip), ClipperLib::ptClip, true);
// Perform the operation with the output to input_subject.
// This pass does not generate a PolyTree, which is a very expensive operation with the current Clipper library
// if there are overapping edges.
+ ClipperLib::Paths input_subject;
clipper.Execute(clipType, input_subject, fillType, fillType);
// Perform an additional Union operation to generate the PolyTree ordering.
clipper.Clear();
@@ -611,101 +439,188 @@ inline ClipperLib::PolyTree _clipper_do_polytree2(const ClipperLib::ClipType cli
clipper.Execute(ClipperLib::ctUnion, retval, fillType, fillType);
return retval;
}
-
-ClipperLib::PolyTree _clipper_do_pl(const ClipperLib::ClipType clipType, const Polylines &subject,
- const Polygons &clip, const ClipperLib::PolyFillType fillType,
- const bool safety_offset_)
+template
+inline ClipperLib::PolyTree _clipper_do_polytree2(
+ const ClipperLib::ClipType clipType,
+ PathProvider1 &&subject,
+ PathProvider2 &&clip,
+ const ClipperLib::PolyFillType fillType,
+ const ApplySafetyOffset do_safety_offset)
+{
+ assert(do_safety_offset == ApplySafetyOffset::No || clipType != ClipperLib::ctUnion);
+ return do_safety_offset == ApplySafetyOffset::Yes ?
+ _clipper_do_polytree2(clipType, std::forward(subject), safety_offset(std::forward(clip)), fillType) :
+ _clipper_do_polytree2(clipType, std::forward(subject), std::forward(clip), fillType);
+}
+
+template
+static inline Polygons _clipper(ClipperLib::ClipType clipType, TSubj &&subject, TClip &&clip, ApplySafetyOffset do_safety_offset)
+{
+ return to_polygons(_clipper_do