From e0089dfe9f2f93ea296e0be628bc9ad87ce91f86 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:05:19 +0300 Subject: [PATCH 01/11] Fix typo cleareance_radius -> clearance_radius --- src/OrcaSlicer.cpp | 12 ++++++------ src/libslic3r/Arrange.cpp | 12 ++++++------ src/libslic3r/Arrange.hpp | 4 ++-- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index bb52a0aea16..bfdaf67a02f 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -3029,7 +3029,7 @@ int CLI::run(int argc, char **argv) double print_height = m_print_config.opt_float("printable_height"); double height_to_lid = m_print_config.opt_float("extruder_clearance_height_to_lid"); double height_to_rod = m_print_config.opt_float("extruder_clearance_height_to_rod"); - double cleareance_radius = m_print_config.opt_float("extruder_clearance_radius"); + double clearance_radius = m_print_config.opt_float("extruder_clearance_radius"); //double plate_stride; std::string bed_texture; @@ -3749,12 +3749,12 @@ int CLI::run(int argc, char **argv) { if (((old_height_to_rod != 0.f) && (old_height_to_rod != height_to_rod)) || ((old_height_to_lid != 0.f) && (old_height_to_lid != height_to_lid)) - || ((old_max_radius != 0.f) && (old_max_radius != cleareance_radius))) + || ((old_max_radius != 0.f) && (old_max_radius != clearance_radius))) { if (is_seq_print_for_curr_plate) { need_arrange = true; - BOOST_LOG_TRIVIAL(info) << boost::format("old_height_to_rod %1%, old_height_to_lid %2%, old_max_radius %3%, current height_to_rod %4%, height_to_lid %5%, cleareance_radius %6%, need arrange!") - %old_height_to_rod %old_height_to_lid %old_max_radius %height_to_rod %height_to_lid %cleareance_radius; + BOOST_LOG_TRIVIAL(info) << boost::format("old_height_to_rod %1%, old_height_to_lid %2%, old_max_radius %3%, current height_to_rod %4%, height_to_lid %5%, clearance_radius %6%, need arrange!") + %old_height_to_rod %old_height_to_lid %old_max_radius %height_to_rod %height_to_lid %clearance_radius; } } } @@ -3898,7 +3898,7 @@ int CLI::run(int argc, char **argv) arrange_cfg.avoid_extrusion_cali_region = avoid_extrusion_cali_region; arrange_cfg.clearance_height_to_rod = height_to_rod; arrange_cfg.clearance_height_to_lid = height_to_lid; - arrange_cfg.cleareance_radius = cleareance_radius; + arrange_cfg.clearance_radius = clearance_radius; arrange_cfg.printable_height = print_height; arrange_cfg.min_obj_distance = 0; if (arrange_cfg.is_seq_print) { @@ -4301,7 +4301,7 @@ int CLI::run(int argc, char **argv) arrange_cfg.avoid_extrusion_cali_region = avoid_extrusion_cali_region; arrange_cfg.clearance_height_to_rod = height_to_rod; arrange_cfg.clearance_height_to_lid = height_to_lid; - arrange_cfg.cleareance_radius = cleareance_radius; + arrange_cfg.clearance_radius = clearance_radius; arrange_cfg.printable_height = print_height; arrange_cfg.min_obj_distance = 0; if (arrange_cfg.is_seq_print) { diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index d82997aaa92..cbb7dd8e8f3 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -90,10 +90,10 @@ void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig* prin params.brim_skirt_distance = skirt_distance; params.bed_shrink_x += params.brim_skirt_distance; params.bed_shrink_y += params.brim_skirt_distance; - // for sequential print, we need to inflate the bed because cleareance_radius is so large + // for sequential print, we need to inflate the bed because clearance_radius is so large if (params.is_seq_print) { - params.bed_shrink_x -= params.cleareance_radius / 2; - params.bed_shrink_y -= params.cleareance_radius / 2; + params.bed_shrink_x -= params.clearance_radius / 2; + params.bed_shrink_y -= params.clearance_radius / 2; } } @@ -108,7 +108,7 @@ void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPri params.min_obj_distance = std::max(params.min_obj_distance, scaled(double(MAX_OUTER_NOZZLE_DIAMETER)/2+0.001)); } else - params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error + params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.clearance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error } double brim_max = 0; bool plate_has_tree_support = false; @@ -135,8 +135,8 @@ void update_unselected_items_inflation(ArrangePolygons& unselected, const Dynami { float exclusion_gap = 1.f; if (params.is_seq_print) { - // bed_shrink_x is typically (-params.cleareance_radius / 2+5) for seq_print - exclusion_gap = std::max(exclusion_gap, params.cleareance_radius / 2 + params.bed_shrink_x + 1.f); // +1mm gap so the exclusion region is not too close + // bed_shrink_x is typically (-params.clearance_radius / 2+5) for seq_print + exclusion_gap = std::max(exclusion_gap, params.clearance_radius / 2 + params.bed_shrink_x + 1.f); // +1mm gap so the exclusion region is not too close // dont forget to move the excluded region for (auto& region : unselected) { if (region.is_virt_object) region.poly.translate(scaled(params.bed_shrink_x), scaled(params.bed_shrink_y)); diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index fd534204143..5ad4815c936 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -131,7 +131,7 @@ struct ArrangeParams { float brim_skirt_distance = 0; float clearance_height_to_rod = 0; float clearance_height_to_lid = 0; - float cleareance_radius = 0; + float clearance_radius = 0; float nozzle_height = 0; float printable_height = 256.0; Vec2d align_center{ 0.5,0.5 }; @@ -168,7 +168,7 @@ struct ArrangeParams { ret += "\"brim_skirt_distance\":" + std::to_string(brim_skirt_distance) + ","; ret += "\"clearance_height_to_rod\":" + std::to_string(clearance_height_to_rod) + ","; ret += "\"clearance_height_to_lid\":" + std::to_string(clearance_height_to_lid) + ","; - ret += "\"cleareance_radius\":" + std::to_string(cleareance_radius) + ","; + ret += "\"clearance_radius\":" + std::to_string(clearance_radius) + ","; ret += "\"printable_height\":" + std::to_string(printable_height) + ","; return ret; } diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 6648b0e6328..6ae6a99ac2a 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -768,7 +768,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) params.clearance_height_to_rod = print_config.extruder_clearance_height_to_rod.value; params.clearance_height_to_lid = print_config.extruder_clearance_height_to_lid.value; - params.cleareance_radius = print_config.extruder_clearance_radius.value; + params.clearance_radius = print_config.extruder_clearance_radius.value; params.printable_height = print_config.printable_height.value; params.allow_rotations = settings.enable_rotation; params.nozzle_height = print.config().nozzle_height.value; From 83522c67eef204f68d408d642b76906bea874887 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 10:11:35 +0300 Subject: [PATCH 02/11] Google-translate Chinese comments --- src/libslic3r/Print.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 03f76fe3a39..7ab98f1753f 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -713,6 +713,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print auto inter_y = inter_max - inter_min; // 如果y方向的重合超过轮廓的膨胀量,说明两个物体在一行,应该先打左边的物体,即先比较二者的x坐标。 + // If the overlap in the y direction exceeds the expansion of the contour, it means that the two objects are in a row and the object on the left should be hit first, that is, the x coordinates of the two should be compared first. if (inter_y > scale_(0.5 * print.config().extruder_clearance_radius.value)) { if (std::max(rx1 - lx2, lx1 - rx2) < unsafe_dist) { if (lx1 > rx1) { @@ -813,6 +814,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print { auto inst = print_instance_with_bounding_box[k].print_instance; // 只需要考虑喷嘴到滑杆的偏移量,这个比整个工具头的碰撞半径要小得多 + // Only the offset from the nozzle to the slide bar needs to be considered, which is much smaller than the collision radius of the entire tool head. auto bbox = print_instance_with_bounding_box[k].bounding_box.inflated(-scale_(0.5 * print.config().extruder_clearance_radius.value)); auto iy1 = bbox.min.y(); auto iy2 = bbox.max.y(); From 52e9e03a0b2cafd0a9506d42220d73b0f2070792 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:29:31 +0300 Subject: [PATCH 03/11] Remove unused legacy brim method --- src/libslic3r/Brim.cpp | 209 ----------------------------------------- src/libslic3r/Brim.hpp | 1 - 2 files changed, 210 deletions(-) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 9690a92d000..5deec514a84 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -1714,213 +1714,4 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_ BOOST_LOG_TRIVIAL(debug) << "brim_width_max, num_loops: " << brim_width_max << ", " << num_loops; } -// Produce brim lines around those objects, that have the brim enabled. -// Collect islands_area to be merged into the final 1st layer convex hull. -ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area) -{ - double brim_width_max = 0; - std::map brim_width_map; - const auto scaled_resolution = scaled(print.config().resolution.value); - Flow flow = print.brim_flow(); - std::vector bottom_layers_expolygons = get_print_bottom_layers_expolygons(print); - ConstPrintObjectPtrs top_level_objects_with_brim = get_top_level_objects_with_brim(print, bottom_layers_expolygons); - Polygons islands = top_level_outer_brim_islands(top_level_objects_with_brim, scaled_resolution); - ExPolygons islands_area_ex = top_level_outer_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing()), brim_width_max, brim_width_map); - islands_area = to_polygons(islands_area_ex); - - Polygons loops = tryExPolygonOffset(islands_area_ex, print); - size_t num_loops = size_t(floor(brim_width_max / flow.spacing())); - BOOST_LOG_TRIVIAL(debug) << "brim_width_max, num_loops: " << brim_width_max << ", " << num_loops; - - loops = union_pt_chained_outside_in(loops); - - std::vector loops_pl_by_levels; - { - Polylines loops_pl = to_polylines(loops); - loops_pl_by_levels.assign(loops_pl.size(), Polylines()); - tbb::parallel_for(tbb::blocked_range(0, loops_pl.size()), - [&loops_pl_by_levels, &loops_pl, &islands_area](const tbb::blocked_range &range) { - for (size_t i = range.begin(); i < range.end(); ++i) { - loops_pl_by_levels[i] = chain_polylines(intersection_pl({ std::move(loops_pl[i]) }, islands_area)); - } - }); - } - - // output - ExtrusionEntityCollection brim; - - // Reduce down to the ordered list of polylines. - Polylines all_loops; - for (Polylines &polylines : loops_pl_by_levels) - append(all_loops, std::move(polylines)); - loops_pl_by_levels.clear(); - - // Flip orientation of open polylines to minimize travel distance. - optimize_polylines_by_reversing(&all_loops); - -#ifdef BRIM_DEBUG_TO_SVG - static int irun = 0; - ++ irun; - - { - SVG svg(debug_out_path("brim-%d.svg", irun).c_str(), get_extents(all_loops)); - svg.draw(union_ex(islands), "blue"); - svg.draw(islands_area_ex, "green"); - svg.draw(all_loops, "black", coord_t(scale_(0.1))); - } -#endif // BRIM_DEBUG_TO_SVG - - all_loops = connect_brim_lines(std::move(all_loops), offset(islands_area_ex, float(SCALED_EPSILON)), float(flow.scaled_spacing()) * 2.f); - -#ifdef BRIM_DEBUG_TO_SVG - { - SVG svg(debug_out_path("brim-connected-%d.svg", irun).c_str(), get_extents(all_loops)); - svg.draw(union_ex(islands), "blue"); - svg.draw(islands_area_ex, "green"); - svg.draw(all_loops, "black", coord_t(scale_(0.1))); - } -#endif // BRIM_DEBUG_TO_SVG - - const bool could_brim_intersects_skirt = std::any_of(print.objects().begin(), print.objects().end(), [&print, &brim_width_map, brim_width_max](PrintObject *object) { - const BrimType &bt = object->config().brim_type; - return (bt == btOuterOnly || bt == btOuterAndInner || bt == btAutoBrim) && print.config().skirt_distance.value < brim_width_map[object->id()]; - }); - - const bool draft_shield = print.config().draft_shield != dsDisabled; - - - // If there is a possibility that brim intersects skirt, go through loops and split those extrusions - // The result is either the original Polygon or a list of Polylines - if (draft_shield && ! print.skirt().empty() && could_brim_intersects_skirt) - { - // Find the bounding polygons of the skirt - const Polygons skirt_inners = offset(dynamic_cast(print.skirt().entities.back())->polygon(), - -float(scale_(print.skirt_flow().spacing()))/2.f, - ClipperLib::jtRound, - float(scale_(0.1))); - const Polygons skirt_outers = offset(dynamic_cast(print.skirt().entities.front())->polygon(), - float(scale_(print.skirt_flow().spacing()))/2.f, - ClipperLib::jtRound, - float(scale_(0.1))); - - // First calculate the trimming region. - ClipperLib_Z::Paths trimming; - { - ClipperLib_Z::Paths input_subject; - ClipperLib_Z::Paths input_clip; - for (const Polygon &poly : skirt_outers) { - input_subject.emplace_back(); - ClipperLib_Z::Path &out = input_subject.back(); - out.reserve(poly.points.size()); - for (const Point &pt : poly.points) - out.emplace_back(pt.x(), pt.y(), 0); - } - for (const Polygon &poly : skirt_inners) { - input_clip.emplace_back(); - ClipperLib_Z::Path &out = input_clip.back(); - out.reserve(poly.points.size()); - for (const Point &pt : poly.points) - out.emplace_back(pt.x(), pt.y(), 0); - } - // init Clipper - ClipperLib_Z::Clipper clipper; - // add polygons - clipper.AddPaths(input_subject, ClipperLib_Z::ptSubject, true); - clipper.AddPaths(input_clip, ClipperLib_Z::ptClip, true); - // perform operation - clipper.Execute(ClipperLib_Z::ctDifference, trimming, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero); - } - - // Second, trim the extrusion loops with the trimming regions. - ClipperLib_Z::Paths loops_trimmed; - { - // Produce ClipperLib_Z::Paths from polylines (not necessarily closed). - ClipperLib_Z::Paths input_clip; - for (const Polyline &loop_pl : all_loops) { - input_clip.emplace_back(); - ClipperLib_Z::Path& out = input_clip.back(); - out.reserve(loop_pl.points.size()); - int64_t loop_idx = &loop_pl - &all_loops.front(); - for (const Point& pt : loop_pl.points) - // The Z coordinate carries index of the source loop. - out.emplace_back(pt.x(), pt.y(), loop_idx + 1); - } - // init Clipper - ClipperLib_Z::Clipper clipper; - clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot, const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) { - // Assign a valid input loop identifier. Such an identifier is strictly positive, the next line is safe even in case one side of a segment - // hat the Z coordinate not set to the contour coordinate. - pt.z() = std::max(std::max(e1bot.z(), e1top.z()), std::max(e2bot.z(), e2top.z())); - }); - // add polygons - clipper.AddPaths(input_clip, ClipperLib_Z::ptSubject, false); - clipper.AddPaths(trimming, ClipperLib_Z::ptClip, true); - // perform operation - ClipperLib_Z::PolyTree loops_trimmed_tree; - clipper.Execute(ClipperLib_Z::ctDifference, loops_trimmed_tree, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero); - ClipperLib_Z::PolyTreeToPaths(std::move(loops_trimmed_tree), loops_trimmed); - } - - // Third, produce the extrusions, sorted by the source loop indices. - { - std::vector> loops_trimmed_order; - loops_trimmed_order.reserve(loops_trimmed.size()); - for (const ClipperLib_Z::Path &path : loops_trimmed) { - size_t input_idx = 0; - for (const ClipperLib_Z::IntPoint &pt : path) - if (pt.z() > 0) { - input_idx = (size_t)pt.z(); - break; - } - assert(input_idx != 0); - loops_trimmed_order.emplace_back(&path, input_idx); - } - std::stable_sort(loops_trimmed_order.begin(), loops_trimmed_order.end(), - [](const std::pair &l, const std::pair &r) { - return l.second < r.second; - }); - - Point last_pt(0, 0); - for (size_t i = 0; i < loops_trimmed_order.size();) { - // Find all pieces that the initial loop was split into. - size_t j = i + 1; - for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ; - const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first; - if (i + 1 == j && first_path.size() > 3 && first_path.front().x() == first_path.back().x() && first_path.front().y() == first_path.back().y()) { - auto *loop = new ExtrusionLoop(); - brim.entities.emplace_back(loop); - loop->paths.emplace_back(erBrim, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height())); - Points &points = loop->paths.front().polyline.points; - points.reserve(first_path.size()); - for (const ClipperLib_Z::IntPoint &pt : first_path) - points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); - i = j; - } else { - //FIXME The path chaining here may not be optimal. - ExtrusionEntityCollection this_loop_trimmed; - this_loop_trimmed.entities.reserve(j - i); - for (; i < j; ++ i) { - this_loop_trimmed.entities.emplace_back(new ExtrusionPath(erBrim, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()))); - const ClipperLib_Z::Path &path = *loops_trimmed_order[i].first; - Points &points = dynamic_cast(this_loop_trimmed.entities.back())->polyline.points; - points.reserve(path.size()); - for (const ClipperLib_Z::IntPoint &pt : path) - points.emplace_back(coord_t(pt.x()), coord_t(pt.y())); - } - chain_and_reorder_extrusion_entities(this_loop_trimmed.entities, &last_pt); - brim.entities.reserve(brim.entities.size() + this_loop_trimmed.entities.size()); - append(brim.entities, std::move(this_loop_trimmed.entities)); - this_loop_trimmed.entities.clear(); - } - last_pt = brim.last_point(); - } - } - } else { - extrusion_entities_append_loops_and_paths(brim.entities, std::move(all_loops), erBrim, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height())); - } - - make_inner_brim(print, top_level_objects_with_brim, bottom_layers_expolygons, brim); - return brim; -} - } // namespace Slic3r diff --git a/src/libslic3r/Brim.hpp b/src/libslic3r/Brim.hpp index a9322fe4b93..4ae592a26bf 100644 --- a/src/libslic3r/Brim.hpp +++ b/src/libslic3r/Brim.hpp @@ -15,7 +15,6 @@ class ObjectID; // Produce brim lines around those objects, that have the brim enabled. // Collect islands_area to be merged into the final 1st layer convex hull. -ExtrusionEntityCollection make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_area); void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_area, std::map& brimMap, std::map& supportBrimMap, From 59fc8bda3184b478ac74ae93752501bf9d06f6be Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:14:30 +0300 Subject: [PATCH 04/11] Remove unreal conditions. --- src/libslic3r/Print.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 7ab98f1753f..5c2b4256923 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2281,18 +2281,13 @@ void Print::_make_skirt() } } - // Number of skirt loops per skirt layer. - size_t n_skirts = m_config.skirt_loops.value; - if (this->has_infinite_skirt() && n_skirts == 0) - n_skirts = 1; - // Initial offset of the brim inner edge from the object (possible with a support & raft). // The skirt will touch the brim if the brim is extruded. auto distance = float(scale_(m_config.skirt_distance.value) - spacing/2.); // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); - for (size_t i = n_skirts, extruder_idx = 0; i > 0; -- i) { + for (size_t i = m_config.skirt_loops, extruder_idx = 0; i > 0; -- i) { this->throw_if_canceled(); // Offset the skirt outside. distance += float(scale_(spacing)); @@ -2343,11 +2338,10 @@ void Print::_make_skirt() append(m_skirt_convex_hull, std::move(poly.points)); // BBS - const int n_object_skirts = 1; const double object_skirt_distance = scale_(1.0); for (auto obj_cvx_hull : object_convex_hulls) { PrintObject* object = obj_cvx_hull.first; - for (int i = 0; i < n_object_skirts; i++) { + for (int i = 0; i < 1; i++) { distance += float(scale_(spacing)); Polygon loop; { From 6b50098813de20aa7d7bcba54959b195be027f46 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:09:48 +0300 Subject: [PATCH 05/11] Fix memory leak - clear object skirt on new slicing --- src/libslic3r/Print.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 5c2b4256923..c5fa5a0226c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2341,6 +2341,7 @@ void Print::_make_skirt() const double object_skirt_distance = scale_(1.0); for (auto obj_cvx_hull : object_convex_hulls) { PrintObject* object = obj_cvx_hull.first; + object->m_skirt.clear(); for (int i = 0; i < 1; i++) { distance += float(scale_(spacing)); Polygon loop; From 302e5b122072eb4545b7444f77cfef783680a9d4 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:08:16 +0300 Subject: [PATCH 06/11] Fix skirt distance calculation --- src/libslic3r/Print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c5fa5a0226c..bfc70d40630 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2283,7 +2283,7 @@ void Print::_make_skirt() // Initial offset of the brim inner edge from the object (possible with a support & raft). // The skirt will touch the brim if the brim is extruded. - auto distance = float(scale_(m_config.skirt_distance.value) - spacing/2.); + auto distance = float(scale_(m_config.skirt_distance.value - spacing/2.)); // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); From 748ae2e7a658bf1ba0390785248836dc9fa1e228 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:27:48 +0300 Subject: [PATCH 07/11] Remove draft shield limited option --- src/libslic3r/PrintConfig.cpp | 12 +++++------- src/libslic3r/PrintConfig.hpp | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index df57b11ed11..d7dcc1ecdad 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -319,7 +319,6 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TimelapseType) static const t_config_enum_values s_keys_map_DraftShield = { { "disabled", dsDisabled }, - { "limited", dsLimited }, { "enabled", dsEnabled } }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(DraftShield) @@ -4006,17 +4005,13 @@ void PrintConfigDef::init_fff_params() def->label = L("Draft shield"); def->tooltip = L("A draft shield is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft. " "It is usually needed only with open frame printers, i.e. without an enclosure. \n\n" - "Options:\n" - "Enabled = skirt is as tall as the highest printed object.\n" - "Limited = skirt is as tall as specified by skirt height.\n\n" + "Enabled = skirt is as tall as the highest printed object. Otherwise 'Skirt height' is used.\n" "Note: With the draft shield active, the skirt will be printed at skirt distance from the object. Therefore, if brims " "are active it may intersect with them. To avoid this, increase the skirt distance value.\n"); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("disabled"); - def->enum_values.push_back("limited"); def->enum_values.push_back("enabled"); def->enum_labels.push_back(L("Disabled")); - def->enum_labels.push_back(L("Limited")); def->enum_labels.push_back(L("Enabled")); def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(dsDisabled)); @@ -6144,9 +6139,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va else if(opt_key == "ironing_direction") { opt_key = "ironing_angle"; } - else if(opt_key == "counterbole_hole_bridging"){ + else if(opt_key == "counterbole_hole_bridging") { opt_key = "counterbore_hole_bridging"; } + else if (opt_key == "draft_shield" && value == "limited") { + value = "disabled"; + } // Ignore the following obsolete configuration keys: static std::set ignore = { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 015befbd9f1..4944c2d17a4 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -225,7 +225,7 @@ enum TimelapseType : int { }; enum DraftShield { - dsDisabled, dsLimited, dsEnabled + dsDisabled, dsEnabled }; enum class PerimeterGeneratorType From 83346aaffa4e993b3d7fff2e9a88fa250a0b35b0 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Sun, 18 Aug 2024 12:54:33 +0300 Subject: [PATCH 08/11] Configure skirt start point --- src/libslic3r/GCode.cpp | 32 +++++++++++++++++++++++++++ src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 1 + src/libslic3r/PrintConfig.cpp | 9 ++++++++ src/libslic3r/PrintConfig.hpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 10 ++++++++- 8 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0fa6bbcbba0..4e01dd7bd68 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3425,6 +3425,33 @@ namespace Skirt { return skirt_loops_per_extruder_out; } + static Point find_start_point(ExtrusionLoop& loop, float start_angle) { + coord_t min_x = std::numeric_limits::max(); + coord_t max_x = std::numeric_limits::min(); + coord_t min_y = min_x; + coord_t max_y = max_x; + + Points pts; + loop.collect_points(pts); + for (Point pt: pts) { + if (pt.x() < min_x) + min_x = pt.x(); + else if (pt.x() > max_x) + max_x = pt.x(); + if (pt.y() < min_y) + min_y = pt.y(); + else if (pt.y() > max_y) + max_y = pt.y(); + } + + Point center((min_x + max_x)/2., (min_y + max_y)/2.); + double r = center.distance_to(Point(min_x, min_y)); + double deg = start_angle * PI / 180; + double shift_x = r * std::cos(deg); + double shift_y = r * std::sin(deg); + return Point(center.x()+shift_x, center.y() + shift_y); + } + } // namespace Skirt // Orca: Klipper can't parse object names with spaces and other spetical characters @@ -3995,6 +4022,11 @@ LayerResult GCode::process_layer( path.height = layer_skirt_flow.height(); path.mm3_per_mm = mm3_per_mm; } + + //set skirt start point location + if (first_layer && i==loops.first) + this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle)); + //FIXME using the support_speed of the 1st object printed. gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index cbab85b88a7..947c0c3288c 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -774,7 +774,7 @@ static std::vector s_Preset_print_options { "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed", "bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", - "outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_height", "draft_shield", + "outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height", "draft_shield", "brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index bfc70d40630..62a4001c7ef 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -225,6 +225,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "min_skirt_length" || opt_key == "draft_shield" || opt_key == "skirt_distance" + || opt_key == "skirt_start_angle" || opt_key == "ooze_prevention" || opt_key == "wipe_tower_x" || opt_key == "wipe_tower_y" diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index d7dcc1ecdad..a152e7ac55b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3992,6 +3992,15 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(2)); + def = this->add("skirt_start_angle", coFloat); + def->label = L("Skirt start point"); + def->tooltip = L("Angle from the object center to skirt start point. Zero is the most right position, counter clockwise is positive angle."); + def->sidetext = L("°"); + def->min = -180; + def->max = 180; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(-135)); + def = this->add("skirt_height", coInt); def->label = L("Skirt height"); //def->label = "Skirt height"; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 4944c2d17a4..d601c13f471 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1220,6 +1220,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloats, retraction_minimum_travel)) ((ConfigOptionBools, retract_when_changing_layer)) ((ConfigOptionFloat, skirt_distance)) + ((ConfigOptionFloat, skirt_start_angle)) ((ConfigOptionInt, skirt_height)) ((ConfigOptionInt, skirt_loops)) ((ConfigOptionFloat, skirt_speed)) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 02c82e06bb8..c79810f34a2 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -569,7 +569,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co bool have_skirt = config->opt_int("skirt_loops") > 0; toggle_field("skirt_height", have_skirt && config->opt_enum("draft_shield") != dsEnabled); - for (auto el : { "skirt_distance", "draft_shield"}) + for (auto el : { "skirt_distance", "skirt_start_angle", "draft_shield"}) toggle_field(el, have_skirt); bool have_brim = (config->opt_enum("brim_type") != btNoBrim); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7950f9a6694..4d2ebb95fa2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2770,7 +2770,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "print_sequence", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", - "nozzle_height", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", + "nozzle_height", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume", "extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index f529b09c133..bb23a435a2a 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -61,7 +61,7 @@ namespace GUI { #define DISABLE_UNDO_SYS -static const std::vector plate_keys = { "curr_bed_type", "first_layer_print_sequence", "first_layer_sequence_choice", "other_layers_print_sequence", "other_layers_sequence_choice", "print_sequence", "spiral_mode"}; +static const std::vector plate_keys = { "curr_bed_type", "skirt_start_angle", "first_layer_print_sequence", "first_layer_sequence_choice", "other_layers_print_sequence", "other_layers_sequence_choice", "print_sequence", "spiral_mode"}; void Tab::Highlighter::set_timer_owner(wxEvtHandler* owner, int timerid/* = wxID_ANY*/) { @@ -2321,6 +2321,7 @@ page = add_options_page(L("Others"), "custom-gcode_other"); // ORCA: icon only v optgroup->append_single_option_line("skirt_loops"); optgroup->append_single_option_line("min_skirt_length"); optgroup->append_single_option_line("skirt_distance"); + optgroup->append_single_option_line("skirt_start_angle"); optgroup->append_single_option_line("skirt_height"); optgroup->append_single_option_line("skirt_speed"); optgroup->append_single_option_line("draft_shield"); @@ -2789,6 +2790,7 @@ void TabPrintPlate::build() auto page = add_options_page(L("Plate Settings"), "empty"); auto optgroup = page->new_optgroup(""); optgroup->append_single_option_line("curr_bed_type"); + optgroup->append_single_option_line("skirt_start_angle"); optgroup->append_single_option_line("print_sequence"); optgroup->append_single_option_line("spiral_mode"); optgroup->append_single_option_line("first_layer_sequence_choice"); @@ -2837,6 +2839,8 @@ void TabPrintPlate::on_value_change(const std::string& opt_key, const boost::any auto plate = dynamic_cast(plate_item.first); if (k == "curr_bed_type") plate->reset_bed_type(); + if (k == "skirt_start_angle") + plate->config()->erase("skirt_start_angle"); if (k == "print_sequence") plate->set_print_seq(PrintSequence::ByDefault); if (k == "first_layer_sequence_choice") @@ -2860,6 +2864,10 @@ void TabPrintPlate::on_value_change(const std::string& opt_key, const boost::any bed_type = m_config->opt_enum("curr_bed_type"); plate->set_bed_type(BedType(bed_type)); } + if (k == "skirt_start_angle") { + float angle = m_config->opt_float("skirt_start_angle"); + plate->config()->set_key_value("skirt_start_angle", new ConfigOptionFloat(angle)); + } if (k == "print_sequence") { print_seq = m_config->opt_enum("print_sequence"); plate->set_print_seq(print_seq); From 0b6a1d36360448c5e6818001b9d8ea99a57567a7 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 09:59:39 +0300 Subject: [PATCH 09/11] Refactor all_objects_are_short --- src/libslic3r/Arrange.cpp | 4 +--- src/libslic3r/Arrange.hpp | 1 + src/libslic3r/Print.cpp | 3 +-- src/libslic3r/Print.hpp | 1 - src/libslic3r/PrintConfig.cpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 9 ++++----- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 1 + 7 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index cbb7dd8e8f3..f21a0948c21 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -103,10 +103,8 @@ void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPri BoundingBox bedbb = Polygon(bedpts).bounding_box(); // set obj distance for auto seq_print if (params.is_seq_print) { - bool all_objects_are_short = std::all_of(selected.begin(), selected.end(), [&](ArrangePolygon& ap) { return ap.height < params.nozzle_height; }); - if (all_objects_are_short) { + if (params.all_objects_are_short) params.min_obj_distance = std::max(params.min_obj_distance, scaled(double(MAX_OUTER_NOZZLE_DIAMETER)/2+0.001)); - } else params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.clearance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error } diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index 5ad4815c936..9330c4049ba 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -133,6 +133,7 @@ struct ArrangeParams { float clearance_height_to_lid = 0; float clearance_radius = 0; float nozzle_height = 0; + bool all_objects_are_short = false; float printable_height = 256.0; Vec2d align_center{ 0.5,0.5 }; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 62a4001c7ef..d689315df17 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -578,10 +578,9 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print polygons->clear(); std::vector intersecting_idxs; - bool all_objects_are_short = print.is_all_objects_are_short(); // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. - float obj_distance = all_objects_are_short ? scale_(0.5*MAX_OUTER_NOZZLE_DIAMETER-0.1) : scale_(0.5*print.config().extruder_clearance_radius.value-0.1); + float obj_distance = print.is_all_objects_are_short() ? scale_(0.5*MAX_OUTER_NOZZLE_DIAMETER-0.1) : scale_(0.5*print.config().extruder_clearance_radius.value-0.1); for (const PrintObject *print_object : print.objects()) { assert(! print_object->model_object()->instances.empty()); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index aebb46899f4..43aac7d87d4 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -38,7 +38,6 @@ class SupportLayer; class TreeSupportData; class TreeSupport; -#define MARGIN_HEIGHT 1.5 #define MAX_OUTER_NOZZLE_DIAMETER 4 // BBS: move from PrintObjectSlice.cpp struct VolumeSlices diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a152e7ac55b..63b20a6ff87 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1613,7 +1613,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comDevelop; - def->set_default_value(new ConfigOptionFloat(4)); + def->set_default_value(new ConfigOptionFloat(2.5)); def = this->add("bed_mesh_min", coPoint); def->label = L("Bed mesh min"); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6365b88a26f..7921b6e2df7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5223,13 +5223,12 @@ void GLCanvas3D::update_sequential_clearance() // the results are then cached for following displacements if (m_sequential_print_clearance_first_displacement) { m_sequential_print_clearance.m_hull_2d_cache.clear(); - bool all_objects_are_short = std::all_of(fff_print()->objects().begin(), fff_print()->objects().end(), \ - [&](PrintObject* obj) { return obj->height() < scale_(fff_print()->config().nozzle_height.value - MARGIN_HEIGHT); }); + auto [object_skirt_offset, _] = fff_print()->object_skirt_offset(); float shrink_factor; - if (all_objects_are_short) - shrink_factor = scale_(0.5 * MAX_OUTER_NOZZLE_DIAMETER - 0.1); + if (fff_print()->is_all_objects_are_short()) + shrink_factor = scale_(std::max(0.5f * MAX_OUTER_NOZZLE_DIAMETER, object_skirt_offset) - 0.1); else - shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON)); + shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - 0.1)); double mitter_limit = scale_(0.1); m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size()); diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 6ae6a99ac2a..86ef530d25a 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -772,6 +772,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) params.printable_height = print_config.printable_height.value; params.allow_rotations = settings.enable_rotation; params.nozzle_height = print.config().nozzle_height.value; + params.all_objects_are_short = print.is_all_objects_are_short(); params.align_center = print_config.best_object_pos.value; params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate; params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; From 2a8b39acd47ecb66dcd6b09ed40c7a6aa76c496b Mon Sep 17 00:00:00 2001 From: vovodroid Date: Thu, 22 Aug 2024 17:12:42 +0300 Subject: [PATCH 10/11] Object skirt --- src/libslic3r/Arrange.cpp | 2 +- src/libslic3r/Arrange.hpp | 2 + src/libslic3r/GCode.cpp | 139 ++++++++++++------- src/libslic3r/GCode.hpp | 7 + src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 186 ++++++++++++++++---------- src/libslic3r/Print.hpp | 2 + src/libslic3r/PrintConfig.cpp | 21 ++- src/libslic3r/PrintConfig.hpp | 8 +- src/slic3r/GUI/ConfigManipulation.cpp | 13 +- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 9 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 14 files changed, 262 insertions(+), 134 deletions(-) diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index f21a0948c21..917ea14c841 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -104,7 +104,7 @@ void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPri // set obj distance for auto seq_print if (params.is_seq_print) { if (params.all_objects_are_short) - params.min_obj_distance = std::max(params.min_obj_distance, scaled(double(MAX_OUTER_NOZZLE_DIAMETER)/2+0.001)); + params.min_obj_distance = std::max(params.min_obj_distance, scaled(std::max(MAX_OUTER_NOZZLE_DIAMETER/2.f, params.object_skirt_offset*2)+0.001)); else params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.clearance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error } diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index 9330c4049ba..8781477bcb9 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -3,6 +3,7 @@ #include "ExPolygon.hpp" #include "PrintConfig.hpp" +#include "Print.hpp" #define BED_SHRINK_SEQ_PRINT 5 @@ -132,6 +133,7 @@ struct ArrangeParams { float clearance_height_to_rod = 0; float clearance_height_to_lid = 0; float clearance_radius = 0; + float object_skirt_offset = 0; float nozzle_height = 0; bool all_objects_are_short = false; float printable_height = 256.0; diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 4e01dd7bd68..7b3b661e8e0 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3356,10 +3356,10 @@ namespace ProcessLayer } // namespace ProcessLayer namespace Skirt { - static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) + static void skirt_loops_per_extruder_all_printing(const Print &print, const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, std::map> &skirt_loops_per_extruder_out) { // Prime all extruders printing over the 1st layer over the skirt lines. - size_t n_loops = print.skirt().entities.size(); + size_t n_loops = skirt.entities.size(); size_t n_tools = layer_tools.extruders.size(); size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools; @@ -3377,6 +3377,7 @@ namespace Skirt { static std::map> make_skirt_loops_per_extruder_1st_layer( const Print &print, + const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, // Heights (print_z) at which the skirt has already been extruded. std::vector &skirt_done) @@ -3386,8 +3387,8 @@ namespace Skirt { std::map> skirt_loops_per_extruder_out; //For sequential print, the following test may fail when extruding the 2nd and other objects. // assert(skirt_done.empty()); - if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt) { - skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); + if (skirt_done.empty() && print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt) { + skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out); skirt_done.emplace_back(layer_tools.print_z); } return skirt_loops_per_extruder_out; @@ -3395,6 +3396,7 @@ namespace Skirt { static std::map> make_skirt_loops_per_extruder_other_layers( const Print &print, + const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, // Heights (print_z) at which the skirt has already been extruded. std::vector &skirt_done) @@ -3402,7 +3404,7 @@ namespace Skirt { // Extrude skirt at the print_z of the raft layers and normal object layers // not at the print_z of the interlaced support material layers. std::map> skirt_loops_per_extruder_out; - if (print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt && + if (print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt && // Not enough skirt layers printed yet. //FIXME infinite or high skirt does not make sense for sequential print! (skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt())) { @@ -3416,7 +3418,7 @@ namespace Skirt { skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair(0, print.config().skirt_loops.value); #else // Prime all extruders planned for this layer, see - skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); + skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out); #endif assert(!skirt_done.empty()); skirt_done.emplace_back(layer_tools.print_z); @@ -3479,6 +3481,57 @@ inline std::string get_instance_name(const PrintObject *object, const PrintInsta return get_instance_name(object, inst.id); } +std::string GCode::generate_skirt(const Print &print, + const ExtrusionEntityCollection &skirt, + const Point& offset, + const LayerTools &layer_tools, + const Layer& layer, + unsigned int extruder_id) +{ + + bool first_layer = (layer.id() == 0 && abs(layer.bottom_z()) < EPSILON); + std::string gcode; + // Extrude skirt at the print_z of the raft layers and normal object layers + // not at the print_z of the interlaced support material layers. + // Map from extruder ID to index of skirt loops to be extruded with that extruder. + std::map> skirt_loops_per_extruder; + skirt_loops_per_extruder = first_layer ? + Skirt::make_skirt_loops_per_extruder_1st_layer(print, skirt, layer_tools, m_skirt_done) : + Skirt::make_skirt_loops_per_extruder_other_layers(print, skirt, layer_tools, m_skirt_done); + + if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { + const std::pair loops = loops_it->second; + + set_origin(unscaled(offset)); + + m_avoid_crossing_perimeters.use_external_mp(); + Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); + double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); + for (size_t i = first_layer ? loops.first : loops.second - 1; i < loops.second; ++i) { + // Adjust flow according to this layer's layer height. + ExtrusionLoop loop = *dynamic_cast(skirt.entities[i]); + for (ExtrusionPath &path : loop.paths) { + path.height = layer_skirt_flow.height(); + path.mm3_per_mm = mm3_per_mm; + } + + //set skirt start point location + if (first_layer && i==loops.first) + this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle)); + + //FIXME using the support_speed of the 1st object printed. + gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); + if (!first_layer) + break; + } + m_avoid_crossing_perimeters.use_external_mp(false); + // Allow a straight travel move to the first object point if this is the first layer (but don't in next layers). + if (first_layer && loops.first == 0) + m_avoid_crossing_perimeters.disable_once(); + } + return gcode; +} + // In sequential mode, process_layer is called once per each object and its copy, // therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object. // In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated. @@ -3730,18 +3783,10 @@ LayerResult GCode::process_layer( m_second_layer_things_done = true; } - // Map from extruder ID to index of skirt loops to be extruded with that extruder. - std::map> skirt_loops_per_extruder; - if (single_object_instance_idx == size_t(-1)) { // Normal (non-sequential) print. gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config()); } - // Extrude skirt at the print_z of the raft layers and normal object layers - // not at the print_z of the interlaced support material layers. - skirt_loops_per_extruder = first_layer ? - Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) : - Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done); // BBS: get next extruder according to flush and soluble auto get_next_extruder = [&](int current_extruder,const std::vector&extruders) { @@ -4008,33 +4053,9 @@ LayerResult GCode::process_layer( // let analyzer tag generator aware of a role type change if (layer_tools.has_wipe_tower && m_wipe_tower) m_last_processor_extrusion_role = erWipeTower; - - if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { - const std::pair loops = loops_it->second; - this->set_origin(0., 0.); - m_avoid_crossing_perimeters.use_external_mp(); - Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); - double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); - for (size_t i = (layer.id() == 0) ? loops.first : loops.second - 1; i < loops.second; ++i) { - // Adjust flow according to this layer's layer height. - ExtrusionLoop loop = *dynamic_cast(print.skirt().entities[i]); - for (ExtrusionPath &path : loop.paths) { - path.height = layer_skirt_flow.height(); - path.mm3_per_mm = mm3_per_mm; - } - - //set skirt start point location - if (first_layer && i==loops.first) - this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle)); - - //FIXME using the support_speed of the 1st object printed. - gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value); - } - m_avoid_crossing_perimeters.use_external_mp(false); - // Allow a straight travel move to the first object point if this is the first layer (but don't in next layers). - if (first_layer && loops.first == 0) - m_avoid_crossing_perimeters.disable_once(); - } + + if (print.config().skirt_type == stCommon && !print.skirt().empty()) + gcode += generate_skirt(print, print.skirt(), Point(0,0), layer_tools, layer, extruder_id); auto objects_by_extruder_it = by_extruder.find(extruder_id); if (objects_by_extruder_it == by_extruder.end()) @@ -4069,8 +4090,17 @@ LayerResult GCode::process_layer( } // BBS - if (print.has_skirt() && print.config().print_sequence == PrintSequence::ByObject && prime_extruder && first_layer && extruder_id == first_extruder_id) { + if (print.config().skirt_type == stObject && + print.config().print_sequence == PrintSequence::ByObject && + !layer.object()->object_skirt().empty() && + ((layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) + ) + { for (InstanceToPrint& instance_to_print : instances_to_print) { + + if (instance_to_print.print_object.object_skirt().empty()) + continue; + if (this->m_objSupportsWithBrim.find(instance_to_print.print_object.id()) != this->m_objSupportsWithBrim.end() && print.m_supportBrimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; @@ -4078,12 +4108,14 @@ LayerResult GCode::process_layer( if (this->m_objsWithBrim.find(instance_to_print.print_object.id()) != this->m_objsWithBrim.end() && print.m_brimMap.at(instance_to_print.print_object.id()).entities.size() > 0) continue; + if (first_layer) + m_skirt_done.clear(); + + if (layer.id() == 1 && m_skirt_done.size() > 1) + m_skirt_done.erase(m_skirt_done.begin()+1,m_skirt_done.end()); const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; - set_origin(unscaled(offset)); - for (ExtrusionEntity* ee : layer.object()->object_skirt().entities) - //FIXME using the support_speed of the 1st object printed. - gcode += this->extrude_entity(*ee, "skirt", m_config.support_speed.value); + gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id); } } @@ -4092,7 +4124,22 @@ LayerResult GCode::process_layer( for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) { if (is_anything_overridden && print_wipe_extrusions == 0) gcode+="; PURGING FINISHED\n"; + for (InstanceToPrint &instance_to_print : instances_to_print) { + if (print.config().skirt_type == stObject && + !instance_to_print.print_object.object_skirt().empty() && + print.config().print_sequence == PrintSequence::ByLayer + && + (layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) + { + if (first_layer) + m_skirt_done.clear(); + const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift; + gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id); + if (instances_to_print.size() > 1 && &instance_to_print != &*(instances_to_print.end() - 1)) + m_skirt_done.pop_back(); + } + const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id]; const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id]; // To control print speed of the 1st object layer printed over raft interface. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 256853c48cf..843b4a39dad 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -308,6 +308,13 @@ class GCode { static std::vector collect_layers_to_print(const PrintObject &object); static std::vector>> collect_layers_to_print(const Print &print); + std::string generate_skirt(const Print &print, + const ExtrusionEntityCollection &skirt, + const Point& offset, + const LayerTools &layer_tools, + const Layer& layer, + unsigned int extruder_id); + LayerResult process_layer( const Print &print, // Set of object & print layers of the same PrintObject and with the same print_z. diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 947c0c3288c..6b27bb32055 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -774,7 +774,7 @@ static std::vector s_Preset_print_options { "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed", "bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", - "outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height", "draft_shield", + "outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height", "draft_shield", "brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index d689315df17..53ff2b3c8c5 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -219,7 +219,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n } else if (steps_ignore.find(opt_key) != steps_ignore.end()) { // These steps have no influence on the G-code whatsoever. Just ignore them. } else if ( - opt_key == "skirt_loops" + opt_key == "skirt_type" + || opt_key == "skirt_loops" || opt_key == "skirt_speed" || opt_key == "skirt_height" || opt_key == "min_skirt_length" @@ -507,7 +508,7 @@ bool Print::has_infinite_skirt() const bool Print::has_skirt() const { - return (m_config.skirt_height > 0 && m_config.skirt_loops > 0) || m_config.draft_shield != dsDisabled; + return (m_config.skirt_height > 0); } bool Print::has_brim() const @@ -570,6 +571,8 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print } return -1; }; + + auto [object_skirt_offset, _] = print.object_skirt_offset(); std::vector print_instance_with_bounding_box; { // sequential_print_horizontal_clearance_valid @@ -580,7 +583,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. - float obj_distance = print.is_all_objects_are_short() ? scale_(0.5*MAX_OUTER_NOZZLE_DIAMETER-0.1) : scale_(0.5*print.config().extruder_clearance_radius.value-0.1); + float obj_distance = print.is_all_objects_are_short() ? scale_(std::max(0.5f * MAX_OUTER_NOZZLE_DIAMETER, object_skirt_offset) - 0.1) : scale_(0.5 * print.config().extruder_clearance_radius.value + object_skirt_offset - 0.1); for (const PrintObject *print_object : print.objects()) { assert(! print_object->model_object()->instances.empty()); @@ -815,7 +818,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print auto inst = print_instance_with_bounding_box[k].print_instance; // 只需要考虑喷嘴到滑杆的偏移量,这个比整个工具头的碰撞半径要小得多 // Only the offset from the nozzle to the slide bar needs to be considered, which is much smaller than the collision radius of the entire tool head. - auto bbox = print_instance_with_bounding_box[k].bounding_box.inflated(-scale_(0.5 * print.config().extruder_clearance_radius.value)); + auto bbox = print_instance_with_bounding_box[k].bounding_box.inflated(-scale_(0.5 * print.config().extruder_clearance_radius.value + object_skirt_offset)); auto iy1 = bbox.min.y(); auto iy2 = bbox.max.y(); (const_cast(inst->model_instance))->arrange_order = k+1; @@ -2287,73 +2290,21 @@ void Print::_make_skirt() // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); - for (size_t i = m_config.skirt_loops, extruder_idx = 0; i > 0; -- i) { - this->throw_if_canceled(); - // Offset the skirt outside. - distance += float(scale_(spacing)); - // Generate the skirt centerline. - Polygon loop; - { - // BBS. skirt_distance is defined as the gap between skirt and outer most brim, so no need to add max_brim_width - Polygons loops = offset(convex_hull, distance, ClipperLib::jtRound, float(scale_(0.1))); - Geometry::simplify_polygons(loops, scale_(0.05), &loops); - if (loops.empty()) - break; - loop = loops.front(); - } - // Extrude the skirt loop. - ExtrusionLoop eloop(elrSkirt); - eloop.paths.emplace_back(ExtrusionPath( - ExtrusionPath( - erSkirt, - (float)mm3_per_mm, // this will be overridden at G-code export time - flow.width(), - (float)initial_layer_print_height // this will be overridden at G-code export time - ))); - eloop.paths.back().polyline = loop.split_at_first_point(); - m_skirt.append(eloop); - if (m_config.min_skirt_length.value > 0) { - // The skirt length is limited. Sum the total amount of filament length extruded, in mm. - extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx]; - if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) { - // Not extruded enough yet with the current extruder. Add another loop. - if (i == 1) - ++ i; - } else { - assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value); - // Enough extruded with the current extruder. Extrude with the next one, - // until the prescribed number of skirt loops is extruded. - if (extruder_idx + 1 < extruders.size()) - ++ extruder_idx; - } - } else { - // The skirt lenght is not limited, extrude the skirt with the 1st extruder only. - } - } - // Brims were generated inside out, reverse to print the outmost contour first. - m_skirt.reverse(); - - // Remember the outer edge of the last skirt line extruded as m_skirt_convex_hull. - for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(scale_(spacing)), ClipperLib::jtRound, float(scale_(0.1)))) - append(m_skirt_convex_hull, std::move(poly.points)); - - // BBS - const double object_skirt_distance = scale_(1.0); - for (auto obj_cvx_hull : object_convex_hulls) { - PrintObject* object = obj_cvx_hull.first; - object->m_skirt.clear(); - for (int i = 0; i < 1; i++) { + if (m_config.skirt_type == stCommon) { + for (size_t i = m_config.skirt_loops, extruder_idx = 0; i > 0; -- i) { + this->throw_if_canceled(); + // Offset the skirt outside. distance += float(scale_(spacing)); + // Generate the skirt centerline. Polygon loop; { // BBS. skirt_distance is defined as the gap between skirt and outer most brim, so no need to add max_brim_width - Polygons loops = offset(obj_cvx_hull.second, object_skirt_distance, ClipperLib::jtRound, float(scale_(0.1))); + Polygons loops = offset(convex_hull, distance, ClipperLib::jtRound, float(scale_(0.1))); Geometry::simplify_polygons(loops, scale_(0.05), &loops); - if (loops.empty()) - break; - loop = loops.front(); + if (loops.empty()) + break; + loop = loops.front(); } - // Extrude the skirt loop. ExtrusionLoop eloop(elrSkirt); eloop.paths.emplace_back(ExtrusionPath( @@ -2361,10 +2312,88 @@ void Print::_make_skirt() erSkirt, (float)mm3_per_mm, // this will be overridden at G-code export time flow.width(), - (float)initial_layer_print_height // this will be overridden at G-code export time + (float)initial_layer_print_height // this will be overridden at G-code export time ))); eloop.paths.back().polyline = loop.split_at_first_point(); - object->m_skirt.append(std::move(eloop)); + m_skirt.append(eloop); + if (m_config.min_skirt_length.value > 0) { + // The skirt length is limited. Sum the total amount of filament length extruded, in mm. + extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx]; + if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) { + // Not extruded enough yet with the current extruder. Add another loop. + if (i == 1) + ++ i; + } else { + assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value); + // Enough extruded with the current extruder. Extrude with the next one, + // until the prescribed number of skirt loops is extruded. + if (extruder_idx + 1 < extruders.size()) + ++ extruder_idx; + } + } else { + // The skirt lenght is not limited, extrude the skirt with the 1st extruder only. + } + } + } else { + m_skirt.clear(); + } + // Brims were generated inside out, reverse to print the outmost contour first. + m_skirt.reverse(); + + // Remember the outer edge of the last skirt line extruded as m_skirt_convex_hull. + for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(scale_(spacing)), ClipperLib::jtRound, float(scale_(0.1)))) + append(m_skirt_convex_hull, std::move(poly.points)); + + if (m_config.skirt_type == stObject) { + // BBS + for (auto obj_cvx_hull : object_convex_hulls) { + double object_skirt_distance = float(scale_(m_config.skirt_distance.value - spacing/2.)); + PrintObject* object = obj_cvx_hull.first; + object->m_skirt.clear(); + extruded_length.assign(extruded_length.size(), 0.); + for (size_t i = m_config.skirt_loops.value, extruder_idx = 0; i > 0; -- i) { + object_skirt_distance += float(scale_(spacing)); + Polygon loop; + { + // BBS. skirt_distance is defined as the gap between skirt and outer most brim, so no need to add max_brim_width + Polygons loops = offset(obj_cvx_hull.second, object_skirt_distance, ClipperLib::jtRound, float(scale_(0.1))); + Geometry::simplify_polygons(loops, scale_(0.05), &loops); + if (loops.empty()) + break; + loop = loops.front(); + } + + // Extrude the skirt loop. + ExtrusionLoop eloop(elrSkirt); + eloop.paths.emplace_back(ExtrusionPath( + ExtrusionPath( + erSkirt, + (float)mm3_per_mm, // this will be overridden at G-code export time + flow.width(), + (float)initial_layer_print_height // this will be overridden at G-code export time + ))); + eloop.paths.back().polyline = loop.split_at_first_point(); + object->m_skirt.append(std::move(eloop)); + if (m_config.min_skirt_length.value > 0) { + // The skirt length is limited. Sum the total amount of filament length extruded, in mm. + extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx]; + if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) { + // Not extruded enough yet with the current extruder. Add another loop. + if (i == 1) + ++ i; + } else { + assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value); + // Enough extruded with the current extruder. Extrude with the next one, + // until the prescribed number of skirt loops is extruded. + if (extruder_idx + 1 < extruders.size()) + ++ extruder_idx; + } + } else { + // The skirt lenght is not limited, extrude the skirt with the 1st extruder only. + } + + } + object->m_skirt.reverse(); } } } @@ -2900,6 +2929,29 @@ void Print::export_gcode_from_previous_file(const std::string& file, GCodeProces BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": process the G-code file %1% successfully")%file.c_str(); } +std::tuple Print::object_skirt_offset(double margin_height) const +{ + if (config().skirt_loops == 0 || config().skirt_type != stObject) + return std::make_tuple(0, 0); + + float max_nozzle_diameter = *std::max_element(m_config.nozzle_diameter.values.begin(), m_config.nozzle_diameter.values.end()); + float max_layer_height = *std::max_element(config().max_layer_height.values.begin(), config().max_layer_height.values.end()); + float line_width = m_config.initial_layer_line_width.get_abs_value(max_nozzle_diameter); + float object_skirt_witdh = skirt_flow().width() + (config().skirt_loops - 1) * skirt_flow().spacing(); + float object_skirt_offset = 0; + + if (is_all_objects_are_short()) + object_skirt_offset = config().skirt_distance + object_skirt_witdh; + else if (config().draft_shield == dsEnabled || config().skirt_height * max_layer_height > config().nozzle_height - margin_height) + object_skirt_offset = config().skirt_distance + line_width; + else if (config().skirt_distance + object_skirt_witdh > config().extruder_clearance_radius/2) + object_skirt_offset = (config().skirt_distance + object_skirt_witdh - config().extruder_clearance_radius/2); + else + return std::make_tuple(0, 0); + + return std::make_tuple(object_skirt_offset, object_skirt_witdh); +} + DynamicConfig PrintStatistics::config() const { DynamicConfig config; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 43aac7d87d4..15c783100b8 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -981,6 +981,8 @@ class Print : public PrintBaseWithState return std::all_of(this->objects().begin(), this->objects().end(), [&](PrintObject* obj) { return obj->height() < scale_(this->config().nozzle_height.value); }); } + std::tuple object_skirt_offset(double margin_height = 0) const; + protected: // Invalidates the step, and its depending steps in Print. bool invalidate_step(PrintStep step); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 63b20a6ff87..cc797427f9c 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -317,6 +317,12 @@ static const t_config_enum_values s_keys_map_TimelapseType = { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TimelapseType) +static const t_config_enum_values s_keys_map_SkirtType = { + { "common", stCommon }, + { "object", stObject } +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SkirtType) + static const t_config_enum_values s_keys_map_DraftShield = { { "disabled", dsDisabled }, { "enabled", dsEnabled } @@ -4025,6 +4031,18 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(dsDisabled)); + def = this->add("skirt_type", coEnum); + def->label = L("Skirt type"); + def->full_label = L("Skirt type"); + def->tooltip = L("Common - single skirt for all objects, Object - individual per object skirt."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("common"); + def->enum_values.push_back("object"); + def->enum_labels.push_back(L("Common")); + def->enum_labels.push_back(L("Object")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(stCommon)); + def = this->add("skirt_loops", coInt); def->label = L("Skirt loops"); def->full_label = L("Skirt loops"); @@ -4047,7 +4065,8 @@ void PrintConfigDef::init_fff_params() def->label = L("Skirt minimum extrusion length"); def->full_label = L("Skirt minimum extrusion length"); def->tooltip = L("Minimum filament extrusion length in mm when printing the skirt. Zero means this feature is disabled.\n\n" - "Using a non zero value is useful if the printer is set up to print without a prime line."); + "Using a non zero value is useful if the printer is set up to print without a prime line.\n" + "Final number of loops is not taling into account whli arranging or validating objects distance. Increase loop number in such case. "); def->min = 0; def->sidetext = L("mm"); def->mode = comAdvanced; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index d601c13f471..683f2d74dbf 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -224,6 +224,10 @@ enum TimelapseType : int { tlSmooth }; +enum SkirtType { + stCommon, stObject +}; + enum DraftShield { dsDisabled, dsEnabled }; @@ -393,6 +397,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLAPillarConnectionMode) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BrimType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TimelapseType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BedType) +CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SkirtType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat) @@ -739,6 +744,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, brim_width)) ((ConfigOptionFloat, brim_ears_detection_length)) ((ConfigOptionFloat, brim_ears_max_angle)) + ((ConfigOptionFloat, skirt_start_angle)) ((ConfigOptionBool, bridge_no_support)) ((ConfigOptionFloat, elefant_foot_compensation)) ((ConfigOptionInt, elefant_foot_compensation_layers)) @@ -1220,9 +1226,9 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloats, retraction_minimum_travel)) ((ConfigOptionBools, retract_when_changing_layer)) ((ConfigOptionFloat, skirt_distance)) - ((ConfigOptionFloat, skirt_start_angle)) ((ConfigOptionInt, skirt_height)) ((ConfigOptionInt, skirt_loops)) + ((ConfigOptionEnum, skirt_type)) ((ConfigOptionFloat, skirt_speed)) ((ConfigOptionFloat, min_skirt_length)) ((ConfigOptionFloats, slow_down_layer_time)) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index c79810f34a2..9100935eac3 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -449,17 +449,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con } } - if (config->opt_enum("print_sequence") == PrintSequence::ByObject && config->opt_int("skirt_height") > 1 && config->opt_int("skirt_loops") > 0) { - const wxString msg_text = _(L("While printing by Object, the extruder may collide skirt.\nThus, reset the skirt layer to 1 to avoid that.")); - MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK); - DynamicPrintConfig new_conf = *config; - is_msg_dlg_already_exist = true; - dialog.ShowModal(); - new_conf.set_key_value("skirt_height", new ConfigOptionInt(1)); - apply(config, &new_conf); - is_msg_dlg_already_exist = false; - } - if (config->opt_enum("seam_slope_type") != SeamScarfType::None && config->get_abs_value("seam_slope_start_height") >= layer_height) { const wxString msg_text = _(L("seam_slope_start_height need to be smaller than layer_height.\nReset to 0.")); @@ -569,7 +558,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co bool have_skirt = config->opt_int("skirt_loops") > 0; toggle_field("skirt_height", have_skirt && config->opt_enum("draft_shield") != dsEnabled); - for (auto el : { "skirt_distance", "skirt_start_angle", "draft_shield"}) + for (auto el : {"skirt_type", "skirt_distance", "skirt_start_angle", "draft_shield"}) toggle_field(el, have_skirt); bool have_brim = (config->opt_enum("brim_type") != btNoBrim); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7921b6e2df7..2d4048cef92 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5228,7 +5228,7 @@ void GLCanvas3D::update_sequential_clearance() if (fff_print()->is_all_objects_are_short()) shrink_factor = scale_(std::max(0.5f * MAX_OUTER_NOZZLE_DIAMETER, object_skirt_offset) - 0.1); else - shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - 0.1)); + shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value + object_skirt_offset - 0.1)); double mitter_limit = scale_(0.1); m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size()); diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 86ef530d25a..90657aada4d 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -766,18 +766,21 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); const PrintConfig &print_config = print.config(); + auto [object_skirt_offset, object_skirt_witdh] = print.object_skirt_offset(); + params.clearance_height_to_rod = print_config.extruder_clearance_height_to_rod.value; params.clearance_height_to_lid = print_config.extruder_clearance_height_to_lid.value; - params.clearance_radius = print_config.extruder_clearance_radius.value; + params.clearance_radius = print_config.extruder_clearance_radius.value + object_skirt_offset * 2; + params.object_skirt_offset = object_skirt_offset; params.printable_height = print_config.printable_height.value; params.allow_rotations = settings.enable_rotation; - params.nozzle_height = print.config().nozzle_height.value; + params.nozzle_height = print_config.nozzle_height.value; params.all_objects_are_short = print.is_all_objects_are_short(); params.align_center = print_config.best_object_pos.value; params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate; params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; params.is_seq_print = settings.is_seq_print; - params.min_obj_distance = scaled(settings.distance); + params.min_obj_distance = settings.distance; params.align_to_y_axis = settings.align_to_y_axis; int state = p->get_prepare_state(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4d2ebb95fa2..cc294ddda96 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2770,7 +2770,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "print_sequence", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", - "nozzle_height", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", + "nozzle_height", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume", "extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bb23a435a2a..86ee6f1f11c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2318,6 +2318,7 @@ void TabPrint::build() page = add_options_page(L("Others"), "custom-gcode_other"); // ORCA: icon only visible on placeholders optgroup = page->new_optgroup(L("Skirt"), L"param_skirt"); + optgroup->append_single_option_line("skirt_type"); optgroup->append_single_option_line("skirt_loops"); optgroup->append_single_option_line("min_skirt_length"); optgroup->append_single_option_line("skirt_distance"); From 5165515167e4d758d6254f3673c6b35b58dae550 Mon Sep 17 00:00:00 2001 From: vovodroid Date: Sat, 7 Sep 2024 12:02:39 +0300 Subject: [PATCH 11/11] Rename skirt types --- src/libslic3r/GCode.cpp | 6 +++--- src/libslic3r/Print.cpp | 6 +++--- src/libslic3r/PrintConfig.cpp | 16 ++++++++-------- src/libslic3r/PrintConfig.hpp | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index e4d36918002..171d68b9480 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4054,7 +4054,7 @@ LayerResult GCode::process_layer( if (layer_tools.has_wipe_tower && m_wipe_tower) m_last_processor_extrusion_role = erWipeTower; - if (print.config().skirt_type == stCommon && !print.skirt().empty()) + if (print.config().skirt_type == stCombined && !print.skirt().empty()) gcode += generate_skirt(print, print.skirt(), Point(0,0), layer_tools, layer, extruder_id); auto objects_by_extruder_it = by_extruder.find(extruder_id); @@ -4090,7 +4090,7 @@ LayerResult GCode::process_layer( } // BBS - if (print.config().skirt_type == stObject && + if (print.config().skirt_type == stPerObject && print.config().print_sequence == PrintSequence::ByObject && !layer.object()->object_skirt().empty() && ((layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled)) @@ -4126,7 +4126,7 @@ LayerResult GCode::process_layer( gcode+="; PURGING FINISHED\n"; for (InstanceToPrint &instance_to_print : instances_to_print) { - if (print.config().skirt_type == stObject && + if (print.config().skirt_type == stPerObject && !instance_to_print.print_object.object_skirt().empty() && print.config().print_sequence == PrintSequence::ByLayer && diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index e02acd381f8..919b2231fb6 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2311,7 +2311,7 @@ void Print::_make_skirt() // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); - if (m_config.skirt_type == stCommon) { + if (m_config.skirt_type == stCombined) { for (size_t i = m_config.skirt_loops, extruder_idx = 0; i > 0; -- i) { this->throw_if_canceled(); // Offset the skirt outside. @@ -2365,7 +2365,7 @@ void Print::_make_skirt() for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(scale_(spacing)), ClipperLib::jtRound, float(scale_(0.1)))) append(m_skirt_convex_hull, std::move(poly.points)); - if (m_config.skirt_type == stObject) { + if (m_config.skirt_type == stPerObject) { // BBS for (auto obj_cvx_hull : object_convex_hulls) { double object_skirt_distance = float(scale_(m_config.skirt_distance.value - spacing/2.)); @@ -2952,7 +2952,7 @@ void Print::export_gcode_from_previous_file(const std::string& file, GCodeProces std::tuple Print::object_skirt_offset(double margin_height) const { - if (config().skirt_loops == 0 || config().skirt_type != stObject) + if (config().skirt_loops == 0 || config().skirt_type != stPerObject) return std::make_tuple(0, 0); float max_nozzle_diameter = *std::max_element(m_config.nozzle_diameter.values.begin(), m_config.nozzle_diameter.values.end()); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 49703fdfaef..c9b80cdf6c5 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -318,8 +318,8 @@ static const t_config_enum_values s_keys_map_TimelapseType = { CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TimelapseType) static const t_config_enum_values s_keys_map_SkirtType = { - { "common", stCommon }, - { "object", stObject } + { "combined", stCombined }, + { "perobject", stPerObject } }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SkirtType) @@ -4044,14 +4044,14 @@ void PrintConfigDef::init_fff_params() def = this->add("skirt_type", coEnum); def->label = L("Skirt type"); def->full_label = L("Skirt type"); - def->tooltip = L("Common - single skirt for all objects, Object - individual per object skirt."); + def->tooltip = L("Combined - single skirt for all objects, Per object - individual object skirt."); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def->enum_values.push_back("common"); - def->enum_values.push_back("object"); - def->enum_labels.push_back(L("Common")); - def->enum_labels.push_back(L("Object")); + def->enum_values.push_back("combined"); + def->enum_values.push_back("perobject"); + def->enum_labels.push_back(L("Combined")); + def->enum_labels.push_back(L("Per object")); def->mode = comAdvanced; - def->set_default_value(new ConfigOptionEnum(stCommon)); + def->set_default_value(new ConfigOptionEnum(stCombined)); def = this->add("skirt_loops", coInt); def->label = L("Skirt loops"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 26a6507d030..ca89523c9bd 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -225,7 +225,7 @@ enum TimelapseType : int { }; enum SkirtType { - stCommon, stObject + stCombined, stPerObject }; enum DraftShield {