diff --git a/README.md b/README.md index ee2688344..7989b0782 100644 --- a/README.md +++ b/README.md @@ -503,6 +503,7 @@ the same layer, enclose them in an `all` expression so they will all be evaluate * `-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. * `--clip-bounding-box=`*minlon*`,`*minlat*`,`*maxlon*`,`*maxlat*: Clip all features to the specified bounding box. + * `--split-complex-polygons=`*limit*`: Subdivide polygons with more than *limit* vertices into multiple features. ### Setting or disabling tile size limits diff --git a/geometry.cpp b/geometry.cpp index 7cb6cf1f2..9a555b019 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -975,16 +975,16 @@ drawvec fix_polygon(drawvec &geom) { return out; } -std::vector chop_polygon(std::vector &geoms) { +std::vector chop_polygon(std::vector &geoms, size_t n) { while (1) { bool again = false; std::vector out; for (size_t i = 0; i < geoms.size(); i++) { - if (geoms[i].size() > 700) { + if (geoms[i].size() > n) { static bool warned = false; if (!warned) { - fprintf(stderr, "Warning: splitting up polygon with more than 700 sides\n"); + fprintf(stderr, "Warning: splitting up polygon with more than %zu sides\n", n); warned = true; } diff --git a/geometry.hpp b/geometry.hpp index 79b8f472a..14e1c79bc 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -71,7 +71,7 @@ int quick_check(long long *bbox, int z, long long buffer); drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain, drawvec const &shared_nodes); drawvec reorder_lines(drawvec &geom); drawvec fix_polygon(drawvec &geom); -std::vector chop_polygon(std::vector &geoms); +std::vector chop_polygon(std::vector &geoms, size_t n); void check_polygon(drawvec &geom); double get_area(drawvec &geom, size_t i, size_t j); double get_mp_area(drawvec &geom); diff --git a/main.cpp b/main.cpp index ae41d8254..4cc6c238e 100644 --- a/main.cpp +++ b/main.cpp @@ -77,6 +77,7 @@ size_t max_tile_features = 200000; int cluster_distance = 0; long justx = -1, justy = -1; std::string attribute_for_id = ""; +size_t polygon_split = 0; int prevent[256]; int additional[256]; @@ -2596,6 +2597,7 @@ int main(int argc, char **argv) { {"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}, {"clip-bounding-box", required_argument, 0, '~'}, + {"split-complex-polygons", required_argument, 0, '~'}, {"Filtering tile contents", 0, 0, 0}, {"prefilter", required_argument, 0, 'C'}, @@ -2695,6 +2697,8 @@ int main(int argc, char **argv) { fprintf(stderr, "%s: Can't parse bounding box --%s=%s\n", argv[0], opt, optarg); exit(EXIT_FAILURE); } + } else if (strcmp(opt, "split-complex-polygons") == 0) { + polygon_split = atoi(optarg); } else if (strcmp(opt, "use-attribute-for-id") == 0) { attribute_for_id = optarg; } else { diff --git a/main.hpp b/main.hpp index 8d89ab63c..9992cd499 100644 --- a/main.hpp +++ b/main.hpp @@ -48,6 +48,7 @@ extern size_t max_tile_size; extern size_t max_tile_features; extern int cluster_distance; extern std::string attribute_for_id; +extern size_t polygon_split; int mkstemp_cloexec(char *name); FILE *fopen_oflag(const char *name, const char *mode, int oflag); diff --git a/tile.cpp b/tile.cpp index 2cf955252..a139a95e5 100644 --- a/tile.cpp +++ b/tile.cpp @@ -493,6 +493,10 @@ void *partial_feature_worker(void *v) { std::vector geoms; geoms.push_back(geom); + if (t == VT_POLYGON && polygon_split > 0) { + geoms = chop_polygon(geoms, polygon_split); + } + if (t == VT_POLYGON) { // Scaling may have made the polygon degenerate. // Give Clipper a chance to try to fix it.