mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-03 07:20:37 +08:00
Remove collinear points from polygons right after slicing the stl into 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 #4726.
This commit is contained in:
parent
66b00c90c3
commit
faeb213ce1
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user