Add an option to calculate feature density as a feature attribute

This commit is contained in:
Eric Fischer 2016-05-27 16:25:40 -07:00
parent 4030cc7c58
commit 692112ec3a
7 changed files with 58 additions and 6 deletions

View File

@ -1,3 +1,7 @@
## 1.11.8
* Add an option to calculate the density of features as a feature attribute
## 1.11.7
* Keep metadata together with geometry for features that don't span many tiles,

View File

@ -118,6 +118,7 @@ resolution is obtained than by using a smaller _maxzoom_ or _detail_.
* -ao or --reorder: Reorder features to put ones with the same properties in sequence, to try to get them to coalesce
* -al or --drop-lines: Let "dot" dropping at lower zooms apply to lines too
* -ap or --drop-polygons: Let "dot" dropping at lower zooms apply to polygons too
* -ag or --calculate-feature-density: Add a new attribute, `tippecanoe_feature_density`, to each feature, to record how densely features are spaced in that area of the tile. You can use this attribute in the style to produce a glowing effect where points are densely packed. It can range from 0 in the sparsest areas to 255 in the densest.
### Doing less

View File

@ -987,6 +987,13 @@ int read_input(std::vector<source> &sources, char *fname, const char *layername,
std::string reading;
int fd;
if (additional[A_CALCULATE_FEATURE_DENSITY]) {
type_and_string tas;
tas.type = VT_NUMBER;
tas.string = "tippecanoe_feature_density";
file_keys[source].insert(tas);
}
if (source >= sources.size()) {
reading = "standard input";
fd = 0;
@ -1771,6 +1778,7 @@ int main(int argc, char **argv) {
{"check-polygons", no_argument, &additional[A_DEBUG_POLYGON], 1},
{"drop-polygons", no_argument, &additional[A_POLYGON_DROP], 1},
{"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 1},
{"calculate-feature-density", no_argument, &additional[A_CALCULATE_FEATURE_DENSITY], 1},
{"no-line-simplification", no_argument, &prevent[P_SIMPLIFY], 1},
{"simplify-only-low-zooms", no_argument, &prevent[P_SIMPLIFY_LOW], 1},

View File

@ -145,6 +145,8 @@ which may not be what you want.
\-al or \-\-drop\-lines: Let "dot" dropping at lower zooms apply to lines too
.IP \(bu 2
\-ap or \-\-drop\-polygons: Let "dot" dropping at lower zooms apply to polygons too
.IP \(bu 2
\-ag or \-\-calculate\-feature\-density: Add a new attribute, \fB\fCtippecanoe_feature_density\fR, to each feature, to record how densely features are spaced in that area of the tile. You can use this attribute in the style to produce a glowing effect where points are densely packed. It can range from 0 in the sparsest areas to 255 in the densest.
.RE
.SS Doing less
.RS

View File

@ -5,6 +5,7 @@
#define A_DEBUG_POLYGON ((int) 'd')
#define A_POLYGON_DROP ((int) 'p')
#define A_PREFER_RADIX_SORT ((int) 'R')
#define A_CALCULATE_FEATURE_DENSITY ((int) 'g')
#define P_SIMPLIFY ((int) 's')
#define P_SIMPLIFY_LOW ((int) 'S')

View File

@ -73,6 +73,7 @@ struct coalesce {
int type;
int m;
bool coalesced;
double spacing;
bool operator<(const coalesce &o) const {
int cmp = coalindexcmp(this, &o);
@ -259,7 +260,7 @@ struct sll {
}
};
void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, unsigned tx, unsigned ty, int buffer, int line_detail, int *within, 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, int m, std::vector<long long> &metakeys, std::vector <long long> &metavals) {
void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, unsigned tx, unsigned ty, int buffer, int line_detail, int *within, 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, int m, std::vector<long long> &metakeys, std::vector<long long> &metavals) {
if (geom.size() > 0 && nextzoom <= maxzoom) {
int xo, yo;
int span = 1 << (nextzoom - z);
@ -387,6 +388,7 @@ struct partial {
int z;
int line_detail;
int maxzoom;
double spacing;
signed char t;
};
@ -599,9 +601,10 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
double fraction_accum = 0;
unsigned long long previndex = 0;
unsigned long long previndex = 0, density_previndex = 0;
double scale = (double) (1LL << (64 - 2 * (z + 8)));
double gap = 0;
double gap = 0, density_gap = 0;
double spacing = 0;
long long original_features = 0;
long long unclipped_features = 0;
@ -796,6 +799,11 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
continue;
}
unsigned long long index = 0;
if (additional[A_CALCULATE_FEATURE_DENSITY] || gamma > 0) {
index = encode(bbox[0] / 2 + bbox[2] / 2, bbox[1] / 2 + bbox[3] / 2);
}
if (gamma >= 0 && (t == VT_POINT ||
(additional[A_LINE_DROP] && t == VT_LINE) ||
(additional[A_POLYGON_DROP] && t == VT_POLYGON))) {
@ -806,14 +814,25 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
continue;
}
if (gamma > 0) {
unsigned long long index = encode(bbox[0] / 2 + bbox[2] / 2, bbox[1] / 2 + bbox[3] / 2);
if (gamma > 0 || additional[A_CALCULATE_FEATURE_DENSITY]) {
if (manage_gap(index, &previndex, scale, gamma, &gap)) {
continue;
}
}
}
if (additional[A_CALCULATE_FEATURE_DENSITY]) {
// Gamma is always 1 for this calculation so there is a reasonable
// interpretation when no features are being dropped.
// The spacing is only calculated if a feature would be retained by
// that standard, so that duplicates aren't reported as infinitely dense.
double o_density_previndex = density_previndex;
if (!manage_gap(index, &density_previndex, scale, 1, &density_gap)) {
spacing = (index - o_density_previndex) / scale;
}
}
fraction_accum += fraction;
if (fraction_accum < 1) {
continue;
@ -840,6 +859,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
p.maxzoom = maxzoom;
p.keys = metakeys;
p.values = metavals;
p.spacing = spacing;
partials.push_back(p);
}
}
@ -900,6 +920,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
c.stringpool = stringpool + pool_off[partials[i].segment];
c.keys = partials[i].keys;
c.values = partials[i].values;
c.spacing = partials[i].spacing;
features[layer].push_back(c);
}
@ -995,6 +1016,21 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
features[k][x].geom.clear();
decode_meta(features[k][x].m, features[k][x].keys, features[k][x].values, features[k][x].stringpool, layer, feature);
if (additional[A_CALCULATE_FEATURE_DENSITY]) {
int glow = 255;
if (features[k][x].spacing > 0) {
glow = (1 / features[k][x].spacing);
if (glow > 255) {
glow = 255;
}
}
mvt_value v;
v.type = mvt_sint;
v.numeric_value.sint_value = glow;
layer.tag(feature, "tippecanoe_feature_density", v);
}
layer.features.push_back(feature);
}

View File

@ -1 +1 @@
#define VERSION "tippecanoe v1.11.7\n"
#define VERSION "tippecanoe v1.11.8\n"