From 6bebc1b42720c2f10cb4e1adbc2d855d5e5555c7 Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Wed, 8 Nov 2023 15:44:01 -0800 Subject: [PATCH] Doing the scan line through the segments --- polygon.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++------ polygon.hpp | 1 + tile.cpp | 6 ++++++ 3 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 polygon.hpp diff --git a/polygon.cpp b/polygon.cpp index 5194625b..9fb978c7 100644 --- a/polygon.cpp +++ b/polygon.cpp @@ -1,3 +1,4 @@ +#include #include "geometry.hpp" struct point { @@ -11,6 +12,10 @@ struct point { typedef std::pair segment; +bool intersect(std::vector &segs, size_t s1, size_t s2) { + return false; +} + struct scan_transition { double y; size_t segment; @@ -38,21 +43,63 @@ std::vector snap_round(std::vector segs) { // to find the pairs that intersect // while not looking at pairs that can't possibly intersect + // index by rounded y coordinates, since we will be + // intersecting with rounded coordinates + std::vector tops; std::vector bottoms; for (size_t i = 0; i < segs.size(); i++) { - if (segs[i].first.y < segs[i].second.y) { - tops.emplace_back(segs[i].first.y, i); - bottoms.emplace_back(segs[i].second.y, i); + if (std::round(segs[i].first.y) < std::round(segs[i].second.y)) { + tops.emplace_back(std::round(segs[i].first.y), i); + bottoms.emplace_back(std::round(segs[i].second.y), i); } else { - tops.emplace_back(segs[i].second.y, i); - bottoms.emplace_back(segs[i].first.y, i); + tops.emplace_back(std::round(segs[i].second.y), i); + bottoms.emplace_back(std::round(segs[i].first.y), i); } } std::sort(tops.begin(), tops.end()); std::sort(bottoms.begin(), bottoms.end()); + + // do the scan + + std::set active; + size_t bottom = 0; + for (size_t i = 0; i < tops.size(); i++) { + // activate anything that is coming into view + + active.insert(tops[i].segment); + if (i + 1 < tops.size() && tops[i + 1].y == tops[i].y) { + continue; + } + + // look at the active segments + + for (size_t s1 : active) { + for (size_t s2 : active) { + if (s1 < s2) { + if (intersect(segs, s1, s2)) { + // if the segments intersected, + // we need to do another scan, + // because introducing a new node + // may have caused new intersections + again = true; + } + } + } + } + + // deactivate anything that is going out of view + + if (i + 1 < tops.size()) { + while (bottom < bottoms.size() && bottoms[bottom].y < tops[i + 1].y) { + auto found = active.find(bottoms[bottom].segment); + active.erase(found); + bottom++; + } + } + } } return segs; @@ -70,7 +117,7 @@ drawvec clean_polygon(drawvec const &geom, int z, int detail) { size_t j; for (j = i + 1; j < geom.size(); j++) { - if (geom[i].op != VT_LINETO) { + if (geom[j].op != VT_LINETO) { break; } } diff --git a/polygon.hpp b/polygon.hpp new file mode 100644 index 00000000..ce63eb3d --- /dev/null +++ b/polygon.hpp @@ -0,0 +1 @@ +drawvec clean_polygon(drawvec const &geom, int z, int detail); diff --git a/tile.cpp b/tile.cpp index d94b1493..33e28b04 100644 --- a/tile.cpp +++ b/tile.cpp @@ -43,6 +43,7 @@ #include "errors.hpp" #include "compression.hpp" #include "protozero/varint.hpp" +#include "polygon.hpp" extern "C" { #include "jsonpull/jsonpull.h" @@ -612,6 +613,11 @@ void *partial_feature_worker(void *v) { int out_detail = (*partials)[i].extra_detail; drawvec geom = (*partials)[i].geoms[0]; + + if (t == VT_POLYGON) { + clean_polygon(geom, z, out_detail); + } + to_tile_scale(geom, z, out_detail); if (t == VT_POLYGON) {