From 5ba24f07123881781962b2b264a632cf93ff3dc2 Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Thu, 9 Nov 2023 14:04:38 -0800 Subject: [PATCH] Get rid of most spikes --- polygon.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/polygon.cpp b/polygon.cpp index d944c85dd..2a05b76d9 100644 --- a/polygon.cpp +++ b/polygon.cpp @@ -12,10 +12,58 @@ struct point { point(double x_, double y_) : x(x_), y(y_) { } + + point() { + x = 0; + y = 0; + } + + bool operator<(point const &s) const { + if (y < s.y || (y == s.y && x < s.x)) { + return true; + } else { + return false; + } + } + + bool operator==(point const &s) const { + return y == s.y && x == s.x; + } }; typedef std::pair segment; +void fix_opposites(std::vector &segs) { + std::map opposites; + segment erased = std::make_pair(point(INT_MAX, INT_MAX), point(INT_MAX, INT_MAX)); + + for (size_t i = 0; i < segs.size(); i++) { + segment opposite = std::make_pair(segs[i].second, segs[i].first); + opposites.emplace(opposite, i); + } + + for (size_t i = 0; i < segs.size(); i++) { + if (segs[i] == erased) { + continue; + } + + auto f = opposites.find(segs[i]); + if (f != opposites.end()) { + segs[i] = erased; + segs[f->second] = erased; + opposites.erase(f); + } + } + + size_t out = 0; + for (size_t i = 0; i < segs.size(); i++) { + if (segs[i] != erased) { + segs[out++] = segs[i]; + } + } + segs.resize(out); +} + // https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect // // beware of @@ -87,7 +135,7 @@ bool intersect(std::vector &segs, size_t s1, size_t s2) { (std::llround(x) == std::llround(segs[s1].second.x) && std::llround(y) == std::llround(segs[s1].second.y))) { // at an endpoint in s1, so it doesn't need to be changed } else { - printf("introduce %f,%f in %f,%f to %f,%f (s1 %zu %zu)\n", x, y, segs[s1].first.x, segs[s1].first.y, segs[s1].second.x, segs[s1].second.y, s1, s2); + // printf("introduce %f,%f in %f,%f to %f,%f (s1 %zu %zu)\n", x, y, segs[s1].first.x, segs[s1].first.y, segs[s1].second.x, segs[s1].second.y, s1, s2); segs.push_back(std::make_pair(point(x, y), segs[s1].second)); segs[s1] = std::make_pair(segs[s1].first, point(x, y)); changed = true; @@ -97,7 +145,7 @@ bool intersect(std::vector &segs, size_t s1, size_t s2) { (std::llround(x) == std::llround(segs[s2].second.x) && std::llround(y) == std::llround(segs[s2].second.y))) { // at an endpoint in s2, so it doesn't need to be changed } else { - printf("introduce %f,%f in %f,%f to %f,%f (s2 %zu %zu)\n", x, y, segs[s2].first.x, segs[s2].first.y, segs[s2].second.x, segs[s2].second.y, s1, s2); + // printf("introduce %f,%f in %f,%f to %f,%f (s2 %zu %zu)\n", x, y, segs[s2].first.x, segs[s2].first.y, segs[s2].second.x, segs[s2].second.y, s1, s2); // printf("introduce %lld,%lld in %lld,%lld to %lld,%lld (s2)\n", std::llround(x), std::llround(y), std::llround(segs[s2].first.x), std::llround(segs[s2].first.y), std::llround(segs[s2].second.x), std::llround(segs[s2].second.y)); segs.push_back(std::make_pair(point(x, y), segs[s2].second)); segs[s2] = std::make_pair(segs[s2].first, point(x, y)); @@ -135,6 +183,14 @@ std::vector snap_round(std::vector segs) { while (again) { again = false; + // find identical opposite-winding segments and adjust for them + // + // this is in the same loop because we may introduce new self-intersections + // in the course of trying to keep spindles alive, and will then need to + // resolve those. + + fix_opposites(segs); + // set up for a scanline traversal of the segments // to find the pairs that intersect // while not looking at pairs that can't possibly intersect @@ -202,18 +258,6 @@ std::vector snap_round(std::vector segs) { } } } - - if (again) { - // let the intersections settle down before we start trying - // to make additional changes - continue; - } - - // find identical opposite-winding segments and adjust for them - // - // this is in the same loop because we may introduce new self-intersections - // in the course of trying to keep spindles alive, and will then need to - // resolve those. } return segs;