|
1 | 1 | #include "geometry/ClipperUtils.h" |
| 2 | +#include "clipper2/clipper.h" |
2 | 3 | #include "utils/printutils.h" |
3 | 4 |
|
4 | 5 | #include <algorithm> |
@@ -94,6 +95,13 @@ void fill_minkowski_insides(const Clipper2Lib::Paths64& a, |
94 | 95 | } |
95 | 96 | } |
96 | 97 |
|
| 98 | +void SimplifyPolyTree(const Clipper2Lib::PolyPath64& polytree, double epsilon, Clipper2Lib::PolyPath64& result) { |
| 99 | + for (const auto& child : polytree) { |
| 100 | + Clipper2Lib::PolyPath64 *newchild = result.AddChild(Clipper2Lib::SimplifyPath(child->Polygon(), epsilon)); |
| 101 | + SimplifyPolyTree(*child, epsilon, *newchild); |
| 102 | + } |
| 103 | +} |
| 104 | + |
97 | 105 | } // namespace |
98 | 106 |
|
99 | 107 | // Using 1 bit less precision than the maximum possible, to limit the chance |
@@ -178,15 +186,14 @@ std::unique_ptr<Polygon2d> toPolygon2d(const Clipper2Lib::PolyTree64& polytree, |
178 | 186 | const double scale = std::ldexp(1.0, -scale_bits); |
179 | 187 | auto processChildren = [scale, &result](auto&& processChildren, const Clipper2Lib::PolyPath64& node) -> void { |
180 | 188 | Outline2d outline; |
181 | | - // Apparently, when using offset(), clipper gets the hole status wrong |
182 | | - //outline.positive = !node->IsHole(); |
183 | | - |
| 189 | + // When using offset, clipper can get the hole status wrong. |
| 190 | + // IsPositive() calculates the area of the polygon, and if it's negative, it's a hole. |
184 | 191 | outline.positive = IsPositive(node.Polygon()); |
185 | | - // TODO: Should we replace the missing CleanPolygons in Clipper2 and call it here? |
186 | 192 |
|
187 | | - // CleanPolygon can in some cases reduce the polygon down to no vertices |
188 | | - const auto &cleaned_path = node.Polygon(); |
| 193 | + constexpr double epsilon = 1.1415; // Epsilon taken from Clipper1's default epsilon. |
| 194 | + const auto cleaned_path = Clipper2Lib::SimplifyPath(node.Polygon(), epsilon); |
189 | 195 |
|
| 196 | + // SimplifyPath can potentially reduce the polygon down to no vertices |
190 | 197 | if (cleaned_path.size() >= 3) { |
191 | 198 | for (const auto& ip : cleaned_path) { |
192 | 199 | outline.vertices.emplace_back(scale * ip.x, scale * ip.y); |
@@ -335,7 +342,7 @@ std::unique_ptr<Polygon2d> applyOffset(const Polygon2d& poly, double offset, Cli |
335 | 342 | isMiter ? miter_limit : 2.0, |
336 | 343 | isRound ? std::ldexp(arc_tolerance, scale_bits) : 1.0 |
337 | 344 | ); |
338 | | - auto p = ClipperUtils::fromPolygon2d(poly, scale_bits); |
| 345 | + auto p = ClipperUtils::fromPolygon2d(poly, scale_bits); |
339 | 346 | co.AddPaths(p, joinType, Clipper2Lib::EndType::Polygon); |
340 | 347 | Clipper2Lib::PolyTree64 result; |
341 | 348 | co.Execute(std::ldexp(offset, scale_bits), result); |
|
0 commit comments