Fixed polygons_simplify() to correctly handle holes.
This fixes some missing tree / organic supports in the middle of an object surrounded by walls all around.
This commit is contained in:
parent
a98467f661
commit
da00cedc84
@ -99,9 +99,11 @@ void Polygon::douglas_peucker(double tolerance)
|
||||
this->points = std::move(p);
|
||||
}
|
||||
|
||||
// this only works on CCW polygons as CW will be ripped out by Clipper's simplify_polygons()
|
||||
Polygons Polygon::simplify(double tolerance) const
|
||||
{
|
||||
// Works on CCW polygons only, CW contour will be reoriented to CCW by Clipper's simplify_polygons()!
|
||||
assert(this->is_counter_clockwise());
|
||||
|
||||
// repeat first point at the end in order to apply Douglas-Peucker
|
||||
// on the whole polygon
|
||||
Points points = this->points;
|
||||
@ -114,13 +116,6 @@ Polygons Polygon::simplify(double tolerance) const
|
||||
return simplify_polygons(pp);
|
||||
}
|
||||
|
||||
void Polygon::simplify(double tolerance, Polygons &polygons) const
|
||||
{
|
||||
Polygons pp = this->simplify(tolerance);
|
||||
polygons.reserve(polygons.size() + pp.size());
|
||||
polygons.insert(polygons.end(), pp.begin(), pp.end());
|
||||
}
|
||||
|
||||
// Only call this on convex polygons or it will return invalid results
|
||||
void Polygon::triangulate_convex(Polygons* polygons) const
|
||||
{
|
||||
@ -562,6 +557,27 @@ void remove_collinear(Polygons &polys)
|
||||
remove_collinear(poly);
|
||||
}
|
||||
|
||||
Polygons polygons_simplify(const Polygons &source_polygons, double tolerance)
|
||||
{
|
||||
Polygons out;
|
||||
out.reserve(source_polygons.size());
|
||||
for (const Polygon &source_polygon : source_polygons) {
|
||||
// Run Douglas / Peucker simplification algorithm on an open polyline (by repeating the first point at the end of the polyline),
|
||||
Points simplified = MultiPoint::_douglas_peucker(to_polyline(source_polygon).points, tolerance);
|
||||
// then remove the last (repeated) point.
|
||||
simplified.pop_back();
|
||||
// Simplify the decimated contour by ClipperLib.
|
||||
bool ccw = ClipperLib::Area(simplified) > 0.;
|
||||
for (Points &path : ClipperLib::SimplifyPolygons(ClipperUtils::SinglePathProvider(simplified), ClipperLib::pftNonZero)) {
|
||||
if (! ccw)
|
||||
// ClipperLib likely reoriented negative area contours to become positive. Reverse holes back to CW.
|
||||
std::reverse(path.begin(), path.end());
|
||||
out.emplace_back(std::move(path));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Do polygons match? If they match, they must have the same topology,
|
||||
// however their contours may be rotated.
|
||||
bool polygons_match(const Polygon &l, const Polygon &r)
|
||||
|
@ -67,8 +67,8 @@ public:
|
||||
bool on_boundary(const Point &point, double eps) const
|
||||
{ return (this->point_projection(point) - point).cast<double>().squaredNorm() < eps * eps; }
|
||||
|
||||
// Works on CCW polygons only, CW contour will be reoriented to CCW by Clipper's simplify_polygons()!
|
||||
Polygons simplify(double tolerance) const;
|
||||
void simplify(double tolerance, Polygons &polygons) const;
|
||||
void densify(float min_length, std::vector<float>* lengths = nullptr);
|
||||
void triangulate_convex(Polygons* polygons) const;
|
||||
Point centroid() const;
|
||||
@ -148,14 +148,7 @@ inline void polygons_append(Polygons &dst, Polygons &&src)
|
||||
}
|
||||
}
|
||||
|
||||
inline Polygons polygons_simplify(const Polygons &polys, double tolerance)
|
||||
{
|
||||
Polygons out;
|
||||
out.reserve(polys.size());
|
||||
for (const Polygon &p : polys)
|
||||
polygons_append(out, p.simplify(tolerance));
|
||||
return out;
|
||||
}
|
||||
Polygons polygons_simplify(const Polygons &polys, double tolerance);
|
||||
|
||||
inline void polygons_rotate(Polygons &polys, double angle)
|
||||
{
|
||||
@ -216,18 +209,22 @@ inline Lines to_lines(const Polygons &polys)
|
||||
return lines;
|
||||
}
|
||||
|
||||
inline Polylines to_polylines(const Polygons &polys)
|
||||
inline Polyline to_polyline(const Polygon &polygon)
|
||||
{
|
||||
Polylines polylines;
|
||||
polylines.assign(polys.size(), Polyline());
|
||||
size_t idx = 0;
|
||||
for (Polygons::const_iterator it = polys.begin(); it != polys.end(); ++ it) {
|
||||
Polyline &pl = polylines[idx ++];
|
||||
pl.points = it->points;
|
||||
pl.points.push_back(it->points.front());
|
||||
}
|
||||
assert(idx == polylines.size());
|
||||
return polylines;
|
||||
Polyline out;
|
||||
out.points.reserve(polygon.size() + 1);
|
||||
out.points.assign(polygon.points.begin(), polygon.points.end());
|
||||
out.points.push_back(polygon.points.front());
|
||||
return out;
|
||||
}
|
||||
|
||||
inline Polylines to_polylines(const Polygons &polygons)
|
||||
{
|
||||
Polylines out;
|
||||
out.reserve(polygons.size());
|
||||
for (const Polygon &polygon : polygons)
|
||||
out.emplace_back(to_polyline(polygon));
|
||||
return out;
|
||||
}
|
||||
|
||||
inline Polylines to_polylines(Polygons &&polys)
|
||||
|
Loading…
Reference in New Issue
Block a user