Skip to content

Commit

Permalink
Merge pull request #142 from mapbox/consistent-clip
Browse files Browse the repository at this point in the history
Simplify lines consistently on opposite sides of tile boundaries
  • Loading branch information
e-n-f committed Jan 7, 2016
2 parents e1e028b + 1f8b6fa commit 5e02bdd
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.6.2

* Make sure line simplification matches on opposite sides of a tile boundary

## 1.6.1

* Use multiple threads for line simplification and polygon cleaning
Expand Down
40 changes: 40 additions & 0 deletions geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -750,8 +750,46 @@ static void douglas_peucker(drawvec &geom, int start, int n, double e) {
}
}

// If any line segment crosses a tile boundary, add a node there
// that cannot be simplified away, to prevent the edge of any
// feature from jumping abruptly at the tile boundary.
drawvec impose_tile_boundaries(drawvec &geom, long long extent) {
drawvec out;

for (unsigned i = 0; i < geom.size(); i++) {
if (i > 0 && geom[i].op == VT_LINETO && (geom[i - 1].op == VT_MOVETO || geom[i - 1].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;

int c = clip(&x1, &y1, &x2, &y2, 0, 0, extent, extent);

if (c > 1) { // clipped
if (x1 != geom[i - 1].x || y1 != geom[i - 1].y) {
out.push_back(draw(VT_LINETO, x1, y1));
out[out.size() - 1].necessary = 1;
}
if (x2 != geom[i - 0].x || y2 != geom[i - 0].y) {
out.push_back(draw(VT_LINETO, x2, y2));
out[out.size() - 1].necessary = 1;
}
}
}

out.push_back(geom[i]);
}

return out;
}

drawvec simplify_lines(drawvec &geom, int z, int detail) {
int res = 1 << (32 - detail - z);
long long area = 0xFFFFFFFF;
if (z != 0) {
area = 1LL << (32 - z);
}

unsigned i;
for (i = 0; i < geom.size(); i++) {
Expand All @@ -764,6 +802,8 @@ drawvec simplify_lines(drawvec &geom, int z, int detail) {
}
}

geom = impose_tile_boundaries(geom, area);

for (i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) {
unsigned j;
Expand Down
6 changes: 3 additions & 3 deletions tile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -493,15 +493,15 @@ void *partial_feature_worker(void *v) {

for (unsigned i = a->task; i < (*partials).size(); i += a->tasks) {
drawvec geom = (*partials)[i].geom;
(*partials)[i].geom.clear(); // avoid keeping two copies in memory
(*partials)[i].geom.clear(); // avoid keeping two copies in memory
signed char t = (*partials)[i].t;
int z = (*partials)[i].z;
int line_detail = (*partials)[i].line_detail;
char *prevent = (*partials)[i].prevent;
char *additional = (*partials)[i].additional;

if ((t == VT_LINE || t == VT_POLYGON) && !prevent['s' & 0xFF]) {
if (1 /* !reduced */) { // XXX why did this not simplify if reduced?
if (1 /* !reduced */) { // XXX why did this not simplify if reduced?
if (t == VT_LINE) {
geom = remove_noop(geom, t, 32 - z - line_detail);
}
Expand Down Expand Up @@ -845,7 +845,7 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi
// This is serial because decode_meta() unifies duplicates
for (unsigned i = 0; i < partials.size(); i++) {
drawvec geom = partials[i].geom;
partials[i].geom.clear(); // avoid keeping two copies in memory
partials[i].geom.clear(); // avoid keeping two copies in memory
long long layer = partials[i].layer;
char *meta = partials[i].meta;
signed char t = partials[i].t;
Expand Down
2 changes: 1 addition & 1 deletion version.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define VERSION "tippecanoe v1.6.1\n"
#define VERSION "tippecanoe v1.6.2\n"

0 comments on commit 5e02bdd

Please sign in to comment.