mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Tippecanoe-decode and tippecanoe-overzoom changes to improve binning performance (#292)
* Add a tippecanoe-decode option to restrict which attributes to decode * Plumb buffer and feature limit around * Check the feature limit * Clarifying cases where output detail can be unspecified * Clip bins to the tile buffer instead of just passing them through * Add missing include * Missed some tests * Add --no-tile-compression option to tippecanoe-overzoom * Update version and changelog
This commit is contained in:
@@ -1076,7 +1076,7 @@ bool pnpoly_mp(std::vector<mvt_geometry> const &geom, long long x, long long y)
|
||||
}
|
||||
|
||||
std::string overzoom(std::vector<input_tile> const &tiles, int nz, int nx, int ny,
|
||||
int detail, int buffer,
|
||||
int detail_or_unspecified, int buffer,
|
||||
std::set<std::string> const &keep,
|
||||
std::set<std::string> const &exclude,
|
||||
std::vector<std::string> const &exclude_prefix,
|
||||
@@ -1087,7 +1087,7 @@ std::string overzoom(std::vector<input_tile> const &tiles, int nz, int nx, int n
|
||||
std::vector<std::string> const &unidecode_data, double simplification,
|
||||
double tiny_polygon_size,
|
||||
std::vector<mvt_layer> const &bins, std::string const &bin_by_id_list,
|
||||
std::string const &accumulate_numeric) {
|
||||
std::string const &accumulate_numeric, size_t feature_limit) {
|
||||
std::vector<source_tile> decoded;
|
||||
|
||||
for (auto const &t : tiles) {
|
||||
@@ -1113,7 +1113,7 @@ std::string overzoom(std::vector<input_tile> const &tiles, int nz, int nx, int n
|
||||
decoded.push_back(out);
|
||||
}
|
||||
|
||||
return overzoom(decoded, nz, nx, ny, detail, buffer, keep, exclude, exclude_prefix, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric);
|
||||
return overzoom(decoded, nz, nx, ny, detail_or_unspecified, buffer, keep, exclude, exclude_prefix, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric, feature_limit);
|
||||
}
|
||||
|
||||
// like a minimal serial_feature, but with mvt_feature-style attributes
|
||||
@@ -1284,18 +1284,54 @@ static bool should_keep(std::string const &key,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void handle_closepath_from_mvt(drawvec &geom) {
|
||||
// mvt geometries close polygons with a mvt_closepath operation
|
||||
// tippecanoe-internal geometries close polygons with a lineto to the initial point
|
||||
|
||||
size_t last_open = 0;
|
||||
|
||||
for (size_t i = 0; i < geom.size(); i++) {
|
||||
if (geom[i].op == mvt_closepath) {
|
||||
geom[i] = draw(mvt_lineto, geom[last_open].x, geom[last_open].y);
|
||||
} else if (geom[i].op == mvt_moveto) {
|
||||
last_open = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void feature_out(std::vector<tile_feature> const &features, mvt_layer &outlayer,
|
||||
std::set<std::string> const &keep,
|
||||
std::set<std::string> const &exclude,
|
||||
std::vector<std::string> const &exclude_prefix,
|
||||
std::unordered_map<std::string, attribute_op> const &attribute_accum,
|
||||
std::string const &accumulate_numeric,
|
||||
key_pool &key_pool) {
|
||||
key_pool &key_pool, int buffer) {
|
||||
// Add geometry to output feature
|
||||
|
||||
drawvec geom = features[0].geom;
|
||||
if (buffer >= 0) {
|
||||
int t = features[0].t;
|
||||
|
||||
if (t == VT_LINE) {
|
||||
geom = clip_lines(geom, 32 - outlayer.detail(), buffer);
|
||||
} else if (t == VT_POLYGON) {
|
||||
drawvec dv;
|
||||
handle_closepath_from_mvt(geom);
|
||||
geom = simple_clip_poly(geom, 32 - outlayer.detail(), buffer, dv, false);
|
||||
} else if (t == VT_POINT) {
|
||||
geom = clip_point(geom, 32 - outlayer.detail(), buffer);
|
||||
}
|
||||
|
||||
geom = remove_noop(geom, t, 0);
|
||||
if (t == VT_POLYGON) {
|
||||
geom = clean_or_clip_poly(geom, 0, 0, false, false);
|
||||
geom = close_poly(geom);
|
||||
}
|
||||
}
|
||||
|
||||
mvt_feature outfeature;
|
||||
outfeature.type = features[0].t;
|
||||
for (auto const &g : features[0].geom) {
|
||||
for (auto const &g : geom) {
|
||||
outfeature.geometry.emplace_back(g.op, g.x, g.y);
|
||||
}
|
||||
|
||||
@@ -1516,22 +1552,27 @@ static std::vector<size_t> parse_ids_string(mvt_value const &v) {
|
||||
|
||||
mvt_tile assign_to_bins(mvt_tile &features,
|
||||
std::vector<mvt_layer> const &bins, std::string const &bin_by_id_list,
|
||||
int z, int x, int y, int detail,
|
||||
int z, int x, int y,
|
||||
std::unordered_map<std::string, attribute_op> const &attribute_accum,
|
||||
std::string const &accumulate_numeric,
|
||||
std::set<std::string> keep,
|
||||
std::set<std::string> exclude,
|
||||
std::vector<std::string> exclude_prefix) {
|
||||
std::vector<std::string> exclude_prefix,
|
||||
int buffer) {
|
||||
std::vector<index_event> events;
|
||||
key_pool key_pool;
|
||||
|
||||
if (bins.size() == 0) {
|
||||
return mvt_tile();
|
||||
}
|
||||
|
||||
// Index bins
|
||||
for (size_t i = 0; i < bins.size(); i++) {
|
||||
for (size_t j = 0; j < bins[i].features.size(); j++) {
|
||||
long long xmin, ymin, xmax, ymax;
|
||||
unsigned long long start, end;
|
||||
|
||||
get_bbox(bins[i].features[j].geometry, &xmin, &ymin, &xmax, &ymax, z, x, y, detail);
|
||||
get_bbox(bins[i].features[j].geometry, &xmin, &ymin, &xmax, &ymax, z, x, y, bins[i].detail());
|
||||
get_quadkey_bounds(xmin, ymin, xmax, ymax, &start, &end);
|
||||
events.emplace_back(start, index_event::ENTER, i, j, xmin, ymin, xmax, ymax);
|
||||
events.emplace_back(end, index_event::EXIT, i, j, xmin, ymin, xmax, ymax);
|
||||
@@ -1551,7 +1592,7 @@ mvt_tile assign_to_bins(mvt_tile &features,
|
||||
fid_to_feature.emplace(features.layers[i].features[j].id, std::make_pair(i, j));
|
||||
}
|
||||
|
||||
get_bbox(features.layers[i].features[j].geometry, &xmin, &ymin, &xmax, &ymax, z, x, y, detail);
|
||||
get_bbox(features.layers[i].features[j].geometry, &xmin, &ymin, &xmax, &ymax, z, x, y, features.layers[i].detail());
|
||||
get_quadkey_bounds(xmin, ymin, xmax, ymax, &start, &end);
|
||||
events.emplace_back(start, index_event::CHECK, i, j, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
@@ -1562,7 +1603,7 @@ mvt_tile assign_to_bins(mvt_tile &features,
|
||||
std::set<active_bin> active;
|
||||
|
||||
mvt_layer outlayer;
|
||||
outlayer.extent = 1 << detail;
|
||||
outlayer.extent = bins[0].extent;
|
||||
outlayer.version = 2;
|
||||
outlayer.name = features.layers[0].name;
|
||||
|
||||
@@ -1680,7 +1721,7 @@ mvt_tile assign_to_bins(mvt_tile &features,
|
||||
if (outfeatures[i].size() > 1) {
|
||||
feature_out(outfeatures[i], outlayer,
|
||||
keep, exclude, exclude_prefix, attribute_accum,
|
||||
accumulate_numeric, key_pool);
|
||||
accumulate_numeric, key_pool, buffer);
|
||||
mvt_feature &nfeature = outlayer.features.back();
|
||||
mvt_value val;
|
||||
val.type = mvt_uint;
|
||||
@@ -1702,7 +1743,7 @@ mvt_tile assign_to_bins(mvt_tile &features,
|
||||
}
|
||||
|
||||
std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int ny,
|
||||
int detail, int buffer,
|
||||
int detail_or_unspecified, int buffer,
|
||||
std::set<std::string> const &keep,
|
||||
std::set<std::string> const &exclude,
|
||||
std::vector<std::string> const &exclude_prefix,
|
||||
@@ -1713,7 +1754,7 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
std::vector<std::string> const &unidecode_data, double simplification,
|
||||
double tiny_polygon_size,
|
||||
std::vector<mvt_layer> const &bins, std::string const &bin_by_id_list,
|
||||
std::string const &accumulate_numeric) {
|
||||
std::string const &accumulate_numeric, size_t feature_limit) {
|
||||
mvt_tile outtile;
|
||||
key_pool key_pool;
|
||||
|
||||
@@ -1721,7 +1762,7 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
for (auto const &layer : tile.tile.layers) {
|
||||
mvt_layer *outlayer = NULL;
|
||||
|
||||
int det = detail;
|
||||
int det = detail_or_unspecified;
|
||||
if (det <= 0) {
|
||||
det = std::round(log(layer.extent) / log(2));
|
||||
}
|
||||
@@ -1840,7 +1881,10 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
|
||||
if (flush_multiplier_cluster) {
|
||||
if (pending_tile_features.size() > 0) {
|
||||
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, accumulate_numeric, key_pool);
|
||||
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, accumulate_numeric, key_pool, -1);
|
||||
if (outlayer->features.size() >= feature_limit) {
|
||||
break;
|
||||
}
|
||||
pending_tile_features.clear();
|
||||
}
|
||||
}
|
||||
@@ -1854,16 +1898,16 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
if (t == VT_POLYGON && tiny_polygon_size > 0) {
|
||||
bool simplified_away_by_reduction = false;
|
||||
|
||||
geom = reduce_tiny_poly(geom, nz, detail, &still_need_simplification_after_reduction, &simplified_away_by_reduction, &accum_area, tiny_polygon_size);
|
||||
geom = reduce_tiny_poly(geom, nz, det, &still_need_simplification_after_reduction, &simplified_away_by_reduction, &accum_area, tiny_polygon_size);
|
||||
} else {
|
||||
still_need_simplification_after_reduction = true;
|
||||
}
|
||||
|
||||
if (simplification > 0 && still_need_simplification_after_reduction) {
|
||||
if (t == VT_POLYGON) {
|
||||
geom = simplify_lines_basic(geom, nz, detail, simplification, 4);
|
||||
geom = simplify_lines_basic(geom, nz, det, simplification, 4);
|
||||
} else if (t == VT_LINE) {
|
||||
geom = simplify_lines_basic(geom, nz, detail, simplification, 0);
|
||||
geom = simplify_lines_basic(geom, nz, det, simplification, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1897,8 +1941,11 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
}
|
||||
|
||||
if (pending_tile_features.size() > 0) {
|
||||
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, accumulate_numeric, key_pool);
|
||||
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, accumulate_numeric, key_pool, -1);
|
||||
pending_tile_features.clear();
|
||||
if (outlayer->features.size() >= feature_limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (preserve_input_order) {
|
||||
@@ -1927,10 +1974,14 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
std::vector<source_tile> sts;
|
||||
sts.push_back(st);
|
||||
|
||||
// feature_limit arg is 1, because we just care whether there are any overzoomed features
|
||||
// left after clipping to the child tile, not about their actual content
|
||||
std::string child = overzoom(sts,
|
||||
nz + 1, nx * 2 + x, ny * 2 + y,
|
||||
detail, buffer, keep, exclude, exclude_prefix, false, NULL,
|
||||
demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric);
|
||||
detail_or_unspecified, buffer, keep, exclude, exclude_prefix, false, NULL,
|
||||
demultiply, filter, preserve_input_order, attribute_accum, unidecode_data,
|
||||
simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric,
|
||||
1);
|
||||
if (child.size() > 0) {
|
||||
next_overzoomed_tiles->emplace_back(nx * 2 + x, ny * 2 + y);
|
||||
}
|
||||
@@ -1940,8 +1991,9 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
|
||||
}
|
||||
|
||||
if (bins.size() > 0) {
|
||||
outtile = assign_to_bins(outtile, bins, bin_by_id_list, nz, nx, ny, detail, attribute_accum, accumulate_numeric,
|
||||
keep, exclude, exclude_prefix);
|
||||
outtile = assign_to_bins(outtile, bins, bin_by_id_list, nz, nx, ny,
|
||||
attribute_accum, accumulate_numeric,
|
||||
keep, exclude, exclude_prefix, buffer);
|
||||
}
|
||||
|
||||
for (ssize_t i = outtile.layers.size() - 1; i >= 0; i--) {
|
||||
|
||||
Reference in New Issue
Block a user