Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find edges shared between polygons and simplify them individually #302

Merged
merged 18 commits into from
Oct 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.14.3

* Add --detect-shared-borders option for better polygon simplification

## 1.14.2

* Enforce that string feature attributes must be encoded as UTF-8
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ resolution is obtained than by using a smaller _maxzoom_ or _detail_.
* -al or --drop-lines: Let "dot" dropping at lower zooms apply to lines too
* -ap or --drop-polygons: Let "dot" dropping at lower zooms apply to polygons too
* -ag or --calculate-feature-density: Add a new attribute, `tippecanoe_feature_density`, to each feature, to record how densely features are spaced in that area of the tile. You can use this attribute in the style to produce a glowing effect where points are densely packed. It can range from 0 in the sparsest areas to 255 in the densest.
* -ab or --detect-shared-borders: In the manner of [TopoJSON](https://github.com/mbostock/topojson/wiki/Introduction), detect borders that are shared between multiple polygons and simplify them identically in each polygon. This takes more time and memory than considering each polygon individually.

### Doing less

Expand Down Expand Up @@ -253,12 +254,12 @@ lower resolutions before failing if it still doesn't fit.
Development
-----------

Requires sqlite3 (should already be installed on MacOS). Rebuilding the manpage
Requires sqlite3 and zlib (should already be installed on MacOS). Rebuilding the manpage
uses md2man (`gem install md2man`).

Linux:

sudo apt-get install libsqlite3-dev
sudo apt-get install libsqlite3-dev zlib1g-dev

Then build:

Expand Down
32 changes: 23 additions & 9 deletions geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,17 +1042,19 @@ drawvec impose_tile_boundaries(drawvec &geom, long long extent) {
return out;
}

drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification) {
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, bool already_marked) {
int res = 1 << (32 - detail - z);
long long area = 1LL << (32 - z);

for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) {
geom[i].necessary = 1;
} else if (geom[i].op == VT_LINETO) {
geom[i].necessary = 0;
} else {
geom[i].necessary = 1;
if (!already_marked) {
for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) {
geom[i].necessary = 1;
} else if (geom[i].op == VT_LINETO) {
geom[i].necessary = 0;
} else {
geom[i].necessary = 1;
}
}
}

Expand All @@ -1073,7 +1075,19 @@ drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds,
geom[j - 1].necessary = 1;

if (j - i > 1) {
douglas_peucker(geom, i, j - i, res * simplification);
if (already_marked && geom[j - 1] < geom[i]) {
drawvec dv;
for (size_t k = j; k > i; k--) {
dv.push_back(geom[k - 1]);
}
douglas_peucker(dv, 0, j - i, res * simplification);
size_t l = 0;
for (size_t k = j; k > i; k--) {
geom[k - 1] = dv[l++];
}
} else {
douglas_peucker(geom, i, j - i, res * simplification);
}
}
i = j - 1;
}
Expand Down
23 changes: 22 additions & 1 deletion geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,30 @@ struct draw {
this->op = nop;
this->x = nx;
this->y = ny;
this->necessary = 0;
}

draw() {
this->op = 0;
this->x = 0;
this->y = 0;
this->necessary = 0;
}

bool operator<(draw const &s) const {
if (y < s.y || (y == s.y && x < s.x)) {
return true;
} else {
return false;
}
}

bool operator==(draw const &s) const {
return y == s.y && x == s.x;
}

bool operator!=(draw const &s) const {
return y != s.y || x != s.x;
}
};

Expand All @@ -43,7 +64,7 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
drawvec clip_lines(drawvec &geom, int z, int detail, long long buffer);
bool point_within_tile(long long x, long long y, int z, int detail, long long buffer);
int quick_check(long long *bbox, int z, int detail, long long buffer);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, bool already_marked);
drawvec reorder_lines(drawvec &geom);
drawvec fix_polygon(drawvec &geom);
std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms);
Expand Down
1 change: 1 addition & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1801,6 +1801,7 @@ int main(int argc, char **argv) {
{"drop-polygons", no_argument, &additional[A_POLYGON_DROP], 1},
{"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 1},
{"calculate-feature-density", no_argument, &additional[A_CALCULATE_FEATURE_DENSITY], 1},
{"detect-shared-borders", no_argument, &additional[A_DETECT_SHARED_BORDERS], 1},

{"no-line-simplification", no_argument, &prevent[P_SIMPLIFY], 1},
{"simplify-only-low-zooms", no_argument, &prevent[P_SIMPLIFY_LOW], 1},
Expand Down
6 changes: 4 additions & 2 deletions man/tippecanoe.1
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ which may not be what you want.
\-ap or \-\-drop\-polygons: Let "dot" dropping at lower zooms apply to polygons too
.IP \(bu 2
\-ag or \-\-calculate\-feature\-density: Add a new attribute, \fB\fCtippecanoe_feature_density\fR, to each feature, to record how densely features are spaced in that area of the tile. You can use this attribute in the style to produce a glowing effect where points are densely packed. It can range from 0 in the sparsest areas to 255 in the densest.
.IP \(bu 2
\-ab or \-\-detect\-shared\-borders: In the manner of TopoJSON \[la]https://github.com/mbostock/topojson/wiki/Introduction\[ra], detect borders that are shared between multiple polygons and simplify them identically in each polygon. This takes more time and memory than considering each polygon individually.
.RE
.SS Doing less
.RS
Expand Down Expand Up @@ -289,14 +291,14 @@ If a tile is larger than 500K, it will try encoding that tile at progressively
lower resolutions before failing if it still doesn't fit.
.SH Development
.PP
Requires sqlite3 (should already be installed on MacOS). Rebuilding the manpage
Requires sqlite3 and zlib (should already be installed on MacOS). Rebuilding the manpage
uses md2man (\fB\fCgem install md2man\fR).
.PP
Linux:
.PP
.RS
.nf
sudo apt\-get install libsqlite3\-dev
sudo apt\-get install libsqlite3\-dev zlib1g\-dev
.fi
.RE
.PP
Expand Down
1 change: 1 addition & 0 deletions options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define A_LINE_DROP ((int) 'l')
#define A_DEBUG_POLYGON ((int) 'd')
#define A_POLYGON_DROP ((int) 'p')
#define A_DETECT_SHARED_BORDERS ((int) 'b')
#define A_PREFER_RADIX_SORT ((int) 'R')
#define A_CALCULATE_FEATURE_DENSITY ((int) 'g')

Expand Down
8 changes: 8 additions & 0 deletions tests/border/in.json

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions tests/border/out/-z1_--detect-shared-borders.json

Large diffs are not rendered by default.