Add an option to generate label points in place of polygons

This commit is contained in:
Erica Fischer
2022-10-04 16:02:31 -07:00
parent 182093bdc7
commit 1885f989bf
9 changed files with 78 additions and 1 deletions
+4
View File
@@ -1,3 +1,7 @@
## 2.9.0
* Add an option to generate label points in place of polygons
## 2.8.1
* Improve precision of polygon ring area calculations
+1
View File
@@ -518,6 +518,7 @@ the same layer, enclose them in an `all` expression so they will all be evaluate
* `-pw` or `--use-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings.
* `-pW` or `--reverse-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings.
* `--clip-bounding-box=`*minlon*`,`*minlat*`,`*maxlon*`,`*maxlat*: Clip all features to the specified bounding box.
* `-aP` or `--convert-polygons-to-label-points`: Replace polygon geometries with a label point or points for the polygon in each tile it intersects.
### Setting or disabling tile size limits
+62
View File
@@ -1364,3 +1364,65 @@ drawvec stairstep(drawvec &geom, int z, int detail) {
return out;
}
struct polygon_label {
long long size;
draw point;
bool operator<(const polygon_label &o) const {
return size > o.size; // reverse sort, largest first
}
};
// 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) {
std::vector<polygon_label> labels;
drawvec dv;
for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) {
size_t j;
for (j = i + 1; j < geom.size(); j++) {
if (geom[j].op != VT_LINETO) {
break;
}
}
long long xsum = 0;
long long ysum = 0;
size_t count = 0;
double area = get_area(geom, i, j);
if (area > 0) { // don't generate anchors for holes
// i + 1 to exclude the first point, which is duplicated as the last
for (size_t k = i + 1; k < j; k++) {
xsum += geom[k].x;
ysum += geom[k].y;
count++;
}
if (count > 0) {
draw d(VT_MOVETO, xsum / count, ysum / count);
polygon_label pl;
pl.size = area;
pl.point = d;
labels.push_back(pl);
}
}
i = j - 1;
}
}
std::sort(labels.begin(), labels.end());
if (labels.size() > 0) {
dv.push_back(labels[0].point);
}
return dv;
}
+1
View File
@@ -76,6 +76,7 @@ std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms);
void check_polygon(drawvec &geom);
double get_area(const drawvec &geom, size_t i, size_t j);
double get_mp_area(drawvec &geom);
drawvec polygon_to_anchor(const drawvec &geom);
drawvec simple_clip_poly(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
drawvec clip_lines(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
+1
View File
@@ -2761,6 +2761,7 @@ int main(int argc, char **argv) {
{"use-source-polygon-winding", no_argument, &prevent[P_USE_SOURCE_POLYGON_WINDING], 1},
{"reverse-source-polygon-winding", no_argument, &prevent[P_REVERSE_SOURCE_POLYGON_WINDING], 1},
{"clip-bounding-box", required_argument, 0, '~'},
{"convert-polygons-to-label-points", no_argument, &additional[A_GENERATE_POLYGON_LABEL_POINTS], 1},
{"Filtering tile contents", 0, 0, 0},
{"prefilter", required_argument, 0, 'C'},
+2
View File
@@ -671,6 +671,8 @@ the line or polygon within one tile unit of its proper location. You can probabl
\fB\fC\-pW\fR or \fB\fC\-\-reverse\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings.
.IP \(bu 2
\fB\fC\-\-clip\-bounding\-box=\fR\fIminlon\fP\fB\fC,\fR\fIminlat\fP\fB\fC,\fR\fImaxlon\fP\fB\fC,\fR\fImaxlat\fP: Clip all features to the specified bounding box.
.IP \(bu 2
\fB\fC\-aP\fR or \fB\fC\-\-convert\-polygons\-to\-label\-points\fR: Replace polygon geometries with a label point or points for the polygon in each tile it intersects.
.RE
.SS Setting or disabling tile size limits
.RS
+1
View File
@@ -26,6 +26,7 @@
#define A_CONVERT_NUMERIC_IDS ((int) 'I')
#define A_HILBERT ((int) 'h')
#define A_VISVALINGAM ((int) 'v')
#define A_GENERATE_POLYGON_LABEL_POINTS ((int) 'P')
#define P_SIMPLIFY ((int) 's')
#define P_SIMPLIFY_LOW ((int) 'S')
+5
View File
@@ -2076,6 +2076,11 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
}
}
if (sf.t == VT_POLYGON && additional[A_GENERATE_POLYGON_LABEL_POINTS]) {
sf.t = VT_POINT;
sf.geometry = polygon_to_anchor(sf.geometry);
}
if (sf.geometry.size() > 0) {
if (partials.size() > max_tile_size) {
// Even being maximally conservative, each feature is still going to be
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef VERSION_HPP
#define VERSION_HPP
#define VERSION "v2.8.1"
#define VERSION "v2.9.0"
#endif