ENH: filter scarf seam switch result on z dir

Jira: none

Signed-off-by: qing.zhang <qing.zhang@bambulab.com>
Change-Id: I54c25d665efda5bb95afb85366e901c52515ac34
This commit is contained in:
qing.zhang 2024-12-27 12:21:03 +08:00 committed by lane.wei
parent 13aaf3e3e1
commit 3520d9d99e
5 changed files with 111 additions and 17 deletions

View File

@ -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 // find the point of the loop that is closest to the current extruder position
// or randomize if requested // or randomize if requested
Point last_pos = this->last_pos(); Point last_pos = this->last_pos();
bool satisfy_scarf_seam_angle_threshold = false;
if (!m_config.spiral_mode && description == "perimeter") { if (!m_config.spiral_mode && description == "perimeter") {
assert(m_layer != nullptr); assert(m_layer != nullptr);
bool is_outer_wall_first = m_config.wall_sequence == WallSequence::OuterInner; 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 } else
loop.split_at(last_pos, false); 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) { if (enable_seam_slope && m_config.seam_slope_conditional.value) {
//BBS: the seam has been decide, only check the seam position angle //BBS: the seam has been decide, only check the seam position angle
const auto nozzle_diameter = EXTRUDER_CONFIG(nozzle_diameter); enable_seam_slope = satisfy_scarf_seam_angle_threshold;
enable_seam_slope = loop.check_seam_point_angle(m_config.scarf_angle_threshold.value * M_PI / 180.0, nozzle_diameter);
} }
// clip the path to avoid the extruder to get exactly on the first point of the loop; // clip the path to avoid the extruder to get exactly on the first point of the loop;

View File

@ -29,6 +29,7 @@
#include <SVG.hpp> #include <SVG.hpp>
#endif #endif
static const int average_filter_window_size = 5;
namespace Slic3r { namespace Slic3r {
namespace SeamPlacerImpl { 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 // gather vector of all seams on the print_object - pair of layer_index and seam__index within that layer
const std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object[po].layers; const std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object[po].layers;
std::vector<std::pair<size_t, size_t>> seams; std::vector<std::pair<size_t, size_t>> seams = gather_all_seams_of_object(layers);
for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) {
const std::vector<SeamCandidate> &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;
}
}
// sort them before alignment. Alignment is sensitive to initializaion, this gives it better chance to choose something nice // 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<size_t, size_t> &left, const std::pair<size_t, size_t> &right) { std::stable_sort(seams.begin(), seams.end(), [&comparator, &layers](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
@ -1256,6 +1249,92 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl::
fclose(aligns); fclose(aligns);
#endif #endif
} }
std::vector<std::pair<size_t, size_t>> SeamPlacer::gather_all_seams_of_object(const std::vector<PrintObjectSeamData::LayerSeams> &layers)
{
// gather vector of all seams on the print_object - pair of layer_index and seam__index within that layer
std::vector<std::pair<size_t, size_t>> seams;
for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) {
const std::vector<SeamPlacerImpl::SeamCandidate> &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<PrintObjectSeamData::LayerSeams> &layers)
{
std::vector<std::pair<size_t, size_t>> 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<int> seam_index_pos;
std::vector<std::vector<int>> 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<int> 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<void(void)> throw_if_canceled_func) void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_canceled_func)
{ {
@ -1311,13 +1390,21 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: align_seam_points : end"; 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 #ifdef DEBUG_FILES
debug_export_points(m_seam_per_object[po].layers, po->bounding_box(), comparator); debug_export_points(m_seam_per_object[po].layers, po->bounding_box(), comparator);
#endif #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; using namespace SeamPlacerImpl;
const PrintObject *po = layer->object(); 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) { if (const Perimeter &perimeter = layer_perimeters.points[closest_perimeter_point_index].perimeter; perimeter.finalized) {
seam_position = perimeter.final_seam_position; seam_position = perimeter.final_seam_position;
seam_index = perimeter.seam_index; seam_index = perimeter.seam_index;
satisfy_angle_threshold = layer_perimeters.points[seam_index].enable_scarf_seam;
} else { } else {
seam_index = po->config().seam_position == spNearest ? pick_nearest_seam_point_index(layer_perimeters.points, perimeter.start_index, unscaled<float>(last_pos)) : seam_index = po->config().seam_position == spNearest ? pick_nearest_seam_point_index(layer_perimeters.points, perimeter.start_index, unscaled<float>(last_pos)) :
perimeter.seam_index; perimeter.seam_index;
seam_position = layer_perimeters.points[seam_index].position; 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()); Point seam_point = Point::new_scale(seam_position.x(), seam_position.y());

View File

@ -69,7 +69,7 @@ struct Perimeter
struct SeamCandidate struct SeamCandidate
{ {
SeamCandidate(const Vec3f &pos, Perimeter &perimeter, float local_ccw_angle, EnforcedBlockedSeamPoint type) 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; const Vec3f position;
// pointer to Perimeter loop of this point. It is shared across all points of the loop // 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; float local_ccw_angle;
EnforcedBlockedSeamPoint type; EnforcedBlockedSeamPoint type;
bool central_enforcer; // marks this candidate as central point of enforced segment on the perimeter - important for alignment 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 struct SeamCandidateCoordinateFunctor
@ -147,7 +149,7 @@ public:
void init(const Print &print, std::function<void(void)> throw_if_canceled_func); void init(const Print &print, std::function<void(void)> 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: private:
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference); 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 size_t layer_idx,
const float max_distance, const float max_distance,
const SeamPlacerImpl::SeamComparator & comparator) const; const SeamPlacerImpl::SeamComparator & comparator) const;
std::vector<std::pair<size_t, size_t>> gather_all_seams_of_object(const std::vector<PrintObjectSeamData::LayerSeams> &layers);
void filter_scarf_seam_switch_by_angle(const float &angle, std::vector<PrintObjectSeamData::LayerSeams> &layers);
}; };
} // namespace Slic3r } // namespace Slic3r

