mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Variable-depth pyramids: don't prune children while a minzoom-gated feature is still pending (#399)
Don't prune variable-depth children while a minzoom-gated feature is pending The minzoom_feature_pending flag from #397 keeps a variable-depth pyramid subdividing until explicit per-feature minzooms are satisfied, but two gaps let features still be dropped: The flag was only set when tippecanoe_minzoom > z + 1, so a feature whose minzoom is exactly z + 1 never marked the tile pending, even though a leaf at z carries only z-visible content. The early-stop commit never consulted the flag: a tile that succeeded in stopping early inserted itself into skip_children_out unconditionally, pruning the children the pending feature needed. The flag only inflated estimated_complexity_out, which the pruning ignores. Set the flag for any feature excluded below its minzoom, include it in the early-stop veto, and skip child pruning while it is set. Adds a fixture covering the minzoom == z + 1 boundary; make test passes with no diffs to existing fixtures.
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
{"type":"Feature","id":1,"tippecanoe":{"minzoom":10},"properties":{"depth":10},"geometry":{"type":"Point","coordinates":[0.05,0.05]}}
|
||||||
|
{"type":"Feature","id":2,"tippecanoe":{"minzoom":11},"properties":{"depth":11},"geometry":{"type":"Point","coordinates":[0.06,0.06]}}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
{ "type": "FeatureCollection", "properties": {
|
||||||
|
"antimeridian_adjusted_bounds": "0.050000,0.050000,0.060000,0.060000",
|
||||||
|
"bounds": "0.050000,0.050000,0.060000,0.060000",
|
||||||
|
"center": "0.060000,0.060000,11",
|
||||||
|
"description": "tests/minzoom-variable-depth/out/-Z10_-z11_--generate-variable-depth-tile-pyramid.json.check.mbtiles",
|
||||||
|
"format": "pbf",
|
||||||
|
"generator_options": "./tippecanoe -q -a@ -f -o tests/minzoom-variable-depth/out/-Z10_-z11_--generate-variable-depth-tile-pyramid.json.check.mbtiles -Z10 -z11 --generate-variable-depth-tile-pyramid tests/minzoom-variable-depth/in.json",
|
||||||
|
"json": "{\"vector_layers\":[{\"id\":\"in\",\"description\":\"\",\"minzoom\":10,\"maxzoom\":11,\"fields\":{\"depth\":\"Number\"}}],\"tilestats\":{\"layerCount\":1,\"layers\":[{\"layer\":\"in\",\"count\":2,\"geometry\":\"Point\",\"attributeCount\":1,\"attributes\":[{\"attribute\":\"depth\",\"count\":2,\"type\":\"number\",\"values\":[10,11],\"min\":10,\"max\":11}]}]}}",
|
||||||
|
"maxzoom": "11",
|
||||||
|
"minzoom": "10",
|
||||||
|
"name": "tests/minzoom-variable-depth/out/-Z10_-z11_--generate-variable-depth-tile-pyramid.json.check.mbtiles",
|
||||||
|
"type": "overlay",
|
||||||
|
"version": "2"
|
||||||
|
}, "features": [
|
||||||
|
{ "type": "FeatureCollection", "properties": { "zoom": 10, "x": 512, "y": 511 }, "features": [
|
||||||
|
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
|
||||||
|
{ "type": "Feature", "id": 1, "properties": { "depth": 10 }, "geometry": { "type": "Point", "coordinates": [ 0.050039, 0.049953 ] } }
|
||||||
|
] }
|
||||||
|
] }
|
||||||
|
,
|
||||||
|
{ "type": "FeatureCollection", "properties": { "zoom": 11, "x": 1024, "y": 1023 }, "features": [
|
||||||
|
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
|
||||||
|
{ "type": "Feature", "id": 1, "properties": { "depth": 10 }, "geometry": { "type": "Point", "coordinates": [ 0.049996, 0.049996 ] } }
|
||||||
|
,
|
||||||
|
{ "type": "Feature", "id": 2, "properties": { "depth": 11 }, "geometry": { "type": "Point", "coordinates": [ 0.059996, 0.059996 ] } }
|
||||||
|
] }
|
||||||
|
] }
|
||||||
|
] }
|
||||||
@@ -1205,9 +1205,9 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sf.tippecanoe_minzoom != -1 && z < sf.tippecanoe_minzoom) {
|
if (sf.tippecanoe_minzoom != -1 && z < sf.tippecanoe_minzoom) {
|
||||||
if (sf.tippecanoe_minzoom > z + 1) {
|
// a leaf at z carries only z-visible content, so an excluded feature at
|
||||||
next_feature_state.minzoom_feature_pending = true;
|
// any deeper minzoom (even z + 1) must block leafing here
|
||||||
}
|
next_feature_state.minzoom_feature_pending = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sf.tippecanoe_maxzoom != -1 && z > sf.tippecanoe_maxzoom) {
|
if (sf.tippecanoe_maxzoom != -1 && z > sf.tippecanoe_maxzoom) {
|
||||||
@@ -2684,7 +2684,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
|||||||
oprogress = progress;
|
oprogress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trying_to_stop_early && line_detail == first_detail && !can_stop_early) {
|
if (trying_to_stop_early && line_detail == first_detail && (!can_stop_early || next_feature_state.minzoom_feature_pending)) {
|
||||||
// didn't work, try a lower detail
|
// didn't work, try a lower detail
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3036,9 +3036,10 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
|||||||
exit(EXIT_PTHREAD);
|
exit(EXIT_PTHREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trying_to_stop_early && line_detail == first_detail) {
|
if (trying_to_stop_early && line_detail == first_detail &&
|
||||||
// We succeeded in stopping early.
|
!next_feature_state.minzoom_feature_pending) {
|
||||||
// Prune the child tiles.
|
// We succeeded in stopping early (and no excluded feature is
|
||||||
|
// waiting for a deeper zoom). Prune the child tiles.
|
||||||
|
|
||||||
strategy.truncated_zooms++;
|
strategy.truncated_zooms++;
|
||||||
skip_children_out.insert(zxy(z, tx, ty));
|
skip_children_out.insert(zxy(z, tx, ty));
|
||||||
|
|||||||
Reference in New Issue
Block a user