mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 16:35:40 +02:00
Treat tiny polygon holes as dust again, but accumulated separately now
This commit is contained in:
+25
-5
@@ -186,7 +186,7 @@ void check_polygon(drawvec &geom) {
|
||||
}
|
||||
}
|
||||
|
||||
drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double *accum_area, serial_feature *this_feature, serial_feature *tiny_feature) {
|
||||
drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double *accum_area, double *accum_hole, serial_feature *this_feature, serial_feature *tiny_feature) {
|
||||
drawvec out;
|
||||
const double pixel = (1LL << (32 - detail - z)) * (double) tiny_polygon_size;
|
||||
bool includes_real = false;
|
||||
@@ -222,7 +222,7 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
|
||||
// OR it is an inner ring and we haven't output an outer ring for it to be
|
||||
// cut out of, so we are just subtracting its area from the tiny polygon
|
||||
// rather than trying to deal with it geometrically
|
||||
if ((area > 0 && area <= pixel * pixel) || (area < 0 && !included_last_outer)) {
|
||||
if ((area > 0 && area <= pixel * pixel) || (area < 0 && -area <= pixel * pixel && !included_last_outer)) {
|
||||
// printf("area is only %f vs %lld so using square\n", area, pixel * pixel);
|
||||
|
||||
*accum_area += area;
|
||||
@@ -243,10 +243,30 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
|
||||
included_last_outer = false;
|
||||
}
|
||||
}
|
||||
|
||||
// this is a tiny hole, and we have a real outer ring that we can cut it out of,
|
||||
// so accumulate some hole, and if we have enough to be worth cutting, cut it out.
|
||||
//
|
||||
// these hole areas are accumulated separately rather than just decrementing
|
||||
// the accumulated area, because otherwise it is possible to accumulate enough
|
||||
// negative area to lose entire outer rings in the process of getting back up to 0.
|
||||
else if (area < 0 && -area <= pixel * pixel && included_last_outer) {
|
||||
*accum_hole -= area;
|
||||
if (*accum_hole > pixel * pixel) {
|
||||
// XXX use centroid;
|
||||
|
||||
out.push_back(draw(VT_MOVETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2 + pixel));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2 + pixel));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2));
|
||||
includes_dust = true;
|
||||
|
||||
*accum_hole -= pixel * pixel;
|
||||
}
|
||||
}
|
||||
|
||||
// i.e., this ring is large enough that it gets to represent itself
|
||||
// or it is a tiny hole out of a real polygon, which we are still treating
|
||||
// as a real geometry because otherwise we can accumulate enough tiny holes
|
||||
// that we will drop the next several outer rings getting back up to 0.
|
||||
else {
|
||||
// printf("area is %f so keeping instead of %lld\n", area, pixel * pixel);
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ drawvec clip_point(drawvec &geom, int z, long long buffer);
|
||||
drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip);
|
||||
drawvec simple_clip_poly(drawvec &geom, int z, int buffer);
|
||||
drawvec close_poly(drawvec &geom);
|
||||
drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double *accum_area, serial_feature *this_feature, serial_feature *tiny_feature);
|
||||
drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double *accum_area, double *accum_hole, serial_feature *this_feature, serial_feature *tiny_feature);
|
||||
int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax);
|
||||
drawvec clip_lines(drawvec &geom, int z, long long buffer);
|
||||
drawvec stairstep(drawvec &geom, int z, int detail);
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
int detail = 12; // tippecanoe-style: mvt extent == 1 << detail
|
||||
int buffer = 5; // tippecanoe-style: mvt buffer == extent * buffer / 256;
|
||||
int buffer = 5; // tippecanoe-style: mvt buffer == extent * buffer / 256;
|
||||
|
||||
std::set<std::string> keep;
|
||||
|
||||
|
||||
@@ -1914,7 +1914,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
int line_detail;
|
||||
for (line_detail = detail; line_detail >= min_detail || line_detail == detail; line_detail--, oprogress = 0) {
|
||||
long long count = 0;
|
||||
double accum_area = 0;
|
||||
double accum_area = 0, accum_hole = 0;
|
||||
|
||||
double fraction_accum = 0;
|
||||
|
||||
@@ -2185,7 +2185,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
bool reduced = false;
|
||||
if (sf.t == VT_POLYGON) {
|
||||
if (!prevent[P_TINY_POLYGON_REDUCTION] && !additional[A_GRID_LOW_ZOOMS]) {
|
||||
sf.geometry = reduce_tiny_poly(sf.geometry, z, line_detail, &reduced, &accum_area, &sf, &tiny_feature);
|
||||
sf.geometry = reduce_tiny_poly(sf.geometry, z, line_detail, &reduced, &accum_area, &accum_hole, &sf, &tiny_feature);
|
||||
if (reduced) {
|
||||
strategy->tiny_polygons++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user