Skip to content

Commit

Permalink
Remove collinear points from polygons right after slicing the stl int…
Browse files Browse the repository at this point in the history
…o polygons.

Triangulation of planar surfaces results in additional edges (i.e. splitting a rectangle into two triangles).
Those edges end up as collinear points in the contour polygons and cause additional, redundant
computation. Most collinear points would be removed by Douglas-Peucker during gcode export.

Fixes slic3r#4726.
  • Loading branch information
platsch authored and lordofhyphens committed Feb 10, 2019
1 parent 66b00c9 commit faeb213
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 0 deletions.
8 changes: 8 additions & 0 deletions xs/src/libslic3r/ExPolygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions xs/src/libslic3r/ExPolygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
36 changes: 36 additions & 0 deletions xs/src/libslic3r/Polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions xs/src/libslic3r/Polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions xs/src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,19 @@ void PrintObject::_slice()
}
}

// remove collinear points from slice polygons (artifacts from stl-triangulation)
std::queue<SurfaceCollection*> queue;
for (Layer* layer : this->layers) {
for (LayerRegion* layerm : layer->regions) {
queue.push(&layerm->slices);
}
}
parallelize<SurfaceCollection*>(
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()) {
Expand Down
8 changes: 8 additions & 0 deletions xs/src/libslic3r/SurfaceCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SurfacesConstPtr> *retval) const
Expand Down
2 changes: 2 additions & 0 deletions xs/src/libslic3r/SurfaceCollection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SurfacesConstPtr> *retval) const;
template <class T> bool any_internal_contains(const T &item) const;
template <class T> bool any_bottom_contains(const T &item) const;
Expand Down

0 comments on commit faeb213

Please sign in to comment.