From 48486b5d7bd9b0a2a94babf77a013f8e4b884266 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Fri, 1 Jun 2018 12:59:28 -0700 Subject: [PATCH 1/2] Add --use-source-polygon-winding and --reverse-source-polygon-winding --- CHANGELOG.md | 4 ++++ README.md | 2 ++ geometry.cpp | 18 ++++++++++++++++-- main.cpp | 2 ++ man/tippecanoe.1 | 4 ++++ options.hpp | 2 ++ tests/polygon-winding/in.json | 19 +++++++++++++++++++ tests/polygon-winding/out/-z0.json | 18 ++++++++++++++++++ .../-z0_--reverse-source-polygon-winding.json | 18 ++++++++++++++++++ .../out/-z0_--use-source-polygon-winding.json | 18 ++++++++++++++++++ version.hpp | 2 +- 11 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 tests/polygon-winding/in.json create mode 100644 tests/polygon-winding/out/-z0.json create mode 100644 tests/polygon-winding/out/-z0_--reverse-source-polygon-winding.json create mode 100644 tests/polygon-winding/out/-z0_--use-source-polygon-winding.json diff --git a/CHANGELOG.md b/CHANGELOG.md index f5fcfa8a..e70f9546 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.29.1 + +* Add --use-source-polygon-winding and --reverse-source-polygon-winding + ## 1.29.0 * Add the option to specify layer file, name, and description as JSON diff --git a/README.md b/README.md index b05fb66c..d7a68c00 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,8 @@ Example: to retain only major TIGER roads at low zoom levels: ### Trying to correct bad source geometry * `-aw` or `--detect-longitude-wraparound`: Detect when adjacent points within a feature jump to the other side of the world, and try to fix the geometry. + * `-pw` or `--use-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings. + * `-pW` or `--reverse-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings. ### Setting or disabling tile size limits diff --git a/geometry.cpp b/geometry.cpp index 980c0615..6f69abec 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -19,6 +19,7 @@ #include "projection.hpp" #include "serial.hpp" #include "main.hpp" +#include "options.hpp" static int pnpoly(drawvec &vert, size_t start, size_t nvert, long long testx, long long testy); static int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax); @@ -912,8 +913,21 @@ drawvec fix_polygon(drawvec &geom) { // Reverse ring if winding order doesn't match // inner/outer expectation - double area = get_area(ring, 0, ring.size()); - if ((area > 0) != outer) { + bool reverse_ring = false; + if (prevent[P_USE_SOURCE_POLYGON_WINDING]) { + // GeoJSON winding is reversed from vector winding + reverse_ring = true; + } else if (prevent[P_REVERSE_SOURCE_POLYGON_WINDING]) { + // GeoJSON winding is reversed from vector winding + reverse_ring = false; + } else { + double area = get_area(ring, 0, ring.size()); + if ((area > 0) != outer) { + reverse_ring = true; + } + } + + if (reverse_ring) { drawvec tmp; for (int a = ring.size() - 1; a >= 0; a--) { tmp.push_back(ring[a]); diff --git a/main.cpp b/main.cpp index 011cf18a..1dbe2896 100644 --- a/main.cpp +++ b/main.cpp @@ -2552,6 +2552,8 @@ int main(int argc, char **argv) { {"Trying to correct bad source geometry", 0, 0, 0}, {"detect-longitude-wraparound", no_argument, &additional[A_DETECT_WRAPAROUND], 1}, + {"use-source-polygon-winding", no_argument, &prevent[P_USE_SOURCE_POLYGON_WINDING], 1}, + {"reverse-source-polygon-winding", no_argument, &prevent[P_REVERSE_SOURCE_POLYGON_WINDING], 1}, {"Filtering tile contents", 0, 0, 0}, {"prefilter", required_argument, 0, 'C'}, diff --git a/man/tippecanoe.1 b/man/tippecanoe.1 index 16747912..a2d7a09c 100644 --- a/man/tippecanoe.1 +++ b/man/tippecanoe.1 @@ -361,6 +361,10 @@ the line or polygon within one tile unit of its proper location. You can probabl .RS .IP \(bu 2 \fB\fC\-aw\fR or \fB\fC\-\-detect\-longitude\-wraparound\fR: Detect when adjacent points within a feature jump to the other side of the world, and try to fix the geometry. +.IP \(bu 2 +\fB\fC\-pw\fR or \fB\fC\-\-use\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings. +.IP \(bu 2 +\fB\fC\-pW\fR or \fB\fC\-\-reverse\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings. .RE .SS Setting or disabling tile size limits .RS diff --git a/options.hpp b/options.hpp index e97dd72f..0b113f62 100644 --- a/options.hpp +++ b/options.hpp @@ -35,6 +35,8 @@ #define P_TINY_POLYGON_REDUCTION ((int) 't') #define P_TILE_COMPRESSION ((int) 'C') #define P_TILE_STATS ((int) 'g') +#define P_USE_SOURCE_POLYGON_WINDING ((int) 'w') +#define P_REVERSE_SOURCE_POLYGON_WINDING ((int) 'W') extern int prevent[256]; extern int additional[256]; diff --git a/tests/polygon-winding/in.json b/tests/polygon-winding/in.json new file mode 100644 index 00000000..c736d690 --- /dev/null +++ b/tests/polygon-winding/in.json @@ -0,0 +1,19 @@ + { + "type": "Polygon", + "coordinates": [ + [ + [100.0, 0.0], + [101.0, 0.0], + [101.0, 1.0], + [100.0, 1.0], + [100.0, 0.0] + ], + [ + [100.8, 0.8], + [100.8, 0.2], + [100.2, 0.2], + [100.2, 0.8], + [100.8, 0.8] + ] + ] + } diff --git a/tests/polygon-winding/out/-z0.json b/tests/polygon-winding/out/-z0.json new file mode 100644 index 00000000..c46816a2 --- /dev/null +++ b/tests/polygon-winding/out/-z0.json @@ -0,0 +1,18 @@ +{ "type": "FeatureCollection", "properties": { +"bounds": "100.000000,0.000000,101.000000,1.000000", +"center": "100.000000,0.000000,0", +"description": "tests/polygon-winding/out/-z0.json.check.mbtiles", +"format": "pbf", +"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 1,\"geometry\": \"Polygon\",\"attributeCount\": 0,\"attributes\": []}]}}", +"maxzoom": "0", +"minzoom": "0", +"name": "tests/polygon-winding/out/-z0.json.check.mbtiles", +"type": "overlay", +"version": "2" +}, "features": [ +{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 100.986328, 1.054628 ], [ 100.986328, 0.000000 ], [ 99.931641, 0.000000 ], [ 99.931641, 1.054628 ], [ 100.986328, 1.054628 ] ], [ [ 100.195312, 0.263671 ], [ 100.722656, 0.263671 ], [ 100.722656, 0.878872 ], [ 100.195312, 0.878872 ], [ 100.195312, 0.263671 ] ] ] } } +] } +] } +] } diff --git a/tests/polygon-winding/out/-z0_--reverse-source-polygon-winding.json b/tests/polygon-winding/out/-z0_--reverse-source-polygon-winding.json new file mode 100644 index 00000000..6e638f12 --- /dev/null +++ b/tests/polygon-winding/out/-z0_--reverse-source-polygon-winding.json @@ -0,0 +1,18 @@ +{ "type": "FeatureCollection", "properties": { +"bounds": "100.000000,0.000000,101.000000,1.000000", +"center": "100.000000,0.000000,0", +"description": "tests/polygon-winding/out/-z0_--reverse-source-polygon-winding.json.check.mbtiles", +"format": "pbf", +"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 1,\"geometry\": \"Polygon\",\"attributeCount\": 0,\"attributes\": []}]}}", +"maxzoom": "0", +"minzoom": "0", +"name": "tests/polygon-winding/out/-z0_--reverse-source-polygon-winding.json.check.mbtiles", +"type": "overlay", +"version": "2" +}, "features": [ +{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 100.722656, 0.878872 ], [ 100.722656, 0.263671 ], [ 100.195312, 0.263671 ], [ 100.195312, 0.878872 ], [ 100.722656, 0.878872 ] ] ] } } +] } +] } +] } diff --git a/tests/polygon-winding/out/-z0_--use-source-polygon-winding.json b/tests/polygon-winding/out/-z0_--use-source-polygon-winding.json new file mode 100644 index 00000000..bb6d8cb1 --- /dev/null +++ b/tests/polygon-winding/out/-z0_--use-source-polygon-winding.json @@ -0,0 +1,18 @@ +{ "type": "FeatureCollection", "properties": { +"bounds": "100.000000,0.000000,101.000000,1.000000", +"center": "100.000000,0.000000,0", +"description": "tests/polygon-winding/out/-z0_--use-source-polygon-winding.json.check.mbtiles", +"format": "pbf", +"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 1,\"geometry\": \"Polygon\",\"attributeCount\": 0,\"attributes\": []}]}}", +"maxzoom": "0", +"minzoom": "0", +"name": "tests/polygon-winding/out/-z0_--use-source-polygon-winding.json.check.mbtiles", +"type": "overlay", +"version": "2" +}, "features": [ +{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ +{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ +{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 100.986328, 1.054628 ], [ 100.986328, 0.000000 ], [ 99.931641, 0.000000 ], [ 99.931641, 1.054628 ], [ 100.986328, 1.054628 ] ], [ [ 100.195312, 0.263671 ], [ 100.722656, 0.263671 ], [ 100.722656, 0.878872 ], [ 100.195312, 0.878872 ], [ 100.195312, 0.263671 ] ] ] } } +] } +] } +] } diff --git a/version.hpp b/version.hpp index 83d12f65..a3433c95 100644 --- a/version.hpp +++ b/version.hpp @@ -1,6 +1,6 @@ #ifndef VERSION_HPP #define VERSION_HPP -#define VERSION "tippecanoe v1.29.0\n" +#define VERSION "tippecanoe v1.29.1\n" #endif From c650329eb2242efb4f76502773c1ffe9edb0358d Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Fri, 1 Jun 2018 13:33:58 -0700 Subject: [PATCH 2/2] Use a complete feature in the winding test instead of a bare geometry --- tests/polygon-winding/in.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/polygon-winding/in.json b/tests/polygon-winding/in.json index c736d690..06b9a87a 100644 --- a/tests/polygon-winding/in.json +++ b/tests/polygon-winding/in.json @@ -1,4 +1,6 @@ - { +{ "type": "Feature", + "properties": {}, + "geometry": { "type": "Polygon", "coordinates": [ [ @@ -17,3 +19,4 @@ ] ] } +}