From 4d81c52093f4da618d27dd5620d45b691db5eb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kerbiriou?= Date: Fri, 12 Aug 2022 19:04:01 +0200 Subject: [PATCH] polygon offsets: scale arc tolerance width offset distance --- include/utils/polygon.h | 9 ++++++--- src/utils/polygon.cpp | 24 ++++++++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/include/utils/polygon.h b/include/utils/polygon.h index a8e01cca181..3de469cf3fb 100644 --- a/include/utils/polygon.h +++ b/include/utils/polygon.h @@ -59,8 +59,6 @@ class ListPolyIt; typedef std::list ListPolygon; //!< A polygon represented by a linked list instead of a vector typedef std::vector ListPolygons; //!< Polygons represented by a vector of linked lists instead of a vector of vectors -// Allowed deviation for round joint while offsetting (this reduces the number of segment, http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm) -static constexpr double clipper_arc_tolerance = INT_EPSILON; // How far a miter can be offseted before being truncated, relative to the offset size (http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/MiterLimit.htm) static constexpr double clipper_miter_limit = 1.2; static constexpr int clipper_init = 0; @@ -398,6 +396,11 @@ class ConstPolygonRef * \param[in,out] backward_is_too_far Whether trying another step backward is blocked by the shortcut length condition. Updated for the next iteration. */ static void smooth_outward_step(const Point p1, const int64_t shortcut_length2, ListPolyIt& p0_it, ListPolyIt& p2_it, bool& forward_is_blocked, bool& backward_is_blocked, bool& forward_is_too_far, bool& backward_is_too_far); + + + /// Allowed deviation for round joints while offsetting (this reduces the number of segment + /// @see http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm + static double calcArcTolerance(int offset); }; @@ -1014,7 +1017,7 @@ class Polygons { Polygons ret; ClipperLib::EndType end_type = (joinType == ClipperLib::jtMiter)? ClipperLib::etOpenSquare : ClipperLib::etOpenRound; - ClipperLib::ClipperOffset clipper(clipper_miter_limit, clipper_arc_tolerance); + ClipperLib::ClipperOffset clipper(clipper_miter_limit, ConstPolygonRef::calcArcTolerance(distance)); clipper.AddPaths(paths, joinType, end_type); clipper.MiterLimit = clipper_miter_limit; clipper.Execute(ret.paths, distance); diff --git a/src/utils/polygon.cpp b/src/utils/polygon.cpp index 1cf94faf8b8..cab44390d51 100644 --- a/src/utils/polygon.cpp +++ b/src/utils/polygon.cpp @@ -86,7 +86,7 @@ Polygons Polygons::approxConvexHull(int extra_outset) for (const ClipperLib::Path& path : paths) { Polygons offset_result; - ClipperLib::ClipperOffset offsetter(clipper_miter_limit, clipper_arc_tolerance); + ClipperLib::ClipperOffset offsetter(clipper_miter_limit, ConstPolygonRef::calcArcTolerance(overshoot)); offsetter.AddPath(path, ClipperLib::jtRound, ClipperLib::etClosedPolygon); offsetter.Execute(offset_result.paths, overshoot); convex_hull.add(offset_result); @@ -281,7 +281,7 @@ Polygons Polygons::intersectionPolyLines(const Polygons& polylines, bool restitc if (restitch) { Polygons result_lines, result_polygons; - const coord_t snap_distance = clipper_arc_tolerance; + const coord_t snap_distance = INT_EPSILON; PolylineStitcher::stitch(ret, result_lines, result_polygons, max_stitch_distance, snap_distance); ret = result_lines; // if polylines got stitched into polygons, split them back up into a polyline again, because the result only admits polylines @@ -339,30 +339,34 @@ coord_t Polygons::polyLineLength() const Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double miter_limit) const { - if (distance == 0) + if (std::abs(distance) < INT_EPSILON / 2) { return *this; } Polygons ret; - ClipperLib::ClipperOffset clipper(miter_limit, clipper_arc_tolerance); + ClipperLib::ClipperOffset clipper(miter_limit, ConstPolygonRef::calcArcTolerance(distance)); clipper.AddPaths(unionPolygons().paths, join_type, ClipperLib::etClosedPolygon); - clipper.MiterLimit = miter_limit; + assert(clipper.MiterLimit == miter_limit); clipper.Execute(ret.paths, distance); return ret; } +double ConstPolygonRef::calcArcTolerance(int offset) { + constexpr double min_tol = std::max(5_mu, INT_EPSILON); + return std::max(min_tol, std::abs(static_cast(offset)) * 1e-2); +} + Polygons ConstPolygonRef::offset(int distance, ClipperLib::JoinType join_type, double miter_limit) const { - if (distance == 0) + Polygons ret; + if (std::abs(distance) < INT_EPSILON / 2) { - Polygons ret; ret.add(*this); return ret; } - Polygons ret; - ClipperLib::ClipperOffset clipper(miter_limit, clipper_arc_tolerance); + ClipperLib::ClipperOffset clipper(miter_limit, calcArcTolerance(distance)); clipper.AddPath(*path, join_type, ClipperLib::etClosedPolygon); - clipper.MiterLimit = miter_limit; + assert(clipper.MiterLimit == miter_limit); clipper.Execute(ret.paths, distance); return ret; }