From 689f923aaf86785e75034a963fe34f51225cd940 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 11 Jan 2022 16:35:34 +0100 Subject: [PATCH 1/5] Seam fixes: - turned off staggering - fixed a bug in one of the heuristics (distance between indices measured instead of actual distance) --- src/libslic3r/GCode/SeamPlacer.cpp | 108 +++++++++++++++++------------ 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index f74775a9a9..90dba7431d 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -327,7 +327,7 @@ void SeamPlacer::plan_perimeters(const std::vector perim void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter, const EdgeGrid::Grid* lower_layer_edge_grid) { - const double seam_offset = nozzle_diameter; + // const double seam_offset = nozzle_diameter; Point seam = last_pos; if (! m_plan.empty() && m_plan_idx < m_plan.size()) { @@ -339,15 +339,18 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext // far from each other. if ((seam.cast() - last_pos.cast()).squaredNorm() > std::pow(scale_(5.*nozzle_diameter), 2.)) seam = this->calculate_seam(*m_plan[m_plan_idx].layer, m_plan[m_plan_idx].seam_position, loop, nozzle_diameter, - m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos); + m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos); } else if (! external_first) { // Internal perimeter printed before the external. // First get list of external seams. std::vector ext_seams; + size_t external_cnt = 0; for (size_t i = 0; i < m_plan.size(); ++i) { - if (m_plan[i].external) + if (m_plan[i].external) { ext_seams.emplace_back(i); + ++external_cnt; + } } if (! ext_seams.empty()) { @@ -374,32 +377,41 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext } // Only accept seam that is reasonably close. - double limit_dist_sqr = std::pow(double(scale_((ext_seam_idx - m_plan_idx) * nozzle_diameter * 2.)), 2.); - if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) { - // Now find a projection of the external seam - const Lines& lines = lines_vect[path_idx]; - Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]); - double dist = (closest.cast() - lines[line_idx].b.cast()).norm(); + if (ext_seam_idx != size_t(-1)) { + // How many nozzle diameters is considered "close"? + const double nozzle_d_limit = 2. * (1. + m_plan.size() / external_cnt); + const double limit_dist_sqr = double(scale_(scale_((unscale(m_plan[ext_seam_idx].pt) - unscale(m_plan[m_plan_idx].pt)).squaredNorm() * std::pow(nozzle_d_limit * nozzle_diameter, 2.)))); - // And walk along the perimeter until we make enough space for - // seams of all perimeters beforethe external one. - double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset); - double last_offset = offset; - offset -= dist; - const Point* a = &closest; - const Point* b = &lines[line_idx].b; - while (++line_idx < int(lines.size()) && offset > 0.) { - last_offset = offset; - offset -= lines[line_idx].length(); - a = &lines[line_idx].a; - b = &lines[line_idx].b; + if (min_dist_sqr < limit_dist_sqr) { + // Now find a projection of the external seam + const Lines& lines = lines_vect[path_idx]; + Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]); + +// This code does staggering of internal perimeters, turned off for now. +// +// double dist = (closest.cast() - lines[line_idx].b.cast()).norm(); +// +// // And walk along the perimeter until we make enough space for +// // seams of all perimeters beforethe external one. +// double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset); +// double last_offset = offset; +// offset -= dist; +// const Point* a = &closest; +// const Point* b = &lines[line_idx].b; +// while (++line_idx < int(lines.size()) && offset > 0.) { +// last_offset = offset; +// offset -= lines[line_idx].length(); +// a = &lines[line_idx].a; +// b = &lines[line_idx].b; +// } +// +// // We have walked far enough, too far maybe. Interpolate on the +// // last segment to find the end precisely. +// offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around") +// double ratio = last_offset / (last_offset - offset); +// seam = (a->cast() + ((b->cast() - a->cast()) * ratio)).cast(); + seam = closest; } - - // We have walked far enough, too far maybe. Interpolate on the - // last segment to find the end precisely. - offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around") - double ratio = last_offset / (last_offset - offset); - seam = (a->cast() + ((b->cast() - a->cast()) * ratio)).cast(); } } } @@ -408,6 +420,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated) seam = m_plan[m_plan_idx - 1].pt; } + m_plan[m_plan_idx].pt = seam; } @@ -417,26 +430,29 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext loop.split_at(seam, true); if (external_first && m_plan_idx+1 1) { - const ExtrusionPath& last = loop.paths.back(); - auto it = last.polyline.points.crbegin() + 1; - for (; it != last.polyline.points.crend(); ++it) { - running_sqr += (it->cast() - (it - 1)->cast()).squaredNorm(); - if (running_sqr > dist_sqr) - break; - running_sqr_last = running_sqr; - } - if (running_sqr <= dist_sqr) - it = last.polyline.points.crend() - 1; - // Now interpolate. - double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last)); - m_plan[m_plan_idx + 1].pt = ((it - 1)->cast() + (it->cast() - (it - 1)->cast()) * std::min(ratio, 1.)).cast(); +// This code does staggering of internal perimeters, turned off for now. +// Next perimeter should start near this one. +// const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.); +// double running_sqr = 0.; +// double running_sqr_last = 0.; +// if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) { +// const ExtrusionPath& last = loop.paths.back(); +// auto it = last.polyline.points.crbegin() + 1; +// for (; it != last.polyline.points.crend(); ++it) { +// running_sqr += (it->cast() - (it - 1)->cast()).squaredNorm(); +// if (running_sqr > dist_sqr) +// break; +// running_sqr_last = running_sqr; +// } +// if (running_sqr <= dist_sqr) +// it = last.polyline.points.crend() - 1; +// // Now interpolate. +// double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last)); +// m_plan[m_plan_idx + 1].pt = ((it - 1)->cast() + (it->cast() - (it - 1)->cast()) * std::min(ratio, 1.)).cast(); +// m_plan[m_plan_idx + 1].precalculated = true; + m_plan[m_plan_idx + 1].pt = m_plan[m_plan_idx].pt; m_plan[m_plan_idx + 1].precalculated = true; - } +// } } ++m_plan_idx; From 3cc907b361ead9ea289203fda62a837b7089370a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 12 Jan 2022 22:13:45 +0100 Subject: [PATCH 2/5] Seams: changed the overhang penalty calculation, it might have been too much compared to the rest Also reduced penalty for flat surfaces a bit, based on some testing (hopefully it is not overfitting on the test models) --- src/libslic3r/GCode/SeamPlacer.cpp | 49 +++++++++++++++++------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 90dba7431d..cef8ce8a37 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -23,28 +23,35 @@ static constexpr float ENFORCER_CENTER_PENALTY = -10.f; - +// This function was introduced in 2016 to assign penalties to overhangs. +// LukasM thinks that it discriminated a bit too much, so especially external +// seams were than placed in funny places (non-overhangs were preferred too much). +// He implemented his own version (below) which applies fixed penalty for really big overlaps. +// static float extrudate_overlap_penalty(float nozzle_r, float weight_zero, float overlap_distance) +// { +// // The extrudate is not fully supported by the lower layer. Fit a polynomial penalty curve. +// // Solved by sympy package: +// /* +// from sympy import * +// (x,a,b,c,d,r,z)=symbols('x a b c d r z') +// p = a + b*x + c*x*x + d*x*x*x +// p2 = p.subs(solve([p.subs(x, -r), p.diff(x).subs(x, -r), p.diff(x,x).subs(x, -r), p.subs(x, 0)-z], [a, b, c, d])) +// from sympy.plotting import plot +// plot(p2.subs(r,0.2).subs(z,1.), (x, -1, 3), adaptive=False, nb_of_points=400) +// */ +// if (overlap_distance < - nozzle_r) { +// // The extrudate is fully supported by the lower layer. This is the ideal case, therefore zero penalty. +// return 0.f; +// } else { +// float x = overlap_distance / nozzle_r; +// float x2 = x * x; +// float x3 = x2 * x; +// return weight_zero * (1.f + 3.f * x + 3.f * x2 + x3); +// } +// } static float extrudate_overlap_penalty(float nozzle_r, float weight_zero, float overlap_distance) { - // The extrudate is not fully supported by the lower layer. Fit a polynomial penalty curve. - // Solved by sympy package: -/* -from sympy import * -(x,a,b,c,d,r,z)=symbols('x a b c d r z') -p = a + b*x + c*x*x + d*x*x*x -p2 = p.subs(solve([p.subs(x, -r), p.diff(x).subs(x, -r), p.diff(x,x).subs(x, -r), p.subs(x, 0)-z], [a, b, c, d])) -from sympy.plotting import plot -plot(p2.subs(r,0.2).subs(z,1.), (x, -1, 3), adaptive=False, nb_of_points=400) -*/ - if (overlap_distance < - nozzle_r) { - // The extrudate is fully supported by the lower layer. This is the ideal case, therefore zero penalty. - return 0.f; - } else { - float x = overlap_distance / nozzle_r; - float x2 = x * x; - float x3 = x2 * x; - return weight_zero * (1.f + 3.f * x + 3.f * x2 + x3); - } + return overlap_distance > nozzle_r ? weight_zero : 0.f; } @@ -535,7 +542,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos std::vector penalties = polygon_angles_at_vertices(polygon, lengths, float(nozzle_r)); // No penalty for reflex points, slight penalty for convex points, high penalty for flat surfaces. const float penaltyConvexVertex = 1.f; - const float penaltyFlatSurface = 5.f; + const float penaltyFlatSurface = 3.f; const float penaltyOverhangHalf = 10.f; // Penalty for visible seams. for (size_t i = 0; i < polygon.points.size(); ++ i) { From 9e2379513704891410c1b93af0a272995dccc793 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 13 Jan 2022 21:37:26 +0100 Subject: [PATCH 3/5] Trying to make the inner seam placement a bit more intelligent: place external seams first, then place inner seam using the normal seam placement function, only limited to vicinity of the closest external seam. --- src/libslic3r/GCode/SeamPlacer.cpp | 186 ++++++++++++++++------------- src/libslic3r/GCode/SeamPlacer.hpp | 2 +- 2 files changed, 101 insertions(+), 87 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index cef8ce8a37..218ced89cb 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -320,12 +320,12 @@ void SeamPlacer::plan_perimeters(const std::vector perim if (perimeters[i]->role() == erExternalPerimeter && perimeters[i]->is_loop()) { last_pos = this->calculate_seam( layer, seam_position, *dynamic_cast(perimeters[i]), nozzle_dmr, - po, lower_layer_edge_grid, last_pos); + po, lower_layer_edge_grid, last_pos, false); m_plan[i].external = true; - m_plan[i].seam_position = seam_position; - m_plan[i].layer = &layer; - m_plan[i].po = po; } + m_plan[i].seam_position = seam_position; + m_plan[i].layer = &layer; + m_plan[i].po = po; m_plan[i].pt = last_pos; } } @@ -346,86 +346,98 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext // far from each other. if ((seam.cast() - last_pos.cast()).squaredNorm() > std::pow(scale_(5.*nozzle_diameter), 2.)) seam = this->calculate_seam(*m_plan[m_plan_idx].layer, m_plan[m_plan_idx].seam_position, loop, nozzle_diameter, - m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos); - } - else if (! external_first) { - // Internal perimeter printed before the external. - // First get list of external seams. - std::vector ext_seams; - size_t external_cnt = 0; - for (size_t i = 0; i < m_plan.size(); ++i) { - if (m_plan[i].external) { - ext_seams.emplace_back(i); - ++external_cnt; - } - } + m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos, false); - if (! ext_seams.empty()) { - // First find the line segment closest to an external seam: - int path_idx = 0; - int line_idx = 0; - size_t ext_seam_idx = size_t(-1); - double min_dist_sqr = std::numeric_limits::max(); - std::vector lines_vect; - for (int i = 0; i < int(loop.paths.size()); ++i) { - lines_vect.emplace_back(loop.paths[i].polyline.lines()); - const Lines& lines = lines_vect.back(); - for (int j = 0; j < int(lines.size()); ++j) { - for (size_t k : ext_seams) { - double d_sqr = lines[j].distance_to_squared(m_plan[k].pt); - if (d_sqr < min_dist_sqr) { - path_idx = i; - line_idx = j; - ext_seam_idx = k; - min_dist_sqr = d_sqr; + if (m_plan[m_plan_idx].seam_position == spAligned) + m_seam_history.add_seam(m_plan[m_plan_idx].po, m_plan[m_plan_idx].pt, loop.polygon().bounding_box()); + } + else { + if (!external_first) { + // Internal perimeter printed before the external. + // First get list of external seams. + std::vector ext_seams; + size_t external_cnt = 0; + for (size_t i = 0; i < m_plan.size(); ++i) { + if (m_plan[i].external) { + ext_seams.emplace_back(i); + ++external_cnt; + } + } + + if (!ext_seams.empty()) { + // First find the line segment closest to an external seam: + int path_idx = 0; + int line_idx = 0; + size_t ext_seam_idx = size_t(-1); + double min_dist_sqr = std::numeric_limits::max(); + std::vector lines_vect; + for (int i = 0; i < int(loop.paths.size()); ++i) { + lines_vect.emplace_back(loop.paths[i].polyline.lines()); + const Lines& lines = lines_vect.back(); + for (int j = 0; j < int(lines.size()); ++j) { + for (size_t k : ext_seams) { + double d_sqr = lines[j].distance_to_squared(m_plan[k].pt); + if (d_sqr < min_dist_sqr) { + path_idx = i; + line_idx = j; + ext_seam_idx = k; + min_dist_sqr = d_sqr; + } } } } - } - // Only accept seam that is reasonably close. - if (ext_seam_idx != size_t(-1)) { - // How many nozzle diameters is considered "close"? - const double nozzle_d_limit = 2. * (1. + m_plan.size() / external_cnt); - const double limit_dist_sqr = double(scale_(scale_((unscale(m_plan[ext_seam_idx].pt) - unscale(m_plan[m_plan_idx].pt)).squaredNorm() * std::pow(nozzle_d_limit * nozzle_diameter, 2.)))); + // Only accept seam that is reasonably close. + if (ext_seam_idx != size_t(-1)) { + // How many nozzle diameters is considered "close"? + const double nozzle_d_limit = 2. * (1. + m_plan.size() / external_cnt); + const double limit_dist_sqr = double(scale_(scale_((unscale(m_plan[ext_seam_idx].pt) - unscale(m_plan[m_plan_idx].pt)).squaredNorm() * std::pow(nozzle_d_limit * nozzle_diameter, 2.)))); - if (min_dist_sqr < limit_dist_sqr) { - // Now find a projection of the external seam - const Lines& lines = lines_vect[path_idx]; - Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]); + if (min_dist_sqr < limit_dist_sqr) { + // Now find a projection of the external seam + //const Lines& lines = lines_vect[path_idx]; + //Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]); -// This code does staggering of internal perimeters, turned off for now. -// -// double dist = (closest.cast() - lines[line_idx].b.cast()).norm(); -// -// // And walk along the perimeter until we make enough space for -// // seams of all perimeters beforethe external one. -// double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset); -// double last_offset = offset; -// offset -= dist; -// const Point* a = &closest; -// const Point* b = &lines[line_idx].b; -// while (++line_idx < int(lines.size()) && offset > 0.) { -// last_offset = offset; -// offset -= lines[line_idx].length(); -// a = &lines[line_idx].a; -// b = &lines[line_idx].b; -// } -// -// // We have walked far enough, too far maybe. Interpolate on the -// // last segment to find the end precisely. -// offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around") -// double ratio = last_offset / (last_offset - offset); -// seam = (a->cast() + ((b->cast() - a->cast()) * ratio)).cast(); - seam = closest; + // This code does staggering of internal perimeters, turned off for now. + // + // double dist = (closest.cast() - lines[line_idx].b.cast()).norm(); + // + // // And walk along the perimeter until we make enough space for + // // seams of all perimeters beforethe external one. + // double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset); + // double last_offset = offset; + // offset -= dist; + // const Point* a = &closest; + // const Point* b = &lines[line_idx].b; + // while (++line_idx < int(lines.size()) && offset > 0.) { + // last_offset = offset; + // offset -= lines[line_idx].length(); + // a = &lines[line_idx].a; + // b = &lines[line_idx].b; + // } + // + // // We have walked far enough, too far maybe. Interpolate on the + // // last segment to find the end precisely. + // offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around") + // double ratio = last_offset / (last_offset - offset); + // seam = (a->cast() + ((b->cast() - a->cast()) * ratio)).cast(); + seam = m_plan[ext_seam_idx].pt; + } } } } - } - else { - // We should have a candidate ready from before. If not, use last_pos. - if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated) - seam = m_plan[m_plan_idx - 1].pt; + else { + // We should have a candidate ready from before. If not, use last_pos. + if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated) + seam = m_plan[m_plan_idx - 1].pt; + } + + // seam now contains a hot candidate for internal seam. Use it unless there is a sharp corner nearby. + // We will call the normal seam planning function, pretending that we are currently at the candidate point + // and set to spNearest. If the ideal seam it finds is close to current candidate, use it. + // This is to prevent having seams very close to corners, just because of external seam position. + seam = calculate_seam(*m_plan[m_plan_idx].layer, spNearest, loop, nozzle_diameter, + m_plan[m_plan_idx].po, lower_layer_edge_grid, seam, true); } m_plan[m_plan_idx].pt = seam; } @@ -466,15 +478,13 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext } -// Returns a seam for an EXTERNAL perimeter. +// Returns "best" seam for a given perimeter. Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_position, const ExtrusionLoop& loop, coordf_t nozzle_dmr, const PrintObject* po, - const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos) + const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos, bool prefer_nearest) { - assert(loop.role() == erExternalPerimeter); Polygon polygon = loop.polygon(); bool was_clockwise = polygon.make_counter_clockwise(); - BoundingBox polygon_bb = polygon.bounding_box(); const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5); size_t po_idx = std::find(m_po_list.begin(), m_po_list.end(), po) - m_po_list.begin(); @@ -498,7 +508,9 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos assert(layer_idx < po->layer_count()); - if (this->is_custom_seam_on_layer(layer_idx, po_idx)) { + const bool custom_seam = loop.role() == erExternalPerimeter && this->is_custom_seam_on_layer(layer_idx, po_idx); + + if (custom_seam) { // Seam enf/blockers can begin and end in between the original vertices. // Let add extra points in between and update the leghths. polygon.densify(MINIMAL_POLYGON_SIDE); @@ -511,7 +523,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos if (seam_position == spAligned) { // Seam is aligned to the seam at the preceding layer. if (po != nullptr) { - std::optional pos = m_seam_history.get_last_seam(m_po_list[po_idx], layer_idx, polygon_bb); + std::optional pos = m_seam_history.get_last_seam(m_po_list[po_idx], layer_idx, loop.polygon().bounding_box()); if (pos.has_value()) { last_pos = *pos; last_pos_weight = is_custom_enforcer_on_layer(layer_idx, po_idx) ? 0.f : 1.f; @@ -571,8 +583,12 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos float dist_max = 0.1f * lengths.back(); // 5.f * nozzle_dmr penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max); penalties[i] = std::max(0.f, penalty); + if (prefer_nearest) { + // This hack limits the search around the nearest position projection. + penalties[i] += dist_to_last_pos_proj > 10.f * nozzle_r ? 100.f : 0.f; + } } - + // Penalty for overhangs. if (lower_layer_edge_grid) { // Use the edge grid distance field structure over the lower layer to calculate overhangs. @@ -591,10 +607,11 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos penalties[i] += extrudate_overlap_penalty(float(nozzle_r), penaltyOverhangHalf, float(dist)); } } - + // Custom seam. Huge (negative) constant penalty is applied inside // blockers (enforcers) to rule out points that should not win. - this->apply_custom_seam(polygon, po_idx, penalties, lengths, layer_idx, seam_position); + if (custom_seam) + this->apply_custom_seam(polygon, po_idx, penalties, lengths, layer_idx, seam_position); // Find a point with a minimum penalty. size_t idx_min = std::min_element(penalties.begin(), penalties.end()) - penalties.begin(); @@ -615,9 +632,6 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos } } - if (seam_position == spAligned) - m_seam_history.add_seam(po, polygon.points[idx_min], polygon_bb); - // Export the contour into a SVG file. #if 0 diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 57c3532c3b..0d72939b2f 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -65,7 +65,7 @@ private: // When given an external perimeter (!), returns the seam. Point calculate_seam(const Layer& layer, const SeamPosition seam_position, const ExtrusionLoop& loop, coordf_t nozzle_dmr, const PrintObject* po, - const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos); + const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos, bool prefer_nearest); struct CustomTrianglesPerLayer { Polygons polys; From b86effada01fc82be021195a26fd1135aae7cdf9 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 13 Jan 2022 21:52:54 +0100 Subject: [PATCH 4/5] Fixed one possible crash and a warning --- src/libslic3r/GCode/SeamPlacer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 218ced89cb..eee7162e11 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -366,8 +366,8 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext if (!ext_seams.empty()) { // First find the line segment closest to an external seam: - int path_idx = 0; - int line_idx = 0; + //int path_idx = 0; + //int line_idx = 0; size_t ext_seam_idx = size_t(-1); double min_dist_sqr = std::numeric_limits::max(); std::vector lines_vect; @@ -378,8 +378,8 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext for (size_t k : ext_seams) { double d_sqr = lines[j].distance_to_squared(m_plan[k].pt); if (d_sqr < min_dist_sqr) { - path_idx = i; - line_idx = j; + //path_idx = i; + //line_idx = j; ext_seam_idx = k; min_dist_sqr = d_sqr; } @@ -495,7 +495,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos if (po == m_last_po && layer.print_z == m_last_print_z) layer_po = m_last_layer_po; else { - layer_po = po->get_layer_at_printz(layer.print_z); + layer_po = po ? po->get_layer_at_printz(layer.print_z) : nullptr; m_last_po = po; m_last_print_z = layer.print_z; m_last_layer_po = layer_po; From ed508d49d63ec367350fd6f47491dca7dddec04f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 20 Jan 2022 10:24:52 +0100 Subject: [PATCH 5/5] Changed the inner seam replacement threshold to 3*nozzle_diameter --- src/libslic3r/GCode/SeamPlacer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index eee7162e11..bcd238a728 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -585,7 +585,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos penalties[i] = std::max(0.f, penalty); if (prefer_nearest) { // This hack limits the search around the nearest position projection. - penalties[i] += dist_to_last_pos_proj > 10.f * nozzle_r ? 100.f : 0.f; + penalties[i] += dist_to_last_pos_proj > 6.f * nozzle_r ? 100.f : 0.f; } }