Don't choose a label point that is too close to a border

This commit is contained in:
Erica Fischer
2022-10-06 11:46:10 -07:00
parent 7127f8af97
commit ffd07befce
+31 -11
View File
@@ -1451,6 +1451,28 @@ struct polygon_label {
}
};
bool acceptable(const drawvec &dv, size_t start, size_t count, long long x, long long y, long long xmin, long long ymin, long long xmax, long long ymax) {
if (!pnpoly(dv, start, count, x, y)) {
return false;
}
// minimal acceptable distance from border:
double min = ceil(sqrt((xmax - xmin) * (xmax - xmin) + (ymax - ymin) * (ymax - ymin)) * 0.05);
double squaremin = min * min;
for (size_t i = start; i < start + count; i++) {
double dx = dv[i].x - x;
double dy = dv[i].y - y;
double squared = dx * dx + dy * dy;
if (squared < squaremin) {
printf("within but too close to the border\n");
return false;
}
}
return true;
}
// Generate a label point for a polygon feature, currently at the centroid of its largest-area
// outer ring within the tile.
drawvec polygon_to_anchor(const drawvec &geom) {
@@ -1469,6 +1491,7 @@ drawvec polygon_to_anchor(const drawvec &geom) {
long long xsum = 0;
long long ysum = 0;
size_t count = 0;
long long xmin = LLONG_MAX, ymin = LLONG_MAX, xmax = LLONG_MIN, ymax = LLONG_MIN;
double area = get_area(geom, i, j);
if (area > 0) { // don't generate anchors for holes
@@ -1477,27 +1500,24 @@ drawvec polygon_to_anchor(const drawvec &geom) {
xsum += geom[k].x;
ysum += geom[k].y;
count++;
xmin = std::min(xmin, geom[k].x);
ymin = std::min(ymin, geom[k].y);
xmax = std::max(xmax, geom[k].x);
ymax = std::max(ymax, geom[k].y);
}
if (count > 0) {
draw d(VT_MOVETO, xsum / count, ysum / count);
d = centerOfMass(geom, i, j, d);
if (!pnpoly(geom, i, j - i - 1, d.x, d.y)) {
if (!acceptable(geom, i, j - i - 1, d.x, d.y, xmin, ymin, xmax, ymax)) {
// Center of mass is not actually within the polygon,
// so just start trying to subdivide the bounding box
// until something works.
long long xmin = LLONG_MAX, ymin = LLONG_MAX, xmax = LLONG_MIN, ymax = LLONG_MIN;
for (size_t k = i + 1; k < j; k++) {
xmin = std::min(xmin, geom[k].x);
ymin = std::min(ymin, geom[k].y);
xmax = std::max(xmax, geom[k].x);
ymax = std::max(ymax, geom[k].y);
}
for (long long sub = 2;
sub < 128 && (xmax - xmin) > 2 * sub && (ymax - ymin) > 2 * sub;
sub < 32 && (xmax - xmin) > 2 * sub && (ymax - ymin) > 2 * sub;
sub *= 2) {
for (long long x = 1; x < sub; x++) {
for (long long y = 1; y < sub; y++) {
@@ -1505,7 +1525,7 @@ drawvec polygon_to_anchor(const drawvec &geom) {
draw maybe(VT_MOVETO,
xmin + x * (xmax - xmin) / sub,
ymin + y * (ymax - ymin) / sub);
if (pnpoly(geom, i, j - 1, maybe.x, maybe.y)) {
if (acceptable(geom, i, j - 1, maybe.x, maybe.y, xmin, ymin, xmax, ymax)) {
d = maybe;
printf("ok!\n");
goto found;