Merge pull request #581 from mapbox/force-polygon-winding

Add --use-source-polygon-winding and --reverse-source-polygon-winding
This commit is contained in:
Eric Fischer 2018-06-01 23:19:43 +02:00 committed by GitHub
commit 6e231f5911
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 107 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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]);

View File

@ -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'},

View File

@ -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

View File

@ -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];

View File

@ -0,0 +1,22 @@
{ "type": "Feature",
"properties": {},
"geometry": {
"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]
]
]
}
}

View File

@ -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 ] ] ] } }
] }
] }
] }

View File

@ -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 ] ] ] } }
] }
] }
] }

View File

@ -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 ] ] ] } }
] }
] }
] }

View File

@ -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