From 3520d9d99ebc82459876426431cfc390340646a2 Mon Sep 17 00:00:00 2001 From: "qing.zhang" Date: Fri, 27 Dec 2024 12:21:03 +0800 Subject: [PATCH] ENH: filter scarf seam switch result on z dir Jira: none Signed-off-by: qing.zhang Change-Id: I54c25d665efda5bb95afb85366e901c52515ac34 --- src/libslic3r/GCode.cpp | 6 +- src/libslic3r/GCode/SeamPlacer.cpp | 109 ++++++++++++++++++++++++++--- src/libslic3r/GCode/SeamPlacer.hpp | 8 ++- src/libslic3r/Layer.cpp | 2 +- src/libslic3r/PrintConfig.hpp | 3 +- 5 files changed, 111 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index d6d0e3d8e..65b02c902 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4539,10 +4539,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // find the point of the loop that is closest to the current extruder position // or randomize if requested Point last_pos = this->last_pos(); + bool satisfy_scarf_seam_angle_threshold = false; if (!m_config.spiral_mode && description == "perimeter") { assert(m_layer != nullptr); bool is_outer_wall_first = m_config.wall_sequence == WallSequence::OuterInner; - m_seam_placer.place_seam(m_layer, loop, is_outer_wall_first, this->last_pos()); + m_seam_placer.place_seam(m_layer, loop, is_outer_wall_first, this->last_pos(), satisfy_scarf_seam_angle_threshold); } else loop.split_at(last_pos, false); @@ -4557,8 +4558,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou if (enable_seam_slope && m_config.seam_slope_conditional.value) { //BBS: the seam has been decide, only check the seam position angle - const auto nozzle_diameter = EXTRUDER_CONFIG(nozzle_diameter); - enable_seam_slope = loop.check_seam_point_angle(m_config.scarf_angle_threshold.value * M_PI / 180.0, nozzle_diameter); + enable_seam_slope = satisfy_scarf_seam_angle_threshold; } // clip the path to avoid the extruder to get exactly on the first point of the loop; diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 7d8bdf3e8..afedcf616 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -29,6 +29,7 @@ #include #endif +static const int average_filter_window_size = 5; namespace Slic3r { namespace SeamPlacerImpl { @@ -1125,15 +1126,7 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl:: // gather vector of all seams on the print_object - pair of layer_index and seam__index within that layer const std::vector &layers = m_seam_per_object[po].layers; - std::vector> seams; - for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { - const std::vector &layer_perimeter_points = layers[layer_idx].points; - size_t current_point_index = 0; - while (current_point_index < layer_perimeter_points.size()) { - seams.emplace_back(layer_idx, layer_perimeter_points[current_point_index].perimeter.seam_index); - current_point_index = layer_perimeter_points[current_point_index].perimeter.end_index; - } - } + std::vector> seams = gather_all_seams_of_object(layers); // sort them before alignment. Alignment is sensitive to initializaion, this gives it better chance to choose something nice std::stable_sort(seams.begin(), seams.end(), [&comparator, &layers](const std::pair &left, const std::pair &right) { @@ -1256,6 +1249,92 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl:: fclose(aligns); #endif } +std::vector> SeamPlacer::gather_all_seams_of_object(const std::vector &layers) +{ + // gather vector of all seams on the print_object - pair of layer_index and seam__index within that layer + std::vector> seams; + for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { + const std::vector &layer_perimeter_points = layers[layer_idx].points; + size_t current_point_index = 0; + while (current_point_index < layer_perimeter_points.size()) { + seams.emplace_back(layer_idx, layer_perimeter_points[current_point_index].perimeter.seam_index); + current_point_index = layer_perimeter_points[current_point_index].perimeter.end_index; + } + } + return seams; +} + +void SeamPlacer::filter_scarf_seam_switch_by_angle(const float &angle, std::vector &layers) +{ + std::vector> seams = gather_all_seams_of_object(layers); + + float max_distance = SeamPlacer::seam_align_tolerable_dist_factor * layers[seams[0].first].points[seams[0].second].perimeter.flow_width; + + std::vector seam_index_pos; + std::vector> seam_index_group; + //get each seam line group + for (size_t seam_idx = 0; seam_idx < seams.size(); seam_idx++) { + if (layers[seams[seam_idx].first].points[seams[seam_idx].second].is_grouped) + continue; + + layers[seams[seam_idx].first].points[seams[seam_idx].second].is_grouped = true; + seam_index_pos.push_back(seam_idx); + size_t prev_idx = seam_idx; + size_t next_seam = seam_idx + 1; + for (; next_seam < seams.size(); next_seam++) { + if (layers[seams[next_seam].first].points[seams[next_seam].second].is_grouped || seams[prev_idx].first == seams[next_seam].first) + continue; + + // if the seam is not continous with prev layer, break + if (seams[prev_idx].first + 1 != seams[next_seam].first) + break; + + if ((layers[seams[prev_idx].first].points[seams[prev_idx].second].position - layers[seams[next_seam].first].points[seams[next_seam].second].position).norm() <= + max_distance) { + + layers[seams[next_seam].first].points[seams[next_seam].second].is_grouped = true; + + float next_seam_angle = layers[seams[next_seam].first].points[seams[next_seam].second].local_ccw_angle; + + if (next_seam_angle < 0) + next_seam_angle *= -1; + + if (PI - angle > next_seam_angle) { + layers[seams[next_seam].first].points[seams[next_seam].second].enable_scarf_seam = true; + } + + prev_idx = next_seam; + seam_index_pos.push_back(next_seam); + } + } + + seam_index_group.emplace_back(std::move(seam_index_pos)); + seam_index_pos.clear(); + } + + // filter + { + for (size_t k = 0; k < seam_index_group.size(); k++) { + std::vector seam_group = seam_index_group[k]; + if (seam_group.size() <= 1) continue; + int half_window = average_filter_window_size / 2; + // average filter + for (size_t idx = 0; idx < seam_group.size(); idx++) { + double sum = 0; + int count = 0; + + for (int window_idx = -half_window; window_idx <= half_window; ++window_idx) { + int index = idx + window_idx; + if (index >= 0 && index < seam_group.size()) { + sum += layers[seams[seam_group[index]].first].points[seams[seam_group[index]].second].enable_scarf_seam ? 1 : 0; + count++; + } + } + layers[seams[seam_group[idx]].first].points[seams[seam_group[idx]].second].enable_scarf_seam = (sum / count) >= 0.5 ? true : false; + } + } + } +} void SeamPlacer::init(const Print &print, std::function throw_if_canceled_func) { @@ -1311,13 +1390,21 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: align_seam_points : end"; } + //check if enable scarf seam for each seam point + if (configured_seam_preference == spAligned || configured_seam_preference == spRear) { + BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: check_enable_scarf_seam : start"; + //find seam lines and get angle imformation + filter_scarf_seam_switch_by_angle(po->config().scarf_angle_threshold / 180.0f * PI, m_seam_per_object[po].layers); + //filter scarf seam setting with gaussian filter + BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: check_enable_scarf_seam : end"; + } #ifdef DEBUG_FILES debug_export_points(m_seam_per_object[po].layers, po->bounding_box(), comparator); #endif } } -void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const +void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos, bool &satisfy_angle_threshold) const { using namespace SeamPlacerImpl; const PrintObject *po = layer->object(); @@ -1343,10 +1430,12 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern if (const Perimeter &perimeter = layer_perimeters.points[closest_perimeter_point_index].perimeter; perimeter.finalized) { seam_position = perimeter.final_seam_position; seam_index = perimeter.seam_index; + satisfy_angle_threshold = layer_perimeters.points[seam_index].enable_scarf_seam; } else { seam_index = po->config().seam_position == spNearest ? pick_nearest_seam_point_index(layer_perimeters.points, perimeter.start_index, unscaled(last_pos)) : perimeter.seam_index; seam_position = layer_perimeters.points[seam_index].position; + satisfy_angle_threshold = layer_perimeters.points[seam_index].enable_scarf_seam; } Point seam_point = Point::new_scale(seam_position.x(), seam_position.y()); diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 0c431202e..aabc64967 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -69,7 +69,7 @@ struct Perimeter struct SeamCandidate { SeamCandidate(const Vec3f &pos, Perimeter &perimeter, float local_ccw_angle, EnforcedBlockedSeamPoint type) - : position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(local_ccw_angle), type(type), central_enforcer(false) + : position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(local_ccw_angle), type(type), central_enforcer(false), enable_scarf_seam(false),is_grouped(false) {} const Vec3f position; // pointer to Perimeter loop of this point. It is shared across all points of the loop @@ -82,6 +82,8 @@ struct SeamCandidate float local_ccw_angle; EnforcedBlockedSeamPoint type; bool central_enforcer; // marks this candidate as central point of enforced segment on the perimeter - important for alignment + bool enable_scarf_seam; // marks this candidate as a candidate for scarf seam + bool is_grouped; }; struct SeamCandidateCoordinateFunctor @@ -147,7 +149,7 @@ public: void init(const Print &print, std::function throw_if_canceled_func); - void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const; + void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos, bool &satisfy_angle_threshold) const; private: void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference); @@ -160,6 +162,8 @@ private: const size_t layer_idx, const float max_distance, const SeamPlacerImpl::SeamComparator & comparator) const; + std::vector> gather_all_seams_of_object(const std::vector &layers); + void filter_scarf_seam_switch_by_angle(const float &angle, std::vector &layers); }; } // namespace Slic3r diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 761614831..2c2802033 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -182,7 +182,7 @@ void Layer::make_perimeters() && config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness && config.fuzzy_skin_point_distance == other_config.fuzzy_skin_point_distance && config.seam_slope_conditional == other_config.seam_slope_conditional - && config.scarf_angle_threshold == other_config.scarf_angle_threshold + //&& config.scarf_angle_threshold == other_config.scarf_angle_threshold && config.seam_slope_entire_loop == other_config.seam_slope_entire_loop && config.seam_slope_steps == other_config.seam_slope_steps && config.seam_slope_inner_walls == other_config.seam_slope_inner_walls) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 52a4a0ae9..c0f639a4e 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -875,6 +875,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionInt, interlocking_beam_layer_count)) ((ConfigOptionInt, interlocking_depth)) ((ConfigOptionInt, interlocking_boundary_avoidance)) + ((ConfigOptionInt, scarf_angle_threshold)) ) @@ -955,7 +956,7 @@ PRINT_CONFIG_CLASS_DEFINE( // Orca: seam slopes //((ConfigOptionEnum, seam_slope_type)) ((ConfigOptionBool, seam_slope_conditional)) - ((ConfigOptionInt, scarf_angle_threshold)) + //((ConfigOptionInt, scarf_angle_threshold)) //((ConfigOptionFloatOrPercent, seam_slope_start_height)) //((ConfigOptionFloatOrPercent, seam_slope_gap)) ((ConfigOptionBool, seam_slope_entire_loop))