diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp index 0e7a50e49..bebf14b96 100644 --- a/xs/src/libslic3r/ExPolygon.cpp +++ b/xs/src/libslic3r/ExPolygon.cpp @@ -129,6 +129,14 @@ ExPolygon::has_boundary_point(const Point &point) const return false; } +void +ExPolygon::remove_colinear_points() +{ + this->contour.remove_collinear_points(); + for (Polygon &p : this->holes) + p.remove_collinear_points(); +} + void ExPolygon::remove_vertical_collinear_points(coord_t tolerance) { diff --git a/xs/src/libslic3r/ExPolygon.hpp b/xs/src/libslic3r/ExPolygon.hpp index fcdabc272..f7e03ed4a 100644 --- a/xs/src/libslic3r/ExPolygon.hpp +++ b/xs/src/libslic3r/ExPolygon.hpp @@ -37,6 +37,8 @@ class ExPolygon bool contains_b(const Point &point) const; bool has_boundary_point(const Point &point) const; BoundingBox bounding_box() const { return this->contour.bounding_box(); }; + /// removes collinear points within SCALED_EPSILON tolerance + void remove_colinear_points(); void remove_vertical_collinear_points(coord_t tolerance); void simplify_p(double tolerance, Polygons* polygons) const; Polygons simplify_p(double tolerance) const; diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp index a3bebb034..f3caaa8ff 100644 --- a/xs/src/libslic3r/Polygon.cpp +++ b/xs/src/libslic3r/Polygon.cpp @@ -156,6 +156,42 @@ Polygon::douglas_peucker(double tolerance) this->points.pop_back(); } +void +Polygon::remove_collinear_points() +{ + if(this->points.size() > 2) { + // copy points and append both 1 and last point in place to cover the boundaries + Points pp; + pp.reserve(this->points.size()+2); + pp.push_back(this->points.back()); + pp.insert(pp.begin()+1, this->points.begin(), this->points.end()); + pp.push_back(this->points.front()); + // delete old points vector. Will be re-filled in the loop + this->points.clear(); + + size_t i = 0; + size_t k = 0; + while (i < pp.size()-2) { + k = i+1; + const Point &p1 = pp[i]; + while (k < pp.size()-1) { + const Point &p2 = pp[k]; + const Point &p3 = pp[k+1]; + Line l(p1, p3); + if(l.distance_to(p2) < SCALED_EPSILON) { + k++; + } else { + if(i > 0) this->points.push_back(p1); // implicitly removes the first point we appended above + i = k; + break; + } + } + if(k > pp.size()-2) break; // all remaining points are collinear and can be skipped + } + this->points.push_back(pp[i]); + } +} + void Polygon::remove_vertical_collinear_points(coord_t tolerance) { diff --git a/xs/src/libslic3r/Polygon.hpp b/xs/src/libslic3r/Polygon.hpp index 2e7985d0d..83efa7806 100644 --- a/xs/src/libslic3r/Polygon.hpp +++ b/xs/src/libslic3r/Polygon.hpp @@ -41,6 +41,8 @@ class Polygon : public MultiPoint { // Tested by counting intersections along a horizontal line. bool contains(const Point &point) const; void douglas_peucker(double tolerance); + /// removes collinear points within SCALED_EPSILON tolerance + void remove_collinear_points(); void remove_vertical_collinear_points(coord_t tolerance); Polygons simplify(double tolerance) const; void simplify(double tolerance, Polygons &polygons) const; diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index d66e68b8d..6b68d3103 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -842,6 +842,19 @@ void PrintObject::_slice() } } + // remove collinear points from slice polygons (artifacts from stl-triangulation) + std::queue queue; + for (Layer* layer : this->layers) { + for (LayerRegion* layerm : layer->regions) { + queue.push(&layerm->slices); + } + } + parallelize( + queue, + boost::bind(&Slic3r::SurfaceCollection::remove_collinear_points, _1), + this->_print->config.threads.value + ); + // remove last layer(s) if empty bool done = false; while (! this->layers.empty()) { diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp index 8d9a01744..6e4a15927 100644 --- a/xs/src/libslic3r/SurfaceCollection.cpp +++ b/xs/src/libslic3r/SurfaceCollection.cpp @@ -39,6 +39,14 @@ SurfaceCollection::simplify(double tolerance) this->surfaces = ss; } +void +SurfaceCollection::remove_collinear_points() +{ + for(Surface &surface : this->surfaces) { + surface.expolygon.remove_colinear_points(); + } +} + /* group surfaces by common properties */ void SurfaceCollection::group(std::vector *retval) const diff --git a/xs/src/libslic3r/SurfaceCollection.hpp b/xs/src/libslic3r/SurfaceCollection.hpp index 0fb30a734..505710620 100644 --- a/xs/src/libslic3r/SurfaceCollection.hpp +++ b/xs/src/libslic3r/SurfaceCollection.hpp @@ -18,6 +18,8 @@ class SurfaceCollection operator Polygons() const; operator ExPolygons() const; void simplify(double tolerance); + /// Unifies straight multi-segment lines to a single line (artifacts from stl-triangulation) + void remove_collinear_points(); void group(std::vector *retval) const; template bool any_internal_contains(const T &item) const; template bool any_bottom_contains(const T &item) const;