diff --git a/Makefile b/Makefile index 57c81d1d..d267e077 100644 --- a/Makefile +++ b/Makefile @@ -68,16 +68,16 @@ tippecanoe-enumerate: enumerate.o tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o pmtiles_file.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -tile-join: tile-join.o projection.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o pmtiles_file.o clip.o attribute.o thread.o +tile-join: tile-join.o projection.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o pmtiles_file.o clip.o attribute.o thread.o read_json.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread -unit: unit.o text.o sort.o mvt.o projection.o clip.o attribute.o jsonpull/jsonpull.o evaluator.o +unit: unit.o text.o sort.o mvt.o projection.o clip.o attribute.o jsonpull/jsonpull.o evaluator.o read_json.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread -tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o text.o attribute.o read_json.o projection.o +tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o text.o attribute.o read_json.o projection.o read_json.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread -include $(wildcard *.d) diff --git a/clip.cpp b/clip.cpp index e6975a03..7e2a1f3c 100644 --- a/clip.cpp +++ b/clip.cpp @@ -13,6 +13,7 @@ #include "serial.hpp" #include "attribute.hpp" #include "projection.hpp" +#include "read_json.hpp" static std::vector> clip_poly1(std::vector> &geom, long long minx, long long miny, long long maxx, long long maxy, @@ -1075,6 +1076,42 @@ bool pnpoly_mp(std::vector const &geom, long long x, long long y) return found; } +clipbbox parse_clip_poly(std::string arg) { + json_pull *jp = json_begin_string(arg.c_str()); + json_object *j = json_read_tree(jp); + if (j->type != JSON_HASH) { + fprintf(stderr, "Expected JSON geometry object, not %s\n", arg.c_str()); + } + + std::pair parsed_geometry = parse_geometry(j, jp, j, 0, 0, 0, 1LL << 32, false); + json_end(jp); + + clipbbox out; + out.minx = LLONG_MAX; + out.miny = LLONG_MAX; + out.maxx = LLONG_MIN; + out.maxy = LLONG_MIN; + for (auto const &d : parsed_geometry.second) { + if (d.op == VT_MOVETO || d.op == VT_LINETO) { + if (d.x < out.minx) { + out.minx = d.x; + } + if (d.y < out.miny) { + out.miny = d.y; + } + if (d.x > out.maxx) { + out.maxx = d.x; + } + if (d.y > out.maxy) { + out.maxy = d.y; + } + } + } + out.dv = std::move(parsed_geometry.second); + + return out; +} + std::string overzoom(std::vector const &tiles, int nz, int nx, int ny, int detail_or_unspecified, int buffer, std::set const &keep, diff --git a/geometry.hpp b/geometry.hpp index 2284ab95..45161f3b 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -125,6 +125,8 @@ struct clipbbox { long long miny; long long maxx; long long maxy; + + drawvec dv; // empty, or arbitrary clipping polygon }; std::string overzoom(std::vector const &tiles, int nz, int nx, int ny, @@ -162,4 +164,6 @@ draw center_of_mass_mp(const drawvec &dv); void get_quadkey_bounds(long long xmin, long long ymin, long long xmax, long long ymax, unsigned long long *start, unsigned long long *end); +clipbbox parse_clip_poly(std::string arg); + #endif diff --git a/overzoom.cpp b/overzoom.cpp index 514c7669..63822d0f 100644 --- a/overzoom.cpp +++ b/overzoom.cpp @@ -72,6 +72,7 @@ int main(int argc, char **argv) { {"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}, }; @@ -162,7 +163,7 @@ int main(int argc, char **argv) { do_compress = false; break; - case 'k' & 0x1F: + 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); @@ -173,6 +174,13 @@ int main(int argc, char **argv) { 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); diff --git a/read_json.cpp b/read_json.cpp index bf5a5e3f..a77fe4be 100644 --- a/read_json.cpp +++ b/read_json.cpp @@ -179,7 +179,7 @@ static std::vector to_feature(drawvec &geom) { } std::pair parse_geometry(json_object *geometry, json_pull *jp, json_object *j, - int z, int x, int y, int extent, bool fix_longitudes) { + int z, int x, int y, long long extent, bool fix_longitudes) { json_object *geometry_type = json_hash_get(geometry, "type"); if (geometry_type == NULL) { fprintf(stderr, "Filter output:%d: null geometry (additional not reported): ", jp->line); diff --git a/read_json.hpp b/read_json.hpp index 84e0853b..6323c497 100644 --- a/read_json.hpp +++ b/read_json.hpp @@ -12,6 +12,8 @@ extern int mb_geometry[GEOM_TYPES]; void json_context(json_object *j); void parse_coordinates(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature); +std::pair parse_geometry(json_object *geometry, json_pull *jp, json_object *j, + int z, int x, int y, long long extent, bool fix_longitudes); std::vector parse_layers(FILE *fp, int z, unsigned x, unsigned y, int extent, bool fix_longitudes); serial_val stringify_value(json_object *value, const char *reading, int line, json_object *feature);