Adding optional clipping to tippecanoe-overzoom (#298)

* Plumb a clip bounding box around through overzoom

* Actually do some clipping

* Add a test

* Fix post-binning clipping

* Factoring out geometry parsing from feature parsing

* Accept a clip polygon argument to tippecanoe-overzoom

* Progress in the direction of polygon clipping

* Fix the wagyu flags. We need intersection, not union

* Remove debug spew

* Clip points to polygon bounds too

* Copy the geometric binning code to serve as intersection-finding code

* Add clipper2 for linestring clipping

* Compiles, but does not actually seem to clip. Hmm.

* Oh, it helps if I actually call the function

* Add clipping tests

* Add missing fixture, and don't crash if it is missing

* Remember to do polygon clipping after binning too

* Fix scaling before post-binning clipping. Add test.

* Remove unused parts of clipper

* Rename for consistency

* Revert accidentally added line

* Clip the clip regions to the tile bounds to reduce their complexity

* Add a test of clipping the clip region down to the tile boundary

* Update version and changelog
This commit is contained in:
Erica Fischer
2024-11-27 13:43:40 -08:00
committed by GitHub
parent 11e3196c9a
commit dcc616d3d4
31 changed files with 9458 additions and 163 deletions
+52 -1
View File
@@ -10,6 +10,7 @@
#include "attribute.hpp"
#include "text.hpp"
#include "read_json.hpp"
#include "projection.hpp"
extern char *optarg;
extern int optind;
@@ -29,6 +30,7 @@ std::string accumulate_numeric;
std::set<std::string> keep;
std::set<std::string> exclude;
std::vector<std::string> exclude_prefix;
std::vector<clipbbox> clipbboxes;
void usage(char **argv) {
fprintf(stderr, "Usage: %s -o newtile.pbf.gz tile.pbf.gz oz/ox/oy nz/nx/ny\n", argv[0]);
@@ -68,6 +70,8 @@ int main(int argc, char **argv) {
{"bin-by-id-list", required_argument, 0, 'c' & 0x1F},
{"accumulate-numeric-attributes", required_argument, 0, 'a' & 0x1F},
{"no-tile-compression", no_argument, 0, 'd' & 0x1F},
{"clip-bounding-box", required_argument, 0, 'k' & 0x1F},
{"clip-polygon", required_argument, 0, 'l' & 0x1F},
{0, 0, 0, 0},
};
@@ -158,6 +162,25 @@ int main(int argc, char **argv) {
do_compress = false;
break;
case 'k' & 0x1F: {
clipbbox clip;
if (sscanf(optarg, "%lf,%lf,%lf,%lf", &clip.lon1, &clip.lat1, &clip.lon2, &clip.lat2) == 4) {
projection->project(clip.lon1, clip.lat1, 32, &clip.minx, &clip.maxy);
projection->project(clip.lon2, clip.lat2, 32, &clip.maxx, &clip.miny);
clipbboxes.push_back(clip);
} else {
fprintf(stderr, "%s: Can't parse bounding box --clip-bounding-box=%s\n", argv[0], optarg);
exit(EXIT_ARGS);
}
break;
}
case 'l' & 0x1F: {
clipbbox clip = parse_clip_poly(optarg);
clipbboxes.push_back(clip);
break;
}
default:
fprintf(stderr, "Unrecognized flag -%c\n", i);
usage(argv);
@@ -236,6 +259,34 @@ int main(int argc, char **argv) {
fclose(f);
}
// clip the clip polygons, if any, to the tile bounds,
// to reduce their complexity
if (clipbboxes.size() > 0) {
long long wx1 = (nx - buffer / 256.0) * (1LL << (32 - nz));
long long wy1 = (ny - buffer / 256.0) * (1LL << (32 - nz));
long long wx2 = (nx + 1 + buffer / 256.0) * (1LL << (32 - nz));
long long wy2 = (ny + 1 + buffer / 256.0) * (1LL << (32 - nz));
drawvec tile_bounds;
tile_bounds.emplace_back(VT_MOVETO, wx1, wy1);
tile_bounds.emplace_back(VT_LINETO, wx2, wy1);
tile_bounds.emplace_back(VT_LINETO, wx2, wy2);
tile_bounds.emplace_back(VT_LINETO, wx1, wy2);
tile_bounds.emplace_back(VT_LINETO, wx1, wy1);
for (auto &c : clipbboxes) {
c.minx = std::max(c.minx, wx1);
c.miny = std::max(c.miny, wy1);
c.maxx = std::min(c.maxx, wx2);
c.maxy = std::min(c.maxy, wy2);
if (c.dv.size() > 0) {
c.dv = clip_poly_poly(c.dv, tile_bounds);
}
}
}
json_object *json_filter = NULL;
if (filter.size() > 0) {
json_filter = parse_filter(filter.c_str());
@@ -262,7 +313,7 @@ int main(int argc, char **argv) {
its.push_back(std::move(t));
}
std::string out = overzoom(its, nz, nx, ny, detail, buffer, keep, exclude, exclude_prefix, do_compress, NULL, demultiply, json_filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric, SIZE_MAX);
std::string out = overzoom(its, nz, nx, ny, detail, buffer, keep, exclude, exclude_prefix, do_compress, NULL, demultiply, json_filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric, SIZE_MAX, clipbboxes);
FILE *f = fopen(outfile, "wb");
if (f == NULL) {