mirror of
https://github.com/mapbox/tippecanoe.git
synced 2025-02-01 16:58:05 +00:00
Add an option to calculate feature density as a feature attribute
This commit is contained in:
parent
4030cc7c58
commit
692112ec3a
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
8
main.cpp
8
main.cpp
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
44
tile.cpp
44
tile.cpp
@ -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);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
#define VERSION "tippecanoe v1.11.7\n"
|
||||
#define VERSION "tippecanoe v1.11.8\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user