mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Treat points created by clipping and tiny polygon placeholders as not shared
Points that clipping creates along a feature's edges, other than at the existing vertices, and the vertices of tiny polygon placeholders, are not vertices of the original geometry, so they are now marked as not being shared nodes instead of being looked up in the global list of shared nodes when they are simplified. This could only change the output where a vertex of some other feature happens to fall exactly on one of these new points, and in practice none of them ever turned out to be shared nodes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2nBqZisxNQfmEmon3vE9v
This commit is contained in:
+9
-3
@@ -5,9 +5,15 @@
|
||||
instead of again in every tile at every zoom level. Each vertex now carries
|
||||
whether it is a shared node, in the upper bits of its serialized operation
|
||||
byte and in a new field of `draw`, through clipping and into the geometry
|
||||
for the next zoom level. Only vertices that are created during tiling,
|
||||
by clipping or by polygon cleaning, or that come back from a prefilter,
|
||||
still need to be looked up. Output is unchanged.
|
||||
for the next zoom level. Vertices that are already being kept, because they
|
||||
begin a ring or are on the tile boundary, are not looked up at all.
|
||||
* Points that clipping creates along a feature's edges, and the vertices
|
||||
of tiny polygon placeholders, are no longer considered to be shared nodes,
|
||||
since they are not vertices of the original geometry. This could only
|
||||
change the output where a vertex of some other feature happens to fall
|
||||
exactly on one of these new points, and means that only
|
||||
vertices that come back from a prefilter, or that are created by polygon
|
||||
cleaning, still need to be looked up in the list of shared nodes during tiling.
|
||||
|
||||
# 2.82.0
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "read_json.hpp"
|
||||
|
||||
// A vertex being clipped, which remembers whether it is a shared node.
|
||||
// Vertices created at the intersections with the clipping edges don't know.
|
||||
struct clip_point_d {
|
||||
double first;
|
||||
double second;
|
||||
@@ -146,9 +145,10 @@ drawvec clip_lines(drawvec &geom, long long minx, long long miny, long long maxx
|
||||
int c = clip(&x1, &y1, &x2, &y2, minx, miny, maxx, maxy);
|
||||
|
||||
if (c > 1) { // clipped
|
||||
// endpoints that weren't moved by clipping keep their node state
|
||||
out.push_back(draw(VT_MOVETO, x1, y1, (x1 == geom[i - 1].x && y1 == geom[i - 1].y) ? geom[i - 1].node : NODE_UNKNOWN));
|
||||
out.push_back(draw(VT_LINETO, x2, y2, (x2 == geom[i].x && y2 == geom[i].y) ? geom[i].node : NODE_UNKNOWN));
|
||||
// endpoints that weren't moved by clipping keep their node state;
|
||||
// new endpoints along the segment aren't original vertices, so aren't shared nodes
|
||||
out.push_back(draw(VT_MOVETO, x1, y1, (x1 == geom[i - 1].x && y1 == geom[i - 1].y) ? geom[i - 1].node : NODE_NOT_SHARED));
|
||||
out.push_back(draw(VT_LINETO, x2, y2, (x2 == geom[i].x && y2 == geom[i].y) ? geom[i].node : NODE_NOT_SHARED));
|
||||
out.push_back(draw(VT_MOVETO, geom[i].x, geom[i].y, geom[i].node));
|
||||
} else if (c == 1) { // unchanged
|
||||
out.push_back(geom[i]);
|
||||
@@ -800,6 +800,12 @@ static clip_point_d intersect1(clip_point_d const &a, clip_point_d const &b, int
|
||||
|
||||
// If the intersection is at one of the endpoints of the segment,
|
||||
// it is the same vertex, and has the same node state.
|
||||
//
|
||||
// Otherwise it is a new point along the segment, which is not a vertex
|
||||
// of the original geometry, so it is treated as not being a shared node.
|
||||
// (It could only be one if some other feature had a vertex exactly where
|
||||
// this feature's edge crosses the clipping line, without this feature
|
||||
// having a vertex there too.)
|
||||
static clip_point_d intersect(clip_point_d const &a, clip_point_d const &b, int edge, long long minx, long long miny, long long maxx, long long maxy) {
|
||||
clip_point_d p = intersect1(a, b, edge, minx, miny, maxx, maxy);
|
||||
double x = std::round(p.first), y = std::round(p.second);
|
||||
@@ -808,6 +814,8 @@ static clip_point_d intersect(clip_point_d const &a, clip_point_d const &b, int
|
||||
p.node = a.node;
|
||||
} else if (x == b.first && y == b.second) {
|
||||
p.node = b.node;
|
||||
} else {
|
||||
p.node = NODE_NOT_SHARED;
|
||||
}
|
||||
|
||||
return p;
|
||||
@@ -1123,11 +1131,14 @@ drawvec reduce_tiny_poly(drawvec const &geom, int z, int detail, bool *still_nee
|
||||
if (area > 0 && *accum_area > pixel * pixel) {
|
||||
// XXX use centroid;
|
||||
|
||||
out.emplace_back(VT_MOVETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2 + pixel);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2 + pixel);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2);
|
||||
// This placeholder is synthetic, so none of its vertices
|
||||
// can be shared nodes from the original geometry.
|
||||
|
||||
out.emplace_back(VT_MOVETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2, NODE_NOT_SHARED);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2, NODE_NOT_SHARED);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2 + pixel, NODE_NOT_SHARED);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2 + pixel, NODE_NOT_SHARED);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2, NODE_NOT_SHARED);
|
||||
|
||||
*accum_area -= pixel * pixel;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user