Little refactoring of douglas_peucker()

This commit is contained in:
Vojtech Bubnik 2023-05-02 15:48:24 +02:00
parent 6d0ceeb886
commit fd437dcaf5
7 changed files with 46 additions and 28 deletions

View File

@ -184,14 +184,14 @@ Polygons ExPolygon::simplify_p(double tolerance) const
{
Polygon p = this->contour;
p.points.push_back(p.points.front());
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
p.points = MultiPoint::douglas_peucker(p.points, tolerance);
p.points.pop_back();
pp.emplace_back(std::move(p));
}
// holes
for (Polygon p : this->holes) {
p.points.push_back(p.points.front());
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
p.points = MultiPoint::douglas_peucker(p.points, tolerance);
p.points.pop_back();
pp.emplace_back(std::move(p));
}

View File

@ -52,15 +52,15 @@ template bool contains(const ExPolygons &vector, const Point &point);
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
{
Polygons pp;
for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) {
Polygon p = *it;
p.points.push_back(p.points.front());
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
p.points.pop_back();
pp.push_back(p);
Polygons simplified_raw;
for (const Polygon &source_polygon : polygons) {
Points simplified = MultiPoint::douglas_peucker(to_polyline(source_polygon).points, tolerance);
if (simplified.size() > 3) {
simplified.pop_back();
simplified_raw.push_back(Polygon{ std::move(simplified) });
}
}
*retval = Slic3r::simplify_polygons(pp);
*retval = Slic3r::simplify_polygons(simplified_raw);
}
double linint(double value, double oldmin, double oldmax, double newmin, double newmax)

View File

@ -103,7 +103,7 @@ bool MultiPoint::remove_duplicate_points()
return false;
}
Points MultiPoint::_douglas_peucker(const Points &pts, const double tolerance)
Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
{
Points result_pts;
double tolerance_sq = tolerance * tolerance;

View File

@ -81,7 +81,7 @@ public:
}
}
static Points _douglas_peucker(const Points &points, const double tolerance);
static Points douglas_peucker(const Points &points, const double tolerance);
static Points visivalingam(const Points& pts, const double& tolerance);
inline auto begin() { return points.begin(); }

View File

@ -96,7 +96,7 @@ bool Polygon::make_clockwise()
void Polygon::douglas_peucker(double tolerance)
{
this->points.push_back(this->points.front());
Points p = MultiPoint::_douglas_peucker(this->points, tolerance);
Points p = MultiPoint::douglas_peucker(this->points, tolerance);
p.pop_back();
this->points = std::move(p);
}
@ -110,7 +110,7 @@ Polygons Polygon::simplify(double tolerance) const
// on the whole polygon
Points points = this->points;
points.push_back(points.front());
Polygon p(MultiPoint::_douglas_peucker(points, tolerance));
Polygon p(MultiPoint::douglas_peucker(points, tolerance));
p.points.pop_back();
Polygons pp;
@ -577,23 +577,40 @@ void remove_collinear(Polygons &polys)
remove_collinear(poly);
}
Polygons polygons_simplify(const Polygons &source_polygons, double tolerance)
static inline void simplify_polygon_impl(const Points &points, double tolerance, bool strictly_simple, Polygons &out)
{
Points simplified = MultiPoint::douglas_peucker(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, strictly_simple)) {
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));
}
}
Polygons polygons_simplify(Polygons &&source_polygons, double tolerance, bool strictly_simple /* = true */)
{
Polygons out;
out.reserve(source_polygons.size());
for (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),
source_polygon.points.emplace_back(source_polygon.points.front());
simplify_polygon_impl(source_polygon.points, tolerance, strictly_simple, out);
}
return out;
}
Polygons polygons_simplify(const Polygons &source_polygons, double tolerance, bool strictly_simple /* = true */)
{
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));
}
simplify_polygon_impl(to_polyline(source_polygon).points, tolerance, strictly_simple, out);
}
return out;
}

View File

@ -149,7 +149,8 @@ inline void polygons_append(Polygons &dst, Polygons &&src)
}
}
Polygons polygons_simplify(const Polygons &polys, double tolerance);
Polygons polygons_simplify(Polygons &&polys, double tolerance, bool strictly_simple = true);
Polygons polygons_simplify(const Polygons &polys, double tolerance, bool strictly_simple = true);
inline void polygons_rotate(Polygons &polys, double angle)
{

View File

@ -110,7 +110,7 @@ Points Polyline::equally_spaced_points(double distance) const
void Polyline::simplify(double tolerance)
{
this->points = MultiPoint::_douglas_peucker(this->points, tolerance);
this->points = MultiPoint::douglas_peucker(this->points, tolerance);
}
#if 0