mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-04 17:35:42 +02:00
Add option to order by estimated prominence
This commit is contained in:
@@ -508,6 +508,8 @@ the same layer, enclose them in an `all` expression so they will all be evaluate
|
|||||||
* `--order-descending-by=`_attribute_: Order features by the specified _attribute_, in reverse alphabetical or numerical order. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
* `--order-descending-by=`_attribute_: Order features by the specified _attribute_, in reverse alphabetical or numerical order. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
||||||
* `--order-smallest-first`: Order features so the smallest geometry comes first in each tile. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
* `--order-smallest-first`: Order features so the smallest geometry comes first in each tile. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
||||||
* `--order-largest-first`: Order features so the largest geometry comes first in each tile. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
* `--order-largest-first`: Order features so the largest geometry comes first in each tile. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
||||||
|
* `--order-prominent-first`: Order features so the most prominent geometry (a combination of size and complexity) comes first in each tile. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
||||||
|
* `--order-prominent-last`: Order features so the most prominent geometry (a combination of size and complexity) comes last in each tile. Multiple `--order-by` and `--order-descending-by` options may be specified, the first being the primary sort key.
|
||||||
|
|
||||||
### Adding calculated attributes
|
### Adding calculated attributes
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -212,7 +212,7 @@ void handle(std::string message, int z, unsigned x, unsigned y, std::set<std::st
|
|||||||
} else if (coordinate_mode == 2) { // integer
|
} else if (coordinate_mode == 2) { // integer
|
||||||
scale = 1;
|
scale = 1;
|
||||||
}
|
}
|
||||||
layer_to_geojson(layer, z, x, y, !pipeline, pipeline, pipeline, false, 0, 0, 0, !force, state, scale);
|
layer_to_geojson(layer, z, x, y, !pipeline, pipeline, pipeline, false, 0, 0, 0, 0, !force, state, scale);
|
||||||
|
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
if (true) {
|
if (true) {
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ std::string attribute_for_id = "";
|
|||||||
std::vector<order_field> order_by;
|
std::vector<order_field> order_by;
|
||||||
bool order_reverse;
|
bool order_reverse;
|
||||||
bool order_by_size = false;
|
bool order_by_size = false;
|
||||||
|
bool order_by_prominence = false;
|
||||||
|
|
||||||
int prevent[256];
|
int prevent[256];
|
||||||
int additional[256];
|
int additional[256];
|
||||||
@@ -2754,6 +2755,8 @@ int main(int argc, char **argv) {
|
|||||||
{"order-descending-by", required_argument, 0, '~'},
|
{"order-descending-by", required_argument, 0, '~'},
|
||||||
{"order-smallest-first", no_argument, 0, '~'},
|
{"order-smallest-first", no_argument, 0, '~'},
|
||||||
{"order-largest-first", no_argument, 0, '~'},
|
{"order-largest-first", no_argument, 0, '~'},
|
||||||
|
{"order-prominent-first", no_argument, 0, '~'},
|
||||||
|
{"order-prominent-last", no_argument, 0, '~'},
|
||||||
|
|
||||||
{"Adding calculated attributes", 0, 0, 0},
|
{"Adding calculated attributes", 0, 0, 0},
|
||||||
{"calculate-feature-density", no_argument, &additional[A_CALCULATE_FEATURE_DENSITY], 1},
|
{"calculate-feature-density", no_argument, &additional[A_CALCULATE_FEATURE_DENSITY], 1},
|
||||||
@@ -2896,6 +2899,12 @@ int main(int argc, char **argv) {
|
|||||||
} else if (strcmp(opt, "order-largest-first") == 0) {
|
} else if (strcmp(opt, "order-largest-first") == 0) {
|
||||||
order_by.push_back(order_field(ORDER_BY_SIZE, true));
|
order_by.push_back(order_field(ORDER_BY_SIZE, true));
|
||||||
order_by_size = true;
|
order_by_size = true;
|
||||||
|
} else if (strcmp(opt, "order-prominent-first") == 0) {
|
||||||
|
order_by.push_back(order_field(ORDER_BY_PROMINENCE, false));
|
||||||
|
order_by_prominence = true;
|
||||||
|
} else if (strcmp(opt, "order-prominent-last") == 0) {
|
||||||
|
order_by.push_back(order_field(ORDER_BY_PROMINENCE, true));
|
||||||
|
order_by_prominence = true;
|
||||||
} else if (strcmp(opt, "simplification-at-maximum-zoom") == 0) {
|
} else if (strcmp(opt, "simplification-at-maximum-zoom") == 0) {
|
||||||
maxzoom_simplification = atof_require(optarg, "Mazoom simplification");
|
maxzoom_simplification = atof_require(optarg, "Mazoom simplification");
|
||||||
if (maxzoom_simplification <= 0) {
|
if (maxzoom_simplification <= 0) {
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ extern std::vector<order_field> order_by;
|
|||||||
// not legal UTF-8, so can't appear as a real attribute name
|
// not legal UTF-8, so can't appear as a real attribute name
|
||||||
#define ORDER_BY_SIZE "\200size"
|
#define ORDER_BY_SIZE "\200size"
|
||||||
extern bool order_by_size;
|
extern bool order_by_size;
|
||||||
|
#define ORDER_BY_PROMINENCE "\200prominence"
|
||||||
|
extern bool order_by_prominence;
|
||||||
|
|
||||||
int mkstemp_cloexec(char *name);
|
int mkstemp_cloexec(char *name);
|
||||||
FILE *fopen_oflag(const char *name, const char *mode, int oflag);
|
FILE *fopen_oflag(const char *name, const char *mode, int oflag);
|
||||||
|
|||||||
@@ -657,6 +657,10 @@ the line or polygon within one tile unit of its proper location. You can probabl
|
|||||||
\fB\fC\-\-order\-smallest\-first\fR: Order features so the smallest geometry comes first in each tile. Multiple \fB\fC\-\-order\-by\fR and \fB\fC\-\-order\-descending\-by\fR options may be specified, the first being the primary sort key.
|
\fB\fC\-\-order\-smallest\-first\fR: Order features so the smallest geometry comes first in each tile. Multiple \fB\fC\-\-order\-by\fR and \fB\fC\-\-order\-descending\-by\fR options may be specified, the first being the primary sort key.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fC\-\-order\-largest\-first\fR: Order features so the largest geometry comes first in each tile. Multiple \fB\fC\-\-order\-by\fR and \fB\fC\-\-order\-descending\-by\fR options may be specified, the first being the primary sort key.
|
\fB\fC\-\-order\-largest\-first\fR: Order features so the largest geometry comes first in each tile. Multiple \fB\fC\-\-order\-by\fR and \fB\fC\-\-order\-descending\-by\fR options may be specified, the first being the primary sort key.
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fC\-\-order\-prominent\-first\fR: Order features so the most prominent geometry (a combination of size and complexity) comes first in each tile. Multiple \fB\fC\-\-order\-by\fR and \fB\fC\-\-order\-descending\-by\fR options may be specified, the first being the primary sort key.
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fC\-\-order\-prominent\-last\fR: Order features so the most prominent geometry (a combination of size and complexity) comes last in each tile. Multiple \fB\fC\-\-order\-by\fR and \fB\fC\-\-order\-descending\-by\fR options may be specified, the first being the primary sort key.
|
||||||
.RE
|
.RE
|
||||||
.SS Adding calculated attributes
|
.SS Adding calculated attributes
|
||||||
.RS
|
.RS
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ void *run_writer(void *a) {
|
|||||||
|
|
||||||
json_writer state(fp);
|
json_writer state(fp);
|
||||||
for (size_t i = 0; i < wa->layers->size(); i++) {
|
for (size_t i = 0; i < wa->layers->size(); i++) {
|
||||||
layer_to_geojson((*(wa->layers))[i], wa->z, wa->x, wa->y, false, true, false, true, 0, 0, 0, true, state, 0);
|
layer_to_geojson((*(wa->layers))[i], wa->z, wa->x, wa->y, false, true, false, true, 0, 0, 0, 0, true, state, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fclose(fp) != 0) {
|
if (fclose(fp) != 0) {
|
||||||
|
|||||||
+22
-10
@@ -192,8 +192,9 @@ static void write_geometry(drawvec const &dv, std::atomic<long long> *fpos, FILE
|
|||||||
void serialize_feature(FILE *geomfile, serial_feature *sf, std::atomic<long long> *geompos, const char *fname, long long wx, long long wy, bool include_minzoom) {
|
void serialize_feature(FILE *geomfile, serial_feature *sf, std::atomic<long long> *geompos, const char *fname, long long wx, long long wy, bool include_minzoom) {
|
||||||
serialize_byte(geomfile, sf->t, geompos, fname);
|
serialize_byte(geomfile, sf->t, geompos, fname);
|
||||||
|
|
||||||
#define FLAG_LAYER 7
|
#define FLAG_LAYER 8
|
||||||
|
|
||||||
|
#define FLAG_PROMINENCE 7
|
||||||
#define FLAG_LABEL_POINT 6
|
#define FLAG_LABEL_POINT 6
|
||||||
#define FLAG_SEQ 5
|
#define FLAG_SEQ 5
|
||||||
#define FLAG_INDEX 4
|
#define FLAG_INDEX 4
|
||||||
@@ -208,6 +209,7 @@ void serialize_feature(FILE *geomfile, serial_feature *sf, std::atomic<long long
|
|||||||
layer |= (sf->seq != 0) << FLAG_SEQ;
|
layer |= (sf->seq != 0) << FLAG_SEQ;
|
||||||
layer |= (sf->index != 0) << FLAG_INDEX;
|
layer |= (sf->index != 0) << FLAG_INDEX;
|
||||||
layer |= (sf->area != 0) << FLAG_AREA;
|
layer |= (sf->area != 0) << FLAG_AREA;
|
||||||
|
layer |= (sf->prominence != 0) << FLAG_PROMINENCE;
|
||||||
layer |= sf->has_id << FLAG_ID;
|
layer |= sf->has_id << FLAG_ID;
|
||||||
layer |= sf->has_tippecanoe_minzoom << FLAG_MINZOOM;
|
layer |= sf->has_tippecanoe_minzoom << FLAG_MINZOOM;
|
||||||
layer |= sf->has_tippecanoe_maxzoom << FLAG_MAXZOOM;
|
layer |= sf->has_tippecanoe_maxzoom << FLAG_MAXZOOM;
|
||||||
@@ -239,6 +241,9 @@ void serialize_feature(FILE *geomfile, serial_feature *sf, std::atomic<long long
|
|||||||
if (sf->area != 0) {
|
if (sf->area != 0) {
|
||||||
serialize_long_long(geomfile, sf->area, geompos, fname);
|
serialize_long_long(geomfile, sf->area, geompos, fname);
|
||||||
}
|
}
|
||||||
|
if (sf->prominence != 0) {
|
||||||
|
serialize_long_long(geomfile, sf->prominence, geompos, fname);
|
||||||
|
}
|
||||||
|
|
||||||
serialize_long_long(geomfile, sf->metapos, geompos, fname);
|
serialize_long_long(geomfile, sf->metapos, geompos, fname);
|
||||||
|
|
||||||
@@ -291,6 +296,7 @@ serial_feature deserialize_feature(FILE *geoms, std::atomic<long long> *geompos_
|
|||||||
sf.index = 0;
|
sf.index = 0;
|
||||||
sf.label_point = 0;
|
sf.label_point = 0;
|
||||||
sf.area = 0;
|
sf.area = 0;
|
||||||
|
sf.prominence = 0;
|
||||||
|
|
||||||
sf.geometry = decode_geometry(geoms, geompos_in, z, tx, ty, sf.bbox, initial_x[sf.segment], initial_y[sf.segment]);
|
sf.geometry = decode_geometry(geoms, geompos_in, z, tx, ty, sf.bbox, initial_x[sf.segment], initial_y[sf.segment]);
|
||||||
if (sf.layer & (1 << FLAG_INDEX)) {
|
if (sf.layer & (1 << FLAG_INDEX)) {
|
||||||
@@ -302,6 +308,9 @@ serial_feature deserialize_feature(FILE *geoms, std::atomic<long long> *geompos_
|
|||||||
if (sf.layer & (1 << FLAG_AREA)) {
|
if (sf.layer & (1 << FLAG_AREA)) {
|
||||||
deserialize_long_long_io(geoms, &sf.area, geompos_in);
|
deserialize_long_long_io(geoms, &sf.area, geompos_in);
|
||||||
}
|
}
|
||||||
|
if (sf.layer & (1 << FLAG_PROMINENCE)) {
|
||||||
|
deserialize_long_long_io(geoms, &sf.prominence, geompos_in);
|
||||||
|
}
|
||||||
|
|
||||||
sf.layer >>= FLAG_LAYER;
|
sf.layer >>= FLAG_LAYER;
|
||||||
|
|
||||||
@@ -539,7 +548,16 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double area = 0;
|
double area = 0;
|
||||||
if (additional[A_DROP_SMALLEST_AS_NEEDED] || additional[A_COALESCE_SMALLEST_AS_NEEDED] || order_by_size) {
|
if (additional[A_DROP_SMALLEST_AS_NEEDED] || additional[A_COALESCE_SMALLEST_AS_NEEDED] || order_by_size || order_by_prominence) {
|
||||||
|
double dist = 0;
|
||||||
|
for (size_t i = 1; i < scaled_geometry.size(); i++) {
|
||||||
|
if (scaled_geometry[i].op == VT_LINETO) {
|
||||||
|
double xd = SHIFT_LEFT(scaled_geometry[i].x - scaled_geometry[i - 1].x);
|
||||||
|
double yd = SHIFT_LEFT(scaled_geometry[i].y - scaled_geometry[i - 1].y);
|
||||||
|
dist += sqrt(xd * xd + yd * yd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sf.t == VT_POLYGON) {
|
if (sf.t == VT_POLYGON) {
|
||||||
for (size_t i = 0; i < scaled_geometry.size(); i++) {
|
for (size_t i = 0; i < scaled_geometry.size(); i++) {
|
||||||
if (scaled_geometry[i].op == VT_MOVETO) {
|
if (scaled_geometry[i].op == VT_MOVETO) {
|
||||||
@@ -555,18 +573,12 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (sf.t == VT_LINE) {
|
} else if (sf.t == VT_LINE) {
|
||||||
double dist = 0;
|
|
||||||
for (size_t i = 1; i < scaled_geometry.size(); i++) {
|
|
||||||
if (scaled_geometry[i].op == VT_LINETO) {
|
|
||||||
double xd = SHIFT_LEFT(scaled_geometry[i].x - scaled_geometry[i - 1].x);
|
|
||||||
double yd = SHIFT_LEFT(scaled_geometry[i].y - scaled_geometry[i - 1].y);
|
|
||||||
dist += sqrt(xd * xd + yd * yd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// treat lines as having the area of a circle with the line as diameter
|
// treat lines as having the area of a circle with the line as diameter
|
||||||
area = M_PI * (dist / 2) * (dist / 2);
|
area = M_PI * (dist / 2) * (dist / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf.prominence = sqrt(dist * dist * area);
|
||||||
|
|
||||||
// VT_POINT area will be calculated in write_tile from the distance between adjacent features.
|
// VT_POINT area will be calculated in write_tile from the distance between adjacent features.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ struct serial_feature {
|
|||||||
unsigned long long index = 0;
|
unsigned long long index = 0;
|
||||||
unsigned long long label_point = 0;
|
unsigned long long label_point = 0;
|
||||||
long long area = 0;
|
long long area = 0;
|
||||||
|
long long prominence = 0;
|
||||||
|
|
||||||
std::vector<long long> keys{};
|
std::vector<long long> keys{};
|
||||||
std::vector<long long> values{};
|
std::vector<long long> values{};
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ struct coalesce {
|
|||||||
bool has_id = false;
|
bool has_id = false;
|
||||||
unsigned long long id = 0;
|
unsigned long long id = 0;
|
||||||
long long area = 0;
|
long long area = 0;
|
||||||
|
long long prominence = 0;
|
||||||
|
|
||||||
bool operator<(const coalesce &o) const {
|
bool operator<(const coalesce &o) const {
|
||||||
int cmp = coalindexcmp(this, &o);
|
int cmp = coalindexcmp(this, &o);
|
||||||
@@ -256,6 +257,11 @@ static mvt_value find_attribute_value(const struct coalesce *c1, std::string key
|
|||||||
v.type = mvt_double;
|
v.type = mvt_double;
|
||||||
v.numeric_value.double_value = c1->area;
|
v.numeric_value.double_value = c1->area;
|
||||||
return v;
|
return v;
|
||||||
|
} else if (key == ORDER_BY_PROMINENCE) {
|
||||||
|
mvt_value v;
|
||||||
|
v.type = mvt_double;
|
||||||
|
v.numeric_value.double_value = c1->prominence;
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<long long> &keys1 = c1->keys;
|
const std::vector<long long> &keys1 = c1->keys;
|
||||||
@@ -324,7 +330,7 @@ struct ordercmp {
|
|||||||
}
|
}
|
||||||
} ordercmp;
|
} ordercmp;
|
||||||
|
|
||||||
void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, unsigned tx, unsigned ty, int buffer, int *within, std::atomic<long long> *geompos, FILE **geomfile, const char *fname, signed char t, int layer, long long metastart, signed char feature_minzoom, int child_shards, int max_zoom_increment, long long seq, int tippecanoe_minzoom, int tippecanoe_maxzoom, int segment, unsigned *initial_x, unsigned *initial_y, std::vector<long long> &metakeys, std::vector<long long> &metavals, bool has_id, unsigned long long id, unsigned long long index, unsigned long long label_point, long long area) {
|
void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, unsigned tx, unsigned ty, int buffer, int *within, std::atomic<long long> *geompos, FILE **geomfile, const char *fname, signed char t, int layer, long long metastart, signed char feature_minzoom, int child_shards, int max_zoom_increment, long long seq, int tippecanoe_minzoom, int tippecanoe_maxzoom, int segment, unsigned *initial_x, unsigned *initial_y, std::vector<long long> &metakeys, std::vector<long long> &metavals, bool has_id, unsigned long long id, unsigned long long index, unsigned long long label_point, long long area, long long prominence) {
|
||||||
if (geom.size() > 0 && (nextzoom <= maxzoom || additional[A_EXTEND_ZOOMS])) {
|
if (geom.size() > 0 && (nextzoom <= maxzoom || additional[A_EXTEND_ZOOMS])) {
|
||||||
int xo, yo;
|
int xo, yo;
|
||||||
int span = 1 << (nextzoom - z);
|
int span = 1 << (nextzoom - z);
|
||||||
@@ -416,6 +422,7 @@ void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, u
|
|||||||
sf.index = index;
|
sf.index = index;
|
||||||
sf.label_point = label_point;
|
sf.label_point = label_point;
|
||||||
sf.area = area;
|
sf.area = area;
|
||||||
|
sf.prominence = prominence;
|
||||||
sf.feature_minzoom = feature_minzoom;
|
sf.feature_minzoom = feature_minzoom;
|
||||||
|
|
||||||
if (metastart < 0) {
|
if (metastart < 0) {
|
||||||
@@ -460,6 +467,7 @@ struct partial {
|
|||||||
bool has_id = 0;
|
bool has_id = 0;
|
||||||
ssize_t renamed = 0;
|
ssize_t renamed = 0;
|
||||||
long long area = 0;
|
long long area = 0;
|
||||||
|
long long prominence = 0;
|
||||||
long long clustered = 0;
|
long long clustered = 0;
|
||||||
std::set<std::string> need_tilestats;
|
std::set<std::string> need_tilestats;
|
||||||
std::map<std::string, accum_state> attribute_accum_state;
|
std::map<std::string, accum_state> attribute_accum_state;
|
||||||
@@ -1431,7 +1439,7 @@ serial_feature next_feature(FILE *geoms, std::atomic<long long> *geompos_in, cha
|
|||||||
|
|
||||||
if (*first_time && pass == 1) { /* only write out the next zoom once, even if we retry */
|
if (*first_time && pass == 1) { /* only write out the next zoom once, even if we retry */
|
||||||
if (sf.tippecanoe_maxzoom == -1 || sf.tippecanoe_maxzoom >= nextzoom) {
|
if (sf.tippecanoe_maxzoom == -1 || sf.tippecanoe_maxzoom >= nextzoom) {
|
||||||
rewrite(sf.geometry, z, nextzoom, maxzoom, sf.bbox, tx, ty, buffer, within, geompos, geomfile, fname, sf.t, sf.layer, sf.metapos, sf.feature_minzoom, child_shards, max_zoom_increment, sf.seq, sf.tippecanoe_minzoom, sf.tippecanoe_maxzoom, sf.segment, initial_x, initial_y, sf.keys, sf.values, sf.has_id, sf.id, sf.index, sf.label_point, sf.area);
|
rewrite(sf.geometry, z, nextzoom, maxzoom, sf.bbox, tx, ty, buffer, within, geompos, geomfile, fname, sf.t, sf.layer, sf.metapos, sf.feature_minzoom, child_shards, max_zoom_increment, sf.seq, sf.tippecanoe_minzoom, sf.tippecanoe_maxzoom, sf.segment, initial_x, initial_y, sf.keys, sf.values, sf.has_id, sf.id, sf.index, sf.label_point, sf.area, sf.prominence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1606,7 +1614,7 @@ void *run_prefilter(void *v) {
|
|||||||
decode_meta(sf.keys, sf.values, rpa->stringpool + rpa->pool_off[sf.segment], tmp_layer, tmp_feature);
|
decode_meta(sf.keys, sf.values, rpa->stringpool + rpa->pool_off[sf.segment], tmp_layer, tmp_feature);
|
||||||
tmp_layer.features.push_back(tmp_feature);
|
tmp_layer.features.push_back(tmp_feature);
|
||||||
|
|
||||||
layer_to_geojson(tmp_layer, 0, 0, 0, false, true, false, true, sf.index, sf.seq, sf.area, true, state, 0);
|
layer_to_geojson(tmp_layer, 0, 0, 0, false, true, false, true, sf.index, sf.seq, sf.area, sf.prominence, true, state, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fclose(rpa->prefilter_fp) != 0) {
|
if (fclose(rpa->prefilter_fp) != 0) {
|
||||||
@@ -1963,12 +1971,14 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
|||||||
if (sf.t == VT_POINT) {
|
if (sf.t == VT_POINT) {
|
||||||
if (area_previndex >= sf.index) {
|
if (area_previndex >= sf.index) {
|
||||||
sf.area = 1;
|
sf.area = 1;
|
||||||
|
sf.prominence = 1;
|
||||||
} else {
|
} else {
|
||||||
double radius = sqrt(sf.index - area_previndex) / 4.0;
|
double radius = sqrt(sf.index - area_previndex) / 4.0;
|
||||||
sf.area = M_PI * radius * radius;
|
sf.area = M_PI * radius * radius;
|
||||||
if (sf.area < 1) {
|
if (sf.area < 1) {
|
||||||
sf.area = 1;
|
sf.area = 1;
|
||||||
}
|
}
|
||||||
|
sf.prominence = sf.area;
|
||||||
}
|
}
|
||||||
|
|
||||||
area_previndex = sf.index;
|
area_previndex = sf.index;
|
||||||
@@ -2128,6 +2138,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
|||||||
p.index = sf.index;
|
p.index = sf.index;
|
||||||
p.renamed = -1;
|
p.renamed = -1;
|
||||||
p.area = sf.area;
|
p.area = sf.area;
|
||||||
|
p.prominence = sf.prominence;
|
||||||
p.clustered = 0;
|
p.clustered = 0;
|
||||||
|
|
||||||
if (line_detail == detail && extra_detail >= 0 && z == maxzoom) {
|
if (line_detail == detail && extra_detail >= 0 && z == maxzoom) {
|
||||||
@@ -2297,6 +2308,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
|||||||
c.id = partials[i].id;
|
c.id = partials[i].id;
|
||||||
c.has_id = partials[i].has_id;
|
c.has_id = partials[i].has_id;
|
||||||
c.area = partials[i].area;
|
c.area = partials[i].area;
|
||||||
|
c.prominence = partials[i].prominence;
|
||||||
|
|
||||||
// printf("segment %d layer %lld is %s\n", partials[i].segment, partials[i].layer, (*layer_unmaps)[partials[i].segment][partials[i].layer].c_str());
|
// printf("segment %d layer %lld is %s\n", partials[i].segment, partials[i].layer, (*layer_unmaps)[partials[i].segment][partials[i].layer].c_str());
|
||||||
|
|
||||||
|
|||||||
+14
-10
@@ -258,7 +258,7 @@ void write_coords(json_writer &state, lonlat const &ll, double scale) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y, bool comma, bool name, bool zoom, bool dropped, unsigned long long index, long long sequence, long long extent, bool complain, json_writer &state, double scale) {
|
void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y, bool comma, bool name, bool zoom, bool dropped, unsigned long long index, long long sequence, long long area, long long prominence, bool complain, json_writer &state, double scale) {
|
||||||
for (size_t f = 0; f < layer.features.size(); f++) {
|
for (size_t f = 0; f < layer.features.size(); f++) {
|
||||||
mvt_feature const &feat = layer.features[f];
|
mvt_feature const &feat = layer.features[f];
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y
|
|||||||
state.json_write_unsigned(feat.id);
|
state.json_write_unsigned(feat.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name || zoom || index != 0 || sequence != 0 || extent != 0) {
|
if (name || zoom || index != 0 || sequence != 0 || area != 0 || prominence != 0) {
|
||||||
state.json_write_string("tippecanoe");
|
state.json_write_string("tippecanoe");
|
||||||
state.json_write_hash();
|
state.json_write_hash();
|
||||||
|
|
||||||
@@ -303,9 +303,13 @@ void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y
|
|||||||
state.json_write_signed(sequence);
|
state.json_write_signed(sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extent != 0) {
|
if (area != 0) {
|
||||||
state.json_write_string("extent");
|
state.json_write_string("extent"); // keep misleading terminology for compatibility
|
||||||
state.json_write_signed(extent);
|
state.json_write_signed(area);
|
||||||
|
}
|
||||||
|
if (prominence != 0) {
|
||||||
|
state.json_write_string("prominence");
|
||||||
|
state.json_write_signed(prominence);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.json_end_hash();
|
state.json_end_hash();
|
||||||
@@ -505,16 +509,16 @@ void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y
|
|||||||
int outer = 0;
|
int outer = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < rings.size(); i++) {
|
for (size_t i = 0; i < rings.size(); i++) {
|
||||||
double area = 0;
|
double poly_area = 0;
|
||||||
for (size_t k = 0; k < rings[i].size(); k++) {
|
for (size_t k = 0; k < rings[i].size(); k++) {
|
||||||
if (rings[i][k].op != VT_CLOSEPATH) {
|
if (rings[i][k].op != VT_CLOSEPATH) {
|
||||||
area += (double) rings[i][k].x * (double) rings[i][(k + 1) % rings[i].size()].y;
|
poly_area += (double) rings[i][k].x * (double) rings[i][(k + 1) % rings[i].size()].y;
|
||||||
area -= (double) rings[i][k].y * (double) rings[i][(k + 1) % rings[i].size()].x;
|
poly_area -= (double) rings[i][k].y * (double) rings[i][(k + 1) % rings[i].size()].x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
area /= 2;
|
poly_area /= 2;
|
||||||
|
|
||||||
areas[i] = area;
|
areas[i] = poly_area;
|
||||||
if (areas[i] >= 0 || i == 0) {
|
if (areas[i] >= 0 || i == 0) {
|
||||||
outer++;
|
outer++;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@ struct json_writer {
|
|||||||
void adds(std::string const &s);
|
void adds(std::string const &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y, bool comma, bool name, bool zoom, bool dropped, unsigned long long index, long long sequence, long long extent, bool complain, json_writer &state, double scale);
|
void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y, bool comma, bool name, bool zoom, bool dropped, unsigned long long index, long long sequence, long long area, long long prominence, bool complain, json_writer &state, double scale);
|
||||||
void fprintq(FILE *f, const char *s);
|
void fprintq(FILE *f, const char *s);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user