From 3d511dbbba9aae96d31ecd61276cba2860390549 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Sat, 11 May 2019 23:23:09 +0200 Subject: [PATCH] Make 'nearest' seam position truly near Implement suggestions by @supermerill in issue #1409. This makes a lot more sense than the current implementation which is very similar to 'aligned'. --- src/libslic3r/GCode.cpp | 28 +++++++++++++++++++++------- src/libslic3r/Point.cpp | 5 +++++ src/libslic3r/Point.hpp | 1 + 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 665f42d67cd..74c863fa5d0 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2621,6 +2621,9 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou last_pos.y() += coord_t(3. * m_layer->object()->bounding_box().radius()); last_pos_weight = 5.f; } + else if (seam_position == spNearest) { + last_pos_weight = 5.f; + } // Insert a projection of last_pos into the polygon. size_t last_pos_proj_idx; @@ -2631,6 +2634,14 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // Parametrize the polygon by its length. std::vector lengths = polygon_parameter_by_length(polygon); + float dist_max = 0.1f * lengths.back(); // 5.f * nozzle_dmr + + std::vector distances(polygon.points.size(), 0.f); + if (seam_position == spNearest) { + for (size_t i = 0; i < polygon.points.size(); ++ i) + distances[i] = last_pos_proj.distance_to_squared(polygon.points[i]); + dist_max = *std::max_element(distances.begin(), distances.end()); + } // For each polygon point, store a penalty. // First calculate the angles, store them as penalties. The angles are caluculated over a minimum arm length of nozzle_r. @@ -2661,13 +2672,16 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // Interpolate penalty between maximum and the penalty for a convex vertex. penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * float(PI * 2. / 3.)); } - // Give a negative penalty for points close to the last point or the prefered seam location. - //float dist_to_last_pos_proj = last_pos_proj.distance_to(polygon.points[i]); - float dist_to_last_pos_proj = (i < last_pos_proj_idx) ? - std::min(lengths[last_pos_proj_idx] - lengths[i], lengths.back() - lengths[last_pos_proj_idx] + lengths[i]) : - std::min(lengths[i] - lengths[last_pos_proj_idx], lengths.back() - lengths[i] + lengths[last_pos_proj_idx]); - float dist_max = 0.1f * lengths.back(); // 5.f * nozzle_dmr - penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max); + if (seam_position == spNearest) { + penalty += last_pos_weight * distances[i] / dist_max; + } else { + // Give a negative penalty for points close to the last point or the prefered seam location. + //float dist_to_last_pos_proj = last_pos_proj.distance_to(polygon.points[i]); + float dist_to_last_pos_proj = (i < last_pos_proj_idx) ? + std::min(lengths[last_pos_proj_idx] - lengths[i], lengths.back() - lengths[last_pos_proj_idx] + lengths[i]) : + std::min(lengths[i] - lengths[last_pos_proj_idx], lengths.back() - lengths[i] + lengths[last_pos_proj_idx]); + penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max); + } penalties[i] = std::max(0.f, penalty); } diff --git a/src/libslic3r/Point.cpp b/src/libslic3r/Point.cpp index c2417d0dc97..7e5f9d5644f 100644 --- a/src/libslic3r/Point.cpp +++ b/src/libslic3r/Point.cpp @@ -66,6 +66,11 @@ void Point::rotate(double angle, const Point ¢er) (*this)(1) = (coord_t)round( (double)center(1) + c * dy + s * dx ); } +double Point::distance_to_squared(const Point &point) const +{ + return sqr((*this)(0) - point.x()) + sqr((*this)(1) - point.y()); +} + int Point::nearest_point_index(const Points &points) const { PointConstPtrs p; diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index dced5c02a79..26d70032062 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -117,6 +117,7 @@ class Point : public Vec2crd void rotate(double angle, const Point ¢er); Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; } Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; } + double distance_to_squared(const Point &point) const; int nearest_point_index(const Points &points) const; int nearest_point_index(const PointConstPtrs &points) const; int nearest_point_index(const PointPtrs &points) const;