Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukáš Hejl <hejl.lukas@gmail.com>2022-07-11 12:31:59 +0300
committerLukáš Hejl <hejl.lukas@gmail.com>2022-07-11 12:31:59 +0300
commitd02a0ec1b27b6877fe523b9510f1d45b4a80922b (patch)
tree500bed4bf76fa83f8efc34232fd50d9f1dfd0766
parent38ca763c369a9a95a59c16f31ca5d878de3c2ba2 (diff)
Fix of #8447 - Zero spacing when Clipper Z-coordinate (line width) equaled zero because the resulting path after clipping had vertices from a clipping polygon (which has Z-coordinate equal to zero).
-rw-r--r--src/libslic3r/PerimeterGenerator.cpp47
1 files changed, 46 insertions, 1 deletions
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index be6c120e0..539679e8d 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -21,7 +21,8 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly
for (int i = 0; i < (int)lines.size(); ++i) {
const ThickLine& line = lines[i];
-
+ assert(line.a_width >= SCALED_EPSILON && line.b_width >= SCALED_EPSILON);
+
const coordf_t line_len = line.length();
if (line_len < SCALED_EPSILON) continue;
@@ -356,6 +357,50 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path &subject, con
clipper.Execute(clipType, clipped_polytree, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero);
ClipperLib_Z::PolyTreeToPaths(clipped_polytree, clipped_paths);
+ // Clipped path could contain vertices from the clip with a Z coordinate equal to zero.
+ // For those vertices, we must assign value based on the subject.
+ // This happens only in sporadic cases.
+ for (ClipperLib_Z::Path &path : clipped_paths)
+ for (ClipperLib_Z::IntPoint &c_pt : path)
+ if (c_pt.z() == 0) {
+ // Now we must find the corresponding line on with this point is located and compute line width (Z coordinate).
+ if (subject.size() <= 2)
+ continue;
+
+ const Point pt(c_pt.x(), c_pt.y());
+ Point projected_pt_min;
+ auto it_min = subject.begin();
+ auto dist_sqr_min = std::numeric_limits<double>::max();
+ Point prev(subject.front().x(), subject.front().y());
+ for (auto it = std::next(subject.begin()); it != subject.end(); ++it) {
+ Point curr(it->x(), it->y());
+ Point projected_pt = pt.projection_onto(Line(prev, curr));
+ if (double dist_sqr = (projected_pt - pt).cast<double>().squaredNorm(); dist_sqr < dist_sqr_min) {
+ dist_sqr_min = dist_sqr;
+ projected_pt_min = projected_pt;
+ it_min = std::prev(it);
+ }
+ prev = curr;
+ }
+
+ assert(dist_sqr_min <= SCALED_EPSILON);
+ assert(std::next(it_min) != subject.end());
+
+ const Point pt_a(it_min->x(), it_min->y());
+ const Point pt_b(std::next(it_min)->x(), std::next(it_min)->y());
+ const double line_len = (pt_b - pt_a).cast<double>().norm();
+ const double dist = (projected_pt_min - pt_a).cast<double>().norm();
+ c_pt.z() = coord_t(double(it_min->z()) + (dist / line_len) * double(std::next(it_min)->z() - it_min->z()));
+ }
+
+ assert([&clipped_paths = std::as_const(clipped_paths)]() -> bool {
+ for (const ClipperLib_Z::Path &path : clipped_paths)
+ for (const ClipperLib_Z::IntPoint &pt : path)
+ if (pt.z() <= 0)
+ return false;
+ return true;
+ }());
+
return clipped_paths;
}