From 358e9cad5b25f28eee78e9f5b7280f78cc0c48ed Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Wed, 28 Oct 2015 14:34:57 -0700 Subject: [PATCH] Use closepath for each polygon ring to match the vector tile spec --- decode.cc | 6 ++++++ geometry.cc | 31 ++++++++++++++++++++++++++++++- geometry.hh | 1 + tile.cc | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/decode.cc b/decode.cc index e6062ab..a31f1ac 100644 --- a/decode.cc +++ b/decode.cc @@ -295,6 +295,12 @@ void handle(std::string message, int z, unsigned x, unsigned y, int describe) { } printf("[ %f, %f ]", rings[i][j].lon, rings[i][j].lat); + } else { + if (j != 0) { + printf(", "); + } + + printf("[ %f, %f ]", rings[i][0].lon, rings[i][0].lat); } } diff --git a/geometry.cc b/geometry.cc index 482142d..3e3ada6 100644 --- a/geometry.cc +++ b/geometry.cc @@ -98,7 +98,6 @@ drawvec remove_noop(drawvec geom, int type, int shift) { } if (geom[i].op == VT_CLOSEPATH) { - fprintf(stderr, "Shouldn't happen\n"); out.push_back(geom[i]); } else { /* moveto or lineto */ out.push_back(geom[i]); @@ -310,6 +309,36 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool cl return out; } +drawvec close_poly(drawvec &geom) { + drawvec out; + + for (unsigned i = 0; i < geom.size(); i++) { + if (geom[i].op == VT_MOVETO) { + unsigned j; + for (j = i + 1; j < geom.size(); j++) { + if (geom[j].op != VT_LINETO) { + break; + } + } + + if (j - 1 > i) { + if (geom[j - 1].x != geom[i].x || geom[j - 1].y != geom[i].y) { + fprintf(stderr, "Internal error: polygon not closed\n"); + } + } + + for (unsigned n = i; n < j - 1; n++) { + out.push_back(geom[n]); + } + out.push_back(draw(VT_CLOSEPATH, 0, 0)); + + i = j - 1; + } + } + + return out; +} + drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double *accum_area) { drawvec out; long long pixel = (1 << (32 - detail - z)) * 2; diff --git a/geometry.hh b/geometry.hh index e4dfc63..c6019d1 100644 --- a/geometry.hh +++ b/geometry.hh @@ -21,6 +21,7 @@ void to_tile_scale(drawvec &geom, int z, int detail); drawvec remove_noop(drawvec geom, int type, int shift); drawvec clip_point(drawvec &geom, int z, int detail, long long buffer); drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool clip); +drawvec close_poly(drawvec &geom); drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double *accum_area); drawvec clip_lines(drawvec &geom, int z, int detail, long long buffer); int quick_check(long long *bbox, int z, int detail, long long buffer); diff --git a/tile.cc b/tile.cc index 5e4cb44..d956a0a 100644 --- a/tile.cc +++ b/tile.cc @@ -656,6 +656,7 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi // Scaling may have made the polygon degenerate. // Give Clipper a chance to try to fix it. geom = clean_or_clip_poly(geom, 0, 0, 0, false); + geom = close_poly(geom); } if (t == VT_POINT || to_feature(geom, NULL)) {