From 3515d218163ad4743b4dc92d162d5b9e86fd434f Mon Sep 17 00:00:00 2001 From: Symmetricity <184246+Symmetricity@users.noreply.github.com> Date: Mon, 18 May 2026 18:25:08 +0200 Subject: [PATCH 1/2] Stabilize polylabel centroid seed Compute the polygon centroid seed relative to a local ring origin before translating it back to map coordinates. This isolates the centroid-origin change from the distance-key ordering candidate so it can be tested independently against the submitted PR stack. --- include/polylabel.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/polylabel.h b/include/polylabel.h index 5d3805eb..894795e1 100644 --- a/include/polylabel.h +++ b/include/polylabel.h @@ -111,18 +111,24 @@ Cell getCentroidCell(const Polygon& polygon) { double area = 0; double cx = 0, cy = 0; const auto& ring = polygon.outer(); + const Point& origin = ring.at(0); + const double ox = origin.get<0>(); + const double oy = origin.get<1>(); for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) { const Point& a = ring[i]; const Point& b = ring[j]; - auto f = a.get<0>() * b.get<1>() - b.get<0>() * a.get<1>(); - cx += (a.get<0>() + b.get<0>()) * f; - cy += (a.get<1>() + b.get<1>()) * f; + const double ax = a.get<0>() - ox; + const double ay = a.get<1>() - oy; + const double bx = b.get<0>() - ox; + const double by = b.get<1>() - oy; + auto f = ax * by - bx * ay; + cx += (ax + bx) * f; + cy += (ay + by) * f; area += f * 3; } - Point c { cx, cy }; - return Cell(area == 0 ? ring.at(0) : Point { cx / area, cy / area }, 0, polygon); + return Cell(area == 0 ? ring.at(0) : Point { ox + cx / area, oy + cy / area }, 0, polygon); } } // namespace detail From f85385bb6a55fd6fbe545a8543ee0c4f8a39140d Mon Sep 17 00:00:00 2001 From: Symmetricity <184246+Symmetricity@users.noreply.github.com> Date: Mon, 18 May 2026 19:11:44 +0200 Subject: [PATCH 2/2] Stabilize polylabel queue ties Break exact priority-queue ties with existing cell geometry values so equivalent cells are not left to implementation-specific heap ordering. This keeps the local-origin centroid candidate isolated from the broader distance-key ordering change while testing whether the remaining macOS versus Linux/Windows point drift is caused by queue ordering alone. --- include/polylabel.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/polylabel.h b/include/polylabel.h index 894795e1..de3a8bc7 100644 --- a/include/polylabel.h +++ b/include/polylabel.h @@ -150,7 +150,11 @@ Point polylabel(const Polygon& polygon, double precision = 0.00001, bool debug = // a priority queue of cells in order of their "potential" (max distance to polygon) auto compareMax = [] (const Cell& a, const Cell& b) { - return a.max < b.max; + if (a.max != b.max) return a.max < b.max; + if (a.d != b.d) return a.d < b.d; + if (a.h != b.h) return a.h > b.h; + if (a.c.get<0>() != b.c.get<0>()) return a.c.get<0>() > b.c.get<0>(); + return a.c.get<1>() > b.c.get<1>(); }; using Queue = std::priority_queue, decltype(compareMax)>; Queue cellQueue(compareMax);