From 97867ecab00c066516c2a4fa67d99af6a9c1c300 Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Mon, 18 Dec 2023 12:04:46 -0800 Subject: [PATCH] Progress on adding filters to tippecanoe-overzoom --- clip.cpp | 109 ++++++++++++++++++++++++++++++++++++++------------ geometry.hpp | 6 ++- overzoom.cpp | 14 ++++++- tile-join.cpp | 2 +- 4 files changed, 101 insertions(+), 30 deletions(-) diff --git a/clip.cpp b/clip.cpp index 512ab2fd..b8afe72d 100644 --- a/clip.cpp +++ b/clip.cpp @@ -754,7 +754,8 @@ static std::vector> clip_poly1(std::vector const &keep, bool do_compress, - std::vector> *next_overzoomed_tiles) { + std::vector> *next_overzoomed_tiles, + size_t multiplier, std::string const &filter) { mvt_tile tile; try { @@ -768,12 +769,70 @@ std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int exit(EXIT_PROTOBUF); } - return overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, do_compress, next_overzoomed_tiles); + return overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, do_compress, next_overzoomed_tiles, multiplier, filter); +} + +struct tile_feature { + drawvec geom; + int t; + bool has_id; + unsigned long long id; + std::vector tags; + mvt_layer const *layer; + + mvt_value value(std::string const &attr) const { + mvt_value v; + v.type = mvt_null; + return v; + } +}; + +struct sorter { + std::string attr; + + sorter(std::string const attr_) + : attr(attr_) { + } + + bool operator()(const struct tile_feature &a, const struct tile_feature &b) { + mvt_value av = a.value(attr); + mvt_value bv = b.value(attr); + + return av < bv; + } +}; + +void feature_out(tile_feature const &feature, mvt_layer &outlayer, std::set const &keep) { + // Add geometry to output feature + + mvt_feature outfeature; + outfeature.type = feature.t; + for (auto const &g : feature.geom) { + outfeature.geometry.emplace_back(g.op, g.x, g.y); + } + + // ID and attributes, if it didn't get clipped away + + if (outfeature.geometry.size() > 0) { + if (feature.has_id) { + outfeature.has_id = true; + outfeature.id = feature.id; + } + + for (size_t i = 0; i + 1 < feature.tags.size(); i += 2) { + if (keep.size() == 0 || keep.find(feature.layer->keys[feature.tags[i]]) != keep.end()) { + outlayer.tag(outfeature, feature.layer->keys[feature.tags[i]], feature.layer->values[feature.tags[i + 1]]); + } + } + + outlayer.features.push_back(outfeature); + } } std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny, int detail, int buffer, std::set const &keep, bool do_compress, - std::vector> *next_overzoomed_tiles) { + std::vector> *next_overzoomed_tiles, + size_t multiplier, std::string const &filter) { mvt_tile outtile; for (auto const &layer : tile.layers) { @@ -788,8 +847,9 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int outlayer.version = layer.version; outlayer.extent = 1LL << det; + std::vector tile_features; + for (auto const &feature : layer.features) { - mvt_feature outfeature; drawvec geom; int t = feature.type; @@ -862,29 +922,27 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int geom = close_poly(geom); } - // Add geometry to output feature + tile_feature tf; + tf.geom = geom; + tf.t = t; + tf.has_id = feature.has_id; + tf.id = feature.id; + tf.tags = feature.tags; + tf.layer = &layer; - outfeature.type = t; - for (auto const &g : geom) { - outfeature.geometry.emplace_back(g.op, g.x, g.y); + tile_features.push_back(tf); + + if (tile_features.size() >= multiplier) { + std::sort(tile_features.begin(), tile_features.end(), sorter(filter)); + feature_out(tile_features[0], outlayer, keep); + tile_features.clear(); } + } - // ID and attributes, if it didn't get clipped away - - if (outfeature.geometry.size() > 0) { - if (feature.has_id) { - outfeature.has_id = true; - outfeature.id = feature.id; - } - - for (size_t i = 0; i + 1 < feature.tags.size(); i += 2) { - if (keep.size() == 0 || keep.find(layer.keys[feature.tags[i]]) != keep.end()) { - outlayer.tag(outfeature, layer.keys[feature.tags[i]], layer.values[feature.tags[i + 1]]); - } - } - - outlayer.features.push_back(outfeature); - } + if (tile_features.size() > 0) { + std::sort(tile_features.begin(), tile_features.end(), sorter(filter)); + feature_out(tile_features[0], outlayer, keep); + tile_features.clear(); } if (outlayer.features.size() > 0) { @@ -905,7 +963,8 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int for (size_t y = 0; y < 2; y++) { std::string child = overzoom(outtile, nz, nx, ny, nz + 1, nx * 2 + x, ny * 2 + y, - detail, buffer, keep, false, NULL); + detail, buffer, keep, false, NULL, + multiplier, filter); if (child.size() > 0) { next_overzoomed_tiles->emplace_back(nx * 2 + x, ny * 2 + y); } diff --git a/geometry.hpp b/geometry.hpp index 1cbaa8ef..c970ce91 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -100,10 +100,12 @@ double distance_from_line(long long point_x, long long point_y, long long segA_x std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny, int detail, int buffer, std::set const &keep, bool do_compress, - std::vector> *next_overzoomed_tiles); + std::vector> *next_overzoomed_tiles, + size_t multiplier, std::string const &filter); std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int ny, int detail, int buffer, std::set const &keep, bool do_compress, - std::vector> *next_overzoomed_tiles); + std::vector> *next_overzoomed_tiles, + size_t multiplier, std::string const &filter); #endif diff --git a/overzoom.cpp b/overzoom.cpp index 1a630413..67d9f2ce 100644 --- a/overzoom.cpp +++ b/overzoom.cpp @@ -12,6 +12,8 @@ extern int optind; int detail = 12; // tippecanoe-style: mvt extent == 1 << detail int buffer = 5; // tippecanoe-style: mvt buffer == extent * buffer / 256; +int multiplier = 1; +std::string filter; std::set keep; @@ -25,7 +27,7 @@ int main(int argc, char **argv) { int i; const char *outfile = NULL; - while ((i = getopt(argc, argv, "y:o:d:b:")) != -1) { + while ((i = getopt(argc, argv, "y:o:d:b:f:m:")) != -1) { switch (i) { case 'y': keep.insert(optarg); @@ -43,6 +45,14 @@ int main(int argc, char **argv) { buffer = atoi(optarg); break; + case 'm': + multiplier = atoi(optarg); + break; + + case 'f': + filter = optarg; + break; + default: usage(argv); } @@ -91,7 +101,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - std::string out = overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, true, NULL); + std::string out = overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, true, NULL, multiplier, filter); fwrite(out.c_str(), sizeof(char), out.size(), f); fclose(f); diff --git a/tile-join.cpp b/tile-join.cpp index 9832a4fd..dfc6f118 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -782,7 +782,7 @@ struct tileset_reader { } if (source.layers.size() != 0) { - std::string ret = overzoom(source, parent_tile.z, parent_tile.x, parent_tile.y, tile.z, tile.x, tile.y, -1, buffer, std::set(), false, &next_overzoomed_tiles); + std::string ret = overzoom(source, parent_tile.z, parent_tile.x, parent_tile.y, tile.z, tile.x, tile.y, -1, buffer, std::set(), false, &next_overzoomed_tiles, 1, ""); return ret; }