mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-03 00:45:41 +02:00
Look up shared nodes once per vertex instead of once per tile
With --no-simplification-of-shared-nodes, simplify_lines() used to offset every vertex of every feature to world coordinates and check it against the Bloom filter and the global sorted list of shared nodes, in every tile at every zoom level. Whether a vertex is a shared node depends only on its world coordinates, so now it is found once, after the list of shared nodes has been made and before the geometry is sorted, by a parallel pass over each reader's geometry that marks each vertex in place, in the upper bits of its serialized operation byte. Decoding puts that state into a new field of draw (which still fits in 16 bytes), and it is carried through clipping, the copies across the antimeridian at z0, and the geometry written for the next zoom level. Polygon cleaning of coalesced features restores the state of any output vertex with the same coordinates as an input vertex. Vertices whose state is still unknown, because they were created by clipping or polygon cleaning or came back from a prefilter, are still looked up in the global list when they are simplified, so the output is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2nBqZisxNQfmEmon3vE9v
This commit is contained in:
@@ -476,7 +476,7 @@ static void rewrite(serial_feature const &osf, int z, int nextzoom, int maxzoom,
|
||||
|
||||
drawvec geom2;
|
||||
for (auto const &g : osf.geometry) {
|
||||
geom2.emplace_back(g.op, SHIFT_RIGHT(g.x + sx), SHIFT_RIGHT(g.y + sy));
|
||||
geom2.emplace_back(g.op, SHIFT_RIGHT(g.x + sx), SHIFT_RIGHT(g.y + sy), g.node);
|
||||
}
|
||||
|
||||
for (xo = bbox2[0]; xo <= bbox2[2]; xo++) {
|
||||
@@ -631,7 +631,9 @@ static double simplify_feature(serial_feature *p, drawvec const &shared_nodes, n
|
||||
// unioned exactly
|
||||
//
|
||||
// don't try to scale up because these are still world coordinates
|
||||
drawvec before = geom;
|
||||
coalesce_polygon(geom, false);
|
||||
restore_node_states(before, geom);
|
||||
}
|
||||
|
||||
// continues to simplify to line_detail even if we have extra detail
|
||||
@@ -979,13 +981,13 @@ static bool clip_to_tile(serial_feature &sf, int z, long long buffer) {
|
||||
|
||||
if (sf.bbox[0] <= (1LL << 32) * buffer / 256) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
sf.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x + (1LL << 32), sf.geometry[i].y));
|
||||
sf.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x + (1LL << 32), sf.geometry[i].y, sf.geometry[i].node));
|
||||
}
|
||||
}
|
||||
|
||||
if (sf.bbox[2] >= (1LL << 32) - ((1LL << 32) * buffer / 256)) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
sf.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x - (1LL << 32), sf.geometry[i].y));
|
||||
sf.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x - (1LL << 32), sf.geometry[i].y, sf.geometry[i].node));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2295,6 +2297,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
|
||||
// don't scale up because this is still world coordinates
|
||||
coalesce_polygon(to_clean, false);
|
||||
restore_node_states(features[simplified_geometry_through]->geometry, to_clean);
|
||||
features[simplified_geometry_through]->geometry = std::move(to_clean);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user