Skip to content

Commit

Permalink
Merge pull request #760 from mapbox/preserve-shared-nodes
Browse files Browse the repository at this point in the history
Add an option to keep intersection nodes from being simplified away
  • Loading branch information
e-n-f committed May 16, 2019
2 parents 9dc92a4 + dcdfb94 commit b550c7b
Show file tree
Hide file tree
Showing 10 changed files with 840 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
## 1.34.3

* Add an option to keep intersection nodes from being simplified away

## 1.34.2

* Be more consistent about when longitudes beyond 180 are allowed.
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -470,6 +470,7 @@ the same layer, enclose them in an `all` expression so they will all be evaluate
the line or polygon within one tile unit of its proper location. You can probably go up to about 10 without too much visible difference.
* `-ps` or `--no-line-simplification`: Don't simplify lines and polygons
* `-pS` or `--simplify-only-low-zooms`: Don't simplify lines and polygons at maxzoom (but do simplify at lower zooms)
* `-pn` or `--no-simplification-of-shared-nodes`: Don't simplify away nodes that appear in more than one feature or are used multiple times within the same feature, so that the intersection node will not be lost from intersecting roads. (This will not be effective if you also use `--coalesce` or `--detect-shared-borders`.)
* `-pt` or `--no-tiny-polygon-reduction`: Don't combine the area of very small polygons into small squares that represent their combined area.

### Attempts to improve shared polygon boundaries
Expand Down
9 changes: 8 additions & 1 deletion geometry.cpp
Expand Up @@ -802,7 +802,7 @@ 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, size_t retain) {
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain, drawvec const &shared_nodes) {
int res = 1 << (32 - detail - z);
long long area = 1LL << (32 - z);

Expand All @@ -814,6 +814,13 @@ drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds,
} else {
geom[i].necessary = 1;
}

if (prevent[P_SIMPLIFY_SHARED_NODES]) {
auto pt = std::lower_bound(shared_nodes.begin(), shared_nodes.end(), geom[i]);
if (pt != shared_nodes.end() && *pt == geom[i]) {
geom[i].necessary = true;
}
}
}

if (mark_tile_bounds) {
Expand Down
2 changes: 1 addition & 1 deletion geometry.hpp
Expand Up @@ -68,7 +68,7 @@ drawvec clip_lines(drawvec &geom, int z, long long buffer);
drawvec stairstep(drawvec &geom, int z, int detail);
bool point_within_tile(long long x, long long y, int z);
int quick_check(long long *bbox, int z, long long buffer);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain, drawvec const &shared_nodes);
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
Expand Up @@ -2569,6 +2569,7 @@ int main(int argc, char **argv) {
{"no-line-simplification", no_argument, &prevent[P_SIMPLIFY], 1},
{"simplify-only-low-zooms", no_argument, &prevent[P_SIMPLIFY_LOW], 1},
{"no-tiny-polygon-reduction", no_argument, &prevent[P_TINY_POLYGON_REDUCTION], 1},
{"no-simplification-of-shared-nodes", no_argument, &prevent[P_SIMPLIFY_SHARED_NODES], 1},

{"Attempts to improve shared polygon boundaries", 0, 0, 0},
{"detect-shared-borders", no_argument, &additional[A_DETECT_SHARED_BORDERS], 1},
Expand Down
1 change: 1 addition & 0 deletions options.hpp
Expand Up @@ -28,6 +28,7 @@

#define P_SIMPLIFY ((int) 's')
#define P_SIMPLIFY_LOW ((int) 'S')
#define P_SIMPLIFY_SHARED_NODES ((int) 'n')
#define P_FEATURE_LIMIT ((int) 'f')
#define P_KILOBYTE_LIMIT ((int) 'k')
#define P_DYNAMIC_DROP ((int) 'd')
Expand Down
263 changes: 263 additions & 0 deletions tests/tl_2018_51685_roads/in.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

34 changes: 31 additions & 3 deletions tile.cpp
Expand Up @@ -381,6 +381,7 @@ struct partial_arg {
std::vector<struct partial> *partials = NULL;
int task = 0;
int tasks = 0;
drawvec *shared_nodes;
};

drawvec revive_polygon(drawvec &geom, double area, int z, int detail) {
Expand Down Expand Up @@ -464,7 +465,7 @@ void *partial_feature_worker(void *v) {
}

if (!already_marked) {
drawvec ngeom = simplify_lines(geom, z, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), (*partials)[i].simplification, t == VT_POLYGON ? 4 : 0);
drawvec ngeom = simplify_lines(geom, z, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), (*partials)[i].simplification, t == VT_POLYGON ? 4 : 0, *(a->shared_nodes));

if (t != VT_POLYGON || ngeom.size() >= 3) {
geom = ngeom;
Expand Down Expand Up @@ -898,7 +899,7 @@ bool find_common_edges(std::vector<partial> &partials, int z, int line_detail, d
}
}
if (!(prevent[P_SIMPLIFY] || (z == maxzoom && prevent[P_SIMPLIFY_LOW]) || (z < maxzoom && additional[A_GRID_LOW_ZOOMS]))) {
simplified_arcs[ai->second] = simplify_lines(dv, z, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), simplification, 4);
simplified_arcs[ai->second] = simplify_lines(dv, z, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), simplification, 4, drawvec());
} else {
simplified_arcs[ai->second] = dv;
}
Expand Down Expand Up @@ -1763,6 +1764,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
std::vector<long long> extents;
std::map<std::string, accum_state> attribute_accum_state;
double coalesced_area = 0;
drawvec shared_nodes;

