mirror of
https://github.com/mapbox/tippecanoe.git
synced 2025-01-22 04:18:01 +00:00
Clip large LineString features down to the bounds of the tile
This commit is contained in:
parent
2d34916fca
commit
120809b004
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ vector_tile.pb.cc vector_tile.pb.h: vector_tile.proto
|
||||
|
||||
PG=
|
||||
|
||||
tippecanoe: geojson.o jsonpull.o vector_tile.pb.o tile.o
|
||||
tippecanoe: geojson.o jsonpull.o vector_tile.pb.o tile.o clip.o
|
||||
g++ $(PG) -O3 -g -Wall -o $@ $^ -lm -lz -lprotobuf-lite -lsqlite3
|
||||
|
||||
libjsonpull.a: jsonpull.o
|
||||
|
9
clip.c
9
clip.c
@ -28,6 +28,7 @@ int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymi
|
||||
int outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax);
|
||||
int outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax);
|
||||
int accept = 0;
|
||||
int changed = 0;
|
||||
|
||||
while (1) {
|
||||
if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop
|
||||
@ -65,13 +66,19 @@ int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymi
|
||||
*x0 = x;
|
||||
*y0 = y;
|
||||
outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax);
|
||||
changed = 1;
|
||||
} else {
|
||||
*x1 = x;
|
||||
*y1 = y;
|
||||
outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax);
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return accept;
|
||||
if (accept == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return changed + 1;
|
||||
}
|
||||
}
|
||||
|
57
tile.cc
57
tile.cc
@ -13,6 +13,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include "tile.h"
|
||||
#include "clip.h"
|
||||
}
|
||||
|
||||
#define CMD_BITS 3
|
||||
@ -340,6 +341,58 @@ void douglas_peucker(struct draw *geom, int n, double e) {
|
||||
}
|
||||
}
|
||||
|
||||
int clip_lines(struct draw *geom, int n, int z, int detail) {
|
||||
struct draw tmp[n * 3];
|
||||
int out = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (i - 1 >= 0 && (geom[i - 1].op == VT_MOVETO || geom[i - 1].op == VT_LINETO) && geom[i].op == VT_LINETO) {
|
||||
double x1 = geom[i - 1].x;
|
||||
double y1 = geom[i - 1].y;
|
||||
|
||||
double x2 = geom[i - 0].x;
|
||||
double y2 = geom[i - 0].y;
|
||||
|
||||
unsigned area = 0xFFFFFFFF;
|
||||
if (z != 0) {
|
||||
area = 1 << (32 - z);
|
||||
}
|
||||
|
||||
int c = clip(&x1, &y1, &x2, &y2, 0, 0, area, area);
|
||||
|
||||
if (c > 1) { // clipped
|
||||
tmp[out].op = VT_MOVETO;
|
||||
tmp[out].x = x1;
|
||||
tmp[out].y = y1;
|
||||
out++;
|
||||
|
||||
tmp[out].op = VT_LINETO;
|
||||
tmp[out].x = x2;
|
||||
tmp[out].y = y2;
|
||||
out++;
|
||||
|
||||
tmp[out].op = VT_MOVETO;
|
||||
tmp[out].x = geom[i].x;
|
||||
tmp[out].y = geom[i].y;
|
||||
out++;
|
||||
} else if (c == 1) { // unchanged
|
||||
tmp[out++] = geom[i];
|
||||
} else { // clipped away entirely
|
||||
tmp[out].op = VT_MOVETO;
|
||||
tmp[out].op = geom[i].x;
|
||||
tmp[out].op = geom[i].y;
|
||||
out++;
|
||||
}
|
||||
} else {
|
||||
tmp[out++] = geom[i];
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(geom, tmp, out * sizeof(struct draw));
|
||||
return out;
|
||||
}
|
||||
|
||||
int simplify_lines(struct draw *geom, int n, int z, int detail) {
|
||||
int res = 1 << (32 - detail - z);
|
||||
|
||||
@ -442,6 +495,10 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
|
||||
deserialize_int(&meta, &t);
|
||||
decode_feature(&meta, geom, z, tx, ty, detail);
|
||||
|
||||
if (t == VT_LINE) {
|
||||
len = clip_lines(geom, len, z, detail);
|
||||
}
|
||||
|
||||
if (t == VT_LINE || t == VT_POLYGON) {
|
||||
len = simplify_lines(geom, len, z, detail);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user