mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Clip large LineString features down to the bounds of the tile
This commit is contained in:
@@ -10,7 +10,7 @@ vector_tile.pb.cc vector_tile.pb.h: vector_tile.proto
|
|||||||
|
|
||||||
PG=
|
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
|
g++ $(PG) -O3 -g -Wall -o $@ $^ -lm -lz -lprotobuf-lite -lsqlite3
|
||||||
|
|
||||||
libjsonpull.a: jsonpull.o
|
libjsonpull.a: jsonpull.o
|
||||||
|
|||||||
@@ -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 outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax);
|
||||||
int outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax);
|
int outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax);
|
||||||
int accept = 0;
|
int accept = 0;
|
||||||
|
int changed = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop
|
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;
|
*x0 = x;
|
||||||
*y0 = y;
|
*y0 = y;
|
||||||
outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax);
|
outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax);
|
||||||
|
changed = 1;
|
||||||
} else {
|
} else {
|
||||||
*x1 = x;
|
*x1 = x;
|
||||||
*y1 = y;
|
*y1 = y;
|
||||||
outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax);
|
outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax);
|
||||||
|
changed = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return accept;
|
if (accept == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return changed + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
#include "clip.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CMD_BITS 3
|
#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 simplify_lines(struct draw *geom, int n, int z, int detail) {
|
||||||
int res = 1 << (32 - detail - z);
|
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);
|
deserialize_int(&meta, &t);
|
||||||
decode_feature(&meta, geom, z, tx, ty, detail);
|
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) {
|
if (t == VT_LINE || t == VT_POLYGON) {
|
||||||
len = simplify_lines(geom, len, z, detail);
|
len = simplify_lines(geom, len, z, detail);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user