Limit decay into polygon dust to reasonably compact polygons

This commit is contained in:
Erica Fischer
2023-11-13 22:16:37 -08:00
parent dd8762da1f
commit bee87bdab2
+25 -1
View File
@@ -176,6 +176,18 @@ void check_polygon(drawvec &geom) {
}
}
double get_perimeter(const drawvec &geom, size_t i, size_t j) {
double perimeter = 0;
for (size_t k = i; k + 1 < j; k++) {
double dx = geom[k].x - geom[k + 1].x;
double dy = geom[k].y - geom[k + 1].y;
perimeter += sqrt(dx * dx + dy * dy);
}
return perimeter;
}
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) {
drawvec out;
const double pixel = (1LL << (32 - detail - z)) * (double) tiny_polygon_size;
@@ -196,6 +208,17 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *still_needs_sim
}
double area = get_area(geom, i, j);
double schwartzberg = 1;
if (area != 0) {
// polygon compactness measure
// https://fisherzachary.github.io/public/r-output.html
// Schwartzberg, Joseph E. 1965. “Reapportionment, gerrymanders, and the notion of compactness”.
// In: Minn. L. Rev. 50, 443.
double perimeter = get_perimeter(geom, i, j);
schwartzberg = 1 / (perimeter / (2 * M_PI * sqrt(std::fabs(area) / M_PI)));
}
// XXX There is an ambiguity here: If the area of a ring is 0 and it is followed by holes,
// we don't know whether the area-0 ring was a hole too or whether it was the outer ring
@@ -213,7 +236,8 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *still_needs_sim
// 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 && schwartzberg > 0.3) ||
(area < 0 && !included_last_outer)) {
*accum_area += area;
*reduced_away = true;