View File

@ -182,7 +182,7 @@ void Layer::make_perimeters()
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness && config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
&& config.fuzzy_skin_point_distance == other_config.fuzzy_skin_point_distance && config.fuzzy_skin_point_distance == other_config.fuzzy_skin_point_distance
&& config.seam_slope_conditional == other_config.seam_slope_conditional && 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_entire_loop == other_config.seam_slope_entire_loop
&& config.seam_slope_steps == other_config.seam_slope_steps && config.seam_slope_steps == other_config.seam_slope_steps
&& config.seam_slope_inner_walls == other_config.seam_slope_inner_walls) && config.seam_slope_inner_walls == other_config.seam_slope_inner_walls)

View File

@ -875,6 +875,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, interlocking_beam_layer_count)) ((ConfigOptionInt, interlocking_beam_layer_count))
((ConfigOptionInt, interlocking_depth)) ((ConfigOptionInt, interlocking_depth))
((ConfigOptionInt, interlocking_boundary_avoidance)) ((ConfigOptionInt, interlocking_boundary_avoidance))
((ConfigOptionInt, scarf_angle_threshold))
) )
@ -955,7 +956,7 @@ PRINT_CONFIG_CLASS_DEFINE(
// Orca: seam slopes // Orca: seam slopes
//((ConfigOptionEnum<SeamScarfType>, seam_slope_type)) //((ConfigOptionEnum<SeamScarfType>, seam_slope_type))
((ConfigOptionBool, seam_slope_conditional)) ((ConfigOptionBool, seam_slope_conditional))
((ConfigOptionInt, scarf_angle_threshold)) //((ConfigOptionInt, scarf_angle_threshold))
//((ConfigOptionFloatOrPercent, seam_slope_start_height)) //((ConfigOptionFloatOrPercent, seam_slope_start_height))
//((ConfigOptionFloatOrPercent, seam_slope_gap)) //((ConfigOptionFloatOrPercent, seam_slope_gap))
((ConfigOptionBool, seam_slope_entire_loop)) ((ConfigOptionBool, seam_slope_entire_loop))