mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Fully deprecate -detect-shared-borders into an alias
This commit is contained in:
@@ -58,7 +58,7 @@ C = $(wildcard *.c) $(wildcard *.cpp)
|
||||
INCLUDES = -I/usr/local/include -I.
|
||||
LIBS = -L/usr/local/lib
|
||||
|
||||
tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o pmtiles_file.o plugin.o read_json.o write_json.o geobuf.o flatgeobuf.o evaluator.o geocsv.o csv.o geojson-loop.o json_logger.o visvalingam.o compression.o clip.o sort.o attribute.o thread.o shared_borders.o
|
||||
tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o pmtiles_file.o plugin.o read_json.o write_json.o geobuf.o flatgeobuf.o evaluator.o geocsv.o csv.o geojson-loop.o json_logger.o visvalingam.o compression.o clip.o sort.o attribute.o thread.o
|
||||
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
|
||||
|
||||
tippecanoe-enumerate: enumerate.o
|
||||
|
||||
@@ -500,7 +500,7 @@ the same layer, enclose them in an `all` expression so they will all be evaluate
|
||||
* `-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)
|
||||
* `--simplification-at-maximum-zoom=`_scale_: Use the specified _scale_ at maxzoom instead of the standard simplification scale (which still applies at lower zooms)
|
||||
* `-pn` or `--no-simplification-of-shared-nodes`: Don't simplify away nodes at which LineStrings or Polygon rings converge, diverge, or cross. (This will not be effective if you also use `--coalesce`.) In between intersection nodes, LineString segments or polygon edges will be simplified identically in each feature if possible. Use this instead of `--detect-shared-borders`.
|
||||
* `-pn` or `--no-simplification-of-shared-nodes`: Don't simplify away nodes at which LineStrings or Polygon rings converge, diverge, or cross. (This will not be effective if you also use `--coalesce`.) In between intersection nodes, LineString segments or polygon edges will be simplified identically in each feature if possible.
|
||||
* `-pt` or `--no-tiny-polygon-reduction`: Don't combine the area of very small polygons into small squares that represent their combined area.
|
||||
* `-pT` or `--no-tiny-polygon-reduction-at-maximum-zoom`: Combine the area of very small polygons into small squares that represent their combined area only at zoom levels below the maximum.
|
||||
* `--tiny-polygon-size=`_size_: Use the specified _size_ for tiny polygons instead of the default 2. Anything above 6 or so will lead to visible artifacts with the default tile detail.
|
||||
@@ -508,7 +508,7 @@ the same layer, enclose them in an `all` expression so they will all be evaluate
|
||||
|
||||
### Attempts to improve shared polygon boundaries
|
||||
|
||||
* `-ab` or `--detect-shared-borders`: DEPRECATED. 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. Use `no-simplification-of-shared-nodes` instead, which is faster and more correct.
|
||||
* `-ab` or `--detect-shared-borders`: This is an alias for `--no-simplification-of-shared-nodes`.
|
||||
* `-aL` or `--grid-low-zooms`: At all zoom levels below _maxzoom_, snap all lines and polygons to a stairstep grid instead of allowing diagonals. You will also want to specify a tile resolution, probably `-D8`. This option provides a way to display continuous parcel, gridded, or binned data at low zooms without overwhelming the tiles with tiny polygons, since features will either get stretched out to the grid unit or lost entirely, depending on how they happened to be aligned in the original data. You probably don't want to use this.
|
||||
|
||||
### Controlling clipping to tile boundaries
|
||||
|
||||
@@ -3691,6 +3691,10 @@ int main(int argc, char **argv) {
|
||||
decode_index = decode_quadkey;
|
||||
}
|
||||
|
||||
if (additional[A_DETECT_SHARED_BORDERS]) {
|
||||
prevent[P_SIMPLIFY_SHARED_NODES] = true;
|
||||
}
|
||||
|
||||
// Wait until here to project the bounding box, so that the behavior is
|
||||
// the same no matter what order the projection and bounding box are
|
||||
// specified in
|
||||
|
||||
+2
-2
@@ -641,7 +641,7 @@ the line or polygon within one tile unit of its proper location. You can probabl
|
||||
.IP \(bu 2
|
||||
\fB\fC\-\-simplification\-at\-maximum\-zoom=\fR\fIscale\fP: Use the specified \fIscale\fP at maxzoom instead of the standard simplification scale (which still applies at lower zooms)
|
||||
.IP \(bu 2
|
||||
\fB\fC\-pn\fR or \fB\fC\-\-no\-simplification\-of\-shared\-nodes\fR: Don't simplify away nodes at which LineStrings or Polygon rings converge, diverge, or cross. (This will not be effective if you also use \fB\fC\-\-coalesce\fR\&.) In between intersection nodes, LineString segments or polygon edges will be simplified identically in each feature if possible. Use this instead of \fB\fC\-\-detect\-shared\-borders\fR\&.
|
||||
\fB\fC\-pn\fR or \fB\fC\-\-no\-simplification\-of\-shared\-nodes\fR: Don't simplify away nodes at which LineStrings or Polygon rings converge, diverge, or cross. (This will not be effective if you also use \fB\fC\-\-coalesce\fR\&.) In between intersection nodes, LineString segments or polygon edges will be simplified identically in each feature if possible.
|
||||
.IP \(bu 2
|
||||
\fB\fC\-pt\fR or \fB\fC\-\-no\-tiny\-polygon\-reduction\fR: Don't combine the area of very small polygons into small squares that represent their combined area.
|
||||
.IP \(bu 2
|
||||
@@ -654,7 +654,7 @@ the line or polygon within one tile unit of its proper location. You can probabl
|
||||
.SS Attempts to improve shared polygon boundaries
|
||||
.RS
|
||||
.IP \(bu 2
|
||||
\fB\fC\-ab\fR or \fB\fC\-\-detect\-shared\-borders\fR: DEPRECATED. 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. Use \fB\fCno\-simplification\-of\-shared\-nodes\fR instead, which is faster and more correct.
|
||||
\fB\fC\-ab\fR or \fB\fC\-\-detect\-shared\-borders\fR: This is an alias for \fB\fC\-\-no\-simplification\-of\-shared\-nodes\fR\&.
|
||||
.IP \(bu 2
|
||||
\fB\fC\-aL\fR or \fB\fC\-\-grid\-low\-zooms\fR: At all zoom levels below \fImaxzoom\fP, snap all lines and polygons to a stairstep grid instead of allowing diagonals. You will also want to specify a tile resolution, probably \fB\fC\-D8\fR\&. This option provides a way to display continuous parcel, gridded, or binned data at low zooms without overwhelming the tiles with tiny polygons, since features will either get stretched out to the grid unit or lost entirely, depending on how they happened to be aligned in the original data. You probably don't want to use this.
|
||||
.RE
|
||||
|
||||
@@ -1,575 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include "geometry.hpp"
|
||||
#include "serial.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
// This should all be removed and replaced with --no-simplification-of-shared-nodes
|
||||
|
||||
// Does not fix up moveto/lineto
|
||||
static drawvec reverse_subring(drawvec const &dv) {
|
||||
drawvec out;
|
||||
|
||||
for (size_t i = dv.size(); i > 0; i--) {
|
||||
out.push_back(dv[i - 1]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
struct edge {
|
||||
unsigned x1 = 0;
|
||||
unsigned y1 = 0;
|
||||
unsigned x2 = 0;
|
||||
unsigned y2 = 0;
|
||||
unsigned ring = 0;
|
||||
|
||||
edge(unsigned _x1, unsigned _y1, unsigned _x2, unsigned _y2, unsigned _ring) {
|
||||
x1 = _x1;
|
||||
y1 = _y1;
|
||||
x2 = _x2;
|
||||
y2 = _y2;
|
||||
ring = _ring;
|
||||
}
|
||||
|
||||
bool operator<(const edge &s) const {
|
||||
long long cmp = (long long) y1 - s.y1;
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) x1 - s.x1;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) y2 - s.y2;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) x2 - s.x2;
|
||||
}
|
||||
return cmp < 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct edgecmp_ring {
|
||||
bool operator()(const edge &a, const edge &b) {
|
||||
long long cmp = (long long) a.y1 - b.y1;
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) a.x1 - b.x1;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) a.y2 - b.y2;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) a.x2 - b.x2;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
cmp = (long long) a.ring - b.ring;
|
||||
}
|
||||
return cmp < 0;
|
||||
}
|
||||
} edgecmp_ring;
|
||||
|
||||
bool edges_same(std::pair<std::vector<edge>::iterator, std::vector<edge>::iterator> e1, std::pair<std::vector<edge>::iterator, std::vector<edge>::iterator> e2) {
|
||||
if ((e2.second - e2.first) != (e1.second - e1.first)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (e1.first != e1.second) {
|
||||
if (e1.first->ring != e2.first->ring) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++e1.first;
|
||||
++e2.first;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool find_common_edges(std::vector<serial_feature> &features, int z, int line_detail, double simplification, int maxzoom, double merge_fraction) {
|
||||
size_t merge_count = ceil((1 - merge_fraction) * features.size());
|
||||
|
||||
for (size_t i = 0; i < features.size(); i++) {
|
||||
if (features[i].t == VT_POLYGON) {
|
||||
{
|
||||
drawvec &g = features[i].geometry;
|
||||
drawvec out;
|
||||
|
||||
for (size_t k = 0; k < g.size(); k++) {
|
||||
if (g[k].op == VT_LINETO && k > 0 && g[k - 1] == g[k]) {
|
||||
;
|
||||
} else {
|
||||
out.push_back(g[k]);
|
||||
}
|
||||
}
|
||||
|
||||
features[i].geometry = out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a mapping from all polygon edges to the set of rings
|
||||
// that each edge appears in. (The ring number is across all polygons;
|
||||
// we don't need to look it back up, just to tell where it changes.)
|
||||
|
||||
std::vector<edge> edges;
|
||||
size_t ring = 0;
|
||||
for (size_t i = 0; i < features.size(); i++) {
|
||||
if (features[i].t == VT_POLYGON) {
|
||||
{
|
||||
for (size_t k = 0; k + 1 < features[i].geometry.size(); k++) {
|
||||
if (features[i].geometry[k].op == VT_MOVETO) {
|
||||
ring++;
|
||||
}
|
||||
|
||||
if (features[i].geometry[k + 1].op == VT_LINETO) {
|
||||
drawvec dv;
|
||||
if (features[i].geometry[k] < features[i].geometry[k + 1]) {
|
||||
dv.push_back(features[i].geometry[k]);
|
||||
dv.push_back(features[i].geometry[k + 1]);
|
||||
} else {
|
||||
dv.push_back(features[i].geometry[k + 1]);
|
||||
dv.push_back(features[i].geometry[k]);
|
||||
}
|
||||
|
||||
edges.push_back(edge(dv[0].x, dv[0].y, dv[1].x, dv[1].y, ring));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_sort(edges.begin(), edges.end(), edgecmp_ring);
|
||||
std::set<draw> necessaries;
|
||||
|
||||
// Now mark all the points where the set of rings using the edge on one side
|
||||
// is not the same as the set of rings using the edge on the other side.
|
||||
|
||||
for (size_t i = 0; i < features.size(); i++) {
|
||||
if (features[i].t == VT_POLYGON) {
|
||||
{
|
||||
drawvec &g = features[i].geometry;
|
||||
|
||||
for (size_t k = 0; k < g.size(); k++) {
|
||||
g[k].necessary = 0;
|
||||
}
|
||||
|
||||
for (size_t a = 0; a < g.size(); a++) {
|
||||
if (g[a].op == VT_MOVETO) {
|
||||
size_t b;
|
||||
|
||||
for (b = a + 1; b < g.size(); b++) {
|
||||
if (g[b].op != VT_LINETO) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -1 because of duplication at the end
|
||||
size_t s = b - a - 1;
|
||||
|
||||
if (s > 0) {
|
||||
drawvec left;
|
||||
if (g[a + (s - 1) % s] < g[a]) {
|
||||
left.push_back(g[a + (s - 1) % s]);
|
||||
left.push_back(g[a]);
|
||||
} else {
|
||||
left.push_back(g[a]);
|
||||
left.push_back(g[a + (s - 1) % s]);
|
||||
}
|
||||
if (left[1] < left[0]) {
|
||||
fprintf(stderr, "left misordered\n");
|
||||
}
|
||||
std::pair<std::vector<edge>::iterator, std::vector<edge>::iterator> e1 = std::equal_range(edges.begin(), edges.end(), edge(left[0].x, left[0].y, left[1].x, left[1].y, 0));
|
||||
|
||||
for (size_t k = 0; k < s; k++) {
|
||||
drawvec right;
|
||||
|
||||
if (g[a + k] < g[a + k + 1]) {
|
||||
right.push_back(g[a + k]);
|
||||
right.push_back(g[a + k + 1]);
|
||||
} else {
|
||||
right.push_back(g[a + k + 1]);
|
||||
right.push_back(g[a + k]);
|
||||
}
|
||||
|
||||
std::pair<std::vector<edge>::iterator, std::vector<edge>::iterator> e2 = std::equal_range(edges.begin(), edges.end(), edge(right[0].x, right[0].y, right[1].x, right[1].y, 0));
|
||||
|
||||
if (right[1] < right[0]) {
|
||||
fprintf(stderr, "left misordered\n");
|
||||
}
|
||||
|
||||
if (e1.first == e1.second || e2.first == e2.second) {
|
||||
fprintf(stderr, "Internal error: polygon edge lookup failed for %lld,%lld to %lld,%lld or %lld,%lld to %lld,%lld\n", (long long) left[0].x, (long long) left[0].y, (long long) left[1].x, (long long) left[1].y, (long long) right[0].x, (long long) right[0].y, (long long) right[1].x, (long long) right[1].y);
|
||||
exit(EXIT_IMPOSSIBLE);
|
||||
}
|
||||
|
||||
if (!edges_same(e1, e2)) {
|
||||
g[a + k].necessary = 1;
|
||||
necessaries.insert(g[a + k]);
|
||||
}
|
||||
|
||||
e1 = e2;
|
||||
}
|
||||
}
|
||||
|
||||
a = b - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edges.clear();
|
||||
std::map<drawvec, size_t> arcs;
|
||||
std::multimap<ssize_t, size_t> merge_candidates; // from arc to serial_feature
|
||||
|
||||
// Roll rings that include a necessary point around so they start at one
|
||||
|
||||
for (size_t i = 0; i < features.size(); i++) {
|
||||
if (features[i].t == VT_POLYGON) {
|
||||
{
|
||||
drawvec &g = features[i].geometry;
|
||||
|
||||
for (size_t k = 0; k < g.size(); k++) {
|
||||
if (necessaries.count(g[k]) != 0) {
|
||||
g[k].necessary = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < g.size(); k++) {
|
||||
if (g[k].op == VT_MOVETO) {
|
||||
ssize_t necessary = -1;
|
||||
ssize_t lowest = k;
|
||||
size_t l;
|
||||
for (l = k + 1; l < g.size(); l++) {
|
||||
if (g[l].op != VT_LINETO) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (g[l].necessary) {
|
||||
necessary = l;
|
||||
}
|
||||
if (g[l] < g[lowest]) {
|
||||
lowest = l;
|
||||
}
|
||||
}
|
||||
|
||||
if (necessary < 0) {
|
||||
necessary = lowest;
|
||||
// Add a necessary marker if there was none in the ring,
|
||||
// so the arc code below can find it.
|
||||
g[lowest].necessary = 1;
|
||||
}
|
||||
|
||||
{
|
||||
drawvec tmp;
|
||||
|
||||
// l - 1 because the endpoint is duplicated
|
||||
for (size_t m = necessary; m < l - 1; m++) {
|
||||
tmp.push_back(g[m]);
|
||||
}
|
||||
for (ssize_t m = k; m < necessary; m++) {
|
||||
tmp.push_back(g[m]);
|
||||
}
|
||||
|
||||
// replace the endpoint
|
||||
tmp.push_back(g[necessary]);
|
||||
|
||||
if (tmp.size() != l - k) {
|
||||
fprintf(stderr, "internal error shifting ring\n");
|
||||
exit(EXIT_IMPOSSIBLE);
|
||||
}
|
||||
|
||||
for (size_t m = 0; m < tmp.size(); m++) {
|
||||
if (m == 0) {
|
||||
tmp[m].op = VT_MOVETO;
|
||||
} else {
|
||||
tmp[m].op = VT_LINETO;
|
||||
}
|
||||
|
||||
g[k + m] = tmp[m];
|
||||
}
|
||||
}
|
||||
|
||||
// Now peel off each set of segments from one necessary point to the next
|
||||
// into an "arc" as in TopoJSON
|
||||
|
||||
for (size_t m = k; m < l; m++) {
|
||||
if (!g[m].necessary) {
|
||||
fprintf(stderr, "internal error in arc building\n");
|
||||
exit(EXIT_IMPOSSIBLE);
|
||||
}
|
||||
|
||||
drawvec arc;
|
||||
size_t n;
|
||||
for (n = m; n < l; n++) {
|
||||
arc.push_back(g[n]);
|
||||
if (n > m && g[n].necessary) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto f = arcs.find(arc);
|
||||
if (f == arcs.end()) {
|
||||
drawvec arc2 = reverse_subring(arc);
|
||||
|
||||
auto f2 = arcs.find(arc2);
|
||||
if (f2 == arcs.end()) {
|
||||
// Add new arc
|
||||
size_t added = arcs.size() + 1;
|
||||
arcs.insert(std::pair<drawvec, size_t>(arc, added));
|
||||
features[i].arc_polygon.push_back(added);
|
||||
merge_candidates.insert(std::pair<ssize_t, size_t>(added, i));
|
||||
} else {
|
||||
features[i].arc_polygon.push_back(-(ssize_t) f2->second);
|
||||
merge_candidates.insert(std::pair<ssize_t, size_t>(-(ssize_t) f2->second, i));
|
||||
}
|
||||
} else {
|
||||
features[i].arc_polygon.push_back(f->second);
|
||||
merge_candidates.insert(std::pair<ssize_t, size_t>(f->second, i));
|
||||
}
|
||||
|
||||
m = n - 1;
|
||||
}
|
||||
|
||||
features[i].arc_polygon.push_back(0);
|
||||
|
||||
k = l - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simplify each arc
|
||||
|
||||
std::vector<drawvec> simplified_arcs;
|
||||
|
||||
for (auto ai = arcs.begin(); ai != arcs.end(); ++ai) {
|
||||
if (simplified_arcs.size() < ai->second + 1) {
|
||||
simplified_arcs.resize(ai->second + 1);
|
||||
}
|
||||
|
||||
drawvec dv = ai->first;
|
||||
for (size_t i = 0; i < dv.size(); i++) {
|
||||
if (i == 0) {
|
||||
dv[i].op = VT_MOVETO;
|
||||
} else {
|
||||
dv[i].op = VT_LINETO;
|
||||
}
|
||||
}
|
||||
if (!(prevent[P_SIMPLIFY] || (z == maxzoom && prevent[P_SIMPLIFY_LOW]) || (z < maxzoom && additional[A_GRID_LOW_ZOOMS]))) {
|
||||
// tx and ty are 0 here because we aren't trying to do anything with the shared_nodes_map
|
||||
simplified_arcs[ai->second] = simplify_lines(dv, z, 0, 0, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), simplification, 4, drawvec(), NULL, 0);
|
||||
} else {
|
||||
simplified_arcs[ai->second] = dv;
|
||||
}
|
||||
}
|
||||
|
||||
// If necessary, merge some adjacent polygons into some other polygons
|
||||
|
||||
struct merge_order {
|
||||
ssize_t edge = 0;
|
||||
unsigned long long gap = 0;
|
||||
size_t p1 = 0;
|
||||
size_t p2 = 0;
|
||||
|
||||
bool operator<(const merge_order &m) const {
|
||||
return gap < m.gap;
|
||||
}
|
||||
};
|
||||
std::vector<merge_order> order;
|
||||
|
||||
for (ssize_t i = 0; i < (ssize_t) simplified_arcs.size(); i++) {
|
||||
auto r1 = merge_candidates.equal_range(i);
|
||||
for (auto r1i = r1.first; r1i != r1.second; ++r1i) {
|
||||
auto r2 = merge_candidates.equal_range(-i);
|
||||
for (auto r2i = r2.first; r2i != r2.second; ++r2i) {
|
||||
if (r1i->second != r2i->second) {
|
||||
merge_order mo;
|
||||
mo.edge = i;
|
||||
if (features[r1i->second].index > features[r2i->second].index) {
|
||||
mo.gap = features[r1i->second].index - features[r2i->second].index;
|
||||
} else {
|
||||
mo.gap = features[r2i->second].index - features[r1i->second].index;
|
||||
}
|
||||
mo.p1 = r1i->second;
|
||||
mo.p2 = r2i->second;
|
||||
order.push_back(mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::stable_sort(order.begin(), order.end());
|
||||
|
||||
size_t merged = 0;
|
||||
for (size_t o = 0; o < order.size(); o++) {
|
||||
if (merged >= merge_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t i = order[o].p1;
|
||||
while (features[i].renamed >= 0) {
|
||||
i = features[i].renamed;
|
||||
}
|
||||
size_t i2 = order[o].p2;
|
||||
while (features[i2].renamed >= 0) {
|
||||
i2 = features[i2].renamed;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < features[i].arc_polygon.size() && merged < merge_count; j++) {
|
||||
if (features[i].arc_polygon[j] == order[o].edge) {
|
||||
{
|
||||
// XXX snap links
|
||||
if (features[order[o].p2].arc_polygon.size() > 0) {
|
||||
// This has to merge the ring that contains the anti-arc to this arc
|
||||
// into the current ring, and then add whatever other rings were in
|
||||
// that feature on to the end.
|
||||
//
|
||||
// This can't be good for keeping parent-child relationships among
|
||||
// the rings in order, but Wagyu should sort that out later
|
||||
|
||||
std::vector<ssize_t> additions;
|
||||
std::vector<ssize_t> &here = features[i].arc_polygon;
|
||||
std::vector<ssize_t> &other = features[i2].arc_polygon;
|
||||
|
||||
#if 0
|
||||
printf("seeking %zd\n", features[i].arc_polygon[j]);
|
||||
printf("before: ");
|
||||
for (size_t k = 0; k < here.size(); k++) {
|
||||
printf("%zd ", here[k]);
|
||||
}
|
||||
printf("\n");
|
||||
printf("other: ");
|
||||
for (size_t k = 0; k < other.size(); k++) {
|
||||
printf("%zd ", other[k]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
for (size_t k = 0; k < other.size(); k++) {
|
||||
size_t l;
|
||||
for (l = k; l < other.size(); l++) {
|
||||
if (other[l] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l >= other.size()) {
|
||||
l--;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (size_t m = k; m <= l; m++) {
|
||||
printf("%zd ", other[m]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
size_t m;
|
||||
for (m = k; m <= l; m++) {
|
||||
if (other[m] == -features[i].arc_polygon[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m <= l) {
|
||||
// Found the shared arc
|
||||
|
||||
here.erase(here.begin() + j);
|
||||
|
||||
size_t off = 0;
|
||||
for (size_t n = m + 1; n < l; n++) {
|
||||
here.insert(here.begin() + j + off, other[n]);
|
||||
off++;
|
||||
}
|
||||
for (size_t n = k; n < m; n++) {
|
||||
here.insert(here.begin() + j + off, other[n]);
|
||||
off++;
|
||||
}
|
||||
} else {
|
||||
// Looking at some other ring
|
||||
|
||||
for (size_t n = k; n <= l; n++) {
|
||||
additions.push_back(other[n]);
|
||||
}
|
||||
}
|
||||
|
||||
k = l;
|
||||
}
|
||||
|
||||
features[i2].arc_polygon.clear();
|
||||
features[i2].renamed = i;
|
||||
merged++;
|
||||
|
||||
for (size_t k = 0; k < additions.size(); k++) {
|
||||
features[i].arc_polygon.push_back(additions[k]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("after: ");
|
||||
for (size_t k = 0; k < here.size(); k++) {
|
||||
printf("%zd ", here[k]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (size_t k = 0; k + 1 < here.size(); k++) {
|
||||
if (here[k] != 0 && here[k + 1] != 0) {
|
||||
if (simplified_arcs[here[k + 1]][0] != simplified_arcs[here[k]][simplified_arcs[here[k]].size() - 1]) {
|
||||
printf("error from %zd to %zd\n", here[k], here[k + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the arc representations of the polygons back into standard polygon geometries
|
||||
|
||||
for (size_t i = 0; i < features.size(); i++) {
|
||||
if (features[i].t == VT_POLYGON) {
|
||||
features[i].geometry.clear();
|
||||
bool at_start = true;
|
||||
draw first(-1, 0, 0);
|
||||
|
||||
for (size_t j = 0; j < features[i].arc_polygon.size(); j++) {
|
||||
ssize_t p = features[i].arc_polygon[j];
|
||||
|
||||
if (p == 0) {
|
||||
if (first.op >= 0) {
|
||||
features[i].geometry.push_back(first);
|
||||
first = draw(-1, 0, 0);
|
||||
}
|
||||
at_start = true;
|
||||
} else if (p > 0) {
|
||||
for (size_t k = 0; k + 1 < simplified_arcs[p].size(); k++) {
|
||||
if (at_start) {
|
||||
features[i].geometry.push_back(draw(VT_MOVETO, simplified_arcs[p][k].x, simplified_arcs[p][k].y));
|
||||
first = draw(VT_LINETO, simplified_arcs[p][k].x, simplified_arcs[p][k].y);
|
||||
} else {
|
||||
features[i].geometry.push_back(draw(VT_LINETO, simplified_arcs[p][k].x, simplified_arcs[p][k].y));
|
||||
}
|
||||
at_start = 0;
|
||||
}
|
||||
} else { /* p < 0 */
|
||||
for (ssize_t k = simplified_arcs[-p].size() - 1; k > 0; k--) {
|
||||
if (at_start) {
|
||||
features[i].geometry.push_back(draw(VT_MOVETO, simplified_arcs[-p][k].x, simplified_arcs[-p][k].y));
|
||||
first = draw(VT_LINETO, simplified_arcs[-p][k].x, simplified_arcs[-p][k].y);
|
||||
} else {
|
||||
features[i].geometry.push_back(draw(VT_LINETO, simplified_arcs[-p][k].x, simplified_arcs[-p][k].y));
|
||||
}
|
||||
at_start = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (merged >= merge_count) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
bool find_common_edges(std::vector<serial_feature> &features, int z, int line_detail, double simplification, int maxzoom, double merge_fraction);
|
||||
File diff suppressed because one or more lines are too long
@@ -47,7 +47,6 @@
|
||||
#include "protozero/varint.hpp"
|
||||
#include "attribute.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "shared_borders.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "jsonpull/jsonpull.h"
|
||||
@@ -622,9 +621,6 @@ static double simplify_feature(serial_feature *p, drawvec const &shared_nodes, n
|
||||
}
|
||||
|
||||
bool already_marked = false;
|
||||
if (additional[A_DETECT_SHARED_BORDERS] && t == VT_POLYGON) {
|
||||
already_marked = true;
|
||||
}
|
||||
|
||||
if (!already_marked) {
|
||||
if (p->coalesced && t == VT_POLYGON) {
|
||||
@@ -1535,7 +1531,6 @@ void skip_tile(decompressor *geoms, std::atomic<long long> *geompos_in, bool com
|
||||
}
|
||||
|
||||
long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, char *global_stringpool, int z, const unsigned tx, const unsigned ty, const int detail, int min_detail, sqlite3 *outdb, const char *outdir, int buffer, const char *fname, compressor **geomfile, std::atomic<long long> *geompos, int minzoom, int maxzoom, double todo, std::atomic<long long> *along, long long alongminus, double gamma, int child_shards, long long *pool_off, unsigned *initial_x, unsigned *initial_y, std::atomic<int> *running, double simplification, std::vector<std::map<std::string, layermap_entry>> *layermaps, std::vector<std::vector<std::string>> *layer_unmaps, size_t tiling_seg, size_t pass, unsigned long long mingap, long long minextent, unsigned long long mindrop_sequence, const char *prefilter, const char *postfilter, json_object *filter, write_tile_args *arg, atomic_strategy *strategy_out, bool compressed_input, node *shared_nodes_map, size_t nodepos, std::vector<std::string> const &unidecode_data, long long estimated_complexity, std::set<zxy> &skip_children_out) {
|
||||
double merge_fraction = 1;
|
||||
double mingap_fraction = 1;
|
||||
double minextent_fraction = 1;
|
||||
double mindrop_sequence_fraction = 1;
|
||||
@@ -2042,7 +2037,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
features.push_back(std::move(sf));
|
||||
|
||||
unsimplified_geometry_size += features.back().geometry.size() * sizeof(draw);
|
||||
if (unsimplified_geometry_size > 10 * 1024 * 1024 && !additional[A_DETECT_SHARED_BORDERS]) {
|
||||
if (unsimplified_geometry_size > 10 * 1024 * 1024) {
|
||||
// we should be safe to simplify here with P_SIMPLIFY_SHARED_NODES, since they will
|
||||
// have been assembled globally, although that also means that simplification
|
||||
// may not be very effective for reducing memory usage.
|
||||
@@ -2227,10 +2222,6 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
}
|
||||
}
|
||||
|
||||
if (additional[A_DETECT_SHARED_BORDERS]) {
|
||||
find_common_edges(features, z, line_detail, simplification, maxzoom, merge_fraction);
|
||||
}
|
||||
|
||||
int tasks = ceil((double) CPUS / *running);
|
||||
if (tasks < 1) {
|
||||
tasks = 1;
|
||||
|
||||
Reference in New Issue
Block a user