mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Merge pull request #252 from mapbox/glow-map2
Add an option to calculate feature density as a feature attribute
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.11.8
|
||||||
|
|
||||||
|
* Add an option to calculate the density of features as a feature attribute
|
||||||
|
|
||||||
## 1.11.7
|
## 1.11.7
|
||||||
|
|
||||||
* Keep metadata together with geometry for features that don't span many tiles,
|
* 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
|
* -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
|
* -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
|
* -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
|
### Doing less
|
||||||
|
|
||||||
|
|||||||
@@ -987,6 +987,13 @@ int read_input(std::vector<source> &sources, char *fname, const char *layername,
|
|||||||
std::string reading;
|
std::string reading;
|
||||||
int fd;
|
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()) {
|
if (source >= sources.size()) {
|
||||||
reading = "standard input";
|
reading = "standard input";
|
||||||
fd = 0;
|
fd = 0;
|
||||||
@@ -1771,6 +1778,7 @@ int main(int argc, char **argv) {
|
|||||||
{"check-polygons", no_argument, &additional[A_DEBUG_POLYGON], 1},
|
{"check-polygons", no_argument, &additional[A_DEBUG_POLYGON], 1},
|
||||||
{"drop-polygons", no_argument, &additional[A_POLYGON_DROP], 1},
|
{"drop-polygons", no_argument, &additional[A_POLYGON_DROP], 1},
|
||||||
{"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 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},
|
{"no-line-simplification", no_argument, &prevent[P_SIMPLIFY], 1},
|
||||||
{"simplify-only-low-zooms", no_argument, &prevent[P_SIMPLIFY_LOW], 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
|
\-al or \-\-drop\-lines: Let "dot" dropping at lower zooms apply to lines too
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\-ap or \-\-drop\-polygons: Let "dot" dropping at lower zooms apply to polygons too
|
\-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
|
.RE
|
||||||
.SS Doing less
|
.SS Doing less
|
||||||
.RS
|
.RS
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#define A_DEBUG_POLYGON ((int) 'd')
|
#define A_DEBUG_POLYGON ((int) 'd')
|
||||||
#define A_POLYGON_DROP ((int) 'p')
|
#define A_POLYGON_DROP ((int) 'p')
|
||||||
#define A_PREFER_RADIX_SORT ((int) 'R')
|
#define A_PREFER_RADIX_SORT ((int) 'R')
|
||||||
|
#define A_CALCULATE_FEATURE_DENSITY ((int) 'g')
|
||||||
|
|
||||||
#define P_SIMPLIFY ((int) 's')
|
#define P_SIMPLIFY ((int) 's')
|
||||||
#define P_SIMPLIFY_LOW ((int) 'S')
|
#define P_SIMPLIFY_LOW ((int) 'S')
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -73,6 +73,7 @@ struct coalesce {
|
|||||||
int type;
|
int type;
|
||||||
int m;
|
int m;
|
||||||
bool coalesced;
|
bool coalesced;
|
||||||
|
double spacing;
|
||||||
|
|
||||||
bool operator<(const coalesce &o) const {
|
bool operator<(const coalesce &o) const {
|
||||||
int cmp = coalindexcmp(this, &o);
|
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) {
|
if (geom.size() > 0 && nextzoom <= maxzoom) {
|
||||||
int xo, yo;
|
int xo, yo;
|
||||||
int span = 1 << (nextzoom - z);
|
int span = 1 << (nextzoom - z);
|
||||||
@@ -387,6 +388,7 @@ struct partial {
|
|||||||
int z;
|
int z;
|
||||||
int line_detail;
|
int line_detail;
|
||||||
int maxzoom;
|
int maxzoom;
|
||||||
|
double spacing;
|
||||||
signed char t;
|
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;
|
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 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 original_features = 0;
|
||||||
long long unclipped_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;
|
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 ||
|
if (gamma >= 0 && (t == VT_POINT ||
|
||||||
(additional[A_LINE_DROP] && t == VT_LINE) ||
|
(additional[A_LINE_DROP] && t == VT_LINE) ||
|
||||||
(additional[A_POLYGON_DROP] && t == VT_POLYGON))) {
|
(additional[A_POLYGON_DROP] && t == VT_POLYGON))) {
|
||||||
@@ -807,13 +815,24 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gamma > 0) {
|
if (gamma > 0) {
|
||||||
unsigned long long index = encode(bbox[0] / 2 + bbox[2] / 2, bbox[1] / 2 + bbox[3] / 2);
|
|
||||||
if (manage_gap(index, &previndex, scale, gamma, &gap)) {
|
if (manage_gap(index, &previndex, scale, gamma, &gap)) {
|
||||||
continue;
|
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;
|
fraction_accum += fraction;
|
||||||
if (fraction_accum < 1) {
|
if (fraction_accum < 1) {
|
||||||
continue;
|
continue;
|
||||||
@@ -840,6 +859,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
|||||||
p.maxzoom = maxzoom;
|
p.maxzoom = maxzoom;
|
||||||
p.keys = metakeys;
|
p.keys = metakeys;
|
||||||
p.values = metavals;
|
p.values = metavals;
|
||||||
|
p.spacing = spacing;
|
||||||
partials.push_back(p);
|
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.stringpool = stringpool + pool_off[partials[i].segment];
|
||||||
c.keys = partials[i].keys;
|
c.keys = partials[i].keys;
|
||||||
c.values = partials[i].values;
|
c.values = partials[i].values;
|
||||||
|
c.spacing = partials[i].spacing;
|
||||||
|
|
||||||
features[layer].push_back(c);
|
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();
|
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);
|
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);
|
layer.features.push_back(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
#define VERSION "tippecanoe v1.11.7\n"
|
#define VERSION "tippecanoe v1.11.8\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user