From 835c08beeb66a4f49678c8cffdb293dddbe950ac Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 5 Oct 2022 10:12:28 +0200 Subject: [PATCH 01/29] Remove accidental leftover commented source file --- src/libslic3r/CMakeLists.txt | 1 - src/libslic3r/TriangulateWall.cpp | 159 ------------------------------ 2 files changed, 160 deletions(-) delete mode 100644 src/libslic3r/TriangulateWall.cpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index f77bbaee83..a118f6ef39 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -268,7 +268,6 @@ set(SLIC3R_SOURCES TriangleMeshSlicer.hpp MeshSplitImpl.hpp TriangulateWall.hpp - TriangulateWall.cpp utils.cpp Utils.hpp Time.cpp diff --git a/src/libslic3r/TriangulateWall.cpp b/src/libslic3r/TriangulateWall.cpp deleted file mode 100644 index eb710d9a57..0000000000 --- a/src/libslic3r/TriangulateWall.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "TriangulateWall.hpp" -#include "MTUtils.hpp" - -namespace Slic3r { - -//class Ring { -// size_t idx = 0, nextidx = 1, startidx = 0, begin = 0, end = 0; - -//public: -// explicit Ring(size_t from, size_t to) : begin(from), end(to) { init(begin); } - -// size_t size() const { return end - begin; } -// std::pair pos() const { return {idx, nextidx}; } -// bool is_lower() const { return idx < size(); } - -// void inc() -// { -// if (nextidx != startidx) nextidx++; -// if (nextidx == end) nextidx = begin; -// idx ++; -// if (idx == end) idx = begin; -// } - -// void init(size_t pos) -// { -// startidx = begin + (pos - begin) % size(); -// idx = startidx; -// nextidx = begin + (idx + 1 - begin) % size(); -// } - -// bool is_finished() const { return nextidx == idx; } -//}; - -//template -//static Sc sq_dst(const Vec<3, Sc> &v1, const Vec<3, Sc>& v2) -//{ -// Vec<3, Sc> v = v1 - v2; -// return v.x() * v.x() + v.y() * v.y() /*+ v.z() * v.z()*/; -//} - -//template -//static Sc trscore(const Ring & onring, -// const Ring & offring, -// const std::vector> &pts) -//{ -// Sc a = sq_dst(pts[onring.pos().first], pts[offring.pos().first]); -// Sc b = sq_dst(pts[onring.pos().second], pts[offring.pos().first]); -// return (std::abs(a) + std::abs(b)) / 2.; -//} - -//template -//class Triangulator { -// const std::vector> *pts; -// Ring *onring, *offring; - -// double calc_score() const -// { -// return trscore(*onring, *offring, *pts); -// } - -// void synchronize_rings() -// { -// Ring lring = *offring; -// auto minsc = trscore(*onring, lring, *pts); -// size_t imin = lring.pos().first; - -// lring.inc(); - -// while(!lring.is_finished()) { -// double score = trscore(*onring, lring, *pts); -// if (score < minsc) { minsc = score; imin = lring.pos().first; } -// lring.inc(); -// } - -// offring->init(imin); -// } - -// void emplace_indices(std::vector &indices) -// { -// Vec3i tr{int(onring->pos().first), int(onring->pos().second), -// int(offring->pos().first)}; -// if (onring->is_lower()) std::swap(tr(0), tr(1)); -// indices.emplace_back(tr); -// } - -//public: -// void run(std::vector &indices) -// { -// synchronize_rings(); - -// double score = 0, prev_score = 0; -// while (!onring->is_finished() || !offring->is_finished()) { -// prev_score = score; -// if (onring->is_finished() || (score = calc_score()) > prev_score) { -// std::swap(onring, offring); -// } else { -// emplace_indices(indices); -// onring->inc(); -// } -// } -// } - -// explicit Triangulator(const std::vector> *points, -// Ring & lower, -// Ring & upper) -// : pts{points}, onring{&upper}, offring{&lower} -// {} -//}; - -//template -//void triangulate_wall(std::vector> &pts, -// std::vector> & ind, -// const Polygon & lower, -// const Polygon & upper, -// double lower_z_mm, -// double upper_z_mm) -//{ -// if (upper.points.size() < 3 || lower.points.size() < 3) return; - -// pts.reserve(lower.points.size() + upper.points.size()); -// for (auto &p : lower.points) -// pts.emplace_back(unscaled(p.x()), unscaled(p.y()), lower_z_mm); -// for (auto &p : upper.points) -// pts.emplace_back(unscaled(p.x()), unscaled(p.y()), upper_z_mm); - -// ind.reserve(2 * (lower.size() + upper.size())); - -// Ring lring{0, lower.points.size()}, uring{lower.points.size(), pts.size()}; -// Triangulator t{&pts, lring, uring}; -// t.run(ind); -//} - -//Wall triangulate_wall(const Polygon &lower, -// const Polygon &upper, -// double lower_z_mm, -// double upper_z_mm) -//{ -// if (upper.points.size() < 3 || lower.points.size() < 3) return {}; - -// Wall wall; -// auto &pts = wall.first; -// auto &ind = wall.second; - -// pts.reserve(lower.points.size() + upper.points.size()); -// for (auto &p : lower.points) -// wall.first.emplace_back(unscaled(p.x()), unscaled(p.y()), lower_z_mm); -// for (auto &p : upper.points) -// wall.first.emplace_back(unscaled(p.x()), unscaled(p.y()), upper_z_mm); - -// ind.reserve(2 * (lower.size() + upper.size())); - -// Ring lring{0, lower.points.size()}, uring{lower.points.size(), pts.size()}; -// Triangulator t{&pts, lring, uring}; -// t.run(ind); - -// return wall; -//} - -} // namespace Slic3r From 6549342008ea73b15b0f17d6f06783e998124bae Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Wed, 5 Oct 2022 11:49:44 +0200 Subject: [PATCH 02/29] Initial Print4Taste bundle. https://github.com/prusa3d/PrusaSlicer-settings/pull/168 --- resources/profiles/Print4Taste.idx | 2 + resources/profiles/Print4Taste.ini | 131 ++++++++++++++ resources/profiles/Print4Taste/MC2.0_bed.stl | Bin 0 -> 684 bytes .../profiles/Print4Taste/MC2.0_texture.svg | 165 ++++++++++++++++++ .../profiles/Print4Taste/MC2.0_thumbnail.png | Bin 0 -> 45346 bytes 5 files changed, 298 insertions(+) create mode 100644 resources/profiles/Print4Taste.idx create mode 100644 resources/profiles/Print4Taste.ini create mode 100644 resources/profiles/Print4Taste/MC2.0_bed.stl create mode 100644 resources/profiles/Print4Taste/MC2.0_texture.svg create mode 100644 resources/profiles/Print4Taste/MC2.0_thumbnail.png diff --git a/resources/profiles/Print4Taste.idx b/resources/profiles/Print4Taste.idx new file mode 100644 index 0000000000..b19d0f3e1a --- /dev/null +++ b/resources/profiles/Print4Taste.idx @@ -0,0 +1,2 @@ +min_slic3r_version = 2.6.0-alpha1 +0.0.1 Initial version \ No newline at end of file diff --git a/resources/profiles/Print4Taste.ini b/resources/profiles/Print4Taste.ini new file mode 100644 index 0000000000..05f76e1c33 --- /dev/null +++ b/resources/profiles/Print4Taste.ini @@ -0,0 +1,131 @@ +# Print profiles for Print4Taste printers (mycusini and procusini brands) +# Created from scratch from default FFF + +[vendor] +# Vendor name will be shown by the Config Wizard. +name = Print4Taste +# 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.1 +# Where to get the updates from? +config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Print4Taste/ + +# The printer models will be shown by the Configuration Wizard in this order, +# also the first model installed & the first nozzle installed will be activated after install. +# Printer model name will be shown by the installation wizard. + + +[printer_model:MC2.0] +name = mycusini 2.0 +variants = 1.0 +technology = FFF +family = mycusini +bed_model = MC2.0_bed.stl +bed_texture = MC2.0_texture.svg +default_materials = mycusini 3D Choco @MC2.0 + +[print:*common_MC2.0*] +bottom_solid_layers = 2 +bridge_speed = 30 +brim_type = no_brim +compatible_printers_condition = printer_notes=~/.*PRINT4TASTE.*/ and printer_notes=~/.*MYCUSINI2.0.*/ +elefant_foot_compensation = 0.1 +ensure_vertical_shell_thickness = 1 +external_perimeter_extrusion_width = 1.15 +external_perimeter_speed = 100% +extra_perimeters = 0 +extruder_clearance_height = 45 +extruder_clearance_radius = 40 +extrusion_width = 1.15 +fill_density = 20% +fill_pattern = grid +first_layer_extrusion_width = 1.15 +first_layer_height = 0.5 +first_layer_speed = 100% +gap_fill_speed = 30 +infill_anchor = 250% +infill_extrusion_width = 1 +infill_overlap = 5% +infill_speed = 30 +layer_height = 0.5 +max_print_speed = 80 +max_volumetric_extrusion_rate_slope_negative = 2 +max_volumetric_extrusion_rate_slope_positive = 2 +max_volumetric_speed = 8 +notes = Extruder clearances:\nHeight: 45 Radius: 40\nHeight: 8 Radius: 12\n\nDon'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_PRINT4TASTE\nPRINTER_MODEL_MYCUSINI2.0 +output_filename_format = [input_filename_base].gco +perimeter_extrusion_width = 1.15 +perimeter_speed = 30 +perimeters = 1 +slice_closing_radius = 0.49 +small_perimeter_speed = 100% +solid_infill_below_area = 10 +solid_infill_extrusion_width = 1.15 +solid_infill_speed = 100% +thin_walls = 0 +top_infill_extrusion_width = 1.15 +top_solid_infill_speed = 100% +top_solid_layers = 3 +travel_speed = 80 +skirts = 0 + +[print:0.50mm SOLID @MC2.0] +inherits = *common_MC2.0* + +[print:0.50mm FILLABLE @MC2.0] +inherits = 0.50mm SOLID @MC2.0 +top_solid_layers = 0 +fill_density = 0% +spiral_vase = 1 + +[print:0.50mm OUTLINES @MC2.0] +inherits = 0.50mm FILLABLE @MC2.0 +bottom_solid_layers = 0 + +[filament:mycusini 3D Choco @MC2.0] +filament_vendor = Print4Taste +bed_temperature = 0 +bridge_fan_speed = 0 +compatible_printers_condition = printer_notes=~/.*PRINT4TASTE.*/ and printer_notes=~/.*MYCUSINI2.0.*/ +cooling = 1 +disable_fan_first_layers = 0 +end_filament_gcode = "" +extrusion_multiplier = 0.95 +fan_always_on = 0 +fan_below_layer_time = 60 +filament_colour = #F4A6FF +filament_density = 1.26 +filament_diameter = 18 +filament_max_volumetric_speed = 8 +filament_notes = "Full cartridge: 18 x 100 mm, 32g\nDensity: 1.26 g/cm3\nCut cartrige size: 18 x ~50 mm, 16g\nMycusini 2.0 does not require temperature control in gcode\n\n\nDon'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_PRINT4TASTE\nPRINTER_MODEL_MYCUSINI2.0" +ilament_retract_before_wipe = 30% +filament_retract_layer_change = 1 +filament_retract_length = 0.3 +filament_retract_lift = 1 +filament_type = GLAZE +filament_wipe = 1 +first_layer_bed_temperature = 0 +first_layer_temperature = 0 +max_fan_speed = 0 +min_fan_speed = 0 +min_print_speed = 9 +slowdown_below_layer_time = 15 +start_filament_gcode = "" +temperature = 0 + +[printer:mycusini 2.0] +printer_model = MC2.0 +printer_variant = 1.0 +bed_shape = 5x2.5,105x2.5,105x112.5,5x112.5 +color_change_gcode = +end_gcode = M83 ;Relative mode to retract\nG1 F2400 E-0.1 ;Retract\nM84 ;Back to absolute mode after retract\nG0 F2400 X90 Y55 Z45 ;Park +max_layer_height = 0.75 +max_print_height = 45 +min_layer_height = 0.3 +nozzle_diameter = 1 +pause_print_gcode = +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_PRINT4TASTE\nPRINTER_MODEL_MYCUSINI2.0 +retract_length = 0.1 +start_gcode = G1 F2400 E-0.3 ;Retract\nG0 F2400 X100 Y55 Z20.7 ;Full coordinates to prevent ramming down\nG0 F2400 X100 Y40 Z0.5 ;Start purge line\nG0 F570 X100 Y10 Z0.5 E0.025 ;Purge slightly more, should make a line only a few mm long +default_print_profile = 0.50mm SOLID @MC2.0 +default_filament_profile = mycusini 3D Choco @MC2.0 \ No newline at end of file diff --git a/resources/profiles/Print4Taste/MC2.0_bed.stl b/resources/profiles/Print4Taste/MC2.0_bed.stl new file mode 100644 index 0000000000000000000000000000000000000000..2db61908d88bde355a170c3a5bc9bc5cc46cf06d GIT binary patch literal 684 zcmb7>!41MN3`IQvLu7)eJ;4PbiiCQoS_yh&3l_*I-K0_%gKx)9QVItwC2^d*Z#%h< zUE|K<)z!7%`^wkV!Ci)KxE-fydbz)CM{Hr1MW%KkdSI}L-xNOLVSe`C30Bzob=>ue{Q2nA0&9my3Z&|)2 z`b8ffM9N`=(wX2|11PIkYFAzHnZTZi|HCX1a-wgAn{4@KSHzrel~sukmHfI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/profiles/Print4Taste/MC2.0_thumbnail.png b/resources/profiles/Print4Taste/MC2.0_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..886dd34547efe01a2a50a2cd9c787a1257b0e698 GIT binary patch literal 45346 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%0Av3sDG^ku3d^GD3$h%g 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 literal 0 HcmV?d00001 From 8a54f91548d72fa43e5fec15410b32f194e8aebb Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:29:45 +0200 Subject: [PATCH 03/29] Sync with PrusaSlicer-settings. --- resources/profiles/Elegoo.idx | 5 +- resources/profiles/Elegoo.ini | 1020 ++++++++++++++++----------------- 2 files changed, 513 insertions(+), 512 deletions(-) diff --git a/resources/profiles/Elegoo.idx b/resources/profiles/Elegoo.idx index cf0da371b1..6fcdedd3f8 100644 --- a/resources/profiles/Elegoo.idx +++ b/resources/profiles/Elegoo.idx @@ -1,2 +1,3 @@ -min_slic3r_version = 2.5.0-alpha3 -1.0.0 Initial version +min_slic3r_version = 2.5.0-alpha3 +1.0.1 Decreased bed size to 220x220. +1.0.0 Initial version diff --git a/resources/profiles/Elegoo.ini b/resources/profiles/Elegoo.ini index a39d33f3f5..d9053e5a24 100644 --- a/resources/profiles/Elegoo.ini +++ b/resources/profiles/Elegoo.ini @@ -1,510 +1,510 @@ -# PrusaSlicer print profiles for the Elegoo printers. -# By Andrew Suzuki (andrewsuzuki.com), adapted from Creality.ini - -[vendor] -# Vendor name will be shown by the Config Wizard. -name = Elegoo -# Configuration version of this file. Config file will only be installed, if the config_version differs. -# This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.0.0 -config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Elegoo/ - -# The printer models will be shown by the Configuration Wizard in this order, -# also the first model installed & the first nozzle installed will be activated after install. -# Printer model name will be shown by the installation wizard. - -[printer_model:NEPTUNE1] -name = Elegoo Neptune-1 -variants = 0.4 -technology = FFF -family = NEPTUNE -bed_model = -bed_texture = -default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO - -[printer_model:NEPTUNE2] -name = Elegoo Neptune-2 -variants = 0.4 -technology = FFF -family = NEPTUNE -bed_model = -bed_texture = -default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO - -[printer_model:NEPTUNE2D] -name = Elegoo Neptune-2D -variants = 0.4 -technology = FFF -family = NEPTUNE -bed_model = -bed_texture = -default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO - -[printer_model:NEPTUNE2S] -name = Elegoo Neptune-2S -variants = 0.4 -technology = FFF -family = NEPTUNE -bed_model = -bed_texture = -default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO - -[printer_model:NEPTUNE3] -name = Elegoo Neptune-3 -variants = 0.4 -technology = FFF -family = NEPTUNE -bed_model = -bed_texture = -default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO - -[printer_model:NEPTUNEX] -name = Elegoo Neptune-X -variants = 0.4 -technology = FFF -family = NEPTUNE -bed_model = -bed_texture = -default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO - -# All presets starting with asterisk, for example *common*, are intermediate and they will -# not make it into the user interface. - -# Common print preset -[print:*common*] -avoid_crossing_perimeters = 0 -bridge_angle = 0 -bridge_flow_ratio = 0.95 -bridge_speed = 25 -brim_width = 0 -clip_multipart_objects = 1 -compatible_printers = -complete_objects = 0 -dont_support_bridges = 1 -elefant_foot_compensation = 0.1 -ensure_vertical_shell_thickness = 1 -external_fill_pattern = rectilinear -external_perimeters_first = 0 -external_perimeter_extrusion_width = 0.45 -external_perimeter_speed = 25 -extra_perimeters = 0 -extruder_clearance_height = 25 -extruder_clearance_radius = 45 -extrusion_width = 0.45 -fill_angle = 45 -fill_density = 20% -fill_pattern = grid -first_layer_extrusion_width = 0.42 -first_layer_height = 0.2 -first_layer_speed = 20 -gap_fill_speed = 30 -gcode_comments = 0 -infill_every_layers = 1 -infill_extruder = 1 -infill_extrusion_width = 0.45 -infill_first = 0 -infill_only_where_needed = 0 -infill_overlap = 25% -infill_speed = 50 -interface_shells = 0 -max_print_speed = 100 -max_volumetric_extrusion_rate_slope_negative = 0 -max_volumetric_extrusion_rate_slope_positive = 0 -max_volumetric_speed = 0 -min_skirt_length = 4 -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 -perimeters = 2 -perimeter_extruder = 1 -perimeter_extrusion_width = 0.45 -perimeter_speed = 40 -post_process = -print_settings_id = -raft_layers = 0 -resolution = 0 -seam_position = nearest -single_extruder_multi_material_priming = 0 -skirts = 1 -skirt_distance = 2 -skirt_height = 2 -small_perimeter_speed = 25 -solid_infill_below_area = 0 -solid_infill_every_layers = 0 -solid_infill_extruder = 1 -solid_infill_extrusion_width = 0.45 -solid_infill_speed = 40 -spiral_vase = 0 -standby_temperature_delta = -5 -support_material = 0 -support_material_extruder = 0 -support_material_extrusion_width = 0.38 -support_material_interface_extruder = 0 -support_material_angle = 0 -support_material_buildplate_only = 0 -support_material_enforce_layers = 0 -support_material_contact_distance = 0.15 -support_material_interface_contact_loops = 0 -support_material_interface_layers = 2 -support_material_interface_spacing = 0.2 -support_material_interface_speed = 100% -support_material_pattern = rectilinear -support_material_spacing = 2 -support_material_speed = 40 -support_material_synchronize_layers = 0 -support_material_threshold = 45 -support_material_with_sheath = 0 -support_material_xy_spacing = 60% -thin_walls = 0 -top_infill_extrusion_width = 0.4 -top_solid_infill_speed = 30 -travel_speed = 150 -wipe_tower = 0 -wipe_tower_bridging = 10 -wipe_tower_rotation_angle = 0 -wipe_tower_width = 60 -wipe_tower_x = 170 -wipe_tower_y = 140 -xy_size_compensation = 0 - -[print:*0.08mm*] -inherits = *common* -layer_height = 0.08 -perimeters = 3 -bottom_solid_layers = 9 -top_solid_layers = 11 - -[print:*0.10mm*] -inherits = *common* -layer_height = 0.1 -perimeters = 3 -bottom_solid_layers = 7 -top_solid_layers = 9 - -[print:*0.12mm*] -inherits = *common* -layer_height = 0.12 -perimeters = 3 -bottom_solid_layers = 6 -top_solid_layers = 7 - -[print:*0.16mm*] -inherits = *common* -layer_height = 0.16 -bottom_solid_layers = 5 -top_solid_layers = 7 - -[print:*0.20mm*] -inherits = *common* -layer_height = 0.20 -bottom_solid_layers = 4 -top_solid_layers = 5 - -[print:*0.24mm*] -inherits = *common* -layer_height = 0.24 -top_infill_extrusion_width = 0.45 -bottom_solid_layers = 3 -top_solid_layers = 4 - -[print:*0.28mm*] -inherits = *common* -layer_height = 0.28 -top_infill_extrusion_width = 0.45 -bottom_solid_layers = 3 -top_solid_layers = 4 - -[print:0.08mm SUPERDETAIL @ELEGOO] -inherits = *0.08mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -[print:0.10mm HIGHDETAIL @ELEGOO] -inherits = *0.10mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -[print:0.12mm DETAIL @ELEGOO] -inherits = *0.12mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -[print:0.16mm OPTIMAL @ELEGOO] -inherits = *0.16mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -[print:0.20mm NORMAL @ELEGOO] -inherits = *0.20mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -[print:0.24mm DRAFT @ELEGOO] -inherits = *0.24mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -[print:0.28mm SUPERDRAFT @ELEGOO] -inherits = *0.28mm* -compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 - -# When submitting new filaments please print the following temperature tower at 0.1mm layer height: -# https://www.thingiverse.com/thing:2615842 -# Pay particular attention to bridging, overhangs and retractions. -# Also print the following bed adhesion test at 0.1 layer height as well: -# https://www.prusaprinters.org/prints/4634-bed-adhesion-warp-test -# At least for PLA, please keep bed temp at 60, as many Elegoo printers do not have any ABL -# So having some leeway to get good bed adhesion is not a luxury for many users - -[filament:*common*] -cooling = 0 -compatible_printers = -extrusion_multiplier = 1 -filament_cost = 0 -filament_density = 0 -filament_diameter = 1.75 -filament_notes = "" -filament_settings_id = "" -filament_soluble = 0 -min_print_speed = 15 -slowdown_below_layer_time = 20 -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ELEGOO.*/ - -[filament:*PLA*] -inherits = *common* -bed_temperature = 60 -fan_below_layer_time = 100 -filament_colour = #DDDDDD -filament_max_volumetric_speed = 15 -filament_type = PLA -filament_density = 1.24 -filament_cost = 20 -first_layer_bed_temperature = 60 -first_layer_temperature = 210 -fan_always_on = 1 -cooling = 1 -max_fan_speed = 100 -min_fan_speed = 100 -bridge_fan_speed = 100 -disable_fan_first_layers = 1 -temperature = 205 - -[filament:*PET*] -inherits = *common* -bed_temperature = 70 -cooling = 1 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #DDDDDD -filament_max_volumetric_speed = 8 -filament_type = PETG -filament_density = 1.27 -filament_cost = 20 -first_layer_bed_temperature = 70 -first_layer_temperature = 240 -fan_always_on = 1 -max_fan_speed = 50 -min_fan_speed = 20 -bridge_fan_speed = 100 -temperature = 240 - -[filament:*ABS*] -inherits = *common* -bed_temperature = 100 -cooling = 0 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #DDDDDD -filament_max_volumetric_speed = 11 -filament_type = ABS -filament_density = 1.04 -filament_cost = 20 -first_layer_bed_temperature = 100 -first_layer_temperature = 245 -fan_always_on = 0 -max_fan_speed = 0 -min_fan_speed = 0 -bridge_fan_speed = 30 -top_fan_speed = 0 -temperature = 245 - -[filament:Generic PLA @ELEGOO] -inherits = *PLA* -filament_vendor = Generic - -[filament:Generic PETG @ELEGOO] -inherits = *PET* -filament_vendor = Generic - -[filament:Generic ABS @ELEGOO] -inherits = *ABS* -first_layer_bed_temperature = 90 -bed_temperature = 90 -filament_vendor = Generic - -# Common printer preset -[printer:*common*] -printer_technology = FFF -before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n -bed_shape = 0x0,235x0,235x235,0x235 -between_objects_gcode = -pause_print_gcode = -deretract_speed = 0 -extruder_colour = #FCE94F -extruder_offset = 0x0 -gcode_flavor = marlin -silent_mode = 0 -remaining_times = 0 -machine_max_acceleration_e = 5000 -machine_max_acceleration_extruding = 500 -machine_max_acceleration_retracting = 1000 -machine_max_acceleration_x = 500 -machine_max_acceleration_y = 500 -machine_max_acceleration_z = 100 -machine_max_feedrate_e = 60 -machine_max_feedrate_x = 500 -machine_max_feedrate_y = 500 -machine_max_feedrate_z = 10 -machine_max_jerk_e = 5 -machine_max_jerk_x = 8 -machine_max_jerk_y = 8 -machine_max_jerk_z = 0.4 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] -max_layer_height = 0.3 -min_layer_height = 0.07 -max_print_height = 250 -nozzle_diameter = 0.4 -printer_notes = -printer_settings_id = -retract_before_travel = 1 -retract_before_wipe = 0% -retract_layer_change = 1 -retract_length = 1 -retract_length_toolchange = 1 -retract_lift = 0 -retract_lift_above = 0 -retract_lift_below = 0 -retract_restart_extra = 0 -retract_restart_extra_toolchange = 0 -retract_speed = 35 -single_extruder_multi_material = 0 -thumbnails = 16x16,220x124 -toolchange_gcode = -use_firmware_retraction = 0 -use_relative_e_distances = 1 -use_volumetric_e = 0 -variable_layer_height = 1 -wipe = 1 -z_offset = 0 -printer_model = -default_print_profile = 0.16mm OPTIMAL @ELEGOO -default_filament_profile = Generic PLA @ELEGOO - -[printer:Elegoo Neptune-2] -inherits = *common* -printer_model = NEPTUNE2 -printer_variant = 0.4 -max_layer_height = 0.28 -min_layer_height = 0.08 -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_ELEGOO\nPRINTER_MODEL_NEPTUNE2\nPRINTER_HAS_BOWDEN -max_print_height = 250 -machine_max_acceleration_e = 5000 -machine_max_acceleration_extruding = 500 -machine_max_acceleration_retracting = 1000 -machine_max_acceleration_x = 500 -machine_max_acceleration_y = 500 -machine_max_acceleration_z = 100 -machine_max_feedrate_e = 60 -machine_max_feedrate_x = 500 -machine_max_feedrate_y = 500 -machine_max_feedrate_z = 10 -machine_max_jerk_e = 5 -machine_max_jerk_x = 8 -machine_max_jerk_y = 8 -machine_max_jerk_z = 0.4 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -nozzle_diameter = 0.4 -retract_before_travel = 2 -retract_length = 5 -retract_speed = 60 -deretract_speed = 40 -retract_before_wipe = 70% -start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 -end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors - - -# Intended for printers with a smaller bed -# [printer:*fastabl*] -# start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 - -# Intended for printers with a larger bed -# [printer:*slowabl*] -# start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nG28 ; home all axis\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 - -# Intended for printers with vendor official firmware verified to support M25 -# [printer:*pauseprint*] -# pause_print_gcode = M25 ; pause print - -# Intended for printers where the Z-axis lowers the print bed during printing -# [printer:*invertedz*] -# end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed down further down\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors - -# Intended for printers with dual extruders and a single hotend/nozzle -[printer:*dualextruder*] -single_extruder_multi_material = 1 -cooling_tube_length = 23 -cooling_tube_retraction = 35 -extra_loading_move = -2 -parking_pos_retraction = 80 -deretract_speed = 40,40 -extruder_colour = #0080C0;#FFFF9F -extruder_offset = 0x0,0x0 -max_layer_height = 0.28,0.28 -min_layer_height = 0.08,0.08 -nozzle_diameter = 0.4,0.4 -retract_before_travel = 2,2 -retract_before_wipe = 70%,70% -retract_layer_change = 1,1 -retract_length = 5,5 -retract_length_toolchange = 1,1 -retract_lift = 0,0 -retract_lift_above = 0,0 -retract_lift_below = 0,0 -retract_restart_extra = 0,0 -retract_restart_extra_toolchange = 0,0 -retract_speed = 60,60 -wipe = 1,1 -start_gcode = T[initial_tool] ; set active extruder\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM140 S{first_layer_bed_temperature[0]} ; set final bed temp\nM104 S150 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\n;G29 ; auto bed levelling - remove ; at beginning of line to enable\n;M420 S1 ; enable mesh - remove ; at beginning of line to enable\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S{first_layer_temperature[0]} ; set final nozzle temp\nM190 S{first_layer_bed_temperature[0]} ; wait for bed temp to stabilize\nM109 S{first_layer_temperature[0]} ; wait for nozzle temp to stabilize\nG1 Z0.28 F240 ; move down to prime nozzle\nG92 E0 ; reset extruder\nG1 E90 ; load filament\nG92 E0 ; reset extruder\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000 ; move over for second prime line\nG92 E0 ; reset extruder\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 ; reset extruder -end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\nG1 E-80 F2000 ; unload filament\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors - -# Copy of Creality CR-X config for the Neptune 2D (dual extruder, single hotend) - -[printer:Elegoo Neptune-2D] -inherits = Elegoo Neptune-2; *dualextruder* -retract_length = 6,6 -printer_model = NEPTUNE2D -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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN - -[printer:Elegoo Neptune-2S] -inherits = Elegoo Neptune-2 -printer_model = NEPTUNE2S -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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN - -[printer:Elegoo Neptune-X] -inherits = Elegoo Neptune-2 -max_print_height = 300 -printer_model = NEPTUNEX -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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN - -[printer:Elegoo Neptune-3] -inherits = Elegoo Neptune-2 -max_print_height = 280 -start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG29 ; run abl mesh\nM420 S1 ; load mesh\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 -printer_model = NEPTUNE3 -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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN - -[printer:Elegoo Neptune-1] -inherits = Elegoo Neptune-2 -bed_shape = 0x0,210x0,210x210,0x210 -max_print_height = 200 -printer_model = NEPTUNE1 -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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN +# PrusaSlicer print profiles for the Elegoo printers. +# By Andrew Suzuki (andrewsuzuki.com), adapted from Creality.ini + +[vendor] +# Vendor name will be shown by the Config Wizard. +name = Elegoo +# Configuration version of this file. Config file will only be installed, if the config_version differs. +# This means, the server may force the PrusaSlicer configuration to be downgraded. +config_version = 1.0.1 +config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Elegoo/ + +# The printer models will be shown by the Configuration Wizard in this order, +# also the first model installed & the first nozzle installed will be activated after install. +# Printer model name will be shown by the installation wizard. + +[printer_model:NEPTUNE1] +name = Elegoo Neptune-1 +variants = 0.4 +technology = FFF +family = NEPTUNE +bed_model = +bed_texture = +default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO + +[printer_model:NEPTUNE2] +name = Elegoo Neptune-2 +variants = 0.4 +technology = FFF +family = NEPTUNE +bed_model = +bed_texture = +default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO + +[printer_model:NEPTUNE2D] +name = Elegoo Neptune-2D +variants = 0.4 +technology = FFF +family = NEPTUNE +bed_model = +bed_texture = +default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO + +[printer_model:NEPTUNE2S] +name = Elegoo Neptune-2S +variants = 0.4 +technology = FFF +family = NEPTUNE +bed_model = +bed_texture = +default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO + +[printer_model:NEPTUNE3] +name = Elegoo Neptune-3 +variants = 0.4 +technology = FFF +family = NEPTUNE +bed_model = +bed_texture = +default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO + +[printer_model:NEPTUNEX] +name = Elegoo Neptune-X +variants = 0.4 +technology = FFF +family = NEPTUNE +bed_model = +bed_texture = +default_materials = Generic PLA @ELEGOO; Generic PETG @ELEGOO; Generic ABS @ELEGOO + +# All presets starting with asterisk, for example *common*, are intermediate and they will +# not make it into the user interface. + +# Common print preset +[print:*common*] +avoid_crossing_perimeters = 0 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 25 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = +complete_objects = 0 +dont_support_bridges = 1 +elefant_foot_compensation = 0.1 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeters_first = 0 +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 25 +extra_perimeters = 0 +extruder_clearance_height = 25 +extruder_clearance_radius = 45 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = grid +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 20 +gap_fill_speed = 30 +gcode_comments = 0 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 50 +interface_shells = 0 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +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 +perimeters = 2 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 40 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +single_extruder_multi_material_priming = 0 +skirts = 1 +skirt_distance = 2 +skirt_height = 2 +small_perimeter_speed = 25 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 40 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.38 +support_material_interface_extruder = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_enforce_layers = 0 +support_material_contact_distance = 0.15 +support_material_interface_contact_loops = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 40 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 30 +travel_speed = 150 +wipe_tower = 0 +wipe_tower_bridging = 10 +wipe_tower_rotation_angle = 0 +wipe_tower_width = 60 +wipe_tower_x = 170 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:*0.08mm*] +inherits = *common* +layer_height = 0.08 +perimeters = 3 +bottom_solid_layers = 9 +top_solid_layers = 11 + +[print:*0.10mm*] +inherits = *common* +layer_height = 0.1 +perimeters = 3 +bottom_solid_layers = 7 +top_solid_layers = 9 + +[print:*0.12mm*] +inherits = *common* +layer_height = 0.12 +perimeters = 3 +bottom_solid_layers = 6 +top_solid_layers = 7 + +[print:*0.16mm*] +inherits = *common* +layer_height = 0.16 +bottom_solid_layers = 5 +top_solid_layers = 7 + +[print:*0.20mm*] +inherits = *common* +layer_height = 0.20 +bottom_solid_layers = 4 +top_solid_layers = 5 + +[print:*0.24mm*] +inherits = *common* +layer_height = 0.24 +top_infill_extrusion_width = 0.45 +bottom_solid_layers = 3 +top_solid_layers = 4 + +[print:*0.28mm*] +inherits = *common* +layer_height = 0.28 +top_infill_extrusion_width = 0.45 +bottom_solid_layers = 3 +top_solid_layers = 4 + +[print:0.08mm SUPERDETAIL @ELEGOO] +inherits = *0.08mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +[print:0.10mm HIGHDETAIL @ELEGOO] +inherits = *0.10mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +[print:0.12mm DETAIL @ELEGOO] +inherits = *0.12mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +[print:0.16mm OPTIMAL @ELEGOO] +inherits = *0.16mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +[print:0.20mm NORMAL @ELEGOO] +inherits = *0.20mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +[print:0.24mm DRAFT @ELEGOO] +inherits = *0.24mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +[print:0.28mm SUPERDRAFT @ELEGOO] +inherits = *0.28mm* +compatible_printers_condition = printer_model=~/(NEPTUNE).*/ and nozzle_diameter[0]==0.4 + +# When submitting new filaments please print the following temperature tower at 0.1mm layer height: +# https://www.thingiverse.com/thing:2615842 +# Pay particular attention to bridging, overhangs and retractions. +# Also print the following bed adhesion test at 0.1 layer height as well: +# https://www.prusaprinters.org/prints/4634-bed-adhesion-warp-test +# At least for PLA, please keep bed temp at 60, as many Elegoo printers do not have any ABL +# So having some leeway to get good bed adhesion is not a luxury for many users + +[filament:*common*] +cooling = 0 +compatible_printers = +extrusion_multiplier = 1 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_notes = "" +filament_settings_id = "" +filament_soluble = 0 +min_print_speed = 15 +slowdown_below_layer_time = 20 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ELEGOO.*/ + +[filament:*PLA*] +inherits = *common* +bed_temperature = 60 +fan_below_layer_time = 100 +filament_colour = #DDDDDD +filament_max_volumetric_speed = 15 +filament_type = PLA +filament_density = 1.24 +filament_cost = 20 +first_layer_bed_temperature = 60 +first_layer_temperature = 210 +fan_always_on = 1 +cooling = 1 +max_fan_speed = 100 +min_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +temperature = 205 + +[filament:*PET*] +inherits = *common* +bed_temperature = 70 +cooling = 1 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #DDDDDD +filament_max_volumetric_speed = 8 +filament_type = PETG +filament_density = 1.27 +filament_cost = 20 +first_layer_bed_temperature = 70 +first_layer_temperature = 240 +fan_always_on = 1 +max_fan_speed = 50 +min_fan_speed = 20 +bridge_fan_speed = 100 +temperature = 240 + +[filament:*ABS*] +inherits = *common* +bed_temperature = 100 +cooling = 0 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #DDDDDD +filament_max_volumetric_speed = 11 +filament_type = ABS +filament_density = 1.04 +filament_cost = 20 +first_layer_bed_temperature = 100 +first_layer_temperature = 245 +fan_always_on = 0 +max_fan_speed = 0 +min_fan_speed = 0 +bridge_fan_speed = 30 +top_fan_speed = 0 +temperature = 245 + +[filament:Generic PLA @ELEGOO] +inherits = *PLA* +filament_vendor = Generic + +[filament:Generic PETG @ELEGOO] +inherits = *PET* +filament_vendor = Generic + +[filament:Generic ABS @ELEGOO] +inherits = *ABS* +first_layer_bed_temperature = 90 +bed_temperature = 90 +filament_vendor = Generic + +# Common printer preset +[printer:*common*] +printer_technology = FFF +before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n +bed_shape = 0x0,220x0,220x220,0x220 +between_objects_gcode = +pause_print_gcode = +deretract_speed = 0 +extruder_colour = #FCE94F +extruder_offset = 0x0 +gcode_flavor = marlin +silent_mode = 0 +remaining_times = 0 +machine_max_acceleration_e = 5000 +machine_max_acceleration_extruding = 500 +machine_max_acceleration_retracting = 1000 +machine_max_acceleration_x = 500 +machine_max_acceleration_y = 500 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 60 +machine_max_feedrate_x = 500 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 10 +machine_max_jerk_e = 5 +machine_max_jerk_x = 8 +machine_max_jerk_y = 8 +machine_max_jerk_z = 0.4 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.3 +min_layer_height = 0.07 +max_print_height = 250 +nozzle_diameter = 0.4 +printer_notes = +printer_settings_id = +retract_before_travel = 1 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 1 +retract_length_toolchange = 1 +retract_lift = 0 +retract_lift_above = 0 +retract_lift_below = 0 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 35 +single_extruder_multi_material = 0 +thumbnails = 16x16,220x124 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 +printer_model = +default_print_profile = 0.16mm OPTIMAL @ELEGOO +default_filament_profile = Generic PLA @ELEGOO + +[printer:Elegoo Neptune-2] +inherits = *common* +printer_model = NEPTUNE2 +printer_variant = 0.4 +max_layer_height = 0.28 +min_layer_height = 0.08 +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_ELEGOO\nPRINTER_MODEL_NEPTUNE2\nPRINTER_HAS_BOWDEN +max_print_height = 250 +machine_max_acceleration_e = 5000 +machine_max_acceleration_extruding = 500 +machine_max_acceleration_retracting = 1000 +machine_max_acceleration_x = 500 +machine_max_acceleration_y = 500 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 60 +machine_max_feedrate_x = 500 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 10 +machine_max_jerk_e = 5 +machine_max_jerk_x = 8 +machine_max_jerk_y = 8 +machine_max_jerk_z = 0.4 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +nozzle_diameter = 0.4 +retract_before_travel = 2 +retract_length = 5 +retract_speed = 60 +deretract_speed = 40 +retract_before_wipe = 70% +start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 +end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors + + +# Intended for printers with a smaller bed +# [printer:*fastabl*] +# start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 + +# Intended for printers with a larger bed +# [printer:*slowabl*] +# start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nG28 ; home all axis\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 + +# Intended for printers with vendor official firmware verified to support M25 +# [printer:*pauseprint*] +# pause_print_gcode = M25 ; pause print + +# Intended for printers where the Z-axis lowers the print bed during printing +# [printer:*invertedz*] +# end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed down further down\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors + +# Intended for printers with dual extruders and a single hotend/nozzle +[printer:*dualextruder*] +single_extruder_multi_material = 1 +cooling_tube_length = 23 +cooling_tube_retraction = 35 +extra_loading_move = -2 +parking_pos_retraction = 80 +deretract_speed = 40,40 +extruder_colour = #0080C0;#FFFF9F +extruder_offset = 0x0,0x0 +max_layer_height = 0.28,0.28 +min_layer_height = 0.08,0.08 +nozzle_diameter = 0.4,0.4 +retract_before_travel = 2,2 +retract_before_wipe = 70%,70% +retract_layer_change = 1,1 +retract_length = 5,5 +retract_length_toolchange = 1,1 +retract_lift = 0,0 +retract_lift_above = 0,0 +retract_lift_below = 0,0 +retract_restart_extra = 0,0 +retract_restart_extra_toolchange = 0,0 +retract_speed = 60,60 +wipe = 1,1 +start_gcode = T[initial_tool] ; set active extruder\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM140 S{first_layer_bed_temperature[0]} ; set final bed temp\nM104 S150 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\n;G29 ; auto bed levelling - remove ; at beginning of line to enable\n;M420 S1 ; enable mesh - remove ; at beginning of line to enable\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S{first_layer_temperature[0]} ; set final nozzle temp\nM190 S{first_layer_bed_temperature[0]} ; wait for bed temp to stabilize\nM109 S{first_layer_temperature[0]} ; wait for nozzle temp to stabilize\nG1 Z0.28 F240 ; move down to prime nozzle\nG92 E0 ; reset extruder\nG1 E90 ; load filament\nG92 E0 ; reset extruder\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000 ; move over for second prime line\nG92 E0 ; reset extruder\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 ; reset extruder +end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\nG1 E-80 F2000 ; unload filament\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors + +# Copy of Creality CR-X config for the Neptune 2D (dual extruder, single hotend) + +[printer:Elegoo Neptune-2D] +inherits = Elegoo Neptune-2; *dualextruder* +retract_length = 6,6 +printer_model = NEPTUNE2D +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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN + +[printer:Elegoo Neptune-2S] +inherits = Elegoo Neptune-2 +printer_model = NEPTUNE2S +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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN + +[printer:Elegoo Neptune-X] +inherits = Elegoo Neptune-2 +max_print_height = 300 +printer_model = NEPTUNEX +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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN + +[printer:Elegoo Neptune-3] +inherits = Elegoo Neptune-2 +max_print_height = 280 +start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG29 ; run abl mesh\nM420 S1 ; load mesh\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 +printer_model = NEPTUNE3 +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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN + +[printer:Elegoo Neptune-1] +inherits = Elegoo Neptune-2 +bed_shape = 0x0,210x0,210x210,0x210 +max_print_height = 200 +printer_model = NEPTUNE1 +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_ELEGOO\nPRINTER_MODEL_NEPTUNE2D\nPRINTER_HAS_BOWDEN From 20bd7f9a263b7b23a5c0f8d08065f6ff45a4b485 Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Mon, 3 Oct 2022 15:59:34 +0200 Subject: [PATCH 04/29] improvements in islands recognition; LinesDistancer class for both Point based and Floating based lines --- src/libslic3r/AABBTreeLines.hpp | 56 +++++++++-- src/libslic3r/SupportSpotsGenerator.cpp | 127 ++++++------------------ 2 files changed, 77 insertions(+), 106 deletions(-) diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 39f828b558..7d6ff1ccc6 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -3,6 +3,7 @@ #include "libslic3r/AABBTreeIndirect.hpp" #include "libslic3r/Line.hpp" +#include namespace Slic3r { @@ -24,16 +25,16 @@ struct IndexedLinesDistancer { inline VectorType closest_point_to_origin(size_t primitive_index, ScalarType &squared_distance) { - VectorType nearest_point; + Vec nearest_point; const LineType &line = lines[primitive_index]; - squared_distance = line_alg::distance_to_squared(line, origin, &nearest_point); - return nearest_point; + squared_distance = line_alg::distance_to_squared(line, origin.template cast(), &nearest_point); + return nearest_point.template cast(); } }; } -// Build a balanced AABB Tree over a vector of float lines, balancing the tree +// Build a balanced AABB Tree over a vector of lines, balancing the tree // on centroids of the lines. // Epsilon is applied to the bounding boxes of the AABB Tree to cope with numeric inaccuracies // during tree traversal. @@ -41,7 +42,7 @@ template inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over_indexed_lines( const std::vector &lines, //FIXME do we want to apply an epsilon? - const float eps = 0) + const double eps = 0) { using TreeType = AABBTreeIndirect::Tree<2, typename LineType::Scalar>; // using CoordType = typename TreeType::CoordType; @@ -103,8 +104,49 @@ inline typename VectorType::Scalar squared_distance_to_indexed_lines( std::numeric_limits::infinity(), hit_idx_out, hit_point_out); } -} +template class LinesDistancer +{ +private: + std::vector lines; + using Scalar = typename LineType::Scalar; + using Floating = typename std::conditional::value, Scalar, double>::type; + AABBTreeIndirect::Tree<2, Scalar> tree; -} +public: + explicit LinesDistancer(const std::vector &lines) : lines(lines) + { + tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(this->lines); + } + + // negative sign means inside + std::tuple> signed_distance_from_lines_extra(const Vec<2, Scalar> &point) const + { + size_t nearest_line_index_out = size_t(-1); + Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero(); + Vec<2, Floating> p = point.template cast(); + auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out); + + if (distance < 0) { return {std::numeric_limits::infinity(), nearest_line_index_out, nearest_point_out}; } + + distance = sqrt(distance); + const LineType &line = lines[nearest_line_index_out]; + Vec<2, Floating> v1 = (line.b - line.a).template cast(); + Vec<2, Floating> v2 = (point - line.a).template cast(); + if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) { distance *= -1.0; } + return {distance, nearest_line_index_out, nearest_point_out}; + } + + Floating signed_distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const + { + auto [dist, idx, np] = signed_distance_from_lines_extra(point); + return dist; + } + + const LineType &get_line(size_t line_idx) const { return lines[line_idx]; } + + const std::vector &get_lines() const { return lines; } +}; + +}} // namespace Slic3r::AABBTreeLines #endif /* SRC_LIBSLIC3R_AABBTREELINES_HPP_ */ diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 697518bd08..09b2bc5aea 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -1,6 +1,9 @@ #include "SupportSpotsGenerator.hpp" +#include "ExPolygon.hpp" #include "ExtrusionEntity.hpp" +#include "Line.hpp" +#include "Polygon.hpp" #include "tbb/parallel_for.h" #include "tbb/blocked_range.h" #include "tbb/blocked_range2d.h" @@ -70,46 +73,10 @@ SupportPoint::SupportPoint(const Vec3f &position, float force, float spot_radius position(position), force(force), spot_radius(spot_radius), direction(direction) { } -class LinesDistancer { -private: - std::vector lines; - AABBTreeIndirect::Tree<2, float> tree; - -public: - explicit LinesDistancer(const std::vector &lines) : - lines(lines) { - tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(this->lines); - } - - // negative sign means inside - float signed_distance_from_lines(const Vec2f &point, size_t &nearest_line_index_out, - Vec2f &nearest_point_out) const { - auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, point, nearest_line_index_out, - nearest_point_out); - if (distance < 0) - return std::numeric_limits::infinity(); - - distance = sqrt(distance); - const ExtrusionLine &line = lines[nearest_line_index_out]; - Vec2f v1 = line.b - line.a; - Vec2f v2 = point - line.a; - if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) { - distance *= -1; - } - return distance; - } - - const ExtrusionLine& get_line(size_t line_idx) const { - return lines[line_idx]; - } - - const std::vector& get_lines() const { - return lines; - } -}; - static const size_t NULL_ISLAND = std::numeric_limits::max(); +using LD = AABBTreeLines::LinesDistancer; + class PixelGrid { Vec2f pixel_size; Vec2f origin; @@ -387,7 +354,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity, std::vector &checked_lines_out, float layer_z, const LayerRegion *layer_region, - const LinesDistancer &prev_layer_lines, + const LD &prev_layer_lines, Issues &issues, const Params ¶ms) { @@ -429,11 +396,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity, // malformation in concave angles does not happen malformation_acc.add_angle(std::max(0.0f, curr_angle)); - size_t nearest_line_idx; - Vec2f nearest_point; - float dist_from_prev_layer = prev_layer_lines.signed_distance_from_lines(current_line.b, nearest_line_idx, - nearest_point); - + auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b); if (fabs(dist_from_prev_layer) < overhang_dist) { bridging_acc.reset(); } else { @@ -491,53 +454,18 @@ std::tuple reckon_islands( } } - std::vector islands; // these search trees will be used to determine to which island does the extrusion belong. - std::vector> island_extrusions; //final assigment of each extrusion to an island. - // initliaze the search from external perimeters - at the beginning, there is island candidate for each external perimeter. - // some of them will disappear (e.g. holes) - for (size_t e = 0; e < extrusions.size(); ++e) { - if (layer_lines[extrusions[e].first].origin_entity->is_loop() && - layer_lines[extrusions[e].first].is_external_perimeter()) { - std::vector copy(extrusions[e].second - extrusions[e].first); - for (size_t ex_line_idx = extrusions[e].first; ex_line_idx < extrusions[e].second; ++ex_line_idx) { - copy[ex_line_idx - extrusions[e].first] = layer_lines[ex_line_idx]; - } - islands.emplace_back(copy); - island_extrusions.push_back( { e }); - } + std::vector> islands; // these search trees will be used to determine to which island does the extrusion belong. + for (const ExPolygon& island : layer->lslices) { + islands.emplace_back(to_lines(island)); } - // backup code if islands not found - // If that happens, just make the first extrusion into island - it may be wrong, but it won't crash. - if (islands.empty() && !extrusions.empty()) { - std::vector copy(extrusions[0].second - extrusions[0].first); - for (size_t ex_line_idx = extrusions[0].first; ex_line_idx < extrusions[0].second; ++ex_line_idx) { - copy[ex_line_idx - extrusions[0].first] = layer_lines[ex_line_idx]; - } - islands.emplace_back(copy); - island_extrusions.push_back( { 0 }); - } - - // assign non external extrusions to islands - for (size_t e = 0; e < extrusions.size(); ++e) { - if (!layer_lines[extrusions[e].first].origin_entity->is_loop() || - !layer_lines[extrusions[e].first].is_external_perimeter()) { - bool island_assigned = false; - for (size_t i = 0; i < islands.size(); ++i) { - if (island_extrusions[i].empty()) { - continue; - } - size_t idx = 0; - Vec2f pt = Vec2f::Zero(); - if (islands[i].signed_distance_from_lines(layer_lines[extrusions[e].first].a, idx, pt) < 0) { - island_extrusions[i].push_back(e); - island_assigned = true; - break; - } - } - if (!island_assigned) { // If extrusion is not assigned for some reason, push it into the first island. As with the previous backup code, - // it may be wrong, but it won't crash - island_extrusions[0].push_back(e); + std::vector> island_extrusions(islands.size(), + std::vector{}); // final assigment of each extrusion to an island. + for (size_t extrusion_idx = 0; extrusion_idx < extrusions.size(); extrusion_idx++) { + Point second_point = Point::new_scale(layer_lines[extrusions[extrusion_idx].first].b); + for (size_t island_idx = 0; island_idx < islands.size(); island_idx++) { + if (islands[island_idx].signed_distance_from_lines(second_point) <= 0.0) { + island_extrusions[island_idx].push_back(extrusion_idx); } } } @@ -553,10 +481,14 @@ std::tuple reckon_islands( } Island island { }; - island.external_lines.insert(island.external_lines.end(), - layer_lines.begin() + extrusions[island_ex[0]].first, - layer_lines.begin() + extrusions[island_ex[0]].second); for (size_t extrusion_idx : island_ex) { + + if (layer_lines[extrusions[extrusion_idx].first].is_external_perimeter()) { + island.external_lines.insert(island.external_lines.end(), + layer_lines.begin() + extrusions[extrusion_idx].first, + layer_lines.begin() + extrusions[extrusion_idx].second); + } + for (size_t lidx = extrusions[extrusion_idx].first; lidx < extrusions[extrusion_idx].second; ++lidx) { line_to_island_mapping[lidx] = result.islands.size(); const ExtrusionLine &line = layer_lines[lidx]; @@ -1050,7 +982,7 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid, #ifdef DETAILED_DEBUG_LOGS weakest_conn.print_info("weakest connection info: "); #endif - LinesDistancer island_lines_dist(island.external_lines); + LD island_lines_dist(island.external_lines); float unchecked_dist = params.min_distance_between_support_points + 1.0f; for (const ExtrusionLine &line : island.external_lines) { @@ -1059,12 +991,9 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid, unchecked_dist += line.len; } else { unchecked_dist = line.len; - Vec2f target_point; - size_t idx; Vec3f pivot_site_search_point = to_3d(Vec2f(line.b + (line.b - line.a).normalized() * 300.0f), layer_z); - island_lines_dist.signed_distance_from_lines(pivot_site_search_point.head<2>(), idx, - target_point); + auto [dist, nidx, target_point] = island_lines_dist.signed_distance_from_lines_extra(pivot_site_search_point.head<2>()); Vec3f support_point = to_3d(target_point, layer_z); auto force = part.is_stable_while_extruding(weakest_conn, line, support_point, layer_z, params); if (force > 0) { @@ -1147,7 +1076,7 @@ std::tuple> check_extrusions_and_build_graph(c } } #endif - LinesDistancer external_lines(layer_lines); + LD external_lines(layer_lines); layer_lines.clear(); prev_layer_grid = layer_grid; @@ -1199,7 +1128,7 @@ std::tuple> check_extrusions_and_build_graph(c } } #endif - external_lines = LinesDistancer(layer_lines); + external_lines = LD(layer_lines); layer_lines.clear(); prev_layer_grid = layer_grid; } From b49a2425ca92512d4a2d0dfdb3e85817dad60dcd Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Tue, 4 Oct 2022 19:27:15 +0200 Subject: [PATCH 05/29] Improve Lines Distancer quality, use it also in SeamPlacer --- src/libslic3r/AABBTreeLines.hpp | 20 +++++++++-- src/libslic3r/ExPolygon.hpp | 23 +++++++++++++ src/libslic3r/GCode/SeamPlacer.cpp | 53 ++++-------------------------- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 7d6ff1ccc6..89a8a7cd58 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -1,6 +1,8 @@ #ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_ #define SRC_LIBSLIC3R_AABBTREELINES_HPP_ +#include "Utils.hpp" +#include "libslic3r.h" #include "libslic3r/AABBTreeIndirect.hpp" #include "libslic3r/Line.hpp" #include @@ -127,12 +129,26 @@ public: auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out); if (distance < 0) { return {std::numeric_limits::infinity(), nearest_line_index_out, nearest_point_out}; } - distance = sqrt(distance); const LineType &line = lines[nearest_line_index_out]; Vec<2, Floating> v1 = (line.b - line.a).template cast(); Vec<2, Floating> v2 = (point - line.a).template cast(); - if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) { distance *= -1.0; } + auto d1 = (v1.x() * v2.y()) - (v1.y() * v2.x()); + + LineType second_line = line; + if ((line.a.template cast() - nearest_point_out).squaredNorm() < SCALED_EPSILON) { + second_line = lines[prev_idx_modulo(nearest_line_index_out, lines.size())]; + } else { + second_line = lines[next_idx_modulo(nearest_line_index_out, lines.size())]; + } + v1 = (second_line.b - second_line.a).template cast(); + v2 = (point - second_line.a).template cast(); + auto d2 = (v1.x() * v2.y()) - (v1.y() * v2.x()); + + auto d = abs(d1) > abs(d2) ? d1 : d2; + + if (d > 0.0) { distance *= -1.0; } + return {distance, nearest_line_index_out, nearest_point_out}; } diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 3e42c86707..7f2aac6281 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_ExPolygon_hpp_ #define slic3r_ExPolygon_hpp_ +#include "Point.hpp" #include "libslic3r.h" #include "Polygon.hpp" #include "Polyline.hpp" @@ -124,6 +125,28 @@ inline Lines to_lines(const ExPolygons &src) return lines; } +inline std::vector to_linesf(const ExPolygons &src) +{ + size_t n_lines = 0; + for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) { + n_lines += it_expoly->contour.points.size(); + for (size_t i = 0; i < it_expoly->holes.size(); ++ i) + n_lines += it_expoly->holes[i].points.size(); + } + std::vector lines; + lines.reserve(n_lines); + for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) { + for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) { + const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points; + for (Points::const_iterator it = points.begin(); it != points.end()-1; ++it) + lines.push_back(Linef(unscaled(*it), unscaled(*(it + 1)))); + lines.push_back(Linef(unscaled(points.back()), unscaled(points.front()))); + } + } + return lines; +} + + inline Polylines to_polylines(const ExPolygon &src) { Polylines polylines; diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 926538ec9c..e18984a641 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -1,6 +1,7 @@ #include "SeamPlacer.hpp" #include "Color.hpp" +#include "Polygon.hpp" #include "PrintConfig.hpp" #include "tbb/parallel_for.h" #include "tbb/blocked_range.h" @@ -995,49 +996,6 @@ void pick_random_seam_point(const std::vector &perimeter_points, perimeter.finalized = true; } -class PerimeterDistancer { - std::vector lines; - AABBTreeIndirect::Tree<2, double> tree; - -public: - PerimeterDistancer(const Layer *layer) { - ExPolygons layer_outline = layer->lslices; - for (const ExPolygon &island : layer_outline) { - assert(island.contour.is_counter_clockwise()); - for (const auto &line : island.contour.lines()) { - lines.emplace_back(unscale(line.a), unscale(line.b)); - } - for (const Polygon &hole : island.holes) { - assert(hole.is_clockwise()); - for (const auto &line : hole.lines()) { - lines.emplace_back(unscale(line.a), unscale(line.b)); - } - } - } - tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines); - } - - float distance_from_perimeter(const Vec2f &point) const { - Vec2d p = point.cast(); - size_t hit_idx_out { }; - Vec2d hit_point_out = Vec2d::Zero(); - auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out); - if (distance < 0) { - return std::numeric_limits::max(); - } - - distance = sqrt(distance); - const Linef &line = lines[hit_idx_out]; - Vec2d v1 = line.b - line.a; - Vec2d v2 = p - line.a; - if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) { - distance *= -1; - } - return distance; - } -} -; - } // namespace SeamPlacerImpl // Parallel process and extract each perimeter polygon of the given print object. @@ -1089,13 +1047,14 @@ void SeamPlacer::calculate_candidates_visibility(const PrintObject *po, void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) { using namespace SeamPlacerImpl; + using PerimeterDistancer = AABBTreeLines::LinesDistancer; std::vector &layers = m_seam_per_object[po].layers; tbb::parallel_for(tbb::blocked_range(0, layers.size()), [po, &layers](tbb::blocked_range r) { std::unique_ptr prev_layer_distancer; if (r.begin() > 0) { // previous layer exists - prev_layer_distancer = std::make_unique(po->layers()[r.begin() - 1]); + prev_layer_distancer = std::make_unique(to_linesf(po->layers()[r.begin() - 1]->lslices)); } for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) { @@ -1106,12 +1065,12 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) } }; bool should_compute_layer_embedding = regions_with_perimeter > 1; - std::unique_ptr current_layer_distancer = std::make_unique(po->layers()[layer_idx]); + std::unique_ptr current_layer_distancer = std::make_unique(to_linesf(po->layers()[layer_idx]->lslices)); for (SeamCandidate &perimeter_point : layers[layer_idx].points) { Vec2f point = Vec2f { perimeter_point.position.head<2>() }; if (prev_layer_distancer.get() != nullptr) { - perimeter_point.overhang = prev_layer_distancer->distance_from_perimeter(point) + perimeter_point.overhang = prev_layer_distancer->signed_distance_from_lines(point.cast()) + 0.6f * perimeter_point.perimeter.flow_width - tan(SeamPlacer::overhang_angle_threshold) * po->layers()[layer_idx]->height; @@ -1120,7 +1079,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) } if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam) - perimeter_point.embedded_distance = current_layer_distancer->distance_from_perimeter(point) + perimeter_point.embedded_distance = current_layer_distancer->signed_distance_from_lines(point.cast()) + 0.6f * perimeter_point.perimeter.flow_width; } } From e02aed31d259c030dae05fed1d5c0a5cd958a144 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Wed, 5 Oct 2022 14:50:22 +0200 Subject: [PATCH 06/29] Added new query to AABBTree: all primitives (triangles/lines) within radius --- src/libslic3r/AABBTreeIndirect.hpp | 60 ++++++++++++++++++++++++++- src/libslic3r/AABBTreeLines.hpp | 49 +++++++++++++++------- tests/libslic3r/test_aabbindirect.cpp | 20 +++++++++ 3 files changed, 114 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/AABBTreeIndirect.hpp b/src/libslic3r/AABBTreeIndirect.hpp index 3db74b8b91..b4b74ef138 100644 --- a/src/libslic3r/AABBTreeIndirect.hpp +++ b/src/libslic3r/AABBTreeIndirect.hpp @@ -519,7 +519,7 @@ namespace detail { const VectorType origin; inline VectorType closest_point_to_origin(size_t primitive_index, - ScalarType& squared_distance){ + ScalarType& squared_distance) const { const auto &triangle = this->faces[primitive_index]; VectorType closest_point = closest_point_to_triangle(origin, this->vertices[triangle(0)].template cast(), @@ -613,6 +613,37 @@ namespace detail { return up_sqr_d; } + template + static inline void indexed_primitives_within_distance_squared_recurisve(const IndexedPrimitivesDistancerType &distancer, + size_t node_idx, + Scalar squared_distance_limit, + std::vector &found_primitives_indices) + { + const auto &node = distancer.tree.node(node_idx); + assert(node.is_valid()); + if (node.is_leaf()) { + Scalar sqr_dist; + distancer.closest_point_to_origin(node.idx, sqr_dist); + if (sqr_dist < squared_distance_limit) { found_primitives_indices.push_back(node.idx); } + } else { + size_t left_node_idx = node_idx * 2 + 1; + size_t right_node_idx = left_node_idx + 1; + const auto &node_left = distancer.tree.node(left_node_idx); + const auto &node_right = distancer.tree.node(right_node_idx); + assert(node_left.is_valid()); + assert(node_right.is_valid()); + + if (node_left.bbox.squaredExteriorDistance(distancer.origin) < squared_distance_limit) { + indexed_primitives_within_distance_squared_recurisve(distancer, left_node_idx, squared_distance_limit, + found_primitives_indices); + } + if (node_right.bbox.squaredExteriorDistance(distancer.origin) < squared_distance_limit) { + indexed_primitives_within_distance_squared_recurisve(distancer, right_node_idx, squared_distance_limit, + found_primitives_indices); + } + } + } + } // namespace detail // Build a balanced AABB Tree over an indexed triangles set, balancing the tree @@ -799,6 +830,33 @@ inline bool is_any_triangle_in_radius( return hit_point.allFinite(); } +// Returns all triangles within the given radius limit +template +inline std::vector all_triangles_in_radius( + // Indexed triangle set - 3D vertices. + const std::vector &vertices, + // Indexed triangle set - triangular faces, references to vertices. + const std::vector &faces, + // AABBTreeIndirect::Tree over vertices & faces, bounding boxes built with the accuracy of vertices. + const TreeType &tree, + // Point to which the distances on the indexed triangle set is searched for. + const VectorType &point, + //Square of maximum distance in which triangles are searched for + typename VectorType::Scalar max_distance_squared) +{ + auto distancer = detail::IndexedTriangleSetDistancer + { vertices, faces, tree, point }; + + if(tree.empty()) + { + return {}; + } + + std::vector found_triangles{}; + detail::indexed_primitives_within_distance_squared_recurisve(distancer, size_t(0), max_distance_squared, found_triangles); + return found_triangles; +} + // Traverse the tree and return the index of an entity whose bounding box // contains a given point. Returns size_t(-1) when the point is outside. diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 89a8a7cd58..8432feda74 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -6,6 +6,7 @@ #include "libslic3r/AABBTreeIndirect.hpp" #include "libslic3r/Line.hpp" #include +#include namespace Slic3r { @@ -26,7 +27,7 @@ struct IndexedLinesDistancer { const VectorType origin; inline VectorType closest_point_to_origin(size_t primitive_index, - ScalarType &squared_distance) { + ScalarType &squared_distance) const { Vec nearest_point; const LineType &line = lines[primitive_index]; squared_distance = line_alg::distance_to_squared(line, origin.template cast(), &nearest_point); @@ -90,20 +91,35 @@ inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over // Finding a closest line, its closest point and squared distance to the closest point // Returns squared distance to the closest point or -1 if the input is empty. template -inline typename VectorType::Scalar squared_distance_to_indexed_lines( - const std::vector &lines, - const TreeType &tree, - const VectorType &point, - size_t &hit_idx_out, - Eigen::PlainObjectBase &hit_point_out) - { - using Scalar = typename VectorType::Scalar; - auto distancer = detail::IndexedLinesDistancer - { lines, tree, point }; +inline typename VectorType::Scalar squared_distance_to_indexed_lines(const std::vector &lines, + const TreeType &tree, + const VectorType &point, + size_t &hit_idx_out, + Eigen::PlainObjectBase &hit_point_out) +{ + using Scalar = typename VectorType::Scalar; + auto distancer = detail::IndexedLinesDistancer{lines, tree, point}; return tree.empty() ? - Scalar(-1) : - AABBTreeIndirect::detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0), - std::numeric_limits::infinity(), hit_idx_out, hit_point_out); + Scalar(-1) : + AABBTreeIndirect::detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0), + std::numeric_limits::infinity(), + hit_idx_out, hit_point_out); +} + +// Returns all lines within the given radius limit +template +inline std::vector all_lines_in_radius(const std::vector &lines, + const TreeType &tree, + const VectorType &point, + typename VectorType::Scalar max_distance_squared) +{ + auto distancer = detail::IndexedLinesDistancer{lines, tree, point}; + + if (tree.empty()) { return {}; } + + std::vector found_lines{}; + AABBTreeIndirect::detail::indexed_primitives_within_distance_squared_recurisve(distancer, size_t(0), max_distance_squared, found_lines); + return found_lines; } template class LinesDistancer @@ -158,6 +174,11 @@ public: return dist; } + std::vector all_lines_in_radius(const Vec<2, typename LineType::Scalar> &point, Floating radius) + { + return all_lines_in_radius(this->lines, this->tree, point, radius * radius); + } + const LineType &get_line(size_t line_idx) const { return lines[line_idx]; } const std::vector &get_lines() const { return lines; } diff --git a/tests/libslic3r/test_aabbindirect.cpp b/tests/libslic3r/test_aabbindirect.cpp index 87cf80943a..def349042e 100644 --- a/tests/libslic3r/test_aabbindirect.cpp +++ b/tests/libslic3r/test_aabbindirect.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -87,6 +88,25 @@ TEST_CASE("Creating a several 2d lines, testing closest point query", "[AABBIndi REQUIRE(hit_point_out.y() == Approx(0.5)); } +TEST_CASE("Creating a several 2d lines, testing all lines in radius query", "[AABBIndirect]") +{ + std::vector lines { }; + lines.push_back(Linef(Vec2d(0.0, 0.0), Vec2d(10.0, 0.0))); + lines.push_back(Linef(Vec2d(-10.0, 10.0), Vec2d(10.0, -10.0))); + lines.push_back(Linef(Vec2d(-2.0, -1.0), Vec2d(-2.0, 1.0))); + lines.push_back(Linef(Vec2d(-1.0, -1.0), Vec2d(-1.0, -1.0))); + lines.push_back(Linef(Vec2d(1.0, 1.0), Vec2d(1.0, 1.0))); + + auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines); + + auto indices = AABBTreeLines::all_lines_in_radius(lines, tree, Vec2d{1.0,1.0}, 4.0); + + REQUIRE(std::find(indices.begin(),indices.end(), 0) != indices.end()); + REQUIRE(std::find(indices.begin(),indices.end(), 1) != indices.end()); + REQUIRE(std::find(indices.begin(),indices.end(), 4) != indices.end()); + REQUIRE(indices.size() == 3); +} + #if 0 #include "libslic3r/EdgeGrid.hpp" #include From 8484f74967d5efd0ad9e1a2cb1acd542e325b95f Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Wed, 5 Oct 2022 16:28:41 +0200 Subject: [PATCH 07/29] Sync with PrusaSlicer-settings --- resources/profiles/TriLAB.idx | 2 + resources/profiles/TriLAB.ini | 188 +++++++++++++++++++++++++++------- 2 files changed, 154 insertions(+), 36 deletions(-) diff --git a/resources/profiles/TriLAB.idx b/resources/profiles/TriLAB.idx index 75819e135a..9ba40c9fc6 100644 --- a/resources/profiles/TriLAB.idx +++ b/resources/profiles/TriLAB.idx @@ -1,3 +1,5 @@ +min_slic3r_version = 2.5.0-alpha0 +1.0.2 Added home to start gcode before heating bed, added DeltiQ 2 material PLA Prusament, fixed gcode for pause print, improved output filename template(added printhead code, added filament used length, truncated timestamp) min_slic3r_version = 2.4.1-rc1 1.0.1 Fix missing AzteQ Industrial ABS material for 0.6, 0.8 nozzle, enabled elefant foot compensation 1.0.0 Added AzteQ Industrial profiles for 0.8 nozzle, updated spool weight and filament cost, some minor setting improvements diff --git a/resources/profiles/TriLAB.ini b/resources/profiles/TriLAB.ini index b5c31d1832..62ddd94a23 100644 --- a/resources/profiles/TriLAB.ini +++ b/resources/profiles/TriLAB.ini @@ -6,7 +6,7 @@ name = TriLAB # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.0.1 +config_version = 1.0.2 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/ # changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% @@ -22,7 +22,7 @@ technology = FFF family = AzteQ bed_model = aq_bed.stl bed_texture = aq_bed_texture.svg -default_materials = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum);AzteQ Industrial (Door Opened) - PLA - Generic;AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum);AzteQ Industrial - ABS - ExtraFill (Fillamentum);AzteQ Industrial - ABS - Generic;AzteQ Industrial - ASA - ExtraFill (Fillamentum);AzteQ Industrial - ASA - Generic;AzteQ Industrial - ASA - Prusament (Prusa);AzteQ Industrial - PA - Nylon PA12 (Fiberlogy);AzteQ Industrial - PC Blend - Prusament (Prusa);AzteQ Industrial - PC - PolyMax (Polymaker);AzteQ Industrial - PC - PolyMax (Polymaker) @0.6 nozzle;AzteQ Industrial - PC/ABS - (Fillamentum);AzteQ Industrial - PC/ABS - (Fillamentum) @0.6 nozzle;AzteQ Industrial - PA - Nylon FX256 (Fillamentum);AzteQ Industrial - PA - Nylon FX256 (Fillamentum) @0.6 nozzle;AzteQ Industrial - ABS - Generic @0.8 nozzle;AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - Prusament (Prusa) @0.8 nozzle;AzteQ Industrial - PC Blend - Prusament (Prusa) @0.8 nozzle +default_materials = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum);AzteQ Industrial (Door Opened) - PLA - Generic;AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum);AzteQ Industrial - ABS - ExtraFill (Fillamentum);AzteQ Industrial - ABS - Generic;AzteQ Industrial - ASA - ExtraFill (Fillamentum);AzteQ Industrial - ASA - Generic;AzteQ Industrial - ASA - Prusament (Prusa Polymers);AzteQ Industrial - PA - Nylon PA12 (Fiberlogy);AzteQ Industrial - PC Blend - Prusament (Prusa Polymers);AzteQ Industrial - PC - PolyMax (Polymaker);AzteQ Industrial - PC - PolyMax (Polymaker) @0.6 nozzle;AzteQ Industrial - PC/ABS - (Fillamentum);AzteQ Industrial - PC/ABS - (Fillamentum) @0.6 nozzle;AzteQ Industrial - PA - Nylon FX256 (Fillamentum);AzteQ Industrial - PA - Nylon FX256 (Fillamentum) @0.6 nozzle;AzteQ Industrial - ABS - Generic @0.8 nozzle;AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - Prusament (Prusa Polymers) @0.8 nozzle;AzteQ Industrial - PC Blend - Prusament (Prusa Polymers) @0.8 nozzle [printer_model:DQ2] name = DeltiQ 2 @@ -31,7 +31,7 @@ technology = FFF family = DeltiQ 2 bed_model = dq2_bed.stl bed_texture = dq2_bed_texture.svg -default_materials = DeltiQ - PLA - Generic;DeltiQ - PLA - ExtraFill (Fillamentum);DeltiQ - PETG - Generic;DeltiQ - PETG (Devil Design);DeltiQ - ABS - Generic;DeltiQ - ABS - ExtraFill (Fillamentum);DeltiQ - ASA - ExtraFill (Fillamentum);DeltiQ - ASA - ASA 275 (Spectrum);DeltiQ - CPE - HG100 (Fillamentum);DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle;DeltiQ - PETG (Devil Design) @0.25 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - PETG (Devil Design) @0.6 nozzle;DeltiQ - ABS - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ASA 275 (Spectrum) @0.6 nozzle;DeltiQ - CPE - HG100 (Fillamentum) @0.6 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle;DeltiQ - PETG (Devil Design) @0.8 nozzle;DeltiQ - PA - Nylon PA12 (Fiberlogy);DeltiQ - PA - Nylon CF15 Carbon (Fillamentum);DeltiQ - MoldLay (Wax-Alike) +default_materials = DeltiQ - PLA - Generic;DeltiQ - PLA - Prusament (Prusa Polymers); DeltiQ - PLA - ExtraFill (Fillamentum);DeltiQ - PETG - Generic;DeltiQ - PETG (Devil Design);DeltiQ - ABS - Generic;DeltiQ - ABS - ExtraFill (Fillamentum);DeltiQ - ASA - ExtraFill (Fillamentum);DeltiQ - ASA - ASA 275 (Spectrum);DeltiQ - CPE - HG100 (Fillamentum);DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle;DeltiQ - PETG (Devil Design) @0.25 nozzle;DeltiQ - PLA - Prusament (Prusa Polymers) @0.6 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - PETG (Devil Design) @0.6 nozzle;DeltiQ - ABS - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ASA 275 (Spectrum) @0.6 nozzle;DeltiQ - CPE - HG100 (Fillamentum) @0.6 nozzle;DeltiQ - PLA - Prusament (Prusa Polymers) @0.8 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle;DeltiQ - PETG (Devil Design) @0.8 nozzle;DeltiQ - PA - Nylon PA12 (Fiberlogy);DeltiQ - PA - Nylon CF15 Carbon (Fillamentum);DeltiQ - MoldLay (Wax-Alike) [printer_model:DQ2P] name = DeltiQ 2 Plus @@ -40,7 +40,7 @@ technology = FFF family = DeltiQ 2 bed_model = dq2_bed.stl bed_texture = dq2_bed_texture.svg -default_materials = DeltiQ - PLA - Generic;DeltiQ - PLA - ExtraFill (Fillamentum);DeltiQ - PETG - Generic;DeltiQ - PETG (Devil Design);DeltiQ - ABS - Generic;DeltiQ - ABS - ExtraFill (Fillamentum);DeltiQ - ASA - ExtraFill (Fillamentum);DeltiQ - ASA - ASA 275 (Spectrum);DeltiQ - CPE - HG100 (Fillamentum);DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle;DeltiQ - PETG (Devil Design) @0.25 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - PETG (Devil Design) @0.6 nozzle;DeltiQ - ABS - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ASA 275 (Spectrum) @0.6 nozzle;DeltiQ - CPE - HG100 (Fillamentum) @0.6 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle;DeltiQ - PETG (Devil Design) @0.8 nozzle;DeltiQ - PA - Nylon PA12 (Fiberlogy);DeltiQ - PA - Nylon CF15 Carbon (Fillamentum);DeltiQ - MoldLay (Wax-Alike) +default_materials = DeltiQ - PLA - Generic;DeltiQ - PLA - Prusament (Prusa Polymers); DeltiQ - PLA - ExtraFill (Fillamentum);DeltiQ - PETG - Generic;DeltiQ - PETG (Devil Design);DeltiQ - ABS - Generic;DeltiQ - ABS - ExtraFill (Fillamentum);DeltiQ - ASA - ExtraFill (Fillamentum);DeltiQ - ASA - ASA 275 (Spectrum);DeltiQ - CPE - HG100 (Fillamentum);DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle;DeltiQ - PETG (Devil Design) @0.25 nozzle;DeltiQ - PLA - Prusament (Prusa Polymers) @0.6 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - PETG (Devil Design) @0.6 nozzle;DeltiQ - ABS - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ExtraFill (Fillamentum) @0.6 nozzle;DeltiQ - ASA - ASA 275 (Spectrum) @0.6 nozzle;DeltiQ - CPE - HG100 (Fillamentum) @0.6 nozzle;DeltiQ - PLA - Prusament (Prusa Polymers) @0.8 nozzle;DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle;DeltiQ - PETG (Devil Design) @0.8 nozzle;DeltiQ - PA - Nylon PA12 (Fiberlogy);DeltiQ - PA - Nylon CF15 Carbon (Fillamentum);DeltiQ - MoldLay (Wax-Alike) [printer_model:DQ2+FP2] name = DeltiQ 2 + FlexPrint 2 @@ -49,7 +49,7 @@ technology = FFF family = DeltiQ 2 bed_model = dq2_bed.stl bed_texture = dq2_bed_texture.svg -default_materials = DeltiQ FP2 - PLA - Generic;DeltiQ FP2 - PLA - ExtraFill (Fillamentum);DeltiQ FP2 - PETG - Generic;DeltiQ FP2 - PETG (Devil Design);DeltiQ FP2 - ABS - Generic;DeltiQ FP2 - ABS - ExtraFill (Fillamentum);DeltiQ FP2 - ASA - ExtraFill (Fillamentum);DeltiQ FP2 - CPE - HG100 (Fillamentum);DeltiQ FP2 - FLEX - Generic;DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 93A (SMARTFIL);DeltiQ FP2 - PEBA 90A - FlexFill (Fillamentum) +default_materials = DeltiQ FP2 - PLA - Generic;DeltiQ FP2 - PLA - Prusament (Prusa Polymers);DeltiQ FP2 - PLA - ExtraFill (Fillamentum);DeltiQ FP2 - PETG - Generic;DeltiQ FP2 - PETG (Devil Design);DeltiQ FP2 - ABS - Generic;DeltiQ FP2 - ABS - ExtraFill (Fillamentum);DeltiQ FP2 - ASA - ExtraFill (Fillamentum);DeltiQ FP2 - CPE - HG100 (Fillamentum);DeltiQ FP2 - FLEX - Generic;DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 93A (SMARTFIL);DeltiQ FP2 - PEBA 90A - FlexFill (Fillamentum) [printer_model:DQ2P+FP2] name = DeltiQ 2 Plus + FlexPrint 2 @@ -58,7 +58,7 @@ technology = FFF family = DeltiQ 2 bed_model = dq2_bed.stl bed_texture = dq2_bed_texture.svg -default_materials = DeltiQ FP2 - PLA - Generic;DeltiQ FP2 - PLA - ExtraFill (Fillamentum);DeltiQ FP2 - PETG - Generic;DeltiQ FP2 - PETG (Devil Design);DeltiQ FP2 - ABS - Generic;DeltiQ FP2 - ABS - ExtraFill (Fillamentum);DeltiQ FP2 - ASA - ExtraFill (Fillamentum);DeltiQ FP2 - CPE - HG100 (Fillamentum);DeltiQ FP2 - FLEX - Generic;DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 93A (SMARTFIL);DeltiQ FP2 - PEBA 90A - FlexFill (Fillamentum) +default_materials = DeltiQ FP2 - PLA - Generic;DeltiQ FP2 - PLA - Prusament (Prusa Polymers);DeltiQ FP2 - PLA - ExtraFill (Fillamentum);DeltiQ FP2 - PETG - Generic;DeltiQ FP2 - PETG (Devil Design);DeltiQ FP2 - ABS - Generic;DeltiQ FP2 - ABS - ExtraFill (Fillamentum);DeltiQ FP2 - ASA - ExtraFill (Fillamentum);DeltiQ FP2 - CPE - HG100 (Fillamentum);DeltiQ FP2 - FLEX - Generic;DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum);DeltiQ FP2 - TPU 93A (SMARTFIL);DeltiQ FP2 - PEBA 90A - FlexFill (Fillamentum) [printer_model:DQ2+FP] name = DeltiQ 2 + FlexPrint @@ -67,7 +67,7 @@ technology = FFF family = DeltiQ 2 bed_model = dq2_bed.stl bed_texture = dq2_bed_texture.svg -default_materials = DeltiQ FP - PLA - Generic;DeltiQ FP - PLA - ExtraFill (Fillamentum);DeltiQ FP - PETG - Generic;DeltiQ FP - PETG (Devil Design);DeltiQ FP - ABS - Generic;DeltiQ FP - ABS - ExtraFill (Fillamentum);DeltiQ FP - ASA - ExtraFill (Fillamentum);DeltiQ FP - CPE - HG100 (Fillamentum);DeltiQ FP - FLEX - Generic +default_materials = DeltiQ FP - PLA - Generic;DeltiQ FP - PLA - Prusament (Prusa Polymers);DeltiQ FP - PLA - ExtraFill (Fillamentum);DeltiQ FP - PETG - Generic;DeltiQ FP - PETG (Devil Design);DeltiQ FP - ABS - Generic;DeltiQ FP - ABS - ExtraFill (Fillamentum);DeltiQ FP - ASA - ExtraFill (Fillamentum);DeltiQ FP - CPE - HG100 (Fillamentum);DeltiQ FP - FLEX - Generic [printer_model:DQ2P+FP] name = DeltiQ 2 Plus + FlexPrint @@ -76,7 +76,7 @@ technology = FFF family = DeltiQ 2 bed_model = dq2_bed.stl bed_texture = dq2_bed_texture.svg -default_materials = DeltiQ FP - PLA - Generic;DeltiQ FP - PLA - ExtraFill (Fillamentum);DeltiQ FP - PETG - Generic;DeltiQ FP - PETG (Devil Design);DeltiQ FP - ABS - Generic;DeltiQ FP - ABS - ExtraFill (Fillamentum);DeltiQ FP - ASA - ExtraFill (Fillamentum);DeltiQ FP - CPE - HG100 (Fillamentum);DeltiQ FP - FLEX - Generic +default_materials = DeltiQ FP - PLA - Generic;DeltiQ FP - PLA - Prusament (Prusa Polymers);DeltiQ FP - PLA - ExtraFill (Fillamentum);DeltiQ FP - PETG - Generic;DeltiQ FP - PETG (Devil Design);DeltiQ FP - ABS - Generic;DeltiQ FP - ABS - ExtraFill (Fillamentum);DeltiQ FP - ASA - ExtraFill (Fillamentum);DeltiQ FP - CPE - HG100 (Fillamentum);DeltiQ FP - FLEX - Generic [printer_model:DQM] name = DeltiQ M @@ -158,7 +158,7 @@ min_skirt_length = 4 notes = only_retract_when_crossing_perimeters = 0 ooze_prevention = 0 -output_filename_format = {input_filename_base}_{printer_model}_{filament_type[0]}_{layer_height}mm_{print_time}_{timestamp}.gcode +output_filename_format = {input_filename_base}_{printer_model}_{filament_notes[0]}_{filament_type[0]}_{print_time}_{round(used_filament)}m_{year}{zdigits(month, 2)}{zdigits(day, 2)}-{hour}{minute}.gcode overhangs = 1 perimeter_acceleration = 1500 perimeter_extruder = 1 @@ -459,7 +459,7 @@ min_skirt_length = 4 notes = only_retract_when_crossing_perimeters = 0 ooze_prevention = 0 -output_filename_format = {input_filename_base}_{printer_model}_{filament_type[0]}_{layer_height}mm_{print_time}_{timestamp}.gcode +output_filename_format = {input_filename_base}_{printer_model}_{filament_notes[0]}_{filament_type[0]}_{print_time}_{round(used_filament)}m_{year}{zdigits(month, 2)}{zdigits(day, 2)}-{hour}{minute}.gcode overhangs = 1 perimeter_acceleration = 1500 perimeter_extruder = 1 @@ -681,7 +681,6 @@ extrusion_multiplier = 1 filament_colour = #FF0000 filament_diameter = 1.75 filament_minimal_purge_on_wipe_tower = 15 -filament_notes = "" filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" filament_settings_id = "" filament_soluble = 0 @@ -691,6 +690,7 @@ end_filament_gcode = "; FILAMENT_END_GCODE" filament_cost = 0 filament_spool_weight = 250 filament_vendor = Generic +filament_notes = "LP-CU" # DeltiQ PLA filaments # @@ -719,6 +719,59 @@ min_print_speed = 10 slowdown_below_layer_time = 4 temperature = 215 +[filament:DeltiQ - PLA - Prusament (Prusa Polymers)] +inherits = DeltiQ - PLA - Generic +bed_temperature = 55 +bridge_fan_speed = 100 +cooling = 1 +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_cost = 550 +filament_density = 1.24 +filament_deretract_speed = nil +filament_max_volumetric_speed = 8 +filament_retract_before_travel = 2 +filament_retract_before_wipe = 90% +filament_retract_layer_change = 1 +filament_retract_length = 4 +filament_retract_lift = 0.2 +filament_retract_lift_above = nil +filament_retract_lift_below = nil +filament_retract_restart_extra = nil +filament_retract_speed = 30 +filament_spool_weight = 201 +filament_vendor = Prusa Polymers +filament_wipe = 1 +first_layer_bed_temperature = 55 +first_layer_temperature = 215 +full_fan_speed_layer = 0 +max_fan_speed = 100 +min_fan_speed = 100 +min_print_speed = 10 +slowdown_below_layer_time = 4 +temperature = 215 + +[filament:DeltiQ - PLA - Prusament (Prusa Polymers) @0.6 nozzle] +inherits = DeltiQ - PLA - Prusament (Prusa Polymers) +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 +filament_max_volumetric_speed = 15 +filament_notes = "BN" + +[filament:DeltiQ - PLA - Prusament (Prusa Polymers) @0.8 nozzle] +inherits = DeltiQ - PLA - Prusament (Prusa Polymers) +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.8 +disable_fan_first_layers = 1 +filament_max_volumetric_speed = 40 +first_layer_temperature = 230 +slowdown_below_layer_time = 8 +temperature = 230 +filament_retract_layer_change = 0 +filament_retract_length = 4.1 +filament_retract_speed = 45 +filament_deretract_speed = 25 +filament_notes = "ZL" + [filament:DeltiQ - PLA - ExtraFill (Fillamentum)] inherits = DeltiQ - PLA - Generic filament_cost = 24.27 @@ -729,11 +782,13 @@ filament_vendor = Fillamentum [filament:DeltiQ - PLA - ExtraFill (Fillamentum) @0.25 nozzle] inherits = DeltiQ - PLA - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.25 +filament_notes = "BN" [filament:DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle] inherits = DeltiQ - PLA - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle] inherits = DeltiQ - PLA - ExtraFill (Fillamentum) @@ -747,6 +802,7 @@ filament_retract_layer_change = 0 filament_retract_length = 4.1 filament_retract_speed = 45 filament_deretract_speed = 25 +filament_notes = "ZL" [filament:DeltiQ FP - PLA - Generic] inherits = DeltiQ - PLA - Generic @@ -767,6 +823,39 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and p filament_retract_length = 1.2 filament_retract_speed = 28 +[filament:DeltiQ FP2 - PLA - Prusament (Prusa Polymers)] +inherits = DeltiQ FP2 - PLA - Generic +bed_temperature = 55 +bridge_fan_speed = 100 +cooling = 1 +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 100 +filament_cost = 550 +filament_density = 1.24 +filament_deretract_speed = nil +filament_max_volumetric_speed = 8 +filament_retract_before_travel = 2 +filament_retract_before_wipe = 90% +filament_retract_layer_change = 1 +filament_retract_length = 1.2 +filament_retract_lift = 0.2 +filament_retract_lift_above = nil +filament_retract_lift_below = nil +filament_retract_restart_extra = nil +filament_retract_speed = 28 +filament_spool_weight = 201 +filament_vendor = Prusa Polymers +filament_wipe = 1 +first_layer_bed_temperature = 55 +first_layer_temperature = 215 +full_fan_speed_layer = 0 +max_fan_speed = 100 +min_fan_speed = 100 +min_print_speed = 10 +slowdown_below_layer_time = 4 +temperature = 215 + [filament:DeltiQ FP2 - PLA - ExtraFill (Fillamentum)] inherits = DeltiQ FP2 - PLA - Generic filament_cost = 24.27 @@ -817,11 +906,13 @@ temperature = 220 max_fan_speed = 65 min_fan_speed = 40 bridge_fan_speed = 100 +filament_notes = "JW" [filament:DeltiQ - PETG (Devil Design) @0.6 nozzle] inherits = DeltiQ - PETG (Devil Design) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:DeltiQ - PETG (Devil Design) @0.8 nozzle] inherits = DeltiQ - PETG (Devil Design) @@ -836,6 +927,7 @@ filament_retract_speed = 45 filament_deretract_speed = 25 filament_retract_before_wipe = 80% filament_wipe = 1 +filament_notes = "ZL" [filament:DeltiQ FP - PETG - Generic] inherits = DeltiQ - PETG - Generic @@ -902,6 +994,7 @@ filament_vendor = Fillamentum inherits = DeltiQ - ABS - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:DeltiQ FP - ABS - Generic] inherits = DeltiQ - ABS - Generic @@ -946,6 +1039,7 @@ temperature = 265 inherits = DeltiQ - ASA - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:DeltiQ FP - ASA - ExtraFill (Fillamentum)] inherits = DeltiQ - ASA - ExtraFill (Fillamentum) @@ -989,7 +1083,7 @@ temperature = 230 inherits = DeltiQ - ASA - ASA 275 (Spectrum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 - +filament_notes = "BN" # DeltiQ CPE filaments # @@ -1026,6 +1120,7 @@ temperature = 260 inherits = DeltiQ - CPE - HG100 (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:DeltiQ FP - CPE - HG100 (Fillamentum)] inherits = DeltiQ - CPE - HG100 (Fillamentum) @@ -1250,6 +1345,7 @@ filament_vendor = Wax-Alike [filament:*AzteQ common*] inherits = *DeltiQ common* compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.4 +filament_notes = "CU" # AzteQ Industrial filaments # @@ -1294,6 +1390,7 @@ temperature = 210 inherits = AzteQ Industrial (Door Opened) - PLA - Generic compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum)] inherits = AzteQ Industrial (Door Opened) - PLA - Generic @@ -1306,6 +1403,7 @@ filament_spool_weight = 229 inherits = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum)] inherits = *AzteQ common* @@ -1349,6 +1447,7 @@ temperature = 215 inherits = AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - ABS - Generic] inherits = *AzteQ common* @@ -1392,6 +1491,7 @@ temperature = 255 inherits = AzteQ Industrial - ABS - Generic compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - ABS - Generic @0.8 nozzle] inherits = AzteQ Industrial - ABS - Generic @@ -1405,6 +1505,7 @@ min_fan_speed = 50 filament_retract_length = 6.1 filament_max_volumetric_speed = 0 start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature" +filament_notes = "ZL" [filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum)] inherits = AzteQ Industrial - ABS - Generic @@ -1416,11 +1517,13 @@ filament_spool_weight = 229 [filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle] inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 +filament_notes = "BN" [filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle] inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8 extrusion_multiplier = 0.95 +filament_notes = "ZL" [filament:AzteQ Industrial - PC/ABS - (Fillamentum)] inherits = AzteQ Industrial - ABS - Generic @@ -1443,6 +1546,7 @@ filament_notes = "S180 ; Probing temperature" inherits = AzteQ Industrial - PC/ABS - (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - PC - PolyMax (Polymaker)] inherits = AzteQ Industrial - ABS - Generic @@ -1464,6 +1568,7 @@ filament_notes = "S180 ; Probing temperature" inherits = AzteQ Industrial - PC - PolyMax (Polymaker) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - ASA - Generic] inherits = *AzteQ common* @@ -1504,6 +1609,7 @@ temperature = 265 inherits = AzteQ Industrial - ASA - Generic compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - ASA - ExtraFill (Fillamentum)] inherits = AzteQ Industrial - ASA - Generic @@ -1520,6 +1626,7 @@ filament_density = 1.07 inherits = AzteQ Industrial - ASA - ExtraFill (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle] inherits = AzteQ Industrial - ASA - ExtraFill (Fillamentum) @@ -1533,27 +1640,29 @@ max_fan_speed = 100 min_fan_speed = 80 filament_retract_length = 6.1 filament_max_volumetric_speed = 0 +filament_notes = "ZL" -[filament:AzteQ Industrial - ASA - Prusament (Prusa)] +[filament:AzteQ Industrial - ASA - Prusament (Prusa Polymers)] inherits = AzteQ Industrial - ASA - Generic filament_cost = 29.16 filament_density = 1.07 filament_spool_weight = 201 -filament_vendor = Prusa +filament_vendor = Prusa Polymers first_layer_temperature = 260 max_fan_speed = 70 min_fan_speed = 70 start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S50 ; Set and wait - chamber temperature" temperature = 260 -[filament:AzteQ Industrial - ASA - Prusament (Prusa) @0.6 nozzle] -inherits = AzteQ Industrial - ASA - Prusament (Prusa) +[filament:AzteQ Industrial - ASA - Prusament (Prusa Polymers) @0.6 nozzle] +inherits = AzteQ Industrial - ASA - Prusament (Prusa Polymers) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" -[filament:AzteQ Industrial - ASA - Prusament (Prusa) @0.8 nozzle] -inherits = AzteQ Industrial - ASA - Prusament (Prusa) +[filament:AzteQ Industrial - ASA - Prusament (Prusa Polymers) @0.8 nozzle] +inherits = AzteQ Industrial - ASA - Prusament (Prusa Polymers) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8 first_layer_bed_temperature = 100 bed_temperature = 100 @@ -1564,6 +1673,7 @@ max_fan_speed = 80 min_fan_speed = 50 filament_retract_length = 4.1 filament_max_volumetric_speed = 0 +filament_notes = "ZL" [filament:AzteQ Industrial - PA - Nylon PA12 (Fiberlogy)] @@ -1611,6 +1721,7 @@ temperature = 255 inherits = AzteQ Industrial - PA - Nylon PA12 (Fiberlogy) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" [filament:AzteQ Industrial - PA - Nylon FX256 (Fillamentum)] inherits = *AzteQ common* @@ -1657,8 +1768,9 @@ temperature = 255 inherits = AzteQ Industrial - PA - Nylon FX256 (Fillamentum) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" -[filament:AzteQ Industrial - PC Blend - Prusament (Prusa)] +[filament:AzteQ Industrial - PC Blend - Prusament (Prusa Polymers)] inherits = *AzteQ common* bed_temperature = 100 bridge_fan_speed = 75 @@ -1683,7 +1795,7 @@ filament_retract_restart_extra = nil filament_retract_speed = 25 filament_soluble = 0 filament_type = PC -filament_vendor = Prusa +filament_vendor = Prusa Polymers filament_wipe = 1 first_layer_bed_temperature = 100 first_layer_temperature = 270 @@ -1696,13 +1808,14 @@ start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chambe temperature = 270 filament_notes = "S180 ; Probing temperature" -[filament:AzteQ Industrial - PC Blend - Prusament (Prusa) @0.6 nozzle] -inherits = AzteQ Industrial - PC Blend - Prusament (Prusa) +[filament:AzteQ Industrial - PC Blend - Prusament (Prusa Polymers) @0.6 nozzle] +inherits = AzteQ Industrial - PC Blend - Prusament (Prusa Polymers) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6 filament_max_volumetric_speed = 15 +filament_notes = "BN" -[filament:AzteQ Industrial - PC Blend - Prusament (Prusa) @0.8 nozzle] -inherits = AzteQ Industrial - PC Blend - Prusament (Prusa) +[filament:AzteQ Industrial - PC Blend - Prusament (Prusa Polymers) @0.8 nozzle] +inherits = AzteQ Industrial - PC Blend - Prusament (Prusa Polymers) compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8 first_layer_bed_temperature = 100 bed_temperature = 100 @@ -1713,6 +1826,7 @@ max_fan_speed = 60 min_fan_speed = 60 filament_retract_length = 7.1 filament_max_volumetric_speed = 0 +filament_notes = "ZL" # DeltiQ Printer # @@ -1796,12 +1910,14 @@ retract_speed = 35 [printer:*DeltiQ 2*] inherits = *DeltiQ* +default_filament_profile = "DeltiQ - PLA - Prusament (Prusa Polymers)" +default_print_profile = DeltiQ 0.20mm Normal before_layer_gcode = ; BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n end_gcode = ; END_GCODE\n\nM140 S0 ; Turn off bed\n\nG28 ; Home\n\nM104 S0 ; Turn off extruder\nM107 ; Turn off fan\n\nG90 ; Absolute positioning\nM220 S100 ; Feedmultiply back to 100percent\n\nM84 S5; Disable motors gcode_flavor = reprapfirmware layer_gcode = ; AFTER_LAYER_CHANGE\n;[layer_z] -pause_print_gcode = M0 -start_gcode = ; START_GCODE\n\nM220 S100 ; Set feedmultiply back to 100percent\n\nT0 ; Select Titan extruder\n\nG90 ; Absolute positioning\nM83; Relative Extruder\n\nM190 S[first_layer_bed_temperature] ; Set and wait - bed temperature\nM104 S[first_layer_temperature]\n\nG28 ; Home all axes\nG32 ; Probe Z and calculate Z plane\n\nG29 ; Mesh bed probe\n\nG1009 ; Go ARC to purge end\n\nG92 E0 ; Zero extruder +pause_print_gcode = M25 +start_gcode = ; START_GCODE\n\nM220 S100 ; Set feedmultiply back to 100percent\n\nT0 ; Select Titan extruder\n\nG90 ; Absolute positioning\nM83; Relative Extruder\n\nG28 ; Home all axes\n\nM190 S[first_layer_bed_temperature] ; Set and wait - bed temperature\nM104 S[first_layer_temperature]\n\nG28 ; Home all axes\nG32 ; Probe Z and calculate Z plane\n\nG29 ; Mesh bed probe\n\nG1009 ; Go ARC to purge end\n\nG92 E0 ; Zero extruder 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_TRILAB\nPRINTER_FAMILY_DQ\nPRINTER_MODEL_DQ2 [printer:DeltiQ 2] @@ -1825,7 +1941,7 @@ printer_variant = 0.6 max_layer_height = 0.4 min_layer_height = 0.2 nozzle_diameter = 0.6 -default_filament_profile = "DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle" +default_filament_profile = "DeltiQ - PLA - Prusament (Prusa Polymers) @0.6 nozzle" default_print_profile = DeltiQ 0.30mm Normal @0.6 nozzle [printer:DeltiQ 2 - 0.8 nozzle] @@ -1834,7 +1950,7 @@ printer_variant = 0.8 max_layer_height = 0.6 min_layer_height = 0.3 nozzle_diameter = 0.8 -default_filament_profile = "DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle" +default_filament_profile = "DeltiQ - PLA - Prusament (Prusa Polymers) @0.8 nozzle" default_print_profile = DeltiQ 0.40mm Normal @0.8 nozzle [printer:DeltiQ 2 Plus] @@ -1858,7 +1974,7 @@ printer_variant = 0.6 max_layer_height = 0.4 min_layer_height = 0.2 nozzle_diameter = 0.6 -default_filament_profile = "DeltiQ - PLA - ExtraFill (Fillamentum) @0.6 nozzle" +default_filament_profile = "DeltiQ - PLA - Prusament (Prusa Polymers) @0.6 nozzle" default_print_profile = DeltiQ 0.30mm Normal @0.6 nozzle [printer:DeltiQ 2 Plus - 0.8 nozzle] @@ -1867,12 +1983,12 @@ printer_variant = 0.8 max_layer_height = 0.6 min_layer_height = 0.3 nozzle_diameter = 0.8 -default_filament_profile = "DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle" +default_filament_profile = "DeltiQ - PLA - Prusament (Prusa Polymers) @0.8 nozzle" default_print_profile = DeltiQ 0.40mm Normal @0.8 nozzle [printer:*DeltiQ 2 FlexPrint*] inherits = *DeltiQ 2* -start_gcode = ; START_GCODE\n\nM220 S100 ; Set feedmultiply back to 100percent\n\nT1 ; Select FlexPrint extruder\n\nG90 ; Absolute positioning\nM83; Relative Extruder\n\nM190 S[first_layer_bed_temperature] ; Set and wait - bed temperature\nM104 S[first_layer_temperature]\n\nG28 ; Home all axes\nG32 ; Probe Z and calculate Z plane\n\nG29 ; Mesh bed probe\n\nG1009 ; Go ARC to purge end\n\nG92 E0 ; Zero extruder +start_gcode = ; START_GCODE\n\nM220 S100 ; Set feedmultiply back to 100percent\n\nT1 ; Select FlexPrint extruder\n\nG90 ; Absolute positioning\nM83; Relative Extruder\n\nG28 ; Home all axes\n\nM190 S[first_layer_bed_temperature] ; Set and wait - bed temperature\nM104 S[first_layer_temperature]\n\nG28 ; Home all axes\nG32 ; Probe Z and calculate Z plane\n\nG29 ; Mesh bed probe\n\nG1009 ; Go ARC to purge end\n\nG92 E0 ; Zero extruder default_print_profile = DeltiQ 0.20mm FLEX default_filament_profile = "DeltiQ FP2 - FLEX - Generic" retract_length = 0.7 @@ -1929,7 +2045,7 @@ retract_lift_below = 0 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 retract_speed = 30 -start_gcode = ; START_GCODE\nT0\nM220 S100 ; Set feedmultiply back to 100 percent\nG90 ; Absolute positioning for motion\nM83 ; Relative extruder\nM107 ; Layer fan off\n\nM140 S[first_layer_bed_temperature] ; Set and continue - bed temperature\nM104 S150 ; Set and continue - hotend probing temperature\n[start_filament_gcode]\nM190 S[first_layer_bed_temperature] ; Set and wait - bed temperature\nM109 [filament_notes] ; Set and wait for material specific hotend probing temperature\n\nG28 ; Home all axes\nG32 ; Probe Z and calculate Z plane\nG29 ; Mesh bed probe\n\nM104 S[first_layer_temperature] ; Set and continue - printing temperature\n\nG1009 ; Purge hotend\nG92 E0 ; Zero extruder +start_gcode = ; START_GCODE\nT0\nM220 S100 ; Set feedmultiply back to 100 percent\nG90 ; Absolute positioning for motion\nM83 ; Relative extruder\nM107 ; Layer fan off\n\nG28 ; Home all axes\n\nM140 S[first_layer_bed_temperature] ; Set and continue - bed temperature\nM104 S150 ; Set and continue - hotend probing temperature\n[start_filament_gcode]\nM190 S[first_layer_bed_temperature] ; Set and wait - bed temperature\nM109 [filament_notes] ; Set and wait for material specific hotend probing temperature\n\nG28 ; Home all axes\nG32 ; Probe Z and calculate Z plane\nG29 ; Mesh bed probe\n\nM104 S[first_layer_temperature] ; Set and continue - printing temperature\n\nG1009 ; Purge hotend\nG92 E0 ; Zero extruder wipe = 1 [printer:AzteQ Industrial] @@ -1937,7 +2053,7 @@ inherits = *AzteQ* printer_model = AQI printer_variant = 0.4 max_print_height = 400 -default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum)" +default_filament_profile = "AzteQ Industrial - ASA - Prusament (Prusa Polymers)" default_print_profile = AzteQ Industrial 0.30mm Normal [printer:AzteQ Industrial - 0.6 nozzle] @@ -1946,7 +2062,7 @@ printer_variant = 0.6 max_layer_height = 0.4 min_layer_height = 0.2 nozzle_diameter = 0.6 -default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle" +default_filament_profile = "AzteQ Industrial - ASA - Prusament (Prusa Polymers) @0.6 nozzle" default_print_profile = AzteQ Industrial 0.30mm Normal @0.6 nozzle [printer:AzteQ Industrial - 0.8 nozzle] @@ -1955,10 +2071,10 @@ printer_variant = 0.8 max_layer_height = 0.6 min_layer_height = 0.2 nozzle_diameter = 0.8 -default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle" +default_filament_profile = "AzteQ Industrial - ASA - Prusament (Prusa Polymers) @0.8 nozzle" default_print_profile = AzteQ Industrial 0.40mm Normal @0.8 nozzle [presets] print = DeltiQ 0.20mm Normal printer = DeltiQ 2 -filament = DeltiQ - PLA - Generic \ No newline at end of file +filament = DeltiQ - PLA - Prusament (Prusa Polymers) \ No newline at end of file From c86deb92db87231d53e549fc91ad97aef7592c5f Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Thu, 6 Oct 2022 12:19:33 +0200 Subject: [PATCH 08/29] improve function name to reflect that it does unscaling (to_unscaled_linesf) --- src/libslic3r/ExPolygon.hpp | 13 +++++++++---- src/libslic3r/GCode/SeamPlacer.cpp | 5 +++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 7f2aac6281..def2be85af 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -125,7 +125,7 @@ inline Lines to_lines(const ExPolygons &src) return lines; } -inline std::vector to_linesf(const ExPolygons &src) +inline std::vector to_unscaled_linesf(const ExPolygons &src) { size_t n_lines = 0; for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) { @@ -138,9 +138,14 @@ inline std::vector to_linesf(const ExPolygons &src) for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) { for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) { const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points; - for (Points::const_iterator it = points.begin(); it != points.end()-1; ++it) - lines.push_back(Linef(unscaled(*it), unscaled(*(it + 1)))); - lines.push_back(Linef(unscaled(points.back()), unscaled(points.front()))); + Vec2d unscaled_a = unscaled(points.front()); + Vec2d unscaled_b = unscaled_a; + for (Points::const_iterator it = points.begin()+1; it != points.end(); ++it){ + unscaled_b = unscaled(*(it)); + lines.push_back(Linef(unscaled_a, unscaled_b)); + unscaled_a = unscaled_b; + } + lines.push_back(Linef(unscaled_a, unscaled(points.front()))); } } return lines; diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index e18984a641..1d7fd5b3c6 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -1054,7 +1054,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) [po, &layers](tbb::blocked_range r) { std::unique_ptr prev_layer_distancer; if (r.begin() > 0) { // previous layer exists - prev_layer_distancer = std::make_unique(to_linesf(po->layers()[r.begin() - 1]->lslices)); + prev_layer_distancer = std::make_unique(to_unscaled_linesf(po->layers()[r.begin() - 1]->lslices)); } for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) { @@ -1065,7 +1065,8 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) } }; bool should_compute_layer_embedding = regions_with_perimeter > 1; - std::unique_ptr current_layer_distancer = std::make_unique(to_linesf(po->layers()[layer_idx]->lslices)); + std::unique_ptr current_layer_distancer = std::make_unique( + to_unscaled_linesf(po->layers()[layer_idx]->lslices)); for (SeamCandidate &perimeter_point : layers[layer_idx].points) { Vec2f point = Vec2f { perimeter_point.position.head<2>() }; From 8ba52ae65c5e92e65a916cdcf10cf6ae4a5a91ed Mon Sep 17 00:00:00 2001 From: Sebastian Nadorp Date: Thu, 1 Sep 2022 22:23:46 +0200 Subject: [PATCH 09/29] Order list of vendors in ConfigWizard: @lukasmatena 's amendment: PR #8795. Thanks. --- src/slic3r/GUI/ConfigWizard_private.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index aa074f9253..d757eed634 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -75,7 +75,7 @@ struct Bundle const std::string& vendor_id() const { return vendor_profile->id; } }; -struct BundleMap : std::unordered_map +struct BundleMap : std::map { static BundleMap load(); From 934d51d26f6a96d2a349b90b3a7e3c6ab0f69584 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Thu, 6 Oct 2022 22:00:48 +0200 Subject: [PATCH 10/29] Taz Workhorse thumbnail --- .../LulzBot/TAZ_WORKHORSE_thumbnail.png | Bin 0 -> 40220 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/profiles/LulzBot/TAZ_WORKHORSE_thumbnail.png diff --git a/resources/profiles/LulzBot/TAZ_WORKHORSE_thumbnail.png b/resources/profiles/LulzBot/TAZ_WORKHORSE_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..133858a6f29734a951fac3da38caa97ca67d1f43 GIT binary patch literal 40220 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Π`M^ z+ukOzSPQ=)A5BDu@+94AVZvYn9~Cvh|LNXrHzMBaa*xp7u{hN`7T4rLhS$7NvP}}? ztsI$(S3s50VMJAJq*xse5R%;55I(Yb)gmjg9ofVllRJ!4w*?iV?g3T=4K*zNLzr1u zCn@M<6}Dz1%qa%81D3>{x|9dpA29V$Tvm<`M#2n5AF1HOx9+ZYaRA*o-c1NY)k5HW z?N+bB91$2(F#deL8n1tjBa4^Q0OL8IENKA0q(B!_HlCh#_AuSS{y3ve+1_xn^v2B6 zPmq*0tpKIvK!dpNNi`MbN9UbRatk+q6wKWEHgZui^i2CK(l0H|p|V^0+bJF+t14NQ z$`NCax&!u6!SAheUX)B&jp%a~-eC%aO{WJ{YF#X-jvjKH`o%j7B7&hno|H!TzSozb zYoAtwDz5+Uu-PCPkv;=Ude8@Rsu_u>&_=&z*@`P9a(~jy6NF?T33sq;d26bu()JmB zQXS(=9>f;8jro4vdy!l;(VmKgHmQ%Bd4cGg8w~(@H(Rx8tqqNiM!A5XRNA2bv@9_M zhjfquM_&+iUbb{zaqX%<$L#1mkCZwK0qc3Y<|Zbm$QKF!vkGq{yH#ztLcv|yqy@Y3 z_aqyLk*BVTgSHd6ceSsD(H=aoV;|aVN4e*Fx;@Q8%i}Ld@Nn>X>526arKiTGoRm{# zKn$2OP;3`g3p>~{%Sx!Fpp0!7onIMbOkIf+5v5ol3Wo|Jg##-K4TOd59eeFbMu-Zc zA){go`@UU8W4Ma|(Sd^w^;Ya1r#$)$L8Z6Ag-Yswh+vQuFl0Wm#!cG?mmWjux)JHA zp<1=ya+NncYYn}AQ#Q@cYW#7X2jh*6>||ND^zvZn3Bg85yiG0E z?=CDlyIlwn&CjmSqbuGE#@#mm`k(MeTlhCpHZ ze$;>r>rdvKVxf(?ip?P!yjWEBcnSs3L40VHF<7P&Q{Bl60x}-LVm48yc`3&Xr?Udl zP%9Frd@8hgmkTZ2l6pr9g$c7Uj`)O%j)0B|=PaS<#UJT;t$7e&BfLd)lf!nAc7-9s zi@E0p%Y_QU1Sx_D%M}rXa5!ZYNoN*N`#H>Hcj{?4u_uH2>BVk>(E!FYu!dlaPoB+0 z##4MR@e3tr_#XU^+(9ebPCuDGT~ltz+*mr8me69+|Z`i*1#*tC^iULH)0 zB!pCR&&X+ss2YrD0S9GLS2sCR@jfbnJd#jXOxW6+Cdt5=8b`eEB}VAhl^euIAq#?! z{E5mm9r}J>nn{8Q4iiO^j;CDOS_rx`1MZ3Pl;&2F;0eF`p3s^GQ-T*qO!2g~gfLlO z_)I$5Ajl>b$jbFkgez5(h?2P9D}bci>xR)|FO3qcmmUm>_N5V%oR7nnsU9JYlI}1> zytSr^ILNxuf_DOz0Nii5VzK?apfPlvH+oR1R7bDolfGBovfWul8kmSg{I~(2fcB)IVO<>#|=njGR#V!Lls`gVg?Lf zR(>xu21h#)i22w59jw~JU{h^SO1?{=DcqmHb0`W6n;$hfVGvBPwTUDz(x-!@lpq`Q z812t65|V|QNCz9%(!{V92ttVHN-)L11tU5t;rH)<>d+u1RL2>pM6OodqL?;A{oacK_FsM%0WZluZFD6D z>}vEy#u6ArRoW;S^aG*rTKlMBoFtq=IymXrzS8u-ac2c9_<>ul1{xo4Qaxq4Y1>B1#h;%i-W@$~~fJgX#A z7#^_Va}ncN9m1E$qBP-l0}Q%2K1*TRrA|-m7&(q)MiP_fKEeRc(U`r1!xQ(e>l(*= zZI-mxy`k>Mp(0P7LX3W3f{G1Uc%i4pR1;05OC9|MN=LQ|Ic^7xYQP!+4AQ8_Ak0^` zEj++zgia>5#&P-;+BXzWdXZYN7GcO{5*hvUuLU!oc0m3MRc~fO5$^61zF?RaON=E~ zw4Mm&h=*xhy`4A3stq>tVq@or5-(Fw$dqI zLDrK6i83_dHasy}Owqs7!H`3`lu7}%c2juscQub90TFjo;Son4gOHTP$`r~8C4a2U z?0(We2t&*;Bfn4h7o znXyHU8;~drg4KE36H)9qT76eFXw*LZAK5mJ2c1 zS65bC&b>yd%WhgYl#(NckEz^naTNsNp6R8xmC=5f^5TtQOAy15o7}RR|D`W`Wh6gjgtY{XGNHzE!uGV2; z?|ThzCS}Pc1soK`wt~v=zz<`T425E06)=aQwNMOt2Zcr0Qnbark+kv5slB9eOAfAl zfECGzj`_j#Vu?fU{a4O(#zIigAqjdvjK#Zwd5s{jQ^s!mD-hT>h(nAe=xn#NyrE2I zG4`mht8?61v9BZVd`aloTn>642A-zKs^^%KR3D5#W>^74?2Tn;Mp1k1xAm}@jl8+Logi3;2-_fa+w;Dlg*D#-_j}s3}qk?g8!)#1t zt_$0R{J&IstuyU6KbPTD*!g;IGUrFS(3M(*cF;qWWdFF*tEm3vq9&)<>{T1$Jyx|G(KL=~ur;wpDI8OnM4|DKgI~&XV=R!e% zuPJ55OTeNRMJtb#jmi=cdJ#(b6UTGI+1iT=i<;8`2(qfY*VN=*%peMm{cKa(5Ro;} zR?*yXfx)C)MiVm#2jGXOEf=!e>N;?br^Jx4PQ5516VGI6vihVGMPlj47yq+)1H2wF zKpdW#odt08JV1oQZC&$)$BjG;ggr)$k6ae;Ez<{sqL>bR>6L>pA+KMd2E};Cf``%; zve0rLO=nsgM|N_>L)HOvNMN=qt747#p1~C`!Vb>%a-N9tgpF3(q9>}D^Ds!L zu6qV)N9hsh)afyvB8i6tq3iz zviWfNO4y^L%8Uuo`MhTaq9OnwRUM3%jdc8@A(xGB(AAdq<#AE1+Ip|mEzcNm5l0r}&J zepUhvunLfDHud95#Fb7J;NwUr8J24Zbiz(uhKtD!vPEKj z6@xyYV|vD8s=j)RvdQ5b4lIek&5Oqy2mIR$t<h>0yQNL!lir-$xNrxy{b99Hpbnvp5}K$Nc+3j!{GK>z)< z6%rArBHay^7F1-{APeU3%V_61E7IsfL$+|gzT^5fm@lEjuC!1eukVh)jwk}q?bNgf znF7%9Vld+KOpdR`L7rzRUpUiQKE^p3zA-3phJ<{h`iLT0}WaY9rgO48w_2Z0Z{L{irF>@*D{K$-3m%d!)ijrjZeJ`T9{u3Oeq;Q!eLMp(T7 z!agc7a0fSlpmeFx3JnQ4QCB7K10N+E3_F07XRd99%i-U|LR_FC*U=0J`-1N1HH221 zpKnZr)DOIdk}PS9L%*}SZS!$^#6N%QZ6N*&>~R`$?|ykRJr7)q&p^ec;=z`&59c31&2!JvN_6LX`E|QE1J3ztdy_rp|PH$;uN`FE_k@ zewel6%mcqodF^a%C0SBrSj>w(gG1?+eF`{l-R}ijn#T70oEy~j{wz%aYh3Kl#Oou; zMZXhX>Xm*gqYuAJ;B#wfHvN|pUQa_1rsYJ2V#L4svMKg&HP9~mw`Ba>3psh7JOR7O z0^Z?LlXc?1i+(J2B4QH5fwmkVKu&yibRzON`gWH^>u4wOG+{4@+fnk`u(4rm$+a9Y z%sL)|4M$5`0&rzusS&2do>%~HGBI#D4t)IxNJZK-)k(ZLKVeW%EM|d_1{2?xHIVB3 zmeP;%514P8-%4cR6DEoJZ`>%XIuO7B7(gvi$lT1%ZtO=su3n2Daq%qp^&zo4?02u( z4KV?_bm){@YY2SUi0hQ`K3?pg(fa!Oy^MthFDGY%rH_w~>ig7>yn=$no<@<$PE9e8 z&Gobpb(AxLOSv~Zk8_c@vnda}aZDun;Rc^urtd$>srNp`#U+>@hIlW%K6{Xfd7w+- z=*@yuVrjB%dUt+*$rK7L(x`i3#UHB;y&OgP$!SiAuTCMgcJLm==>T#;h`(RR1=nb~%xt}aG)FrA}?zR~claStgF&ye~ zLt@5}6iGG|6cV|~vt){PV+yaFu(_;c;Iqd2zFuy1Hp}agiS7TRTpn}7ebFfJWdK*r zkLA;$)*{b|&n`x(fx$2!c3PNp9oKd^`f?*bOT-F^dPw8(tgx??9^!y$R z=5GdqI_e$-MKg=hiA^FiK}!e`F~rS4xO|AAhjB0_T$wX_(){VS!$WA<_zX#6Kb{~5 zVSVwtf!)i3z_-6SufsoH&(3oTUTzYy(cR`J-^Pr64$A<2`Hm$oH`h?JMVVR9vu?t& zQMuD+S(+O2OdK7tCyt1Stf0?L40-(f#hUAMN!?dM)*1(JdJM-TsG@c^x7mIR;|+{m zE@?qBB+uY%?gh#^WHDr;3JV)22c7wjW1|*p-($zkpqg`WaKH=&xi#X}AlB6Xc&jek z{5Rz(wz0ACdNfz2ocPs12o2^6=E`%!+uC_+>vd;f34s|O?R9^rCaK(viX>4gxR1xs zvYbo6!wq}T93?15jz))vAo1os&gl66XDsom6%6rRi087Ef+VOjCTYY)jMA3|4?~Sqv)fG zh-as!rg(~M@}>xVxwBLT-04djU($JQtxJMkMokp)5chG~r>LO(3wkVg&RacVGAiU{ zjq#VGig;+U&@oK1;U^r3#J_f;T-VHYSc8=kSxiydmP zvJOnR66~9A_~%yC-EF*6FPgmOD#gc%UZDU2)9VlrEAcTM_Y8(w>yBqik( zuEL16=m9ivz(S|bU*kUWAuqabFJTIGwD+_b%+G_~i70$1K@*43hp!GK7 zGk_oGT~ja8&*jwl2z(8V{EbLfI3yww3-;6Lk4a-TE8l$(Kh3j;;_YW`zMYp7 zr9oPUkdhc$1|&v01Syf0PJy9YrBkG92ysB9Yp7R3gaJoDMClX-q?_;YulVk|KhK(V z*S+W2XPgzJvf->#v`BI+5U|&9b%Pe_fzGEAAU?M4F&nVeu(d8;Tw!e zfJxU*9<_-T&R36X}%&1g4nlHrMO5f#~k>=(-QuLK^cNT+h z_Pwq$&e!~@8KWlv=pGEL0LygbJ2qb&)A?++8b9Di{nLex@bgeYNKyONlW&(A$s%_M zguvn~3f=bGp?wZxIDP1$gM*pSp@y}LgGj;h=f<{6|EDa@-pZ?0A`)%`VN-oU#xyLG zmrEeQC14+RO^L;otRc%PHyFstM<93uP&xUIiK!_v0S2;Iyib#4znYMIs2X3&uu;%J zK}`jrSrvdNk1iF^?nut})npmE_~NCimy6)CoPL0M)C&mWvXsO`kW49R8R%`;r~e_1 z+2a$&U=pmjvg(k-yq93vcekQzUA?TBKtgBl_a@hR-*pjTvsMV$Jh@~)Eay5~R9XJc zp42`yCH*64y&&*xvr=41Y3geOiRS%V_rma<*b$IscTS6r=YRMuniXX2 z)c;Eh=;rL2zxdC{0dn5Q1X)nNT(6r@>^N==!i0-g9;7!m&S zMD&Xmo4`oa8?pMpUbto0CcoHrCnW-5%uY;i#IUj-l&=&@q%o)Xs$~vIK4L07So$C# zRWoO3eQ@#omSsyaf7ip}XY43j+A?0=sz){ZQzwCi#M6gft64Q*S&fwWw(2OF_>>A2 zEfUWM_QxwzMaUErqT%}m@>@1QV}klY2j zpQmr@S&d%FZ@1#7DC~Kek%t_O`LWDpNA|Rh2GqA4VmwFYP0+Ga4?0l z#YljSqW}$-UaK>c+-^rFPd#Ujqn)Z3%gKJJ#=|`QnVuB%fVLm^99l1rX2oEEbn|CZ zE#3zk1}B*N63Nh@3dY1``shr$LnKFBi7LqrfJD!){DQ4v zu{D3^Y$;;ATRk}1D_9aIEFhLSU^$D>e*c#+TYzCh$Hc+m$q6$Q1xCm{38EMpmTp6` ze|Q!d%w#v3EAxG+H*>x=|Ct$Lg30`{9?Pv(awB4m^I)%xmaTIUi(Z^7`WsO z5|PockQ1>_t3H{Fc~%Zg?w0*Yj@8C}0GSxnP5gv0Yp6>pT-H$s*f^y6_v~sH)*E-hWgpQ`2OTlWwrj=Zn1+m z{=j7{Da(a4Q^IR(rKNixZMd^E7j{4CDy93nW3qPZxeM!^e@VrWU2B3shp*d&UA7;(oiO+oAJu4_1&?w_-1iE@leN^x2HZ2L?2I!cLsXz9qQ>aSbZ{!M5$_0f$ddLfSy^e< z*()3(eW_-3P2A*zQpGX-AKq~k6mSIJ#j$tnV9qC(Q#?z-vhxD=;m0L(Bsl_L9X}mv zQ$sn=q|c8nr-RNl^BSr~*^u0!HxrD^nuRspOllasdx_kc=Z_6)jZ?KM zu``g_-}7gM${IBu+fV}kOWRQsRbS|7iR5)IjqqV7^BivJZm#9@;dWfb@K@89B( z#!c}yuSFgT3aSTa%NRO+xbf`_*+T8x^V+xnbTzy0Y;JF#O-`ZpMsxZ@OC=8OK?1kX z(WCQ91PdCF-GjBuOU~}gS4x#@i#=?F_6>J?iKGOx5I|qw9sfAUQedq{Fhwl}+6$kWKkpcflelbk$>3Ux+h=Fb_A z-qrnpov2lEav;{Pn@-dIUiC<5;^Ujk#ppZDu$u1gAu{KM5nF^Mr3h4_`Q(iziUWJ! zsv!T3+++lLYU56dv`vF415UfRvXWRp-rv#2X5mVWr#@ga9aVRDbd-G2udEQLvYOgO zUdtT5am94r&S;<7C}ox{wd^Z1XEX(6a90Zd@QhdK-W>LEvFWsCHCBeGj+QRNu-KZ3 z20o5YOcnCBtn6|v36-+SqjvW3O>V^LFq&P2^0gB5FhD&^o*}bO>O$JYfqP^ zi4eHEon5@k3eKa$=uFRyMfUa%B31=dPn3XvIWkx@suxOP2k9LvFZdDEOH?pco@I#8 z;uqCKK8o>a2Wg62F$)KqI3R*QOf=!!^Ukw<-Grq4DL5arz?9Uvij3cX2YAXq3) z1Q!TV4)l>c*kFyD9a@E$P0@A15*#KNOd-)1|l6?vA0s0c=N;x z4TWX;Zm7yz6Q{P?t&z}qVpODXZSB^CPPQgr>W0_?Y_e*@wb|JTU=IrmwzrcmD^A2k zY1-bk-P$a{6~IdH`r;%qo(N(CCIAl=u*-r!>>u(kw)@-v7M4^r(E5I~0}_1{VW%o; zvJ2;!y{^r`#WsrIZ4z5T9bBI#r1a^V#0C~4O($JG!nc!x2$Y1JoSc}fY$Oo9#ku4} zx{8|*m061Lmau_$t->M7H+gO@VL^+t@9zRb%}|BUP{*WZOW^bBJ1g%r?7vBR9c-it zWf>nsPHGxLr+|rZ$^l^WQDtRzTb9#S>!))~c{0lNrPg(>G14KXL^wo*_^nZ={6&#d zr4a6gpj#pH2^WiT0}^)Zi4rN^&+&S6Rh{H1`oHnVC>T^fLNa`vggnAuVTA_88uk(0 z2bp1pJ>&`9F1qgOuPmr9H#hC@Vs^P>QjlHJgG@&X|8{W~DK*O~M?%&cODNG>?Z#x+ zL(J!~PdD`Hfc|MPVEfX;|0w9QV?#BV8>*AWMya{F3bnU0M$kv-H(!P%o_10o=kv~u z+bkcwtAF*GY}k?{?&$)q=t>eCNz?%R=MtZ+#p%}yf$9^xe%{H3xrG-|Q)`Y+Nh~~lL1UYg zxyQ=AYI1vs4DzNpNxSD5|FPwucWJ1a&5E%3u)kGNL%M4&;%0S8|r9n(YjHZKxb!XSHe8rsH}URi@!O{X0?n>`bTm! zF}2|0xv!sq<3r!k+L9ccg2dK2_G<6-xIaf|=!h5C+XUSPR6)F#*oU1MVCvHgm~J6^ z-={1g;1;vcZrzGBwRy}aCocyZkQ|NKc=w_Up3?p46Lr&`(jK^AJ165?0Fr-n{; z7&#M@kdSaf+<4G{%ox`#k~{4=^LK4A5nSCm`aRcF`pX!tP7^0VChwr(f$vK9_2q}K zk{enAaPJYWiGEmog*QY^fIk5eWFl}##{KP$*l!tPBBJ@@_r=ps=GXCH%$Qq{h}Dto znZljAR6|Sj!V?{mDH3i`QnlL-2bnZHLo2en42T<`*G{9Ac{1yQB0~r~LYv2yX`~Q6 z?=hH?TCU9B!rFhiE2?}j&O1@B-2QA|Hbp*Txbbrs&k6iKosQ2~_*Eo}-|dVWD7ETc zk2hBQ0o;-yXw~?+0r?$vGKUW1M#DRFq=AK;<<WefihSUv~1h@ z_~8AtvSQ|7c_96a*TH zNzg{{Y0vynywyq(=FDyzXJ)UDEbSGOz5k*-CO-}F$1xED7nphT!N`*XwtM7v$w$U% zX7Od>>PjL)rhod{ya~xaAvv0#pWg{53rgBKccqB7q>QyDbP%lODtCtd#Xjy~)hfbO zVnO%EO#m&M|8caxzI_?4s4jq_s``-mrDAb=V!u6Dyd+Z&{<8TYNt+Swq}ESv@){(_Tz~HdA$mL#V`f)i=9D_;eCiP;U@NPZ)edm;1sL z$c+nz?bWSk>NOT+UL=G&ojxI7oX2Tu1{J1EO|gTZ(Oj1=P`a1@6)7AZh+bXwdwpK# zC!E@_&E9`EwvKZO#AH~r(b6)g!&x7f|E(7Xuz1L^p*WMfNVM3HH0rd?jcQYy)g3MC z=ieMH5jQ+6pv{<2l_dn~XgjEmjXZbBUwP$Q<*eP*zvQhCTCg@Xl7zlr5_Tbc3w)xbIOQD7D zT)$`E4`Pu-HI6%*DNZN;KK>;WBHHhH%Y2@h^=s8PA1kJ<={n*}c=)wAfXRU6h&hP< z9)DqWYt@!Ekw*B}A3|<|KOBF?<>VHFZ&kd_Dt@6rc7T1G@hHN`*J~5?+SbpHLKj8X zMn!PH+88eJMor{(Y$gj0JPz_Z&G0vk(sP5p`LL~pUe>S?o5amRPC@LK;)%BUQxwH` zYgk1`$3FG-cK7`Hr8UrzaH}x zcyFv&mE%~zComRWu7);#AXlI+f{PkElGfxlsF_|g;YdtMj*0}jd}l|z_F4_Lwzb^V z;w#O*V?x-v!4nH!imb76Hh&I=fp6gqa1ZX{==0<5)#aA_2MLS?XM@X^Pk+S!i{chb ze6}eC)JoMCVjSQJ9yD}^R1++Sh9BE)(G_l866>9eXEMITq_X&{{mQRB4H5FyPg#_5 zD8TDR>*qvd(gB-g0+ghr7e~djKD`P&e0zey zbHs=Req*|(_rqwh)k_IzD)Kn0kUC4HyRLOs2J`pOA@5eO+w#hP|J_M%F3?5&R?T;P zt;t=-SE3!5A%vXL913}&k*7mPk=Q6qZb&rxA%DMkuH=yhe`Z^0CQpHGKVT;^v`%V? zH_4sjk{5B6;79_8kzuu8aZcScfcn5~_JMB*rp_YILO|}X!)cfQ2Viy46`vU=Pt56> zUD5e+xX>;($HKE?wL>H2)|D@U)bHp0fPjE1=!4>C1HF|+-=Cj)zEhFeKkx2NbNhbK zYTn=|H6itf2le$1$~b^F)m5e3K!muYWsTv@m~&J?H_yW~u2uKPS|^zJ#YLlC1*YM0 z%Gu_UEpy4aQgeTO^do(dtQ!cMN<(K)_gLplzBr=UZ#KHRy0&g^6rrJ^;48~Cj2Ca# zSUzhQF2B53ef^~Vx-b~C$a8y1^lAxq?aiJ!;!ti_ z?Ui50)JVloXQN&#zf5Tc&58JK-BIb~8&FgD( z!QBOO&3~ARxCkn7o1Z5}^I8(am{azzw~Dv&JlX}Usxv*GTK-%OxHTVfq$}^l`aZ>zl$+K_)T1YZ&=^uy8?utxg5{(b^P2)qr;=1i@ zY_wuPxUGhOzZ>vI)*GxioBdel?sIO%wj(((FyKjpIVs=$xT7Ty?9#-_%sVj_)T|P} zHfNkwnfpDRq_~QYz%C|r`bOs`Sg=%@n00`a%=Hqvym3g7UG!Dc?#}hk*Qbm98nxbU zC*@Il$^xj?)|uj(NkO;SLT((J{qE3B?gK8Ay=a6f%d+P?5SMy#j5!WvdGaYITq4?I zP3Xy~k+dYtPpjUnvthfPtwuM<-!A=8nZqrJ-_H}*fs-z*@^L!-lja<1Gw44&eyaLmsx*jQub>`(D)2V(wkn|&idAi4|d);==T!?mR?NxsE6kwcE+S}rzoh3c-H-9C%|A1|l%YrN5UozeE`oqhxcH)xvF}{s#w{hduxR literal 0 HcmV?d00001 From 0219709d1f632e231428447331c4c4b0c7e6092e Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Thu, 6 Oct 2022 22:03:26 +0200 Subject: [PATCH 11/29] Sync with PrusaSlicer-settings. --- resources/profiles/LulzBot.idx | 9 +- resources/profiles/LulzBot.ini | 329 +++++++++++++++++++-------------- 2 files changed, 195 insertions(+), 143 deletions(-) diff --git a/resources/profiles/LulzBot.idx b/resources/profiles/LulzBot.idx index 8638bdbbeb..e182c33dbb 100644 --- a/resources/profiles/LulzBot.idx +++ b/resources/profiles/LulzBot.idx @@ -1,4 +1,5 @@ -min_slic3r_version = 2.3.0-beta2 -0.0.2 Removed obsolete host keys -min_slic3r_version = 2.2.0-alpha3 -0.0.1 Initial version +min_slic3r_version = 2.3.0-beta2 +0.1.0 General rework. Added new print and filament profiles. +0.0.2 Removed obsolete host keys +min_slic3r_version = 2.2.0-alpha3 +0.0.1 Initial version diff --git a/resources/profiles/LulzBot.ini b/resources/profiles/LulzBot.ini index 2338beaee0..3ab6999227 100644 --- a/resources/profiles/LulzBot.ini +++ b/resources/profiles/LulzBot.ini @@ -1,9 +1,10 @@ -# generated by PrusaSlicer 2.1.1+win64 on 2020-02-25 at 01:51:21 UTC +# LulzBot profiles +# Based on community profiles and original profiles from Cura LulzBot Edition. [vendor] # Vendor name will be shown by the Config Wizard. name = LulzBot -config_version = 0.0.2 +config_version = 0.1.0 config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/LulzBot/ [printer_model:MINI_AERO] @@ -12,18 +13,26 @@ variants = 0.5 technology = FFF #bed_model = mini_bed.stl #bed_texture = mini.svg -default_materials = ColorFabb PLA-PHA @lulzbot;PrintedSolid Jesse PLA @lulzbot +default_materials = Generic PLA @lulzbot; Generic PETG @lulzbot; Jessie PLA @lulzbot [printer_model:TAZ6_AERO] name = Taz6 Aero variants = 0.5 technology = FFF -default_materials = ColorFabb PLA-PHA @lulzbot;PrintedSolid Jesse PLA @lulzbot +default_materials = Generic PLA @lulzbot; Generic PETG @lulzbot; Jessie PLA @lulzbot -[print:0.3mm @lulzbot] +# [printer_model:TAZ_WORKHORSE] +# name = Taz Workhorse +# variants = 0.5 +# technology = FFF +# default_materials = Generic PLA @lulzbot; Generic PETG @lulzbot; Jessie PLA @lulzbot + +[print:*common*] avoid_crossing_perimeters = 0 -bottom_fill_pattern = rectilinear +bottom_fill_pattern = monotonic +top_fill_pattern = monotonic bottom_solid_layers = 3 +top_solid_layers = 4 bridge_acceleration = 500 bridge_angle = 0 bridge_flow_ratio = 1 @@ -34,26 +43,24 @@ compatible_printers = compatible_printers_condition = complete_objects = 0 default_acceleration = 500 -dont_support_bridges = 1 +dont_support_bridges = 0 elefant_foot_compensation = 0 -ensure_vertical_shell_thickness = 0 +ensure_vertical_shell_thickness = 1 +extra_perimeters = 0 external_perimeter_extrusion_width = 0.56 -external_perimeter_speed = 50% +external_perimeter_speed = 35 external_perimeters_first = 0 -extra_perimeters = 1 -extruder_clearance_height = 20 -extruder_clearance_radius = 20 extrusion_width = 0.56 fill_angle = 45 fill_density = 20% -fill_pattern = gyroid +fill_pattern = grid first_layer_acceleration = 500 first_layer_extrusion_width = 0.6 -first_layer_height = 100% -first_layer_speed = 40% +first_layer_height = 0.3 +first_layer_speed = 15 gap_fill_speed = 20 -gcode_comments = 0 -gcode_label_objects = 0 +infill_anchor = 1 +infill_anchor_max = 20 infill_acceleration = 500 infill_every_layers = 1 infill_extruder = 1 @@ -62,33 +69,31 @@ infill_first = 0 infill_only_where_needed = 0 infill_overlap = 25% infill_speed = 60 -inherits = -interface_shells = 0 -layer_height = 0.3 +layer_height = 0.25 max_print_speed = 80 max_volumetric_speed = 0 min_skirt_length = 0 -notes = -only_retract_when_crossing_perimeters = 1 +only_retract_when_crossing_perimeters = 0 ooze_prevention = 0 output_filename_format = [printer_settings_id]_[input_filename_base]_[layer_height]_[filament_type]_[print_time].gcode overhangs = 1 perimeter_acceleration = 500 perimeter_extruder = 1 perimeter_extrusion_width = 0.56 -perimeter_speed = 60 +perimeter_speed = 45 perimeters = 3 post_process = raft_layers = 0 +raft_first_layer_density = 70 resolution = 0 -seam_position = nearest +seam_position = aligned single_extruder_multi_material_priming = 1 skirt_distance = 3 skirt_height = 1 skirts = 3 slice_closing_radius = 0.049 -small_perimeter_speed = 15 -solid_infill_below_area = 70 +small_perimeter_speed = 22 +solid_infill_below_area = 0 solid_infill_every_layers = 0 solid_infill_extruder = 1 solid_infill_extrusion_width = 0.56 @@ -96,7 +101,7 @@ solid_infill_speed = 60 spiral_vase = 0 standby_temperature_delta = -5 support_material = 0 -support_material_angle = 0 +support_material_angle = 45 support_material_auto = 1 support_material_buildplate_only = 0 support_material_contact_distance = 0.2 @@ -110,17 +115,14 @@ support_material_interface_spacing = 0 support_material_interface_speed = 100% support_material_pattern = rectilinear support_material_spacing = 2.5 -support_material_speed = 60 +support_material_speed = 50 support_material_synchronize_layers = 0 support_material_threshold = 0 support_material_with_sheath = 1 -support_material_xy_spacing = 50% +support_material_xy_spacing = 60% thin_walls = 1 -threads = 12 -top_fill_pattern = rectilinear top_infill_extrusion_width = 0.52 top_solid_infill_speed = 40 -top_solid_layers = 3 travel_speed = 175 wipe_tower = 0 wipe_tower_bridging = 10 @@ -130,121 +132,116 @@ wipe_tower_x = 180 wipe_tower_y = 140 xy_size_compensation = 0 +[print:0.14mm DETAIL @lulzbot] +inherits = *common* +layer_height = 0.14 +bottom_solid_layers = 8 +top_solid_layers = 8 +infill_speed = 40 +solid_infill_speed = 50 +perimeter_speed = 35 +external_perimeter_speed = 30 +top_solid_infill_speed = 40 + +[print:0.25mm STANDARD @lulzbot] +inherits = *common* + +[print:0.30mm SPEED @lulzbot] +inherits = *common* +renamed_from = "0.3mm @lulzbot" +layer_height = 0.3 +seam_position = nearest +top_solid_layers = 3 +infill_speed = 45 +perimeter_speed = 40 +external_perimeter_speed = 35 + [filament:ColorFabb PLA-PHA @lulzbot] filament_vendor = ColorFabb bed_temperature = 60 bridge_fan_speed = 100 -compatible_printers = -compatible_printers_condition = -compatible_prints = -compatible_prints_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n" extrusion_multiplier = 1 -fan_always_on = 0 +fan_always_on = 1 fan_below_layer_time = 60 filament_colour = #29B2B2 -filament_cooling_final_speed = 3.4 -filament_cooling_initial_speed = 2.2 -filament_cooling_moves = 4 filament_cost = 0 filament_density = 1.25 -filament_deretract_speed = nil filament_diameter = 2.85 -filament_load_time = 0 -filament_loading_speed = 28 -filament_loading_speed_start = 3 -filament_max_volumetric_speed = 0 -filament_minimal_purge_on_wipe_tower = 15 -filament_notes = "" -filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" -filament_retract_before_travel = nil -filament_retract_before_wipe = nil -filament_retract_layer_change = nil -filament_retract_length = nil -filament_retract_lift = nil -filament_retract_lift_above = nil -filament_retract_lift_below = nil -filament_retract_restart_extra = nil -filament_retract_speed = nil filament_soluble = 0 -filament_toolchange_delay = 0 filament_type = PLA -filament_unload_time = 0 -filament_unloading_speed = 90 -filament_unloading_speed_start = 100 -filament_wipe = nil first_layer_bed_temperature = 60 first_layer_temperature = 200 -inherits = max_fan_speed = 100 min_fan_speed = 35 min_print_speed = 10 -slowdown_below_layer_time = 5 +slowdown_below_layer_time = 10 start_filament_gcode = "; Filament gcode\n" temperature = 200 -[filament:PrintedSolid Jesse PLA @lulzbot] -filament_vendor = PrintedSolid +[filament:Jessie PLA @lulzbot] +filament_vendor = Printed Solid +renamed_from = "PrintedSolid Jesse PLA @lulzbot" bed_temperature = 60 bridge_fan_speed = 100 -compatible_printers = -compatible_printers_condition = -compatible_prints = -compatible_prints_condition = cooling = 1 disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n" extrusion_multiplier = 1 -fan_always_on = 0 +fan_always_on = 1 fan_below_layer_time = 60 filament_colour = #29B2B2 -filament_cooling_final_speed = 3.4 -filament_cooling_initial_speed = 2.2 -filament_cooling_moves = 4 filament_cost = 27 -filament_density = 1.25 -filament_deretract_speed = nil +filament_density = 1.24 filament_diameter = 2.85 -filament_load_time = 0 -filament_loading_speed = 28 -filament_loading_speed_start = 3 -filament_max_volumetric_speed = 0 -filament_minimal_purge_on_wipe_tower = 15 -filament_notes = "" -filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" -filament_retract_before_travel = nil -filament_retract_before_wipe = nil -filament_retract_layer_change = nil -filament_retract_length = nil -filament_retract_lift = nil -filament_retract_lift_above = nil -filament_retract_lift_below = nil -filament_retract_restart_extra = nil -filament_retract_speed = nil -filament_soluble = 0 -filament_toolchange_delay = 0 filament_type = PLA -filament_unload_time = 0 -filament_unloading_speed = 90 -filament_unloading_speed_start = 100 -filament_wipe = nil first_layer_bed_temperature = 60 first_layer_temperature = 220 -inherits = max_fan_speed = 100 -min_fan_speed = 35 +min_fan_speed = 80 min_print_speed = 10 -slowdown_below_layer_time = 5 +slowdown_below_layer_time = 10 start_filament_gcode = "; Filament gcode\n" temperature = 220 +[filament:Generic PLA @lulzbot] +inherits = Jessie PLA @lulzbot +filament_vendor = Generic + +[filament:Generic PETG @lulzbot] +filament_vendor = Generic +bed_temperature = 60 +first_layer_bed_temperature = 65 +first_layer_temperature = 235 +temperature = 230 +bridge_fan_speed = 100 +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 60 +filament_colour = #29B2B2 +filament_cost = 27 +filament_density = 1.27 +filament_diameter = 2.85 +filament_notes = "Use glue stick." +filament_soluble = 0 +filament_toolchange_delay = 0 +filament_type = PETG +max_fan_speed = 80 +min_fan_speed = 40 +min_print_speed = 10 +slowdown_below_layer_time = 10 +start_filament_gcode = "; Filament gcode\n" + [printer:Mini Aero 0.5mm] printer_model = MINI_AERO printer_variant = 0.5 -default_print_profile = 0.3mm @lulzbot -default_filament_profile = PrintedSolid Jesse PLA @lulzbot +default_print_profile = 0.25mm STANDARD @lulzbot +default_filament_profile = Jessie PLA @lulzbot bed_shape = 0x0,154x0,154x154,0x154 before_layer_gcode = between_objects_gcode = @@ -259,22 +256,23 @@ gcode_flavor = marlin high_current_on_filament_swap = 0 inherits = layer_gcode = -machine_max_acceleration_e = 10000,5000 -machine_max_acceleration_extruding = 1500,1250 -machine_max_acceleration_retracting = 1500,1250 -machine_max_acceleration_x = 9000,1000 -machine_max_acceleration_y = 9000,1000 -machine_max_acceleration_z = 100,200 -machine_max_feedrate_e = 40,120 -machine_max_feedrate_x = 800,200 -machine_max_feedrate_y = 800,200 -machine_max_feedrate_z = 8,12 -machine_max_jerk_e = 2.5,2.5 -machine_max_jerk_x = 20,10 -machine_max_jerk_y = 20,10 -machine_max_jerk_z = 0.2,0.4 -machine_min_extruding_rate = 0,0 -machine_min_travel_rate = 0,0 +machine_max_acceleration_e = 10000 +machine_max_acceleration_extruding = 1500 +machine_max_acceleration_retracting = 1500 +machine_max_acceleration_x = 9000 +machine_max_acceleration_y = 9000 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 40 +machine_max_feedrate_x = 300 +machine_max_feedrate_y = 300 +machine_max_feedrate_z = 8 +machine_max_jerk_e = 2.5 +machine_max_jerk_x = 20 +machine_max_jerk_y = 20 +machine_max_jerk_z = 0.2 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +machine_limits_usage = time_estimate_only max_layer_height = 0 max_print_height = 158 min_layer_height = 0.07 @@ -292,7 +290,7 @@ retract_lift_above = 0 retract_lift_below = 0 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 -retract_speed = 40 +retract_speed = 30 silent_mode = 0 single_extruder_multi_material = 0 start_gcode = ;This G-Code has been generated specifically for the LulzBot Mini with Aerosturder\nM73 P0 ; clear GLCD progress bar\nM75 ; start GLCD timer\nG26 ; clear potential 'probe fail' condition\nM107 ; disable fans\nM420 S0 ; disable leveling matrix\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nG92 E0 ; set extruder position to 0\nM140 S{first_layer_bed_temperature[0]} ; start bed heating up\nG28; home all axes\nG0 X0 Y187 Z156 F200 ; move away from endstops\nM109 R{first_layer_temperature[0] - 60} ; soften filament before retraction\n;G1 E-15 F75 ; retract filament (LulzBot Cura is apparently trying to cold pull, might be a contributing factor to hob gear filling with filament)\nM109 R{first_layer_temperature[0] - 60} ; wait for extruder to reach wiping temp\nG1 X45 Y173 F11520 ; move above wiper pad\nG1 Z0 F1200 ; push nozzle into wiper\nG1 X42 Y173 Z-.5 F4000 ; wiping\nG1 X52 Y171 Z-.5 F4000 ; wiping\nG1 X42 Y173 Z0 F4000 ; wiping\nG1 X52 Y171 F4000 ; wiping\nG1 X42 Y173 F4000 ; wiping\nG1 X52 Y171 F4000 ; wiping\nG1 X42 Y173 F4000 ; wiping\nG1 X52 Y171 F4000 ; wiping\nG1 X57 Y173 F4000 ; wiping\nG1 X77 Y171 F4000 ; wiping\nG1 X57 Y173 F4000 ; wiping\nG1 X77 Y171 F4000 ; wiping\nG1 X57 Y173 F4000 ; wiping\nG1 X87 Y171 F4000 ; wiping\nG1 X77 Y173 F4000 ; wiping\nG1 X97 Y171 F4000 ; wiping\nG1 X77 Y173 F4000 ; wiping\nG1 X97 Y171 F4000 ; wiping\nG1 X77 Y173 F4000 ; wiping\nG1 X97 Y171 F4000 ; wiping\nG1 X107 Y173 F4000 ; wiping\nG1 X97 Y171 F4000 ; wiping\nG1 X107 Y173 F4000 ; wiping\nG1 X97 Y171 F4000 ; wiping\nG1 X107 Y173 F4000 ; wiping\nG1 X112 Y171 Z-0.5 F1000 ; wiping\nG1 Z10 ; raise extruder\nG28 X0 Y0 ; home X and Y\nG0 X0 Y187 F200 ; move away from endstops\nM109 R{first_layer_temperature[0] - 60} ; wait for extruder to reach probe temp\nM204 S300 ; set probing acceleration\nG29 ; start auto-leveling sequence\nM420 S1 ; enable leveling matrix\nM425 Z ; use measured Z backlash for compensation\nM425 Z F0 ; turn off measured Z backlash compensation. (if activated in the quality settings, this command will automatically be ignored)\nM204 S2000 ; restore standard acceleration\nG28 X0 Y0 ; re-home to account for build variance of earlier mini builds\nG0 X0 Y187 F200 ; move away from endstops\nG0 Y152 F4000 ; move in front of wiper pad\nG4 S1 ; pause\nM400 ; wait for moves to finish\nM117 Heating... ; progress indicator message on LCD\nM109 R{first_layer_temperature[0]} ; wait for extruder to reach printing temp\nM190 R{first_layer_bed_temperature[0]} ; wait for bed to reach printing temp\nG1 Z2 E0 F75 ; prime tiny bit of filament into the nozzle\nM117 Mini Printing... ; progress indicator message on LCD\nM221 S74 ; Printer specific extrusion modifier. @@ -308,8 +306,8 @@ z_offset = 0 [printer:Taz6 Aero 0.5mm] printer_model = TAZ6_AERO printer_variant = 0.5 -default_print_profile = 0.3mm @lulzbot -default_filament_profile = PrintedSolid Jesse PLA @lulzbot +default_print_profile = 0.25mm STANDARD @lulzbot +default_filament_profile = Jessie PLA @lulzbot bed_shape = 0x0,280x0,280x280,0x280 before_layer_gcode = between_objects_gcode = @@ -324,22 +322,23 @@ gcode_flavor = marlin high_current_on_filament_swap = 0 inherits = layer_gcode = -machine_max_acceleration_e = 1000,5000 -machine_max_acceleration_extruding = 1000,1250 -machine_max_acceleration_retracting = 1000,1250 -machine_max_acceleration_x = 9000,1000 -machine_max_acceleration_y = 9000,1000 -machine_max_acceleration_z = 100,200 -machine_max_feedrate_e = 40,120 -machine_max_feedrate_x = 800,200 -machine_max_feedrate_y = 800,200 -machine_max_feedrate_z = 3,12 -machine_max_jerk_e = 2.5,2.5 -machine_max_jerk_x = 12,10 -machine_max_jerk_y = 12,10 -machine_max_jerk_z = 0.2,0.4 -machine_min_extruding_rate = 0,0 -machine_min_travel_rate = 0,0 +machine_max_acceleration_e = 1000 +machine_max_acceleration_extruding = 500 +machine_max_acceleration_retracting = 1000 +machine_max_acceleration_x = 9000 +machine_max_acceleration_y = 9000 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 40 +machine_max_feedrate_x = 300 +machine_max_feedrate_y = 300 +machine_max_feedrate_z = 3 +machine_max_jerk_e = 10 +machine_max_jerk_x = 8 +machine_max_jerk_y = 8 +machine_max_jerk_z = 0.4 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +machine_limits_usage = time_estimate_only max_layer_height = 0 max_print_height = 250 min_layer_height = 0.07 @@ -358,7 +357,7 @@ retract_lift_above = 0 retract_lift_below = 0 retract_restart_extra = 0 retract_restart_extra_toolchange = 0 -retract_speed = 40 +retract_speed = 30 silent_mode = 0 single_extruder_multi_material = 0 start_gcode = ;This G-Code has been generated specifically for the LulzBot TAZ 6 with Aerosturder\nM73 P0 ; clear GLCD progress bar\nM75 ; start GLCD timer\nG26 ; clear potential 'probe fail' condition\nM107 ; disable fans\nM420 S0 ; disable leveling matrix\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nG92 E0 ; set extruder position to 0\nM140 S{first_layer_bed_temperature[0]} ; start bed heating up\nG28 XY ; home X and Y\nG1 X-19 Y258 F1000 ; move to safe homing position\nM109 R{first_layer_temperature[0] - 60} ; soften filament before homing Z\nG28 Z ; home Z\nG1 E-15 F100 ; retract filament\nM109 R{first_layer_temperature[0] - 60} ; wait for extruder to reach wiping temp\nG1 X-15 Y100 F3000 ; move above wiper pad\nG1 Z1 ; push nozzle into wiper\nG1 X-17 Y95 F1000 ; slow wipe\nG1 X-17 Y90 F1000 ; slow wipe\nG1 X-17 Y85 F1000 ; slow wipe\nG1 X-15 Y90 F1000 ; slow wipe\nG1 X-17 Y80 F1000 ; slow wipe\nG1 X-15 Y95 F1000 ; slow wipe\nG1 X-17 Y75 F2000 ; fast wipe\nG1 X-15 Y65 F2000 ; fast wipe\nG1 X-17 Y70 F2000 ; fast wipe\nG1 X-15 Y60 F2000 ; fast wipe\nG1 X-17 Y55 F2000 ; fast wipe\nG1 X-15 Y50 F2000 ; fast wipe\nG1 X-17 Y40 F2000 ; fast wipe\nG1 X-15 Y45 F2000 ; fast wipe\nG1 X-17 Y35 F2000 ; fast wipe\nG1 X-15 Y40 F2000 ; fast wipe\nG1 X-17 Y70 F2000 ; fast wipe\nG1 X-15 Y30 Z2 F2000 ; fast wipe\nG1 X-17 Y35 F2000 ; fast wipe\nG1 X-15 Y25 F2000 ; fast wipe\nG1 X-17 Y30 F2000 ; fast wipe\nG1 X-15 Y25 Z1.5 F1000 ; slow wipe\nG1 X-17 Y23 F1000 ; slow wipe\nG1 Z10 ; raise extruder\nM109 R{first_layer_temperature[0] - 60} ; wait for extruder to reach probe temp\nG1 X-9 Y-9 ; move above first probe point\nM204 S100 ; set probing acceleration\nG29 ; start auto-leveling sequence\nM420 S1 ; enable leveling matrix\nM425 Z ; use measured Z backlash for compensation\nM425 Z F0 ; turn off measured Z backlash compensation. (if activated in the quality settings, this command will automatically be ignored)\nM204 S500 ; restore standard acceleration\nG1 X0 Y0 Z15 F5000 ; move up off last probe point\nG4 S1 ; pause\nM400 ; wait for moves to finish\nM117 Heating... ; progress indicator message on LCD\nM109 R{first_layer_temperature[0]} ; wait for extruder to reach printing temp\nM190 R{first_layer_bed_temperature[0]} ; wait for bed to reach printing temp\nG1 Z2 E0 F75 ; prime tiny bit of filament into the nozzle\nM117 TAZ 6 Printing... ; progress indicator message on LCD\n @@ -370,3 +369,55 @@ use_volumetric_e = 0 variable_layer_height = 1 wipe = 1 z_offset = 0 + +# [printer:Taz Workhorse 0.5mm] +# printer_model = TAZ_WORKHORSE +# printer_variant = 0.5 +# printer_technology = FFF +# default_print_profile = 0.25mm STANDARD @lulzbot +# default_filament_profile = Jessie PLA @lulzbot +# bed_shape = 0x0,280x0,280x280,0x280 +# deretract_speed = 20 +# end_gcode = M400 ; wait for moves to finish\nM140 S40 ; start bed cooling\nM104 S0 ; disable hotend\nM107 ; disable fans\nG91 ; relative positioning\nG1 E-1 F300 ; filament retraction to release pressure\nG1 Z20 E-5 X-20 Y-20 F3000 ; lift up and retract even more filament\nG1 E6 ; re-prime extruder\nM117 Cooling please wait ; progress indicator message on LCD\nG90 ; absolute positioning\nG1 Y0 F3000 ; move to cooling position\nM190 R40 ; wait for bed to cool down to removal temp\nG1 Y280 F3000 ; present finished print\nM140 S0; cool downs\nM77 ; stop GLCD timer\nM84 ; disable steppers\nG90 ; absolute positioning\nM117 Print Complete. ; print complete message\n +# extra_loading_move = -2 +# extruder_colour = "" +# extruder_offset = 0x0 +# gcode_flavor = marlin +# high_current_on_filament_swap = 0 +# machine_max_acceleration_e = 3000 +# machine_max_acceleration_extruding = 500 +# machine_max_acceleration_retracting = 2000 +# machine_max_acceleration_x = 9000 +# machine_max_acceleration_y = 9000 +# machine_max_acceleration_z = 100 +# machine_max_feedrate_e = 40 +# machine_max_feedrate_x = 300 +# machine_max_feedrate_y = 300 +# machine_max_feedrate_z = 25 +# machine_max_jerk_e = 10 +# machine_max_jerk_x = 8 +# machine_max_jerk_y = 8 +# machine_max_jerk_z = 0.4 +# machine_min_extruding_rate = 0 +# machine_min_travel_rate = 0 +# machine_limits_usage = time_estimate_only +# max_layer_height = 0 +# max_print_height = 285 +# min_layer_height = 0.07 +# nozzle_diameter = 0.5 +# remaining_times = 0 +# retract_before_travel = 2 +# retract_before_wipe = 0% +# retract_layer_change = 0 +# retract_length = 2 +# retract_length_toolchange = 10 +# retract_lift = 0 +# retract_speed = 40 +# silent_mode = 0 +# single_extruder_multi_material = 0 +# start_gcode = ;This G-Code has been generated specifically for the LulzBot TAZ Workhorse with HE Tool Head\n;\n;The following lines can be uncommented for printer specific fine tuning\n;More information can be found at https://marlinfw.org/meta/gcode/\n;\n;M92 E420 ;Set Axis Steps-per-unit\n;M301 P21.0 I1.78 D61.93 ;Set Hotend PID\n;M906 E160 ;Digipot Motor Current ((875mA-750)/5+135) = 160\n;\nM73 P0 ; clear GLCD progress bar\nM75 ; start GLCD timer\nG26 ; clear potential 'probe fail' condition\nM107 ; disable fans\nM420 S0 ; disable previous leveling matrix\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nG92 E0 ; set extruder position to 0\nM140 S{first_layer_bed_temperature[0]} ; start bed heating up\nM109 R{first_layer_temperature[0] - 60} ; soften filament before homing Z\nG28 ; Home all axis\nG1 E-15 F100 ; retract filament\nM109 R{first_layer_temperature[0] - 60} ; wait for extruder to reach wiping temp\n;M206 X0 Y0 Z0 ; uncomment to adjust wipe position (+X ~ nozzle moves left)(+Y ~ nozzle moves forward)(+Z ~ nozzle moves down)\nG12 ; wiping sequence\nM206 X0 Y0 Z0 ; reseting stock nozzle position ### CAUTION: changing this line can affect print quality ###\nM109 R{first_layer_temperature[0] - 60} ; wait for extruder to reach probe temp\nG1 X288 Y-10 F4000; move above first probe point\nM204 S100 ; set probing acceleration\nG29 ; start auto-leveling sequence\nM420 S1 ; activate bed level matrix\nM425 Z ; use measured Z backlash for compensation\nM425 Z F0 ; turn off measured Z backlash compensation. (if activated in the quality settings, this command will automatically be ignored)\nM204 S500 ; restore standard acceleration\nG1 X0 Y0 Z15 F5000 ; move up off last probe point\nG4 S1 ; pause\nM400 ; wait for moves to finish\nM117 Heating... ; progress indicator message on LCD\nM109 R{first_layer_temperature[0]} ; wait for extruder to reach printing temp\nM190 R{first_layer_bed_temperature[0]} ; wait for bed to reach printing temp\nG1 Z2 E0 F75 ; prime tiny bit of filament into the nozzle\nM117 TAZ Workhorse Printing... ; progress indicator message on LCD +# use_relative_e_distances = 0 +# use_volumetric_e = 0 +# variable_layer_height = 1 +# wipe = 1 +# z_offset = 0 From 493ada15a59a6cc6267a5e10681dab3d8a30823f Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 10 Oct 2022 14:14:18 +0200 Subject: [PATCH 12/29] WIP TreeSupports: fix of calculatePlaceables() by Thomas Rahm --- src/libslic3r/TreeModelVolumes.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/TreeModelVolumes.cpp b/src/libslic3r/TreeModelVolumes.cpp index ad27e78712..41e78e45b1 100644 --- a/src/libslic3r/TreeModelVolumes.cpp +++ b/src/libslic3r/TreeModelVolumes.cpp @@ -666,7 +666,13 @@ void TreeModelVolumes::calculatePlaceables(const coord_t radius, const LayerInde tbb::parallel_for(tbb::blocked_range(std::max(1, start_layer), max_required_layer + 1), [this, &data, radius, start_layer](const tbb::blocked_range& range) { for (LayerIndex layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) - data[layer_idx - start_layer] = offset(union_ex(getPlaceableAreas(0, layer_idx)), - radius, jtMiter, 1.2); + data[layer_idx - start_layer] = offset( + union_ex(getPlaceableAreas(0, layer_idx)), + // As a placeable area is calculated by (collision of the layer below) - (collision of the current layer) and the collision is offset by xy_distance, + // it can happen that a small line is considered a flat area to place something onto, even though it is mostly + // xy_distance that cant support it. Making the area smaller by xy_distance fixes this. + - (radius + m_current_min_xy_dist + m_current_min_xy_dist_delta), + jtMiter, 1.2); }); #ifdef SLIC3R_TREESUPPORTS_PROGRESS { From 5cba1e83199c017e07b22abca96d774c44f0a571 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 10 Oct 2022 14:14:55 +0200 Subject: [PATCH 13/29] Improved Point.hpp to_2d() and to_3d() templates to accept Eigen expressions --- src/libslic3r/Point.hpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index da558e4388..949ddbad1f 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -111,11 +111,17 @@ inline double angle(const Eigen::MatrixBase &v1, const Eigen::MatrixBas return atan2(cross2(v1d, v2d), v1d.dot(v2d)); } -template -Eigen::Matrix to_2d(const Eigen::MatrixBase> &ptN) { return { ptN.x(), ptN.y() }; } +template +Eigen::Matrix to_2d(const Eigen::MatrixBase &ptN) { + static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) >= 3, "to_2d(): first parameter is not a 3D or higher dimensional vector"); + return { ptN.x(), ptN.y() }; +} -template -Eigen::Matrix to_3d(const Eigen::MatrixBase> & pt, const T z) { return { pt.x(), pt.y(), z }; } +template +inline Eigen::Matrix to_3d(const Eigen::MatrixBase &pt, const typename Derived::Scalar z) { + static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "to_3d(): first parameter is not a 2D vector"); + return { pt.x(), pt.y(), z }; +} inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale(x), unscale(y)); } inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale(pt.x()), unscale(pt.y())); } From 5cb4b633259eedf2fbfe4daf963415e5f58e26e2 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 10 Oct 2022 14:19:06 +0200 Subject: [PATCH 14/29] WIP TreeSupports: Experimental code draw_branches() to produce trees with circular cross section --- src/libslic3r/TreeSupport.cpp | 514 +++++++++++++++++++++++++++++++++- 1 file changed, 508 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index c408b2f85b..b440818a8a 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -19,6 +19,9 @@ #include "Polyline.hpp" #include "MutablePolygon.hpp" #include "SupportMaterial.hpp" +#include "TriangleMeshSlicer.hpp" +#include "OpenVDBUtils.hpp" +#include #include #include @@ -26,6 +29,7 @@ #include #include #include +#include #ifdef _WIN32 #include //todo Remove! ONLY FOR PUBLIC BETA!! #endif // _WIN32 @@ -97,6 +101,20 @@ static inline void validate_range(const LineInformations &lines) validate_range(l); } +static inline void check_self_intersections(const Polygons &polygons, const std::string_view message) +{ +#ifdef _WIN32 + if (!intersecting_edges(polygons).empty()) + ::MessageBoxA(nullptr, (std::string("TreeSupport infill self intersections: ") + std::string(message)).c_str(), "Bug detected!", MB_OK | MB_SYSTEMMODAL | MB_SETFOREGROUND | MB_ICONWARNING); +#endif // _WIN32 +} +static inline void check_self_intersections(const ExPolygon &expoly, const std::string_view message) +{ +#ifdef _WIN32 + check_self_intersections(to_polygons(expoly), message); +#endif // _WIN32 +} + static inline void clip_for_diff(const Polygon &src, const BoundingBox &bbox, Polygon &out) { out.clear(); @@ -323,6 +341,7 @@ void tree_supports_show_error(std::string message, bool critical) lower_layer.lslices); overhangs = overhangs.empty() ? std::move(enforced_overhangs) : union_(overhangs, enforced_overhangs); } + check_self_intersections(overhangs, "generate_overhangs"); out[layer_id] = std::move(overhangs); } }); @@ -675,7 +694,10 @@ static std::optional> polyline_sample_next_point_at_dis return lines; #else #ifdef _WIN32 - if (! BoundingBox(Point::new_scale(-170., -170.), Point::new_scale(170., 170.)).contains(get_extents(polygon))) + // Max dimensions for MK3 +// if (! BoundingBox(Point::new_scale(-170., -170.), Point::new_scale(170., 170.)).contains(get_extents(polygon))) + // Max dimensions for XL + if (! BoundingBox(Point::new_scale(-250., -250.), Point::new_scale(250., 250.)).contains(get_extents(polygon))) ::MessageBoxA(nullptr, "TreeSupport infill kravsky", "Bug detected!", MB_OK | MB_SYSTEMMODAL | MB_SETFOREGROUND | MB_ICONWARNING); #endif // _WIN32 @@ -702,10 +724,7 @@ static std::optional> polyline_sample_next_point_at_dis ::MessageBoxA(nullptr, "TreeSupport infill negative area", "Bug detected!", MB_OK | MB_SYSTEMMODAL | MB_SETFOREGROUND | MB_ICONWARNING); #endif // _WIN32 assert(intersecting_edges(to_polygons(expoly)).empty()); -#ifdef _WIN32 - if (! intersecting_edges(to_polygons(expoly)).empty()) - ::MessageBoxA(nullptr, "TreeSupport infill self intersections", "Bug detected!", MB_OK | MB_SYSTEMMODAL | MB_SETFOREGROUND | MB_ICONWARNING); -#endif // _WIN32 + check_self_intersections(expoly, "generate_support_infill_lines"); Surface surface(stInternal, std::move(expoly)); try { Polylines pl = filler->fill_surface(&surface, fill_params); @@ -831,6 +850,11 @@ static std::optional> polyline_sample_next_point_at_dis return union_(ret); } +static double layer_z(const SlicingParameters &slicing_params, const size_t layer_idx) +{ + return slicing_params.object_print_z_min + slicing_params.first_object_layer_height + layer_idx * slicing_params.layer_height; +} + static inline SupportGeneratorLayer& layer_initialize( SupportGeneratorLayer &layer_new, const SupporLayerType layer_type, @@ -838,7 +862,7 @@ static inline SupportGeneratorLayer& layer_initialize( const size_t layer_idx) { layer_new.layer_type = layer_type; - layer_new.print_z = slicing_params.object_print_z_min + slicing_params.first_object_layer_height + layer_idx * slicing_params.layer_height; + layer_new.print_z = layer_z(slicing_params, layer_idx); layer_new.height = layer_idx == 0 ? slicing_params.first_object_layer_height : slicing_params.layer_height; layer_new.bottom_z = layer_idx == 0 ? slicing_params.object_print_z_min : layer_new.print_z - layer_new.height; return layer_new; @@ -1082,6 +1106,8 @@ static void generate_initial_areas( overhang_regular = mesh_group_settings.support_offset == 0 ? overhang_raw : safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, mesh_config.min_radius * 1.75 + mesh_config.xy_min_distance, 0, 1); + check_self_intersections(overhang_regular, "overhang_regular1"); + // offset ensures that areas that could be supported by a part of a support line, are not considered unsupported overhang Polygons remaining_overhang = intersection( diff(mesh_group_settings.support_offset == 0 ? @@ -1108,6 +1134,7 @@ static void generate_initial_areas( remaining_overhang = diff(remaining_overhang, safe_offset_inc(overhang_regular, 1.5 * extra_total_offset_acc, raw_collision, offset_step, 0, 1)); // Extending the overhangs by the inflated remaining overhangs. overhang_regular = union_(overhang_regular, diff(safe_offset_inc(remaining_overhang, extra_total_offset_acc, raw_collision, offset_step, 0, 1), relevant_forbidden)); + check_self_intersections(overhang_regular, "overhang_regular2"); } // If the xy distance overrides the z distance, some support needs to be inserted further down. //=> Analyze which support points do not fit on this layer and check if they will fit a few layers down (while adding them an infinite amount of layers down would technically be closer the the setting description, it would not produce reasonable results. ) @@ -1159,6 +1186,7 @@ static void generate_initial_areas( if (mesh_group_settings.minimum_support_area > 0) remove_small(overhang_roofs, mesh_group_settings.minimum_roof_area); overhang_regular = diff(overhang_regular, overhang_roofs, ApplySafetyOffset::Yes); + check_self_intersections(overhang_regular, "overhang_regular3"); for (ExPolygon &roof_part : union_ex(overhang_roofs)) overhang_processing.emplace_back(std::move(roof_part), true); } @@ -3044,6 +3072,475 @@ static void draw_areas( "finalize_interface_and_support_areas " << dur_finalize << " ms"; } +#if 1 +// Test whether two circles, each on its own plane in 3D intersect. +// Circles are considered intersecting, if the lowest point on one circle is below the other circle's plane. +// Assumption: The two planes are oriented the same way. +static bool circles_intersect( + const Vec3d &p1, const Vec3d &n1, const double r1, + const Vec3d &p2, const Vec3d &n2, const double r2) +{ + assert(n1.dot(n2) >= 0); + + const Vec3d z = n1.cross(n2); + const Vec3d dir1 = z.cross(n1); + const Vec3d lowest_point1 = p1 + dir1 * (r1 / dir1.norm()); + assert(n2.dot(p1) >= n2.dot(lowest_point1)); + if (n2.dot(lowest_point1) <= 0) + return true; + const Vec3d dir2 = z.cross(n2); + const Vec3d lowest_point2 = p2 + dir2 * (r2 / dir2.norm()); + assert(n1.dot(p2) >= n1.dot(lowest_point2)); + return n1.dot(lowest_point2) <= 0; +} + +template +void triangulate_fan(indexed_triangle_set &its, int ifan, int ibegin, int iend) +{ + // at least 3 vertices, increasing order. + assert(ibegin + 3 <= iend); + assert(ibegin >= 0 && iend <= its.vertices.size()); + assert(ifan >= 0 && ifan < its.vertices.size()); + int num_faces = iend - ibegin; + its.indices.reserve(its.indices.size() + num_faces * 3); + for (int v = ibegin, u = iend - 1; v < iend; u = v ++) { + if (flip_normals) + its.indices.push_back({ ifan, u, v }); + else + its.indices.push_back({ ifan, v, u }); + } +} + +static void triangulate_strip(indexed_triangle_set &its, int ibegin1, int iend1, int ibegin2, int iend2) +{ + // at least 3 vertices, increasing order. + assert(ibegin1 + 3 <= iend1); + assert(ibegin1 >= 0 && iend1 <= its.vertices.size()); + assert(ibegin2 + 3 <= iend2); + assert(ibegin2 >= 0 && iend2 <= its.vertices.size()); + int n1 = iend1 - ibegin1; + int n2 = iend2 - ibegin2; + its.indices.reserve(its.indices.size() + (n1 + n2) * 3); + + // For the first vertex of 1st strip, find the closest vertex on the 2nd strip. + int istart2 = ibegin2; + { + const Vec3f &p1 = its.vertices[ibegin1]; + auto d2min = std::numeric_limits::max(); + for (int i = ibegin2; i < iend2; ++ i) { + const Vec3f &p2 = its.vertices[i]; + const float d2 = (p2 - p1).squaredNorm(); + if (d2 < d2min) { + d2min = d2; + istart2 = i; + } + } + } + + // Now triangulate the strip zig-zag fashion taking always the shortest connection if possible. + for (int u = ibegin1, v = istart2; n1 > 0 || n2 > 0;) { + bool take_first; + int u2, v2; + auto update_u2 = [&u2, u, ibegin1, iend1]() { + u2 = u; + if (++ u2 == iend1) + u2 = ibegin1; + }; + auto update_v2 = [&v2, v, ibegin2, iend2]() { + v2 = v; + if (++ v2 == iend2) + v2 = ibegin2; + }; + if (n1 == 0) { + take_first = false; + update_v2(); + } else if (n2 == 0) { + take_first = true; + update_u2(); + } else { + update_u2(); + update_v2(); + float l1 = (its.vertices[u2] - its.vertices[v]).squaredNorm(); + float l2 = (its.vertices[v2] - its.vertices[u]).squaredNorm(); + take_first = l1 < l2; + } + if (take_first) { + its.indices.push_back({ u, u2, v }); + -- n1; + u = u2; + } else { + its.indices.push_back({ u, v2, v }); + -- n2; + v = v2; + } + } +} + +// Discretize 3D circle, append to output vector, return ranges of indices of the points added. +static std::pair discretize_circle(const Vec3f ¢er, const Vec3f &normal, const float radius, const float eps, std::vector &pts) +{ + // Calculate discretization step and number of steps. + float angle_step = 2. * acos(1. - eps / radius); + auto nsteps = int(ceil(2 * M_PI / angle_step)); + angle_step = 2 * M_PI / nsteps; + + // Prepare coordinate system for the circle plane. + Vec3f x = normal.cross(Vec3f(0.f, -1.f, 0.f)).normalized(); + Vec3f y = normal.cross(x).normalized(); + assert(std::abs(x.cross(y).dot(normal) - 1.f) < EPSILON); + + // Discretize the circle. + int begin = int(pts.size()); + pts.reserve(pts.size() + nsteps); + float angle = 0; + x *= radius; + y *= radius; + for (int i = 0; i < nsteps; ++ i) { + pts.emplace_back(center + x * cos(angle) + y * sin(angle)); + angle += angle_step; + } + return { begin, int(pts.size()) }; +} + +static void extrude_branch( + const std::vector &path, + const TreeSupportSettings &config, + const SlicingParameters &slicing_params, + const std::vector &move_bounds, + indexed_triangle_set &result) +{ + Vec3d p1, p2, p3; + Vec3d v1, v2; + Vec3d nprev; + Vec3d ncurrent; + assert(path.size() >= 2); + static constexpr const float eps = 0.015f; + std::pair prev_strip; + +// char fname[2048]; +// static int irun = 0; + + for (size_t ipath = 1; ipath < path.size(); ++ ipath) { + const SupportElement &prev = *path[ipath - 1]; + const SupportElement ¤t = *path[ipath]; + assert(prev.state.layer_idx + 1 == current.state.layer_idx); + p1 = to_3d(unscaled(prev .state.result_on_layer), layer_z(slicing_params, prev .state.layer_idx)); + p2 = to_3d(unscaled(current.state.result_on_layer), layer_z(slicing_params, current.state.layer_idx)); + v1 = (p2 - p1).normalized(); + if (ipath == 1) { + nprev = v1; + // Extrude the bottom half sphere. + float radius = unscaled(config.getRadius(prev.state)); + float angle_step = 2. * acos(1. - eps / radius); + auto nsteps = int(ceil(M_PI / (2. * angle_step))); + angle_step = M_PI / (2. * nsteps); + int ifan = int(result.vertices.size()); + result.vertices.emplace_back((p1 - nprev * radius).cast()); + float angle = angle_step; + for (int i = 1; i < nsteps; ++ i, angle += angle_step) { + std::pair strip = discretize_circle((p1 - nprev * radius * cos(angle)).cast(), nprev.cast(), radius * sin(angle), eps, result.vertices); + if (i == 1) + triangulate_fan(result, ifan, strip.first, strip.second); + else + triangulate_strip(result, prev_strip.first, prev_strip.second, strip.first, strip.second); +// sprintf(fname, "d:\\temp\\meshes\\tree-partial-%d.obj", ++ irun); +// its_write_obj(result, fname); + prev_strip = strip; + } + } + if (ipath + 1 == path.size()) { + // End of the tube. + ncurrent = v1; + // Extrude the top half sphere. + float radius = unscaled(config.getRadius(current.state)); + float angle_step = 2. * acos(1. - eps / radius); + auto nsteps = int(ceil(M_PI / (2. * angle_step))); + angle_step = M_PI / (2. * nsteps); + float angle = M_PI / 2.; + for (int i = 0; i < nsteps; ++ i, angle -= angle_step) { + std::pair strip = discretize_circle((p2 + ncurrent * radius * cos(angle)).cast(), ncurrent.cast(), radius * sin(angle), eps, result.vertices); + triangulate_strip(result, prev_strip.first, prev_strip.second, strip.first, strip.second); +// sprintf(fname, "d:\\temp\\meshes\\tree-partial-%d.obj", ++ irun); +// its_write_obj(result, fname); + prev_strip = strip; + } + int ifan = int(result.vertices.size()); + result.vertices.emplace_back((p2 + ncurrent * radius).cast()); + triangulate_fan(result, ifan, prev_strip.first, prev_strip.second); +// sprintf(fname, "d:\\temp\\meshes\\tree-partial-%d.obj", ++ irun); +// its_write_obj(result, fname); + } else { + const SupportElement &next = *path[ipath + 1]; + assert(current.state.layer_idx + 1 == next.state.layer_idx); + p3 = to_3d(unscaled(next.state.result_on_layer), layer_z(slicing_params, next.state.layer_idx)); + v2 = (p3 - p2).normalized(); + ncurrent = (v1 + v2).normalized(); + float radius = unscaled(config.getRadius(current.state)); + std::pair strip = discretize_circle(p2.cast(), ncurrent.cast(), radius, eps, result.vertices); + triangulate_strip(result, prev_strip.first, prev_strip.second, strip.first, strip.second); + prev_strip = strip; +// sprintf(fname, "d:\\temp\\meshes\\tree-partial-%d.obj", ++irun); +// its_write_obj(result, fname); + } +#if 0 + if (circles_intersect(p1, nprev, settings.getRadius(prev), p2, ncurrent, settings.getRadius(current))) { + // Cannot connect previous and current slice using a simple zig-zag triangulation, + // because the two circles intersect. + + } else { + // Continue with chaining. + + } +#endif + } +} +#endif + +static void draw_branches( + PrintObject &print_object, + const TreeModelVolumes &volumes, + const TreeSupportSettings &config, + const std::vector &overhangs, + std::vector &move_bounds, + + SupportGeneratorLayersPtr &bottom_contacts, + SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayersPtr &intermediate_layers, + SupportGeneratorLayerStorage &layer_storage) +{ + static int irun = 0; + + const SlicingParameters& slicing_params = print_object.slicing_parameters(); + + // All SupportElements are put into a layer independent storage to improve parallelization. + std::vector> elements_with_link_down; + std::vector linear_data_layers; + { + std::vector> map_downwards_old; + std::vector> map_downwards_new; + linear_data_layers.emplace_back(0); + for (LayerIndex layer_idx = 0; layer_idx < LayerIndex(move_bounds.size()); ++ layer_idx) { + SupportElements *layer_above = layer_idx + 1 < move_bounds.size() ? &move_bounds[layer_idx + 1] : nullptr; + map_downwards_new.clear(); + std::sort(map_downwards_old.begin(), map_downwards_old.end(), [](auto& l, auto& r) { return l.first < r.first; }); + SupportElements &layer = move_bounds[layer_idx]; + for (size_t elem_idx = 0; elem_idx < layer.size(); ++ elem_idx) { + SupportElement &elem = layer[elem_idx]; + int child = -1; + if (layer_idx > 0) { + auto it = std::lower_bound(map_downwards_old.begin(), map_downwards_old.end(), &elem, [](auto& l, const SupportElement* r) { return l.first < r; }); + if (it != map_downwards_old.end() && it->first == &elem) { + child = it->second; + // Only one link points to a node above from below. + assert(!(++it != map_downwards_old.end() && it->first == &elem)); + } + const SupportElement *pchild = child == -1 ? nullptr : &move_bounds[layer_idx - 1][child]; + if ((! pchild && elem.state.target_height == layer_idx) || (pchild && ! pchild->state.result_on_layer_is_set())) + // We either come from nowhere at the final layer or we had invalid parents 2. should never happen but just to be sure + continue; + } + for (int32_t parent_idx : elem.parents) { + SupportElement &parent = (*layer_above)[parent_idx]; + if (parent.state.result_on_layer_is_set()) + map_downwards_new.emplace_back(&parent, elem_idx); + } + + elements_with_link_down.push_back({ &elem, int(child) }); + } + std::swap(map_downwards_old, map_downwards_new); + linear_data_layers.emplace_back(elements_with_link_down.size()); + } + } + + std::unique_ptr> closest_surface_point; + { + TriangleMesh mesh = print_object.model_object()->raw_mesh(); + mesh.transform(print_object.trafo_centered()); + double scale = 10.; + openvdb::FloatGrid::Ptr grid = mesh_to_grid(mesh.its, {}, scale, 0., 0.); + closest_surface_point = openvdb::tools::ClosestSurfacePoint::create(*grid); + std::vector pts, prev, projections; + std::vector distances; + for (const std::pair &element : elements_with_link_down) { + Vec3d pt = to_3d(unscaled(element.first->state.result_on_layer), layer_z(slicing_params, element.first->state.layer_idx)) * scale; + pts.push_back({ pt.x(), pt.y(), pt.z() }); + } + + const double collision_extra_gap = 1. * scale; + const double max_nudge_collision_avoidance = 2. * scale; + const double max_nudge_smoothing = 1. * scale; + + for (size_t iter = 0; iter < 1000; ++ iter) { + prev = pts; + projections = pts; + distances.assign(pts.size(), std::numeric_limits::max()); + closest_surface_point->searchAndReplace(projections, distances); + size_t num_moved = 0; + for (size_t i = 0; i < projections.size(); ++ i) { + const SupportElement &element = *elements_with_link_down[i].first; + const int below = elements_with_link_down[i].second; + if (pts[i] != projections[i]) { + // Nudge the circle center away from the collision. + Vec3d v{ projections[i].x() - pts[i].x(), projections[i].y() - pts[i].y(), projections[i].z() - pts[i].z() }; + double depth = v.norm(); + assert(std::abs(distances[i] - depth) < EPSILON); + double radius = unscaled(config.getRadius(element.state)) * scale; + if (depth < radius) { + // Collision detected to be removed. + ++ num_moved; + double dxy = sqrt(sqr(radius) - sqr(v.z())); + double nudge_dist_max = dxy - std::hypot(v.x(), v.y()) + //FIXME 1mm gap + + collision_extra_gap; + // Shift by maximum 2mm. + double nudge_dist = std::min(std::max(0., nudge_dist_max), max_nudge_collision_avoidance); + Vec2d nudge_v = to_2d(v).normalized() * (- nudge_dist); + pts[i].x() += nudge_v.x(); + pts[i].y() += nudge_v.y(); + } + } + // Laplacian smoothing + if (! element.parents.empty() && (below != -1 || element.state.layer_idx == 0)) { + Vec2d avg{ 0, 0 }; + const SupportElements &above = move_bounds[element.state.layer_idx + 1]; + const size_t offset_above = linear_data_layers[element.state.layer_idx + 1]; + for (auto iparent : element.parents) { + avg.x() += prev[offset_above + iparent].x(); + avg.y() += prev[offset_above + iparent].y(); + } + size_t cnt = element.parents.size(); + if (below != -1) { + const size_t offset_below = linear_data_layers[element.state.layer_idx - 1]; + avg.x() += prev[offset_below + below].x(); + avg.y() += prev[offset_below + below].y(); + ++ cnt; + } + avg /= double(cnt); + static constexpr const double smoothing_factor = 0.5; + Vec2d old_pos{ pts[i].x(), pts[i].y() }; + Vec2d new_pos = (1. - smoothing_factor) * old_pos + smoothing_factor * avg; + Vec2d shift = new_pos - old_pos; + double nudge_dist_max = shift.norm(); + // Shift by maximum 1mm, less than the collision avoidance factor. + double nudge_dist = std::min(std::max(0., nudge_dist_max), max_nudge_smoothing); + Vec2d nudge_v = shift.normalized() * nudge_dist; + pts[i].x() += nudge_v.x(); + pts[i].y() += nudge_v.y(); + } + } + printf("iteration: %d, moved: %d\n", int(iter), int(num_moved)); + if (num_moved == 0) + break; + } + +#if 1 + for (size_t i = 0; i < projections.size(); ++ i) { + elements_with_link_down[i].first->state.result_on_layer.x() = scaled(pts[i].x()) / scale; + elements_with_link_down[i].first->state.result_on_layer.y() = scaled(pts[i].y()) / scale; + } +#endif + } + + std::vector support_layer_storage(move_bounds.size()); + std::vector support_roof_storage(move_bounds.size()); + + // Unmark all nodes. + for (SupportElements &elements : move_bounds) + for (SupportElement &element : elements) + element.state.marked = false; + + // Traverse all nodes, generate tubes. + // Traversal stack with nodes and thier current parent + std::vector path; + indexed_triangle_set cummulative_mesh; + indexed_triangle_set partial_mesh; + indexed_triangle_set temp_mesh; + for (LayerIndex layer_idx = 0; layer_idx + 1 < LayerIndex(move_bounds.size()); ++ layer_idx) { + SupportElements &layer = move_bounds[layer_idx]; + SupportElements &layer_above = move_bounds[layer_idx + 1]; + + for (SupportElement &start_element : layer) + if (! start_element.state.marked && ! start_element.parents.empty()) { + // Collect elements up to a bifurcation above. + start_element.state.marked = true; + for (size_t parent_idx = 0; parent_idx < start_element.parents.size(); ++ parent_idx) { + path.clear(); + path.emplace_back(&start_element); + // Traverse each branch until it branches again. + SupportElement &first_parent = layer_above[start_element.parents[parent_idx]]; + assert(path.back()->state.layer_idx + 1 == first_parent.state.layer_idx); + path.emplace_back(&first_parent); + if (first_parent.parents.size() < 2) + first_parent.state.marked = true; + if (first_parent.parents.size() == 1) { + for (SupportElement *parent = &first_parent;;) { + SupportElement &next_parent = move_bounds[parent->state.layer_idx + 1][parent->parents.front()]; + assert(path.back()->state.layer_idx + 1 == next_parent.state.layer_idx); + path.emplace_back(&next_parent); + if (next_parent.parents.size() > 1) + break; + next_parent.state.marked = true; + if (next_parent.parents.size() == 0) + break; + parent = &next_parent; + } + } + // Triangulate the tube. + partial_mesh.clear(); + extrude_branch(path, config, slicing_params, move_bounds, partial_mesh); +#if 0 + char fname[2048]; + sprintf(fname, "d:\\temp\\meshes\\tree-raw-%d.obj", ++ irun); + its_write_obj(partial_mesh, fname); +#if 0 + temp_mesh.clear(); + cut_mesh(partial_mesh, layer_z(slicing_params, path.back()->state.layer_idx) + EPSILON, nullptr, &temp_mesh, false); + sprintf(fname, "d:\\temp\\meshes\\tree-trimmed1-%d.obj", irun); + its_write_obj(temp_mesh, fname); + partial_mesh.clear(); + cut_mesh(temp_mesh, layer_z(slicing_params, path.front()->state.layer_idx) - EPSILON, &partial_mesh, nullptr, false); + sprintf(fname, "d:\\temp\\meshes\\tree-trimmed2-%d.obj", irun); +#endif + its_write_obj(partial_mesh, fname); +#endif + its_merge(cummulative_mesh, partial_mesh); + } + } + } + + std::vector slice_z; + for (size_t layer_idx = 0; layer_idx < move_bounds.size(); ++ layer_idx) { + double print_z = slicing_params.object_print_z_min + slicing_params.first_object_layer_height + layer_idx * slicing_params.layer_height; + double layer_height = layer_idx == 0 ? slicing_params.first_object_layer_height : slicing_params.layer_height; + slice_z.emplace_back(float(print_z - layer_height * 0.5)); + } + // Remove the trailing slices. + while (! slice_z.empty()) + if (move_bounds[slice_z.size() - 1].empty()) + slice_z.pop_back(); + else + break; + +#if 0 + its_write_obj(cummulative_mesh, "d:\\temp\\meshes\\tree.obj"); +#endif + + MeshSlicingParamsEx params; + params.closing_radius = float(print_object.config().slice_closing_radius.value); + params.mode = MeshSlicingParams::SlicingMode::Positive; + std::vector slices = slice_mesh_ex(cummulative_mesh, slice_z, params); + for (size_t layer_idx = 0; layer_idx < slice_z.size(); ++ layer_idx) + if (! slices[layer_idx].empty()) { + SupportGeneratorLayer *&l = intermediate_layers[layer_idx]; + if (l == nullptr) + l = &layer_allocate(layer_storage, SupporLayerType::Base, slicing_params, layer_idx); + append(l->polygons, to_polygons(std::move(slices[layer_idx]))); + } + + finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage, + bottom_contacts, top_contacts, intermediate_layers, layer_storage); +} + /*! * \brief Create the areas that need support. * @@ -3147,8 +3644,13 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume auto t_place = std::chrono::high_resolution_clock::now(); // ### draw these points as circles +#if 0 draw_areas(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, bottom_contacts, top_contacts, intermediate_layers, layer_storage); +#else + draw_branches(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, + bottom_contacts, top_contacts, intermediate_layers, layer_storage); +#endif auto t_draw = std::chrono::high_resolution_clock::now(); auto dur_pre_gen = 0.001 * std::chrono::duration_cast(t_precalc - t_start).count(); From 4fb7bb8deca1b9e21ccfd3ea453a47b3d98014d9 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 10 Oct 2022 14:41:05 +0200 Subject: [PATCH 15/29] SPE-1342 - Fixed crash after undo in SLA support point gizmo --- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 026fae17b6..b562eb49a0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -78,14 +78,14 @@ void GLGizmoSlaSupports::data_changed() if (mo) { if (mo->sla_points_status == sla::PointsStatus::Generating) get_data_from_backend(); - } #if ENABLE_RAYCAST_PICKING - if (m_raycasters.empty()) - on_register_raycasters_for_picking(); - else - update_raycasters_for_picking_transform(); + if (m_raycasters.empty()) + on_register_raycasters_for_picking(); + else + update_raycasters_for_picking_transform(); #endif // ENABLE_RAYCAST_PICKING + } } From 418734f41b5f1e7a02c9e78a3062955568408933 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 10 Oct 2022 16:58:43 +0200 Subject: [PATCH 16/29] WIP Tree supports with circular crossections: Clipping the remaining collisions with the object. --- src/libslic3r/TreeSupport.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index b440818a8a..258d554dec 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -3537,6 +3537,16 @@ static void draw_branches( append(l->polygons, to_polygons(std::move(slices[layer_idx]))); } + // Trim the slices. + tbb::parallel_for(tbb::blocked_range(0, intermediate_layers.size()), + [&](const tbb::blocked_range &range) { + for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) + if (SupportGeneratorLayer *layer = intermediate_layers[layer_idx]; layer) { + Polygons &poly = intermediate_layers[layer_idx]->polygons; + poly = diff_clipped(poly, volumes.getCollision(0, layer_idx, true)); + } + }); + finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage, bottom_contacts, top_contacts, intermediate_layers, layer_storage); } From 009fe1cab43a1488c2ab5262a17980b7459864b9 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 12 Oct 2022 14:12:07 +0200 Subject: [PATCH 17/29] New method ConfigOptionDef::set_enum_values() to initialize enum names / values for UI combo boxes using an initializer list of pairs of values. --- src/libslic3r/Config.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 151043a04f..a8d0473b7b 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1786,6 +1786,17 @@ public: // Initialized by ConfigOptionEnum::get_enum_values() const t_config_enum_values *enum_keys_map = nullptr; + void set_enum_values(std::initializer_list> il) { + enum_values.clear(); + enum_values.reserve(il.size()); + enum_labels.clear(); + enum_labels.reserve(il.size()); + for (const std::pair p : il) { + enum_values.emplace_back(p.first); + enum_labels.emplace_back(p.second); + } + } + bool has_enum_value(const std::string &value) const { for (const std::string &v : enum_values) if (v == value) From 2365b3a8ddf4d5666d3c4d5ddac323cd9bc3696f Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 12 Oct 2022 14:33:36 +0200 Subject: [PATCH 18/29] WIP TreeSupports: Now it is possible to switch between the normal and the "organic" supports. --- src/libslic3r/PrintConfig.cpp | 15 +- src/libslic3r/PrintConfig.hpp | 2 +- src/libslic3r/PrintObject.cpp | 2 +- src/libslic3r/SupportMaterial.cpp | 1 + src/libslic3r/TreeModelVolumes.cpp | 2 +- src/libslic3r/TreeSupport.cpp | 245 ++++++++++++++++++++++++----- 6 files changed, 216 insertions(+), 51 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 9a3bc3ce6f..841bee5b9f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -138,7 +138,8 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SupportMaterialPattern) static const t_config_enum_values s_keys_map_SupportMaterialStyle { { "grid", smsGrid }, { "snug", smsSnug }, - { "tree", smsTree } + { "tree", smsTree }, + { "organic", smsOrganic } }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SupportMaterialStyle) @@ -2782,12 +2783,12 @@ void PrintConfigDef::init_fff_params() "will create more stable supports, while snug support towers will save material and reduce " "object scarring."); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def->enum_values.push_back("grid"); - def->enum_values.push_back("snug"); - def->enum_values.push_back("tree"); - def->enum_labels.push_back(L("Grid")); - def->enum_labels.push_back(L("Snug")); - def->enum_labels.push_back(L("Tree")); + def->set_enum_values({ + { "grid", L("Grid") }, + { "snug", L("Snug") }, + { "tree", L("Tree") }, + { "organic", L("Organic") } + }); def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(smsGrid)); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 48493aa0bd..0a6daf2d28 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -85,7 +85,7 @@ enum SupportMaterialPattern { }; enum SupportMaterialStyle { - smsGrid, smsSnug, smsTree, + smsGrid, smsSnug, smsTree, smsOrganic, }; enum SupportMaterialInterfacePattern { diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 7ea55a3a4e..9ffb57a723 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2197,7 +2197,7 @@ void PrintObject::combine_infill() void PrintObject::_generate_support_material() { - if (m_config.support_material_style == smsTree) { + if (m_config.support_material_style == smsTree || m_config.support_material_style == smsOrganic) { fff_tree_support_generate(*this, std::function([this](){ this->throw_if_canceled(); })); } else { PrintObjectSupportMaterial support_material(this, m_slicing_params); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 4910168873..b1b6600bc2 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -800,6 +800,7 @@ public: { switch (m_style) { case smsTree: + case smsOrganic: assert(false); [[fallthrough]]; case smsGrid: diff --git a/src/libslic3r/TreeModelVolumes.cpp b/src/libslic3r/TreeModelVolumes.cpp index 41e78e45b1..e098636fd4 100644 --- a/src/libslic3r/TreeModelVolumes.cpp +++ b/src/libslic3r/TreeModelVolumes.cpp @@ -39,7 +39,7 @@ TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &pr // Support must be enabled and set to Tree style. assert(config.support_material); - assert(config.support_material_style == smsTree); + assert(config.support_material_style == smsTree || config.support_material_style == smsOrganic); // Calculate maximum external perimeter width over all printing regions, taking into account the default layer height. coordf_t external_perimeter_width = 0.; diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index 258d554dec..fecbef8313 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -211,7 +211,7 @@ static std::vector>> group_me #endif // NDEBUG // Support must be enabled and set to Tree style. assert(object_config.support_material); - assert(object_config.support_material_style == smsTree); + assert(object_config.support_material_style == smsTree || object_config.support_material_style == smsOrganic); bool found_existing_group = false; TreeSupportSettings next_settings{ TreeSupportMeshGroupSettings{ print_object } }; @@ -330,18 +330,39 @@ void tree_supports_show_error(std::string message, bool critical) if (! (enforced_layer || blockers_layers.empty() || blockers_layers[layer_id].empty())) overhangs = diff(overhangs, blockers_layers[layer_id], ApplySafetyOffset::Yes); } - if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty()) + //check_self_intersections(overhangs, "generate_overhangs1"); + if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty()) { // Has some support enforcers at this layer, apply them to the overhangs, don't apply the support threshold angle. - if (Polygons enforced_overhangs = intersection(raw_overhangs_calculated ? raw_overhangs : diff(current_layer.lslices, lower_layer.lslices), enforcers_layers[layer_id]); + //enforcers_layers[layer_id] = union_(enforcers_layers[layer_id]); + //check_self_intersections(enforcers_layers[layer_id], "generate_overhangs - enforcers"); + //check_self_intersections(to_polygons(lower_layer.lslices), "generate_overhangs - lowerlayers"); + if (Polygons enforced_overhangs = intersection(raw_overhangs_calculated ? raw_overhangs : diff(current_layer.lslices, lower_layer.lslices), enforcers_layers[layer_id] /*, ApplySafetyOffset::Yes */); ! enforced_overhangs.empty()) { //FIXME this is a hack to make enforcers work on steep overhangs. - enforced_overhangs = diff(offset(enforced_overhangs, + //check_self_intersections(enforced_overhangs, "generate_overhangs - enforced overhangs1"); + //Polygons enforced_overhangs_prev = enforced_overhangs; + //check_self_intersections(to_polygons(union_ex(enforced_overhangs)), "generate_overhangs - enforced overhangs11"); + //check_self_intersections(offset(union_ex(enforced_overhangs), + //FIXME this is a fudge constant! + // scaled(0.4)), "generate_overhangs - enforced overhangs12"); + enforced_overhangs = diff(offset(union_ex(enforced_overhangs), //FIXME this is a fudge constant! scaled(0.4)), lower_layer.lslices); +#ifdef TREESUPPORT_DEBUG_SVG + if (! intersecting_edges(enforced_overhangs).empty()) { + static int irun = 0; + SVG::export_expolygons(debug_out_path("treesupport-self-intersections-%d.svg", ++irun), + { { { union_ex(enforced_overhangs_prev) }, { "prev", "yellow", 0.5f } }, + { { lower_layer.lslices }, { "lower_layer.lslices", "gray", 0.5f } }, + { { union_ex(enforced_overhangs) }, { "enforced_overhangs", "red", "black", "", scaled(0.1f), 0.5f } } }); + } +#endif // TREESUPPORT_DEBUG_SVG + //check_self_intersections(enforced_overhangs, "generate_overhangs - enforced overhangs2"); overhangs = overhangs.empty() ? std::move(enforced_overhangs) : union_(overhangs, enforced_overhangs); + //check_self_intersections(overhangs, "generate_overhangs - enforcers"); } - check_self_intersections(overhangs, "generate_overhangs"); + } out[layer_id] = std::move(overhangs); } }); @@ -1106,7 +1127,7 @@ static void generate_initial_areas( overhang_regular = mesh_group_settings.support_offset == 0 ? overhang_raw : safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, mesh_config.min_radius * 1.75 + mesh_config.xy_min_distance, 0, 1); - check_self_intersections(overhang_regular, "overhang_regular1"); + //check_self_intersections(overhang_regular, "overhang_regular1"); // offset ensures that areas that could be supported by a part of a support line, are not considered unsupported overhang Polygons remaining_overhang = intersection( @@ -1134,7 +1155,7 @@ static void generate_initial_areas( remaining_overhang = diff(remaining_overhang, safe_offset_inc(overhang_regular, 1.5 * extra_total_offset_acc, raw_collision, offset_step, 0, 1)); // Extending the overhangs by the inflated remaining overhangs. overhang_regular = union_(overhang_regular, diff(safe_offset_inc(remaining_overhang, extra_total_offset_acc, raw_collision, offset_step, 0, 1), relevant_forbidden)); - check_self_intersections(overhang_regular, "overhang_regular2"); + //check_self_intersections(overhang_regular, "overhang_regular2"); } // If the xy distance overrides the z distance, some support needs to be inserted further down. //=> Analyze which support points do not fit on this layer and check if they will fit a few layers down (while adding them an infinite amount of layers down would technically be closer the the setting description, it would not produce reasonable results. ) @@ -1186,7 +1207,7 @@ static void generate_initial_areas( if (mesh_group_settings.minimum_support_area > 0) remove_small(overhang_roofs, mesh_group_settings.minimum_roof_area); overhang_regular = diff(overhang_regular, overhang_roofs, ApplySafetyOffset::Yes); - check_self_intersections(overhang_regular, "overhang_regular3"); + //check_self_intersections(overhang_regular, "overhang_regular3"); for (ExPolygon &roof_part : union_ex(overhang_roofs)) overhang_processing.emplace_back(std::move(roof_part), true); } @@ -2397,6 +2418,8 @@ static void set_points_on_areas(const SupportElement &elem, SupportElements *lay next_elem.state.result_on_layer = move_inside_if_outside(next_elem.influence_area, elem.state.result_on_layer); // do not call recursive because then amount of layers would be restricted by the stack size } + // Mark the parent element as accessed from a valid child element. + next_elem.state.marked = true; } } @@ -2515,15 +2538,23 @@ static void create_nodes_from_area( { // Initialize points on layer 0, with a "random" point in the influence area. // Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result. - for (SupportElement &init : move_bounds.front()) { - init.state.result_on_layer = move_inside_if_outside(init.influence_area, init.state.next_position); - // Also set the parent nodes, as these will be required for the first iteration of the loop below. - set_points_on_areas(init, move_bounds.size() > 1 ? &move_bounds[1] : nullptr); + { + SupportElements *layer_above = move_bounds.size() > 1 ? &move_bounds[1] : nullptr; + for (SupportElement &elem : *layer_above) + elem.state.marked = false; + for (SupportElement &init : move_bounds.front()) { + init.state.result_on_layer = move_inside_if_outside(init.influence_area, init.state.next_position); + // Also set the parent nodes, as these will be required for the first iteration of the loop below and mark the parent nodes. + set_points_on_areas(init, layer_above); + } } for (LayerIndex layer_idx = 1; layer_idx < LayerIndex(move_bounds.size()); ++ layer_idx) { auto &layer = move_bounds[layer_idx]; auto *layer_above = layer_idx + 1 < move_bounds.size() ? &move_bounds[layer_idx + 1] : nullptr; + if (layer_above) + for (SupportElement &elem : *layer_above) + elem.state.marked = false; for (SupportElement &elem : layer) { assert(! elem.state.deleted); assert(elem.state.layer_idx == layer_idx); @@ -2537,11 +2568,6 @@ static void create_nodes_from_area( } // we dont need to remove yet the parents as they will have a lower dtt and also no result_on_layer set elem.state.deleted = true; - for (int32_t parent_idx : elem.parents) - // When the roof was not able to generate downwards enough, the top elements may have not moved, and have result_on_layer already set. - // As this branch needs to be removed => all parents result_on_layer have to be invalidated. - (*layer_above)[parent_idx].state.result_on_layer_reset(); - continue; } else { // set the point where the branch will be placed on the model if (elem.state.to_model_gracious) @@ -2550,13 +2576,67 @@ static void create_nodes_from_area( set_to_model_contact_simple(elem); } } - if (! elem.state.deleted) - // element is valid now setting points in the layer above + if (! elem.state.deleted && ! elem.state.marked && elem.state.target_height == layer_idx) + // Just a tip surface with no supporting element. + elem.state.deleted = true; + if (elem.state.deleted) { + for (int32_t parent_idx : elem.parents) + // When the roof was not able to generate downwards enough, the top elements may have not moved, and have result_on_layer already set. + // As this branch needs to be removed => all parents result_on_layer have to be invalidated. + (*layer_above)[parent_idx].state.result_on_layer_reset(); + } + if (! elem.state.deleted) { + // Element is valid now setting points in the layer above and mark the parent nodes. set_points_on_areas(elem, layer_above); + } } } +#ifndef NDEBUG + // Verify the tree connectivity including the branch slopes. + for (LayerIndex layer_idx = 0; layer_idx + 1 < LayerIndex(move_bounds.size()); ++ layer_idx) { + auto &layer = move_bounds[layer_idx]; + auto &above = move_bounds[layer_idx + 1]; + for (SupportElement &elem : layer) + if (! elem.state.deleted) { + for (int32_t iparent : elem.parents) { + SupportElement &parent = above[iparent]; + assert(! parent.state.deleted); + assert(elem.state.result_on_layer_is_set() == parent.state.result_on_layer_is_set()); + if (elem.state.result_on_layer_is_set()) { + double radius_increase = config.getRadius(elem.state) - config.getRadius(parent.state); + assert(radius_increase >= 0); + double shift = (elem.state.result_on_layer - parent.state.result_on_layer).cast().norm(); + assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); + } + } + } + } +#endif // NDEBUG + remove_deleted_elements(move_bounds); + +#ifndef NDEBUG + // Verify the tree connectivity including the branch slopes. + for (LayerIndex layer_idx = 0; layer_idx + 1 < LayerIndex(move_bounds.size()); ++ layer_idx) { + auto &layer = move_bounds[layer_idx]; + auto &above = move_bounds[layer_idx + 1]; + for (SupportElement &elem : layer) { + assert(! elem.state.deleted); + for (int32_t iparent : elem.parents) { + SupportElement &parent = above[iparent]; + assert(! parent.state.deleted); + assert(elem.state.result_on_layer_is_set() == parent.state.result_on_layer_is_set()); + if (elem.state.result_on_layer_is_set()) { + double radius_increase = config.getRadius(elem.state) - config.getRadius(parent.state); + assert(radius_increase >= 0); + double shift = (elem.state.result_on_layer - parent.state.result_on_layer).cast().norm(); + assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); + } + } + } + } +#endif // NDEBUG } // For producing circular / elliptical areas from SupportElements (one DrawArea per one SupportElement) @@ -2677,7 +2757,8 @@ static void generate_branch_areas(const TreeModelVolumes &volumes, const TreeSup polygons_with_correct_center.emplace_back(std::move(part)); } // Increase the area again, to ensure the nozzle path when calculated later is very similar to the one assumed above. - polygons = diff_clipped(offset(polygons_with_correct_center, config.support_line_width / 2, jtMiter, 1.2), + assert(contains(polygons, draw_area.element->state.result_on_layer)); + polygons = diff_clipped(offset(polygons_with_correct_center, config.support_line_width / 2, jtMiter, 1.2), //FIXME Vojtech: Clipping may split the region into multiple pieces again, reversing the fixing effort. collision); } @@ -2723,10 +2804,12 @@ static void smooth_branch_areas( [&](const tbb::blocked_range &range) { for (size_t processing_idx = range.begin(); processing_idx < range.end(); ++ processing_idx) { DrawArea &draw_area = linear_data[processing_base + processing_idx]; + assert(draw_area.element->state.layer_idx == layer_idx); double max_outer_wall_distance = 0; bool do_something = false; for (int32_t parent_idx : draw_area.element->parents) { const SupportElement &parent = layer_above[parent_idx]; + assert(parent.state.layer_idx == layer_idx + 1); if (config.getRadius(parent.state) != config.getCollisionRadius(parent.state)) { do_something = true; max_outer_wall_distance = std::max(max_outer_wall_distance, (draw_area.element->state.result_on_layer - parent.state.result_on_layer).cast().norm() - (config.getRadius(*draw_area.element) - config.getRadius(parent))); @@ -2734,14 +2817,35 @@ static void smooth_branch_areas( } max_outer_wall_distance += max_radius_change_per_layer; // As this change is a bit larger than what usually appears, lost radius can be slowly reclaimed over the layers. if (do_something) { + assert(contains(draw_area.polygons, draw_area.element->state.result_on_layer)); Polygons max_allowed_area = offset(draw_area.polygons, float(max_outer_wall_distance), jtMiter, 1.2); for (int32_t parent_idx : draw_area.element->parents) { const SupportElement &parent = layer_above[parent_idx]; +#ifndef NDEBUG + assert(parent.state.layer_idx == layer_idx + 1); + assert(contains(linear_data[processing_base_above + parent_idx].polygons, parent.state.result_on_layer)); + double radius_increase = config.getRadius(draw_area.element->state) - config.getRadius(parent.state); + assert(radius_increase >= 0); + double shift = (draw_area.element->state.result_on_layer - parent.state.result_on_layer).cast().norm(); + assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); +#endif // NDEBUG if (config.getRadius(parent.state) != config.getCollisionRadius(parent.state)) { // No other element on this layer than the current one may be connected to &parent, // thus it is safe to update parent's DrawArea directly. Polygons &dst = linear_data[processing_base_above + parent_idx].polygons; - dst = intersection(dst, max_allowed_area); +// Polygons orig = dst; + if (! dst.empty()) { + dst = intersection(dst, max_allowed_area); +#if 0 + if (dst.empty()) { + static int irun = 0; + SVG::export_expolygons(debug_out_path("treesupport-extrude_areas-smooth-error-%d.svg", irun ++), + { { { union_ex(max_allowed_area) }, { "max_allowed_area", "yellow", 0.5f } }, + { { union_ex(orig) }, { "orig", "red", "black", "", scaled(0.1f), 0.5f } } }); + ::MessageBoxA(nullptr, "TreeSupport smoothing bug", "Bug detected!", MB_OK | MB_SYSTEMMODAL | MB_SETFOREGROUND | MB_ICONWARNING); + } +#endif + } } } } @@ -3010,9 +3114,7 @@ static void draw_areas( // Only one link points to a node above from below. assert(! (++ it != map_downwards_old.end() && it->first == &elem)); } - if ((! child && elem.state.target_height == layer_idx) || (child && !child->state.result_on_layer_is_set())) - // We either come from nowhere at the final layer or we had invalid parents 2. should never happen but just to be sure - continue; + assert(child ? child->state.result_on_layer_is_set() : elem.state.target_height > layer_idx); } for (int32_t parent_idx : elem.parents) { SupportElement &parent = (*layer_above)[parent_idx]; @@ -3026,12 +3128,66 @@ static void draw_areas( linear_data_layers.emplace_back(linear_data.size()); } +#ifndef NDEBUG + for (size_t i = 0; i < move_bounds.size(); ++ i) { + size_t begin = linear_data_layers[i]; + size_t end = linear_data_layers[i + 1]; + for (size_t j = begin; j < end; ++ j) + assert(linear_data[j].element == &move_bounds[i][j - begin]); + } +#endif // NDEBUG + auto t_start = std::chrono::high_resolution_clock::now(); // Generate the circles that will be the branches. generate_branch_areas(volumes, config, move_bounds, linear_data); + +#if 0 + assert(linear_data_layers.size() == move_bounds.size() + 1); + for (const auto &draw_area : linear_data) + assert(contains(draw_area.polygons, draw_area.element->state.result_on_layer)); + for (size_t i = 0; i < move_bounds.size(); ++ i) { + size_t begin = linear_data_layers[i]; + size_t end = linear_data_layers[i + 1]; + for (size_t j = begin; j < end; ++ j) { + const auto &draw_area = linear_data[j]; + assert(draw_area.element == &move_bounds[i][j - begin]); + assert(contains(draw_area.polygons, draw_area.element->state.result_on_layer)); + } + } +#endif + +#if 0 + for (size_t area_layer_idx = 0; area_layer_idx + 1 < linear_data_layers.size(); ++ area_layer_idx) { + size_t begin = linear_data_layers[area_layer_idx]; + size_t end = linear_data_layers[area_layer_idx + 1]; + Polygons polygons; + for (size_t area_idx = begin; area_idx < end; ++ area_idx) { + DrawArea &area = linear_data[area_idx]; + append(polygons, area.polygons); + } + SVG::export_expolygons(debug_out_path("treesupport-extrude_areas-raw-%d.svg", area_layer_idx), + { { { union_ex(polygons) }, { "parent", "red", "black", "", scaled(0.1f), 0.5f } } }); + } +#endif + auto t_generate = std::chrono::high_resolution_clock::now(); // In some edgecases a branch may go though a hole, where the regular radius does not fit. This can result in an apparent jump in branch radius. As such this cases need to be caught and smoothed out. smooth_branch_areas(config, move_bounds, linear_data, linear_data_layers); + +#if 0 + for (size_t area_layer_idx = 0; area_layer_idx + 1 < linear_data_layers.size(); ++area_layer_idx) { + size_t begin = linear_data_layers[area_layer_idx]; + size_t end = linear_data_layers[area_layer_idx + 1]; + Polygons polygons; + for (size_t area_idx = begin; area_idx < end; ++area_idx) { + DrawArea& area = linear_data[area_idx]; + append(polygons, area.polygons); + } + SVG::export_expolygons(debug_out_path("treesupport-extrude_areas-smooth-%d.svg", area_layer_idx), + { { { union_ex(polygons) }, { "parent", "red", "black", "", scaled(0.1f), 0.5f } } }); + } +#endif + auto t_smooth = std::chrono::high_resolution_clock::now(); // drop down all trees that connect non gracefully with the model drop_non_gracious_areas(volumes, linear_data, support_layer_storage); @@ -3256,7 +3412,7 @@ static void extrude_branch( float angle_step = 2. * acos(1. - eps / radius); auto nsteps = int(ceil(M_PI / (2. * angle_step))); angle_step = M_PI / (2. * nsteps); - float angle = M_PI / 2.; + auto angle = float(M_PI / 2.); for (int i = 0; i < nsteps; ++ i, angle -= angle_step) { std::pair strip = discretize_circle((p2 + ncurrent * radius * cos(angle)).cast(), ncurrent.cast(), radius * sin(angle), eps, result.vertices); triangulate_strip(result, prev_strip.first, prev_strip.second, strip.first, strip.second); @@ -3335,9 +3491,7 @@ static void draw_branches( assert(!(++it != map_downwards_old.end() && it->first == &elem)); } const SupportElement *pchild = child == -1 ? nullptr : &move_bounds[layer_idx - 1][child]; - if ((! pchild && elem.state.target_height == layer_idx) || (pchild && ! pchild->state.result_on_layer_is_set())) - // We either come from nowhere at the final layer or we had invalid parents 2. should never happen but just to be sure - continue; + assert(pchild ? pchild->state.result_on_layer_is_set() : elem.state.target_height > layer_idx); } for (int32_t parent_idx : elem.parents) { SupportElement &parent = (*layer_above)[parent_idx]; @@ -3370,7 +3524,8 @@ static void draw_branches( const double max_nudge_collision_avoidance = 2. * scale; const double max_nudge_smoothing = 1. * scale; - for (size_t iter = 0; iter < 1000; ++ iter) { + static constexpr const size_t num_iter = 100; // 1000; + for (size_t iter = 0; iter < num_iter; ++ iter) { prev = pts; projections = pts; distances.assign(pts.size(), std::numeric_limits::max()); @@ -3404,18 +3559,24 @@ static void draw_branches( Vec2d avg{ 0, 0 }; const SupportElements &above = move_bounds[element.state.layer_idx + 1]; const size_t offset_above = linear_data_layers[element.state.layer_idx + 1]; + double weight = 0.; for (auto iparent : element.parents) { - avg.x() += prev[offset_above + iparent].x(); - avg.y() += prev[offset_above + iparent].y(); + double w = config.getRadius(above[iparent].state); + avg.x() += w * prev[offset_above + iparent].x(); + avg.y() += w * prev[offset_above + iparent].y(); + weight += w; } size_t cnt = element.parents.size(); if (below != -1) { const size_t offset_below = linear_data_layers[element.state.layer_idx - 1]; - avg.x() += prev[offset_below + below].x(); - avg.y() += prev[offset_below + below].y(); + const double w = weight; // config.getRadius(move_bounds[element.state.layer_idx - 1][below].state); + avg.x() += w * prev[offset_below + below].x(); + avg.y() += w * prev[offset_below + below].y(); ++ cnt; + weight += w; } - avg /= double(cnt); + //avg /= double(cnt); + avg /= weight; static constexpr const double smoothing_factor = 0.5; Vec2d old_pos{ pts[i].x(), pts[i].y() }; Vec2d new_pos = (1. - smoothing_factor) * old_pos + smoothing_factor * avg; @@ -3654,13 +3815,15 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume auto t_place = std::chrono::high_resolution_clock::now(); // ### draw these points as circles -#if 0 - draw_areas(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, - bottom_contacts, top_contacts, intermediate_layers, layer_storage); -#else - draw_branches(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, - bottom_contacts, top_contacts, intermediate_layers, layer_storage); -#endif + + if (print_object.config().support_material_style == smsTree) + draw_areas(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, + bottom_contacts, top_contacts, intermediate_layers, layer_storage); + else { + assert(print_object.config().support_material_style == smsOrganic); + draw_branches(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds, + bottom_contacts, top_contacts, intermediate_layers, layer_storage); + } auto t_draw = std::chrono::high_resolution_clock::now(); auto dur_pre_gen = 0.001 * std::chrono::duration_cast(t_precalc - t_start).count(); From 842283cd3ba0beb39ab97e663ccabd2a42488f8e Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 13 Oct 2022 14:42:25 +0200 Subject: [PATCH 19/29] WIP TreeSupports - organic supports: Partial fix for bottoms of supports over object locked against laplacian smoothing --- src/libslic3r/TreeSupport.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index fecbef8313..d5758cf07b 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -3534,7 +3534,8 @@ static void draw_branches( for (size_t i = 0; i < projections.size(); ++ i) { const SupportElement &element = *elements_with_link_down[i].first; const int below = elements_with_link_down[i].second; - if (pts[i] != projections[i]) { + const bool locked = below == -1 && element.state.layer_idx > 0; + if (! locked && pts[i] != projections[i]) { // Nudge the circle center away from the collision. Vec3d v{ projections[i].x() - pts[i].x(), projections[i].y() - pts[i].y(), projections[i].z() - pts[i].z() }; double depth = v.norm(); @@ -3555,7 +3556,7 @@ static void draw_branches( } } // Laplacian smoothing - if (! element.parents.empty() && (below != -1 || element.state.layer_idx == 0)) { + if (! locked && ! element.parents.empty()) { Vec2d avg{ 0, 0 }; const SupportElements &above = move_bounds[element.state.layer_idx + 1]; const size_t offset_above = linear_data_layers[element.state.layer_idx + 1]; From b6e1a7ed52134e67c03ae64bd84a8d4621a3ce71 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 13 Oct 2022 14:43:03 +0200 Subject: [PATCH 20/29] WIP TreeSupports highly experimental: Add 2nd perimeter to thick tree supports for stability. --- src/libslic3r/SupportMaterial.cpp | 44 ++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index b1b6600bc2..c4a4efbf24 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -3238,6 +3238,20 @@ static inline void fill_expolygons_generate_paths( fill_expolygons_generate_paths(dst, std::move(expolygons), filler, fill_params, density, role, flow); } +static Polylines draw_perimeters(const ExPolygon &expoly, double clip_length) +{ + // Draw the perimeters. + Polylines polylines; + polylines.reserve(expoly.holes.size() + 1); + for (size_t i = 0; i <= expoly.holes.size(); ++ i) { + Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points); + pl.points.emplace_back(pl.points.front()); + pl.clip_end(clip_length); + polylines.emplace_back(std::move(pl)); + } + return polylines; +} + static inline void tree_supports_generate_paths( ExtrusionEntitiesPtr &dst, const Polygons &polygons, @@ -3336,7 +3350,20 @@ static inline void tree_supports_generate_paths( const double clip_length = spacing * 0.15; const double anchor_length = spacing * 6.; ClipperLib_Z::Paths anchor_candidates; - for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) { + for (ExPolygon& expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width()))) { + double area = expoly.area(); + if (area > sqr(scaled(5.))) { + // Make the tree branch stable by adding another perimeter. + ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width()); + if (level2.size() == 1) { + Polylines polylines; + extrusion_entities_append_paths(dst, draw_perimeters(expoly, clip_length), erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(), + // Disable reversal of the path, always start with the anchor, always print CCW. + false); + expoly = level2.front(); + } + } + // Try to produce one more perimeter to place the seam anchor. // First genrate a 2nd perimeter loop as a source for anchor candidates. // The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection. @@ -3466,9 +3493,9 @@ static inline void fill_expolygons_with_sheath_generate_paths( fill_params.density = density; fill_params.dont_adjust = true; - double spacing = flow.scaled_spacing(); + const double spacing = flow.scaled_spacing(); // Clip the sheath path to avoid the extruder to get exactly on the first point of the loop. - double clip_length = spacing * 0.15; + const double clip_length = spacing * 0.15; for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) { // Don't reorder the skirt and its infills. @@ -3478,16 +3505,7 @@ static inline void fill_expolygons_with_sheath_generate_paths( eec->no_sort = true; } ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst; - // Draw the perimeters. - Polylines polylines; - polylines.reserve(expoly.holes.size() + 1); - for (size_t i = 0; i <= expoly.holes.size(); ++ i) { - Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points); - pl.points.emplace_back(pl.points.front()); - pl.clip_end(clip_length); - polylines.emplace_back(std::move(pl)); - } - extrusion_entities_append_paths(out, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height()); + extrusion_entities_append_paths(out, draw_perimeters(expoly, clip_length), erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height()); // Fill in the rest. fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow); if (no_sort && ! eec->empty()) From bfc1b3be823b948a52523ff448bee6004130bc2f Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 13 Oct 2022 15:25:15 +0200 Subject: [PATCH 21/29] Eject removable media with CM_Request_Device_EjectW SPE-1328 --- src/slic3r/GUI/Plater.cpp | 1 + src/slic3r/GUI/RemovableDriveManager.cpp | 221 ++++++++++++++++++++++- 2 files changed, 216 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 326bd79e26..91c901f787 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2192,6 +2192,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path) ); } else { + notification_manager->close_notification_of_type(NotificationType::ExportFinished); notification_manager->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index 5fb8b01321..2189f2ad91 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -10,9 +10,9 @@ #include #include #include - #include - +#include +#include #else // unix, linux & OSX includes #include @@ -72,6 +72,192 @@ std::vector RemovableDriveManager::search_for_removable_drives() cons return current_drives; } +namespace { +// returns the device instance handle of a storage volume or 0 on error +// called from eject_inner, based on https://stackoverflow.com/a/58848961 +DEVINST get_dev_inst_by_device_number(long device_number, UINT drive_type, WCHAR* dos_device_name) +{ + bool is_floppy = (wcsstr(dos_device_name, L"\\Floppy") != NULL); // TODO: could be tested better? + GUID* guid; + switch (drive_type) { + case DRIVE_REMOVABLE: + if (is_floppy) { + // we are interested only in SD cards or USB sticks + BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Drive is floppy disk."; + return 0; + //guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY; + } else { + guid = (GUID*)&GUID_DEVINTERFACE_DISK; + } + break; + case DRIVE_FIXED: + // we are interested only in SD cards or USB sticks + BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Drive is harddisk."; + return 0; + //guid = (GUID*)&GUID_DEVINTERFACE_DISK; + //break; + case DRIVE_CDROM: + BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Drive is cd-rom."; + // we are interested only in SD cards or USB sticks + return 0; + //guid = (GUID*)&GUID_DEVINTERFACE_CDROM; + //break; + default: + return 0; + } + + // Get device interface info set handle for all devices attached to system + HDEVINFO h_dev_info = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + if (h_dev_info == INVALID_HANDLE_VALUE) { + BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Invalid dev info handle."; + return 0; + } + + // Retrieve a context structure for a device interface of a device information set + BYTE buf[1024]; + PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buf; + SP_DEVICE_INTERFACE_DATA spdid; + SP_DEVINFO_DATA spdd; + DWORD size; + + spdid.cbSize = sizeof(spdid); + + // Loop through devices and compare device numbers + for (DWORD index = 0; SetupDiEnumDeviceInterfaces(h_dev_info, NULL, guid, index, &spdid); ++index) { + SetupDiGetDeviceInterfaceDetail(h_dev_info, &spdid, NULL, 0, &size, NULL); + // check the buffer size + if (size == 0 || size > sizeof(buf)) { + continue; + } + // prepare structures + pspdidd->cbSize = sizeof(*pspdidd); + ZeroMemory(&spdd, sizeof(spdd)); + spdd.cbSize = sizeof(spdd); + // fill structures + long res = SetupDiGetDeviceInterfaceDetail(h_dev_info, &spdid, pspdidd, size, &size, &spdd); + if (!res) { + continue; + } + // open the drive with pspdidd->DevicePath to compare device numbers + HANDLE drive_handle = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (drive_handle == INVALID_HANDLE_VALUE) { + continue; + } + // get its device number + STORAGE_DEVICE_NUMBER sdn; + DWORD bytes_returned = 0; + res = DeviceIoControl(drive_handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL); + CloseHandle(drive_handle); + if (!res) { + continue; + } + //compare + if (device_number != (long)sdn.DeviceNumber) { + continue; + } + // this is the drive, return the device instance + SetupDiDestroyDeviceInfoList(h_dev_info); + return spdd.DevInst; + } + + SetupDiDestroyDeviceInfoList(h_dev_info); + BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Enmurating couldn't find the drive."; + return 0; +} + +// Perform eject using CM_Request_Device_EjectW. +// Returns 0 if success. +int eject_inner(const std::string& path) +{ + // Following implementation is based on https://stackoverflow.com/a/58848961 + assert(path.size() > 0); + std::wstring wpath = std::wstring(); + wpath += boost::nowide::widen(path)[0]; // drive letter wide + wpath[0] &= ~0x20; // make sure drive letter is uppercase + assert(wpath[0] >= 'A' && wpath[0] <= 'Z'); + std::wstring root_path = wpath + L":\\"; // for GetDriveType + std::wstring device_path = wpath + L":"; //for QueryDosDevice + std::wstring volume_access_path = L"\\\\.\\" + wpath + L":"; // for CreateFile + long device_number = -1; + + // open the storage volume + HANDLE volume_handle = CreateFileW(volume_access_path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); + if (volume_handle == INVALID_HANDLE_VALUE) { + BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid value of file handle.", path); + return 1; + } + + // get the volume's device number + STORAGE_DEVICE_NUMBER sdn; + DWORD bytes_returned = 0; + long res = DeviceIoControl(volume_handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL); + if (res) { + device_number = sdn.DeviceNumber; + } + CloseHandle(volume_handle); + + if (device_number == -1) { + BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid device number.", path); + return 1; + } + + // get the drive type which is required to match the device numbers correctely + UINT drive_type = GetDriveTypeW(root_path.c_str()); + + // get the dos device name (like \device\floppy0) to decide if it's a floppy or not + WCHAR dos_device_name[MAX_PATH]; + res = QueryDosDeviceW(device_path.c_str(), dos_device_name, MAX_PATH); + if (!res) { + BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid dos device name.", path); + return 1; + } + + // get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number + DEVINST dev_inst = get_dev_inst_by_device_number(device_number, drive_type, dos_device_name); + + if (dev_inst == 0) { + BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid device instance handle.", path); + return 1; + } + + PNP_VETO_TYPE veto_type = PNP_VetoTypeUnknown; + WCHAR veto_name[MAX_PATH]; + veto_name[0] = 0; + + // get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives! + DEVINST dev_inst_parent = 0; + res = CM_Get_Parent(&dev_inst_parent, dev_inst, 0); + +#if 0 + // loop with several tries and sleep (this is running on main UI thread) + for (int i = 0; i < 3; ++i) { + veto_name[0] = 0; + // CM_Query_And_Remove_SubTree doesn't work for restricted users + //res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K! + //res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP) + res = CM_Request_Device_EjectW(dev_inst_parent, &veto_type, veto_name, MAX_PATH, 0); + //res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP) + if (res == CR_SUCCESS && veto_type == PNP_VetoTypeUnknown) { + return 0; + } + // Wait for next try. + // This is main thread! + Sleep(500); + } +#endif // 0 + + // perform eject + res = CM_Request_Device_EjectW(dev_inst_parent, &veto_type, veto_name, MAX_PATH, 0); + if (res == CR_SUCCESS && veto_type == PNP_VetoTypeUnknown) { + return 0; + } + + BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Request to eject device has failed.", path); + return 1; +} + +} // Called from UI therefore it blocks the UI thread. // It also blocks updates at the worker thread. // Win32 implementation. @@ -86,6 +272,28 @@ void RemovableDriveManager::eject_drive() BOOST_LOG_TRIVIAL(info) << "Ejecting started"; std::scoped_lock lock(m_drives_mutex); auto it_drive_data = this->find_last_save_path_drive_data(); + if (it_drive_data != m_current_drives.end()) { + if (!eject_inner(m_last_save_path)) { + // success + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair< DriveData, bool >(std::move(*it_drive_data), true))); + } else { + // failed to eject + // this should not happen, throwing exception might be the way here + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair(*it_drive_data, false))); + } + } else { + // drive not found in m_current_drives + assert(m_callback_evt_handler); + if (m_callback_evt_handler) + wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair({"",""}, false))); + } +#if 0 + // Implementation used until 2.5.x version + // Some usb drives does not eject properly (still visible in file explorer). Some even does not write all content and eject. if (it_drive_data != m_current_drives.end()) { // get handle to device std::string mpath = "\\\\.\\" + m_last_save_path; @@ -102,16 +310,16 @@ void RemovableDriveManager::eject_drive() //these 3 commands should eject device safely but they dont, the device does disappear from file explorer but the "device was safely remove" notification doesnt trigger. //sd cards does trigger WM_DEVICECHANGE messege, usb drives dont BOOL e1 = DeviceIoControl(handle, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr); - BOOST_LOG_TRIVIAL(debug) << "FSCTL_LOCK_VOLUME " << e1 << " ; " << deviceControlRetVal << " ; " << GetLastError(); + BOOST_LOG_TRIVIAL(error) << "FSCTL_LOCK_VOLUME " << e1 << " ; " << deviceControlRetVal << " ; " << GetLastError(); BOOL e2 = DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr); - BOOST_LOG_TRIVIAL(debug) << "FSCTL_DISMOUNT_VOLUME " << e2 << " ; " << deviceControlRetVal << " ; " << GetLastError(); - // some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here but it returns error to me + BOOST_LOG_TRIVIAL(error) << "FSCTL_DISMOUNT_VOLUME " << e2 << " ; " << deviceControlRetVal << " ; " << GetLastError(); + // some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here with FALSE as third parameter, which should set PreventMediaRemoval BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr); if (error == 0) { CloseHandle(handle); BOOST_LOG_TRIVIAL(error) << "Ejecting " << mpath << " failed (IOCTL_STORAGE_EJECT_MEDIA)" << deviceControlRetVal << " " << GetLastError(); assert(m_callback_evt_handler); - if (m_callback_evt_handler) + if (m_callback_evt_handler) wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair(*it_drive_data, false))); return; } @@ -122,6 +330,7 @@ void RemovableDriveManager::eject_drive() wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair< DriveData, bool >(std::move(*it_drive_data), true))); m_current_drives.erase(it_drive_data); } +#endif // 0 } std::string RemovableDriveManager::get_removable_drive_path(const std::string &path) From 53e9a8f687e91b04afe0e599e76aca7217a9d413 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:01:34 +0200 Subject: [PATCH 22/29] Removed BETA label. --- .../profiles/RatRig/VC3_300_thumbnail.png | Bin 37840 -> 34392 bytes .../profiles/RatRig/VC3_400_thumbnail.png | Bin 37840 -> 34392 bytes .../profiles/RatRig/VC3_500_thumbnail.png | Bin 37840 -> 34392 bytes .../profiles/RatRig/VMINION_thumbnail.png | Bin 31846 -> 29842 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/profiles/RatRig/VC3_300_thumbnail.png b/resources/profiles/RatRig/VC3_300_thumbnail.png index c9150d2b03aec2a9b58a4180f4cda776007fdf53..3e35aaf3e638aca76c746d7613a2b26ebe293ea5 100644 GIT binary patch literal 34392 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�tzu# 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 delta 31544 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

L%Dc&;_E_EN`J3VrT39M|mi8HJw-9#cfh1-qe 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 o=G&+Gudg{B{vTf+ Date: Wed, 19 Oct 2022 08:52:35 +0200 Subject: [PATCH 23/29] Tech ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL set as default --- src/libslic3r/Technologies.hpp | 2 -- src/slic3r/GUI/3DScene.cpp | 24 +---------------- src/slic3r/GUI/3DScene.hpp | 15 ----------- src/slic3r/GUI/GCodeViewer.cpp | 10 ------- src/slic3r/GUI/GLCanvas3D.cpp | 45 +------------------------------ src/slic3r/GUI/GUI_ObjectList.cpp | 6 ----- src/slic3r/GUI/Plater.cpp | 16 ++--------- src/slic3r/GUI/Selection.cpp | 32 +--------------------- 8 files changed, 5 insertions(+), 145 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index ad23b4cbe1..695c58abeb 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -39,8 +39,6 @@ //==================== #define ENABLE_2_5_0_ALPHA1 1 -// Enable removal of wipe tower magic object_id equal to 1000 -#define ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) // Enable removal of legacy OpenGL calls #define ENABLE_LEGACY_OPENGL_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) // Enable OpenGL ES diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 9945b40471..cedc7ef2a6 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -912,7 +912,6 @@ void GLVolumeCollection::load_object_auxiliary( } #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #if ENABLE_OPENGL_ES int GLVolumeCollection::load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, @@ -923,26 +922,9 @@ int GLVolumeCollection::load_wipe_tower_preview( float rotation_angle, bool size_unknown, float brim_width) #endif // ENABLE_OPENGL_ES #else -#if ENABLE_OPENGL_ES -int GLVolumeCollection::load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, - float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh) -#else -int GLVolumeCollection::load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, - float rotation_angle, bool size_unknown, float brim_width) -#endif // ENABLE_OPENGL_ES -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL -#else -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL int GLVolumeCollection::load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized) -#else -int GLVolumeCollection::load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, - float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized) -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL { if (depth < 0.01f) @@ -1210,11 +1192,7 @@ int GLVolumeCollection::load_wipe_tower_preview( #endif // !ENABLE_LEGACY_OPENGL_REMOVAL v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0)); v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle)); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL - v.composite_id = GLVolume::CompositeID(INT_MAX, 0, 0); -#else - v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL + v.composite_id = GLVolume::CompositeID(INT_MAX, 0, 0); v.geometry_id.first = 0; v.geometry_id.second = wipe_tower_instance_id().id; v.is_wipe_tower = true; diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index b48ad90a82..1e8897c4e0 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -668,7 +668,6 @@ public: // Timestamp of the last change of the milestone size_t timestamp); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #if ENABLE_OPENGL_ES int load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); @@ -676,15 +675,6 @@ public: int load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); #endif // ENABLE_OPENGL_ES -#else -#if ENABLE_OPENGL_ES - int load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); -#else - int load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); -#endif // ENABLE_OPENGL_ES -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else std::vector load_object( const ModelObject *model_object, @@ -710,13 +700,8 @@ public: size_t timestamp, bool opengl_initialized); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL int load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized); -#else - int load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index be232c178b..562c67cebc 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2349,21 +2349,11 @@ void GCodeViewer::load_shells(const Print& print, bool initialized) const float brim_width = print.wipe_tower_data(extruders_count).brim_width; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, !print.is_step_done(psWipeTower), brim_width); #else - m_shells.volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, - !print.is_step_done(psWipeTower), brim_width); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL -#else -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, !print.is_step_done(psWipeTower), brim_width, initialized); -#else - m_shells.volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, - !print.is_step_done(psWipeTower), brim_width, initialized); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL } } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 04a6918711..f77eed369b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1341,18 +1341,12 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) { -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (current_printer_technology() != ptSLA) return; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL m_render_sla_auxiliaries = visible; for (GLVolume* vol : m_volumes.volumes) { -#if !ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL - if (vol->composite_id.object_id == 1000) - continue; // the wipe tower -#endif // !ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) && vol->composite_id.volume_id < 0) @@ -1363,14 +1357,8 @@ void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObje void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject* mo, int instance_idx, const ModelVolume* mv) { for (GLVolume* vol : m_volumes.volumes) { -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (vol->is_wipe_tower) vol->is_active = (visible && mo == nullptr); -#else - if (vol->composite_id.object_id == 1000) { // wipe tower - vol->is_active = (visible && mo == nullptr); - } -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL else { if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) @@ -2348,7 +2336,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re float brim_width = print->wipe_tower_data(extruders_count).brim_width; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #if ENABLE_OPENGL_ES int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), @@ -2359,26 +2346,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re brim_width); #endif // ENABLE_OPENGL_ES #else -#if ENABLE_OPENGL_ES - int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( - 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), - brim_width, &m_wipe_tower_mesh); -#else - int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( - 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), - brim_width); -#endif // ENABLE_OPENGL_ES -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL -#else -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), brim_width, m_initialized); -#else - int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( - 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), - brim_width, m_initialized); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL if (volume_idx_wipe_tower_old != -1) map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new; @@ -3855,15 +3825,9 @@ void GLCanvas3D::do_move(const std::string& snapshot_type) model_object->invalidate_bounding_box(); } } -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL else if (v->is_wipe_tower) // Move a wipe tower proxy. wipe_tower_origin = v->get_volume_offset(); -#else - else if (object_idx == 1000) - // Move a wipe tower proxy. - wipe_tower_origin = v->get_volume_offset(); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL } // Fixes flying instances @@ -3924,18 +3888,11 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type) Selection::EMode selection_mode = m_selection.get_mode(); for (const GLVolume* v : m_volumes.volumes) { -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (v->is_wipe_tower) { -#else - int object_idx = v->object_idx(); - if (object_idx == 1000) { // the wipe tower -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL const Vec3d offset = v->get_volume_offset(); post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z()))); } -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL - int object_idx = v->object_idx(); -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL + const int object_idx = v->object_idx(); if (object_idx < 0 || (int)m_model->objects.size() <= object_idx) continue; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index b8c04f8cf6..0984ded3a2 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1960,15 +1960,9 @@ void ObjectList::del_layers_from_object(const int obj_idx) bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type) { assert(idx >= 0); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (m_objects->empty() || int(m_objects->size()) <= obj_idx) // Cannot delete a wipe tower return false; -#else - if (obj_idx == 1000 || idx<0) - // Cannot delete a wipe tower or volume with negative id - return false; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL ModelObject* object = (*m_objects)[obj_idx]; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 91c901f787..eb8b5b01a1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1253,11 +1253,7 @@ void Sidebar::show_info_sizer() ModelObjectPtrs objects = p->plater->model().objects; int obj_idx = selection.get_object_idx(); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (m_mode < comExpert || objects.empty() || obj_idx < 0 || int(objects.size()) <= obj_idx || -#else - if (m_mode < comExpert || objects.empty() || obj_idx < 0 || obj_idx == 1000 || -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL objects[obj_idx]->volumes.empty() || // hack to avoid crash when deleting the last object on the bed (selection.is_single_full_object() && objects[obj_idx]->instances.size()> 1) || !(selection.is_single_full_instance() || selection.is_single_volume())) { @@ -2932,23 +2928,15 @@ Selection& Plater::priv::get_selection() int Plater::priv::get_selected_object_idx() const { - int idx = get_selection().get_object_idx(); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL + const int idx = get_selection().get_object_idx(); return (0 <= idx && idx < int(model.objects.size())) ? idx : -1; -#else - return ((0 <= idx) && (idx < 1000)) ? idx : -1; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL } int Plater::priv::get_selected_volume_idx() const { auto& selection = get_selection(); - int idx = selection.get_object_idx(); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL + const int idx = selection.get_object_idx(); if (idx < 0 || int(model.objects.size()) <= idx) -#else - if ((0 > idx) || (idx > 1000)) -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL return-1; const GLVolume* v = selection.get_first_volume(); if (model.objects[idx]->volumes.size() > 1) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c6ddd1fa3e..2423b10a09 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -544,11 +544,7 @@ bool Selection::is_single_full_instance() const bool Selection::is_from_single_object() const { const int idx = get_object_idx(); -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL return 0 <= idx && idx < int(m_model->objects.size()); -#else - return 0 <= idx && idx < 1000; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL } bool Selection::is_sla_compliant() const @@ -1404,16 +1400,10 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement) if (done.size() == m_volumes->size()) break; -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if ((*m_volumes)[i]->is_wipe_tower) continue; int object_idx = (*m_volumes)[i]->object_idx(); -#else - int object_idx = (*m_volumes)[i]->object_idx(); - if (object_idx >= 1000) - continue; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL // Process unselected volumes of the object. for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) { @@ -1458,16 +1448,10 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co if (done.size() == m_volumes->size()) break; -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if ((*m_volumes)[i]->is_wipe_tower) continue; - int object_idx = (*m_volumes)[i]->object_idx(); -#else - int object_idx = (*m_volumes)[i]->object_idx(); - if (object_idx >= 1000) - continue; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL + const int object_idx = (*m_volumes)[i]->object_idx(); // Process unselected volumes of the object. for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) { @@ -2965,17 +2949,10 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ break; const GLVolume* volume_i = (*m_volumes)[i]; -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (volume_i->is_wipe_tower) continue; const int object_idx = volume_i->object_idx(); -#else - const int object_idx = volume_i->object_idx(); - if (object_idx >= 1000) - continue; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL - const int instance_idx = volume_i->instance_idx(); #if ENABLE_WORLD_COORDINATE const Geometry::Transformation& curr_inst_trafo_i = volume_i->get_instance_transformation(); @@ -3073,17 +3050,10 @@ void Selection::synchronize_unselected_volumes() { for (unsigned int i : m_list) { const GLVolume* volume = (*m_volumes)[i]; -#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL if (volume->is_wipe_tower) continue; const int object_idx = volume->object_idx(); -#else - const int object_idx = volume->object_idx(); - if (object_idx >= 1000) - continue; -#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL - const int volume_idx = volume->volume_idx(); #if ENABLE_WORLD_COORDINATE const Geometry::Transformation& trafo = volume->get_volume_transformation(); From 24f671e924cbf673762e0c7e302c28f81d124edf Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 Oct 2022 12:32:54 +0200 Subject: [PATCH 24/29] Little clean-up of ConstVectorOfPtrsAdaptor to be more vector like. --- src/libslic3r/GCode/ToolOrdering.cpp | 2 +- src/libslic3r/Print.hpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 870096bb9b..c5554c2fa1 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -658,7 +658,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int return std::max(0.f, volume_to_wipe); // Soluble filament cannot be wiped in a random infill, neither the filament after it // we will sort objects so that dedicated for wiping are at the beginning: - ConstPrintObjectPtrs object_list = print.objects().vector(); + ConstPrintObjectPtrs object_list(print.objects().begin(), print.objects().end()); std::sort(object_list.begin(), object_list.end(), [](const PrintObject* a, const PrintObject* b) { return a->config().wipe_into_objects; }); // We will now iterate through diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index c2777083d8..967c9e707b 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -129,7 +129,6 @@ public: bool empty() const { return m_data->empty(); } const T* operator[](size_t i) const { return (*m_data)[i]; } const T* at(size_t i) const { return m_data->at(i); } - std::vector vector() const { return std::vector(this->begin(), this->end()); } protected: ConstVectorOfPtrsAdaptor(const std::vector *data) : m_data(data) {} private: From acbc60f3e357825f74108942386343698a4c6ed0 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 Oct 2022 15:50:17 +0200 Subject: [PATCH 25/29] Better const correctness --- src/libslic3r/Brim.cpp | 2 +- src/libslic3r/TreeSupport.cpp | 2 +- src/slic3r/GUI/DoubleSlider.cpp | 6 +++--- src/slic3r/GUI/DoubleSlider.hpp | 4 ++-- src/slic3r/GUI/GUI_Preview.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 9ed56bea46..5239d7f032 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -564,7 +564,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance } #endif // BRIM_DEBUG_TO_SVG - const bool could_brim_intersects_skirt = std::any_of(print.objects().begin(), print.objects().end(), [&print](PrintObject *object) { + const bool could_brim_intersects_skirt = std::any_of(print.objects().begin(), print.objects().end(), [&print](const PrintObject *object) { const BrimType &bt = object->config().brim_type; return (bt == btOuterOnly || bt == btOuterAndInner) && print.config().skirt_distance.value < object->config().brim_width; }); diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index d5758cf07b..b60744e327 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -3908,7 +3908,7 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume void fff_tree_support_generate(PrintObject &print_object, std::function throw_on_cancel) { size_t idx = 0; - for (PrintObject* po : print_object.print()->objects()) { + for (const PrintObject *po : print_object.print()->objects()) { if (po == &print_object) break; ++idx; diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 717af39ba8..31b2c5c90e 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -2123,13 +2123,13 @@ void Control::show_cog_icon_context_menu() GUI::wxGetApp().plater()->PopupMenu(&menu); } -bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs, std::function break_condition) +bool check_color_change(const PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs, std::function break_condition) { double prev_area = area(object->get_layer(frst_layer_id)->lslices); bool detected = false; for (size_t i = frst_layer_id+1; i < layers_cnt; i++) { - Layer* layer = object->get_layer(i); + const Layer* layer = object->get_layer(i); double cur_area = area(layer->lslices); // check for overhangs @@ -2169,7 +2169,7 @@ void Control::auto_color_change() if (object->layer_count() < 2) continue; - check_color_change(object, 1, object->layers().size(), false, [this, extruders_cnt](Layer* layer) + check_color_change(object, 1, object->layers().size(), false, [this, extruders_cnt](const Layer* layer) { int tick = get_tick_from_value(layer->print_z); if (tick >= 0 && !m_ticks.has_tick(tick)) { diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index e4654d6047..3a862c2868 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -31,10 +31,10 @@ constexpr double epsilon() { return 0.0011; } bool equivalent_areas(const double& bottom_area, const double& top_area); // return true if color change was detected -bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs, +bool check_color_change(const PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs, // what to do with detected color change // and return true when detection have to be desturbed - std::function break_condition); + std::function break_condition); // custom message the slider sends to its parent to notify a tick-change: wxDECLARE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 7989c3cdce..93cbca3c4f 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -574,7 +574,7 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee if (i < min_solid_height) continue; - if (DoubleSlider::check_color_change(object, i, num_layers, true, [this, object](Layer*) { + if (DoubleSlider::check_color_change(object, i, num_layers, true, [this, object](const Layer*) { NotificationManager* notif_mngr = wxGetApp().plater()->get_notification_manager(); notif_mngr->push_notification( NotificationType::SignDetected, NotificationManager::NotificationLevel::PrintInfoNotificationLevel, From 2ced7629482ea0b0feab66906b6a97fe0d57b747 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 Oct 2022 16:26:59 +0200 Subject: [PATCH 26/29] Integrating a C++20 like span library https://github.com/tcbrindle/span Replacing a homebrew const pointer wrapper const correctness helper with the C++20 like span library. One day when we switch to C++20 we will just use the C++20 spans instead. --- src/CMakeLists.txt | 1 + src/libslic3r/Brim.cpp | 2 +- src/libslic3r/GCode.hpp | 1 - src/libslic3r/MultiMaterialSegmentation.cpp | 4 +- src/libslic3r/Print.hpp | 59 +- src/libslic3r/PrintObject.cpp | 2 +- src/tcbspan/CMakeLists.txt | 6 + src/tcbspan/README.md | 124 ++++ src/tcbspan/span.hpp | 618 ++++++++++++++++++++ tests/fff_print/test_print.cpp | 2 +- tests/fff_print/test_printobject.cpp | 6 +- tests/fff_print/test_support_material.cpp | 2 +- 12 files changed, 770 insertions(+), 57 deletions(-) create mode 100644 src/tcbspan/CMakeLists.txt create mode 100644 src/tcbspan/README.md create mode 100644 src/tcbspan/span.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50eccfc849..1c1b166385 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ add_subdirectory(libigl) add_subdirectory(hints) add_subdirectory(qoi) add_subdirectory(libnest2d) +add_subdirectory(tcbspan) find_package(Qhull 7.2 REQUIRED) add_library(qhull INTERFACE) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 5239d7f032..62d8867851 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -39,7 +39,7 @@ static void append_and_translate(Polygons &dst, const Polygons &src, const Print dst[dst_idx].translate(instance.shift.x(), instance.shift.y()); } -static float max_brim_width(const ConstPrintObjectPtrsAdaptor &objects) +static float max_brim_width(const SpanOfConstPtrs &objects) { assert(!objects.empty()); return float(std::accumulate(objects.begin(), objects.end(), 0., diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index ce4a505fc6..4592402e37 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -32,7 +32,6 @@ class GCode; namespace { struct Item; } struct PrintInstance; -class ConstPrintObjectPtrsAdaptor; class OozePrevention { public: diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 9560096bed..21b53c40dd 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1305,7 +1305,7 @@ static inline std::vector> mmu_segmentation_top_and_bott { const size_t num_extruders = print_object.print()->config().nozzle_diameter.size() + 1; const size_t num_layers = input_expolygons.size(); - const ConstLayerPtrsAdaptor layers = print_object.layers(); + const SpanOfConstPtrs layers = print_object.layers(); // Maximum number of top / bottom layers accounts for maximum overlap of one thread group into a neighbor thread group. int max_top_layers = 0; @@ -1685,7 +1685,7 @@ std::vector> multi_material_segmentation_by_painting(con std::vector> painted_lines(num_layers); std::array painted_lines_mutex; std::vector edge_grids(num_layers); - const ConstLayerPtrsAdaptor layers = print_object.layers(); + const SpanOfConstPtrs layers = print_object.layers(); std::vector input_expolygons(num_layers); throw_on_cancel_callback(); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 967c9e707b..9e21111ce1 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -21,6 +21,7 @@ #include #include +#include namespace Slic3r { @@ -117,37 +118,12 @@ private: inline bool operator==(const PrintRegion &lhs, const PrintRegion &rhs) { return lhs.config_hash() == rhs.config_hash() && lhs.config() == rhs.config(); } inline bool operator!=(const PrintRegion &lhs, const PrintRegion &rhs) { return ! (lhs == rhs); } -template -class ConstVectorOfPtrsAdaptor { -public: - // Returning a non-const pointer to const pointers to T. - T * const * begin() const { return m_data->data(); } - T * const * end() const { return m_data->data() + m_data->size(); } - const T* front() const { return m_data->front(); } - const T* back() const { return m_data->back(); } - size_t size() const { return m_data->size(); } - bool empty() const { return m_data->empty(); } - const T* operator[](size_t i) const { return (*m_data)[i]; } - const T* at(size_t i) const { return m_data->at(i); } -protected: - ConstVectorOfPtrsAdaptor(const std::vector *data) : m_data(data) {} -private: - const std::vector *m_data; -}; +// For const correctness: Wrapping a vector of non-const pointers as a span of const pointers. +template +using SpanOfConstPtrs = tcb::span; -typedef std::vector LayerPtrs; -typedef std::vector ConstLayerPtrs; -class ConstLayerPtrsAdaptor : public ConstVectorOfPtrsAdaptor { - friend PrintObject; - ConstLayerPtrsAdaptor(const LayerPtrs *data) : ConstVectorOfPtrsAdaptor(data) {} -}; - -typedef std::vector SupportLayerPtrs; -typedef std::vector ConstSupportLayerPtrs; -class ConstSupportLayerPtrsAdaptor : public ConstVectorOfPtrsAdaptor { - friend PrintObject; - ConstSupportLayerPtrsAdaptor(const SupportLayerPtrs *data) : ConstVectorOfPtrsAdaptor(data) {} -}; +using LayerPtrs = std::vector; +using SupportLayerPtrs = std::vector; class BoundingBoxf3; // TODO: for temporary constructor parameter @@ -255,8 +231,8 @@ public: // Size of an object: XYZ in scaled coordinates. The size might not be quite snug in XY plane. const Vec3crd& size() const { return m_size; } const PrintObjectConfig& config() const { return m_config; } - ConstLayerPtrsAdaptor layers() const { return ConstLayerPtrsAdaptor(&m_layers); } - ConstSupportLayerPtrsAdaptor support_layers() const { return ConstSupportLayerPtrsAdaptor(&m_support_layers); } + auto layers() const { return SpanOfConstPtrs(const_cast(m_layers.data()), m_layers.size()); } + auto support_layers() const { return SpanOfConstPtrs(const_cast(m_support_layers.data()), m_support_layers.size()); } const Transform3d& trafo() const { return m_trafo; } // Trafo with the center_offset() applied after the transformation, to center the object in XY before slicing. Transform3d trafo_centered() const @@ -497,21 +473,10 @@ struct PrintStatistics } }; -typedef std::vector PrintObjectPtrs; -typedef std::vector ConstPrintObjectPtrs; -class ConstPrintObjectPtrsAdaptor : public ConstVectorOfPtrsAdaptor { - friend Print; - ConstPrintObjectPtrsAdaptor(const PrintObjectPtrs *data) : ConstVectorOfPtrsAdaptor(data) {} -}; +using PrintObjectPtrs = std::vector; +using ConstPrintObjectPtrs = std::vector; -typedef std::vector PrintRegionPtrs; -/* -typedef std::vector ConstPrintRegionPtrs; -class ConstPrintRegionPtrsAdaptor : public ConstVectorOfPtrsAdaptor { - friend Print; - ConstPrintRegionPtrsAdaptor(const PrintRegionPtrs *data) : ConstVectorOfPtrsAdaptor(data) {} -}; -*/ +using PrintRegionPtrs = std::vector; // The complete print tray with possibly multiple objects. class Print : public PrintBaseWithState @@ -574,7 +539,7 @@ public: const PrintConfig& config() const { return m_config; } const PrintObjectConfig& default_object_config() const { return m_default_object_config; } const PrintRegionConfig& default_region_config() const { return m_default_region_config; } - ConstPrintObjectPtrsAdaptor objects() const { return ConstPrintObjectPtrsAdaptor(&m_objects); } + SpanOfConstPtrs objects() const { return SpanOfConstPtrs(const_cast(m_objects.data()), m_objects.size()); } PrintObject* get_object(size_t idx) { return const_cast(m_objects[idx]); } const PrintObject* get_object(size_t idx) const { return m_objects[idx]; } // PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 9ffb57a723..bdcb034abf 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2205,7 +2205,7 @@ void PrintObject::_generate_support_material() } } -static void project_triangles_to_slabs(ConstLayerPtrsAdaptor layers, const indexed_triangle_set &custom_facets, const Transform3f &tr, bool seam, std::vector &out) +static void project_triangles_to_slabs(SpanOfConstPtrs layers, const indexed_triangle_set &custom_facets, const Transform3f &tr, bool seam, std::vector &out) { if (custom_facets.indices.empty()) return; diff --git a/src/tcbspan/CMakeLists.txt b/src/tcbspan/CMakeLists.txt new file mode 100644 index 0000000000..0668f838e3 --- /dev/null +++ b/src/tcbspan/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 2.8.12) +project(tcbspan) + +add_library(tcbspan STATIC + span.hpp +) diff --git a/src/tcbspan/README.md b/src/tcbspan/README.md new file mode 100644 index 0000000000..6e2fba84cf --- /dev/null +++ b/src/tcbspan/README.md @@ -0,0 +1,124 @@ +Bundled with PrusaSlicer: +https://github.com/tcbrindle/span +commit 836dc6a0efd9849cb194e88e4aa2387436bb079b +This is not the full distribution, it only contains README and span.hpp +Original README follows: + + +[![Standard](https://img.shields.io/badge/c%2B%2B-11/14/17/20-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) +[![License](https://img.shields.io/badge/license-BSL-blue.svg)](http://www.boost.org/LICENSE_1_0.txt) +[![Build Status](https://travis-ci.org/tcbrindle/span.svg?branch=master)](https://travis-ci.org/tcbrindle/span) +[![Build status](https://ci.appveyor.com/api/projects/status/ow7cj56s108fs439/branch/master?svg=true)](https://ci.appveyor.com/project/tcbrindle/span/branch/master) +[![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/-vlZZR) + +`std::span` implementation for C++11 and later +============================================== + +This repository contains a single-header implementation of C++20's `std::span`, +conforming to the C++20 committee draft. +It is compatible with C++11, but will use newer language features if they +are available. + +It differs from the implementation in the [Microsoft GSL](https://github.com/Microsoft/GSL/) +in that it is single-header and does not depend on any other GSL facilities. It +also works with C++11, while the GSL version requires C++14. + +Usage +----- + +The recommended way to use the implementation simply copy the file `span.hpp` +from `include/tcb/` into your own sources and `#include` it like +any other header. By default, it lives in namespace `tcb`, but this can be +customised by setting the macro `TCB_SPAN_NAMESPACE_NAME` to an appropriate string +before `#include`-ing the header -- or simply edit the source code. + +The rest of the repository contains testing machinery, and is not required for +use. + +Compatibility +------------- + +This implementation requires a conforming C++11 (or later) compiler, and is tested as far +back as GCC 5, Clang 3.5 and MSVC 2015 Update 3. Older compilers may work, but this is not guaranteed. + +Documentation +------------- + +Documentation for `std::span` is available [on cppreference](https://en.cppreference.com/w/cpp/container/span). + +Implementation Notes +-------------------- + +### Bounds Checking ### + +This implementation of `span` includes optional bounds checking, which is handled +either by throwing an exception or by calling `std::terminate()`. + +The default behaviour with C++14 and later is to check the macro `NDEBUG`: +if this is set, bounds checking is disabled. Otherwise, `std::terminate()` will +be called if there is a precondition violation (i.e. the same behaviour as +`assert()`). If you wish to terminate on errors even if `NDEBUG` is set, define +the symbol `TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION` before `#include`-ing the +header. + +Alternatively, if you want to throw on a contract violation, define +`TCB_SPAN_THROW_ON_CONTRACT_VIOLATION`. This will throw an exception of an +implementation-defined type (deriving from `std::logic_error`), allowing +cleanup to happen. Note that defining this symbol will cause the checks to be +run even if `NDEBUG` is set. + +Lastly, if you wish to disable contract checking even in debug builds, +`#define TCB_SPAN_NO_CONTRACT_CHECKING`. + +Under C++11, due to the restrictions on `constexpr` functions, contract checking +is disabled by default even if `NDEBUG` is not set. You can change this by +defining either of the above symbols, but this will result in most of `span`'s +interface becoming non-`constexpr`. + +### `constexpr` ### + +This implementation is fully `constexpr` under C++17 and later. Under earlier +versions, it is "as `constexpr` as possible". + +Note that even in C++17, it is generally not possible to declare a `span` +as non-default constructed `constexpr` variable, for the same reason that you +cannot form a `constexpr` pointer to a value: it involves taking the address of +a compile-time variable in a way that would be visible at run-time. +You can however use a `span` freely in a `constexpr` function. For example: + +```cpp +// Okay, even in C++11 +constexpr std::ptrdiff_t get_span_size(span span) +{ + return span.size(); +} + +constexpr int arr[] = {1, 2, 3}; +constexpr auto size = get_span_size(arr); // Okay +constexpr span span{arr}; // ERROR -- not a constant expression +constexpr const int* p = arr; // ERROR -- same +``` + +Constructor deduction guides are provided if the compiler supports them. For +older compilers, a set of `make_span()` functions are provided as an extension +which use the same logic, for example: + + ```cpp + constexpr int c_array[] = {1, 2, 3}; + std::array std_array{1, 2, 3}; + const std::vector vec{1, 2, 3}; + + auto s1 = make_span(c_array); // returns span + auto s2 = make_span(std_array); // returns span + auto s3 = make_span(vec); // returns span + ``` + +Alternatives +------------ + +* [Microsoft/GSL](https://github.com/Microsoft/GSL): The original `span` reference + implementation from which `std::span` was born. + +* [martinmoene/span_lite](https://github.com/martinmoene/span-lite): An + alternative implementation which offers C++98 compatibility. + diff --git a/src/tcbspan/span.hpp b/src/tcbspan/span.hpp new file mode 100644 index 0000000000..fdc3a988a4 --- /dev/null +++ b/src/tcbspan/span.hpp @@ -0,0 +1,618 @@ + +/* +This is an implementation of C++20's std::span +http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf +*/ + +// Copyright Tristan Brindle 2018. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file ../../LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TCB_SPAN_HPP_INCLUDED +#define TCB_SPAN_HPP_INCLUDED + +#include +#include +#include +#include + +#ifndef TCB_SPAN_NO_EXCEPTIONS +// Attempt to discover whether we're being compiled with exception support +#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) +#define TCB_SPAN_NO_EXCEPTIONS +#endif +#endif + +#ifndef TCB_SPAN_NO_EXCEPTIONS +#include +#include +#endif + +// Various feature test macros + +#ifndef TCB_SPAN_NAMESPACE_NAME +#define TCB_SPAN_NAMESPACE_NAME tcb +#endif + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define TCB_SPAN_HAVE_CPP17 +#endif + +#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +#define TCB_SPAN_HAVE_CPP14 +#endif + +namespace TCB_SPAN_NAMESPACE_NAME { + +// Establish default contract checking behavior +#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \ + !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \ + !defined(TCB_SPAN_NO_CONTRACT_CHECKING) +#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14) +#define TCB_SPAN_NO_CONTRACT_CHECKING +#else +#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION +#endif +#endif + +#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) +struct contract_violation_error : std::logic_error { + explicit contract_violation_error(const char* msg) : std::logic_error(msg) + {} +}; + +inline void contract_violation(const char* msg) +{ + throw contract_violation_error(msg); +} + +#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) +[[noreturn]] inline void contract_violation(const char* /*unused*/) +{ + std::terminate(); +} +#endif + +#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING) +#define TCB_SPAN_STRINGIFY(cond) #cond +#define TCB_SPAN_EXPECT(cond) \ + cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond)) +#else +#define TCB_SPAN_EXPECT(cond) +#endif + +#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables) +#define TCB_SPAN_INLINE_VAR inline +#else +#define TCB_SPAN_INLINE_VAR +#endif + +#if defined(TCB_SPAN_HAVE_CPP14) || \ + (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) +#define TCB_SPAN_HAVE_CPP14_CONSTEXPR +#endif + +#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) +#define TCB_SPAN_CONSTEXPR14 constexpr +#else +#define TCB_SPAN_CONSTEXPR14 +#endif + +#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) && \ + (!defined(_MSC_VER) || _MSC_VER > 1900) +#define TCB_SPAN_CONSTEXPR_ASSIGN constexpr +#else +#define TCB_SPAN_CONSTEXPR_ASSIGN +#endif + +#if defined(TCB_SPAN_NO_CONTRACT_CHECKING) +#define TCB_SPAN_CONSTEXPR11 constexpr +#else +#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14 +#endif + +#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides) +#define TCB_SPAN_HAVE_DEDUCTION_GUIDES +#endif + +#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte) +#define TCB_SPAN_HAVE_STD_BYTE +#endif + +#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr) +#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC +#endif + +#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC) +#define TCB_SPAN_ARRAY_CONSTEXPR constexpr +#else +#define TCB_SPAN_ARRAY_CONSTEXPR +#endif + +#ifdef TCB_SPAN_HAVE_STD_BYTE +using byte = std::byte; +#else +using byte = unsigned char; +#endif + +#if defined(TCB_SPAN_HAVE_CPP17) +#define TCB_SPAN_NODISCARD [[nodiscard]] +#else +#define TCB_SPAN_NODISCARD +#endif + +TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX; + +template +class span; + +namespace detail { + +template +struct span_storage { + constexpr span_storage() noexcept = default; + + constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept + : ptr(p_ptr) + {} + + E* ptr = nullptr; + static constexpr std::size_t size = S; +}; + +template +struct span_storage { + constexpr span_storage() noexcept = default; + + constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept + : ptr(p_ptr), size(p_size) + {} + + E* ptr = nullptr; + std::size_t size = 0; +}; + +// Reimplementation of C++17 std::size() and std::data() +#if defined(TCB_SPAN_HAVE_CPP17) || \ + defined(__cpp_lib_nonmember_container_access) +using std::data; +using std::size; +#else +template +constexpr auto size(const C& c) -> decltype(c.size()) +{ + return c.size(); +} + +template +constexpr std::size_t size(const T (&)[N]) noexcept +{ + return N; +} + +template +constexpr auto data(C& c) -> decltype(c.data()) +{ + return c.data(); +} + +template +constexpr auto data(const C& c) -> decltype(c.data()) +{ + return c.data(); +} + +template +constexpr T* data(T (&array)[N]) noexcept +{ + return array; +} + +template +constexpr const E* data(std::initializer_list il) noexcept +{ + return il.begin(); +} +#endif // TCB_SPAN_HAVE_CPP17 + +#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t) +using std::void_t; +#else +template +using void_t = void; +#endif + +template +using uncvref_t = + typename std::remove_cv::type>::type; + +template +struct is_span : std::false_type {}; + +template +struct is_span> : std::true_type {}; + +template +struct is_std_array : std::false_type {}; + +template +struct is_std_array> : std::true_type {}; + +template +struct has_size_and_data : std::false_type {}; + +template +struct has_size_and_data())), + decltype(detail::data(std::declval()))>> + : std::true_type {}; + +template > +struct is_container { + static constexpr bool value = + !is_span::value && !is_std_array::value && + !std::is_array::value && has_size_and_data::value; +}; + +template +using remove_pointer_t = typename std::remove_pointer::type; + +template +struct is_container_element_type_compatible : std::false_type {}; + +template +struct is_container_element_type_compatible< + T, E, + typename std::enable_if< + !std::is_same< + typename std::remove_cv()))>::type, + void>::value && + std::is_convertible< + remove_pointer_t()))> (*)[], + E (*)[]>::value + >::type> + : std::true_type {}; + +template +struct is_complete : std::false_type {}; + +template +struct is_complete : std::true_type {}; + +} // namespace detail + +template +class span { + static_assert(std::is_object::value, + "A span's ElementType must be an object type (not a " + "reference type or void)"); + static_assert(detail::is_complete::value, + "A span's ElementType must be a complete type (not a forward " + "declaration)"); + static_assert(!std::is_abstract::value, + "A span's ElementType cannot be an abstract class type"); + + using storage_type = detail::span_storage; + +public: + // constants and types + using element_type = ElementType; + using value_type = typename std::remove_cv::type; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = pointer; + using reverse_iterator = std::reverse_iterator; + + static constexpr size_type extent = Extent; + + // [span.cons], span constructors, copy, assignment, and destructor + template < + std::size_t E = Extent, + typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0> + constexpr span() noexcept + {} + + TCB_SPAN_CONSTEXPR11 span(pointer ptr, size_type count) + : storage_(ptr, count) + { + TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent); + } + + TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem) + : storage_(first_elem, last_elem - first_elem) + { + TCB_SPAN_EXPECT(extent == dynamic_extent || + last_elem - first_elem == + static_cast(extent)); + } + + template ::value, + int>::type = 0> + constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N) + {} + + template &, ElementType>::value, + int>::type = 0> + TCB_SPAN_ARRAY_CONSTEXPR span(std::array& arr) noexcept + : storage_(arr.data(), N) + {} + + template &, ElementType>::value, + int>::type = 0> + TCB_SPAN_ARRAY_CONSTEXPR span(const std::array& arr) noexcept + : storage_(arr.data(), N) + {} + + template < + typename Container, std::size_t E = Extent, + typename std::enable_if< + E == dynamic_extent && detail::is_container::value && + detail::is_container_element_type_compatible< + Container&, ElementType>::value, + int>::type = 0> + constexpr span(Container& cont) + : storage_(detail::data(cont), detail::size(cont)) + {} + + template < + typename Container, std::size_t E = Extent, + typename std::enable_if< + E == dynamic_extent && detail::is_container::value && + detail::is_container_element_type_compatible< + const Container&, ElementType>::value, + int>::type = 0> + constexpr span(const Container& cont) + : storage_(detail::data(cont), detail::size(cont)) + {} + + constexpr span(const span& other) noexcept = default; + + template ::value, + int>::type = 0> + constexpr span(const span& other) noexcept + : storage_(other.data(), other.size()) + {} + + ~span() noexcept = default; + + TCB_SPAN_CONSTEXPR_ASSIGN span& + operator=(const span& other) noexcept = default; + + // [span.sub], span subviews + template + TCB_SPAN_CONSTEXPR11 span first() const + { + TCB_SPAN_EXPECT(Count <= size()); + return {data(), Count}; + } + + template + TCB_SPAN_CONSTEXPR11 span last() const + { + TCB_SPAN_EXPECT(Count <= size()); + return {data() + (size() - Count), Count}; + } + + template + using subspan_return_t = + span; + + template + TCB_SPAN_CONSTEXPR11 subspan_return_t subspan() const + { + TCB_SPAN_EXPECT(Offset <= size() && + (Count == dynamic_extent || Offset + Count <= size())); + return {data() + Offset, + Count != dynamic_extent ? Count : size() - Offset}; + } + + TCB_SPAN_CONSTEXPR11 span + first(size_type count) const + { + TCB_SPAN_EXPECT(count <= size()); + return {data(), count}; + } + + TCB_SPAN_CONSTEXPR11 span + last(size_type count) const + { + TCB_SPAN_EXPECT(count <= size()); + return {data() + (size() - count), count}; + } + + TCB_SPAN_CONSTEXPR11 span + subspan(size_type offset, size_type count = dynamic_extent) const + { + TCB_SPAN_EXPECT(offset <= size() && + (count == dynamic_extent || offset + count <= size())); + return {data() + offset, + count == dynamic_extent ? size() - offset : count}; + } + + // [span.obs], span observers + constexpr size_type size() const noexcept { return storage_.size; } + + constexpr size_type size_bytes() const noexcept + { + return size() * sizeof(element_type); + } + + TCB_SPAN_NODISCARD constexpr bool empty() const noexcept + { + return size() == 0; + } + + // [span.elem], span element access + TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const + { + TCB_SPAN_EXPECT(idx < size()); + return *(data() + idx); + } + + TCB_SPAN_CONSTEXPR11 reference front() const + { + TCB_SPAN_EXPECT(!empty()); + return *data(); + } + + TCB_SPAN_CONSTEXPR11 reference back() const + { + TCB_SPAN_EXPECT(!empty()); + return *(data() + (size() - 1)); + } + + constexpr pointer data() const noexcept { return storage_.ptr; } + + // [span.iterators], span iterator support + constexpr iterator begin() const noexcept { return data(); } + + constexpr iterator end() const noexcept { return data() + size(); } + + TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept + { + return reverse_iterator(end()); + } + + TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept + { + return reverse_iterator(begin()); + } + +private: + storage_type storage_{}; +}; + +#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES + +/* Deduction Guides */ +template +span(T (&)[N])->span; + +template +span(std::array&)->span; + +template +span(const std::array&)->span; + +template +span(Container&)->span()))>::type>; + +template +span(const Container&)->span; + +#endif // TCB_HAVE_DEDUCTION_GUIDES + +template +constexpr span +make_span(span s) noexcept +{ + return s; +} + +template +constexpr span make_span(T (&arr)[N]) noexcept +{ + return {arr}; +} + +template +TCB_SPAN_ARRAY_CONSTEXPR span make_span(std::array& arr) noexcept +{ + return {arr}; +} + +template +TCB_SPAN_ARRAY_CONSTEXPR span +make_span(const std::array& arr) noexcept +{ + return {arr}; +} + +template +constexpr span()))>::type> +make_span(Container& cont) +{ + return {cont}; +} + +template +constexpr span +make_span(const Container& cont) +{ + return {cont}; +} + +template +span +as_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template < + class ElementType, size_t Extent, + typename std::enable_if::value, int>::type = 0> +span +as_writable_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template +constexpr auto get(span s) -> decltype(s[N]) +{ + return s[N]; +} + +} // namespace TCB_SPAN_NAMESPACE_NAME + +namespace std { + +template +class tuple_size> + : public integral_constant {}; + +template +class tuple_size>; // not defined + +template +class tuple_element> { +public: + static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent && + I < Extent, + ""); + using type = ElementType; +}; + +} // end namespace std + +#endif // TCB_SPAN_HPP_INCLUDED diff --git a/tests/fff_print/test_print.cpp b/tests/fff_print/test_print.cpp index 395f758410..d8ab5a3faa 100644 --- a/tests/fff_print/test_print.cpp +++ b/tests/fff_print/test_print.cpp @@ -62,7 +62,7 @@ SCENARIO("Print: Changing number of solid surfaces does not cause all surfaces t // Precondition: Ensure that the model has 2 solid top layers (39, 38) // and one solid bottom layer (0). auto test_is_solid_infill = [&print](size_t obj_id, size_t layer_id) { - const Layer &layer = *(print.objects().at(obj_id)->get_layer((int)layer_id)); + const Layer &layer = *print.objects()[obj_id]->get_layer((int)layer_id); // iterate over all of the regions in the layer for (const LayerRegion *region : layer.regions()) { // for each region, iterate over the fill surfaces diff --git a/tests/fff_print/test_printobject.cpp b/tests/fff_print/test_printobject.cpp index 8d322f58fe..cbc47345c7 100644 --- a/tests/fff_print/test_printobject.cpp +++ b/tests/fff_print/test_printobject.cpp @@ -18,7 +18,7 @@ SCENARIO("PrintObject: object layer heights", "[PrintObject]") { { "layer_height", 2 }, { "nozzle_diameter", 3 } }); - ConstLayerPtrsAdaptor layers = print.objects().front()->layers(); + SpanOfConstPtrs layers = print.objects().front()->layers(); THEN("The output vector has 10 entries") { REQUIRE(layers.size() == 10); } @@ -37,7 +37,7 @@ SCENARIO("PrintObject: object layer heights", "[PrintObject]") { { "layer_height", 10 }, { "nozzle_diameter", 11 } }); - ConstLayerPtrsAdaptor layers = print.objects().front()->layers(); + SpanOfConstPtrs layers = print.objects().front()->layers(); THEN("The output vector has 3 entries") { REQUIRE(layers.size() == 3); } @@ -55,7 +55,7 @@ SCENARIO("PrintObject: object layer heights", "[PrintObject]") { { "layer_height", 15 }, { "nozzle_diameter", 16 } }); - ConstLayerPtrsAdaptor layers = print.objects().front()->layers(); + SpanOfConstPtrs layers = print.objects().front()->layers(); THEN("The output vector has 2 entries") { REQUIRE(layers.size() == 2); } diff --git a/tests/fff_print/test_support_material.cpp b/tests/fff_print/test_support_material.cpp index c5087263c3..0720b270cb 100644 --- a/tests/fff_print/test_support_material.cpp +++ b/tests/fff_print/test_support_material.cpp @@ -27,7 +27,7 @@ SCENARIO("SupportMaterial: support_layers_z and contact_distance", "[SupportMate auto check = [](Slic3r::Print &print, bool &first_support_layer_height_ok, bool &layer_height_minimum_ok, bool &layer_height_maximum_ok, bool &top_spacing_ok) { - ConstSupportLayerPtrsAdaptor support_layers = print.objects().front()->support_layers(); + SpanOfConstPtrs support_layers = print.objects().front()->support_layers(); first_support_layer_height_ok = support_layers.front()->print_z == print.config().first_layer_height.value; From f57744ad129d9cb6dc845232b1c9f1ddc1b0ac0d Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 19 Oct 2022 16:40:41 +0200 Subject: [PATCH 27/29] Follow-up to 2ced7629482ea0b0feab66906b6a97fe0d57b747 Integrating a C++20 like span library https://github.com/tcbrindle/span --- src/CMakeLists.txt | 1 - src/tcbspan/CMakeLists.txt | 6 ------ 2 files changed, 7 deletions(-) delete mode 100644 src/tcbspan/CMakeLists.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1c1b166385..50eccfc849 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,6 @@ add_subdirectory(libigl) add_subdirectory(hints) add_subdirectory(qoi) add_subdirectory(libnest2d) -add_subdirectory(tcbspan) find_package(Qhull 7.2 REQUIRED) add_library(qhull INTERFACE) diff --git a/src/tcbspan/CMakeLists.txt b/src/tcbspan/CMakeLists.txt deleted file mode 100644 index 0668f838e3..0000000000 --- a/src/tcbspan/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12) -project(tcbspan) - -add_library(tcbspan STATIC - span.hpp -) From 43cc8f8cbff37c54b697d69a23a5d5ce3b70bf43 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 20 Oct 2022 15:46:07 +0200 Subject: [PATCH 28/29] Fixed crash in MeshClipper::recalculate_triangles() --- src/slic3r/GUI/MeshUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index 1abb126286..960948b247 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -182,7 +182,7 @@ void MeshClipper::recalculate_triangles() // it so it lies on our line. This will be the figure to subtract // from the cut. The coordinates must not overflow after the transform, // make the rectangle a bit smaller. - const coord_t size = (std::numeric_limits::max() - scale_(std::max(std::abs(e*a), std::abs(e*b)))) / 4; + const coord_t size = (std::numeric_limits::max()/2 - scale_(std::max(std::abs(e * a), std::abs(e * b)))) / 4; Polygons ep {Polygon({Point(-size, 0), Point(size, 0), Point(size, 2*size), Point(-size, 2*size)})}; ep.front().rotate(angle); ep.front().translate(scale_(-e * a), scale_(-e * b)); From 03a256180a94ccb354ef5b203eb103ba6d035576 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 20 Oct 2022 16:35:05 +0200 Subject: [PATCH 29/29] Tech ENABLE_RAYCAST_PICKING - Fixed active/inactive state of scene raycasters when opening/closing a gizmo which hides non selected volumes --- src/slic3r/GUI/GLCanvas3D.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f77eed369b..80b769a27b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1356,6 +1356,9 @@ void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObje void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject* mo, int instance_idx, const ModelVolume* mv) { +#if ENABLE_RAYCAST_PICKING + std::vector>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume); +#endif // ENABLE_RAYCAST_PICKING for (GLVolume* vol : m_volumes.volumes) { if (vol->is_wipe_tower) vol->is_active = (visible && mo == nullptr); @@ -1382,6 +1385,11 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } } } +#if ENABLE_RAYCAST_PICKING + auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr item) { return item->get_raycaster() == vol->mesh_raycaster.get(); }); + if (it != raycasters->end()) + (*it)->set_active(vol->is_active); +#endif // ENABLE_RAYCAST_PICKING } if (visible && !mo)