Skip to content

Commit

Permalink
Even-odd wagyu after scaling to counterbalance ring reversals
Browse files Browse the repository at this point in the history
  • Loading branch information
e-n-f committed Dec 15, 2023
1 parent 15a3e31 commit 318f05a
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 9 deletions.
11 changes: 8 additions & 3 deletions clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ static void decode_clipped(mapbox::geometry::multi_polygon<long long> &t, drawve
}
}

drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip, bool try_scaling) {
drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip, bool try_scaling, bool even_odd) {
geom = remove_noop(geom, VT_POLYGON, 0);
mapbox::geometry::multi_polygon<long long> result;

Expand Down Expand Up @@ -308,7 +308,11 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip, bool try

try {
result.clear();
wagyu.execute(mapbox::geometry::wagyu::clip_type_union, result, mapbox::geometry::wagyu::fill_type_positive, mapbox::geometry::wagyu::fill_type_positive);
if (even_odd) {
wagyu.execute(mapbox::geometry::wagyu::clip_type_union, result, mapbox::geometry::wagyu::fill_type_even_odd, mapbox::geometry::wagyu::fill_type_even_odd);
} else {
wagyu.execute(mapbox::geometry::wagyu::clip_type_union, result, mapbox::geometry::wagyu::fill_type_positive, mapbox::geometry::wagyu::fill_type_positive);
}
} catch (std::runtime_error &e) {
FILE *f = fopen("/tmp/wagyu.log", "w");
fprintf(f, "%s\n", e.what());
Expand Down Expand Up @@ -858,7 +862,8 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int

geom = remove_noop(geom, t, 0);
if (t == VT_POLYGON) {
geom = clean_or_clip_poly(geom, 0, 0, false, false);
// this is after scaling, so even-odd to balance scaling errors between features
geom = clean_or_clip_poly(geom, 0, 0, false, false, true);
geom = close_poly(geom);
}

Expand Down
2 changes: 1 addition & 1 deletion geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void to_tile_scale(drawvec &geom, int z, int detail);
drawvec from_tile_scale(drawvec const &geom, int z, int detail);
drawvec remove_noop(drawvec geom, int type, int shift);
drawvec clip_point(drawvec &geom, int z, long long buffer);
drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip, bool try_scaling);
drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip, bool try_scaling, bool even_odd);
drawvec close_poly(drawvec &geom);
drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *still_needs_simplification, bool *reduced_away, double *accum_area, serial_feature *this_feature, serial_feature *tiny_feature);
int clip(long long *x0, long long *y0, long long *x1, long long *y1, long long xmin, long long ymin, long long xmax, long long ymax);
Expand Down
3 changes: 2 additions & 1 deletion plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ std::vector<mvt_layer> parse_layers(int fd, int z, unsigned x, unsigned y, std::

if (mb_geometry[t] == VT_POLYGON) {
// we can try scaling up because these are tile coordinates
dv = clean_or_clip_poly(dv, 0, 0, false, true);
// these are already scaled, so even-odd winding
dv = clean_or_clip_poly(dv, 0, 0, false, true, true);
if (dv.size() < 3) {
dv.clear();
}
Expand Down
47 changes: 43 additions & 4 deletions tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,8 @@ double simplify_partial(partial *p, drawvec const &shared_nodes, node *shared_no
// unioned exactly
//
// don't try to scale up because these are still world coordinates
geom = clean_or_clip_poly(geom, 0, 0, false, false);
// positive winding because these are world coordinates
geom = clean_or_clip_poly(geom, 0, 0, false, false, true);
}

// continues to simplify to line_detail even if we have extra detail
Expand Down Expand Up @@ -611,7 +612,42 @@ void *partial_feature_worker(void *v) {
int z = (*partials)[i].z;
int out_detail = (*partials)[i].extra_detail;

#if 0
if ((*partials)[i].geoms[0].size() < 1) {
fprintf(stderr, "expected at least one geometry in partial_feature_worker\n");
exit(EXIT_IMPOSSIBLE);
}
for (size_t x = 1; x < (*partials)[i].geoms.size(); x++) {
for (auto const &d : (*partials)[i].geoms[x]) {
(*partials)[i].geoms[0].push_back(d);
}
}
(*partials)[i].geoms.resize(1);
#endif

if ((*partials)[i].geoms.size() != 1) {
fprintf(stderr, "expected single geometry in partial_feature_worker\n");
exit(EXIT_IMPOSSIBLE);
}
drawvec geom = (*partials)[i].geoms[0];

if (t == VT_POLYGON) {
// clean multi-ring polygons with positive winding before scaling
// so that polygon dust will be unioned on positively

size_t ring_count = 0;
for (size_t x = 0; x < geom.size(); x++) {
if (geom[x].op == VT_MOVETO) {
ring_count++;

if (ring_count == 2) {
geom = clean_or_clip_poly(geom, 0, 0, false, false, false);
break;
}
}
}
}

to_tile_scale(geom, z, out_detail);

if (t == VT_POLYGON) {
Expand All @@ -620,7 +656,8 @@ void *partial_feature_worker(void *v) {
{
drawvec before = geom;
// we can try scaling up because this is now tile scale
geom = clean_or_clip_poly(geom, 0, 0, false, true);
// even-odd since we have scaled
geom = clean_or_clip_poly(geom, 0, 0, false, true, true);
if (additional[A_DEBUG_POLYGON]) {
check_polygon(geom);
}
Expand Down Expand Up @@ -2293,7 +2330,8 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
for (auto &g : partials[simplified_geometry_through].geoms) {
if (partials[simplified_geometry_through].t == VT_POLYGON) {
// don't scale up because this is still world coordinates
g = clean_or_clip_poly(g, 0, 0, false, false);
// positive winding because this before scaling
g = clean_or_clip_poly(g, 0, 0, false, false, false);
}
}
}
Expand Down Expand Up @@ -2533,7 +2571,8 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
if (layer_features[x].type == VT_POLYGON) {
if (layer_features[x].coalesced) {
// we can try scaling up because this is tile coordinates
layer_features[x].geom = clean_or_clip_poly(layer_features[x].geom, 0, 0, false, true);
// positive winding because we are trying to union features here
layer_features[x].geom = clean_or_clip_poly(layer_features[x].geom, 0, 0, false, true, false);
}

layer_features[x].geom = close_poly(layer_features[x].geom);
Expand Down

0 comments on commit 318f05a

Please sign in to comment.