Clip large LineString features down to the bounds of the tile

This commit is contained in:
Eric Fischer 2014-09-26 17:07:52 -07:00
parent 2d34916fca
commit 120809b004
3 changed files with 66 additions and 2 deletions

View File

@ -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
View File

@ -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
View File

@ -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);
}