int within[child_shards];
std::atomic<long long> geompos[child_shards];
Expand Down Expand Up @@ -1962,6 +1964,12 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
}

if (sf.geometry.size() > 0) {
if (prevent[P_SIMPLIFY_SHARED_NODES]) {
for (auto &g : sf.geometry) {
shared_nodes.push_back(g);
}
}

partial p;
p.geoms.push_back(sf.geometry);
p.layer = sf.layer;
Expand Down Expand Up @@ -1991,6 +1999,25 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
coalesced_area = 0;
}

{
drawvec just_shared_nodes;
std::sort(shared_nodes.begin(), shared_nodes.end());

for (size_t i = 0; i + 1 < shared_nodes.size(); i++) {
if (shared_nodes[i] == shared_nodes[i + 1]) {
just_shared_nodes.push_back(shared_nodes[i]);

draw d = shared_nodes[i];
i++;
while (i + 1 < shared_nodes.size() && shared_nodes[i + 1] == d) {
i++;
}
}
}

shared_nodes = just_shared_nodes;
}

for (size_t i = 0; i < partials.size(); i++) {
partial &p = partials[i];

Expand Down Expand Up @@ -2073,6 +2100,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
args[i].task = i;
args[i].tasks = tasks;
args[i].partials = &partials;
args[i].shared_nodes = &shared_nodes;

if (tasks > 1) {
if (pthread_create(&pthreads[i], NULL, partial_feature_worker, &args[i]) != 0) {
Expand Down Expand Up @@ -2186,7 +2214,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
if (layer_features[x].coalesced && layer_features[x].type == VT_LINE) {
layer_features[x].geom = remove_noop(layer_features[x].geom, layer_features[x].type, 0);
layer_features[x].geom = simplify_lines(layer_features[x].geom, 32, 0,
!(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), simplification, layer_features[x].type == VT_POLYGON ? 4 : 0);
!(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), simplification, layer_features[x].type == VT_POLYGON ? 4 : 0, shared_nodes);
}

if (layer_features[x].type == VT_POLYGON) {
Expand Down
2 changes: 1 addition & 1 deletion version.hpp
@@ -1,6 +1,6 @@
#ifndef VERSION_HPP
#define VERSION_HPP

#define VERSION "v1.34.2"
#define VERSION "v1.34.3"

#endif

0 comments on commit b550c7b

Please sign in to comment.