From d6720f95ff29dd9bcaba369cf665238be295371c Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 29 Feb 2024 11:38:16 +1100 Subject: [PATCH] Fix adaptive glitch by removing coincident points Remove adjacent coincident and nearly-coincident points from Path. This is based on PR#5276 by sundtek, but only collapses adjacent points on the Path. It also addresses (IMO) most of the feedback on the original PR. see also discussion on the forum: https://forum.freecadweb.org/viewtopic.php?f=15&t=42755&start=10#p555566 --- src/Mod/Path/libarea/Adaptive.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Mod/Path/libarea/Adaptive.cpp b/src/Mod/Path/libarea/Adaptive.cpp index 0986a64d3a..0f96b56465 100644 --- a/src/Mod/Path/libarea/Adaptive.cpp +++ b/src/Mod/Path/libarea/Adaptive.cpp @@ -147,6 +147,27 @@ inline DoublePoint GetPathDirectionV(const Path &pth, size_t pointIndex) return DirectionV(p1, p2); } +// Returns true if points 'a' and 'b' are coincident or nearly so. +bool isClose(const IntPoint &a, const IntPoint &b) { + return abs(a.X - b.X) <= 1 && abs(a.Y - b.Y) <= 1; +} + +// Remove coincident and almost-coincident points from Paths. +void filterCloseValues(Paths &ppg) { + for (auto& pth : ppg) { + while (true) { + auto i = std::adjacent_find(pth.begin(), pth.end(), isClose); + if (i == pth.end()) + break; + pth.erase(i); + } + // adjacent_find doesn't compare first with last element, so + // do that manually. + while (pth.size() > 1 && isClose(pth.front(), pth.back())) + pth.pop_back(); + } +} + //***************************************** // Utils //***************************************** @@ -1654,9 +1675,11 @@ void Adaptive2d::ApplyStockToLeave(Paths &inputPaths) clipof.Clear(); clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); clipof.Execute(inputPaths, -1); + filterCloseValues(inputPaths); clipof.Clear(); clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); clipof.Execute(inputPaths, 1); + filterCloseValues(inputPaths); } }