mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Add an option for clustering features
This commit is contained in:
@@ -1385,6 +1385,34 @@ void *run_prefilter(void *v) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_tilestats(std::string const &layername, int z, std::vector<std::map<std::string, layermap_entry>> *layermaps, size_t tiling_seg, std::vector<std::vector<std::string>> *layer_unmaps, std::string const &key, serial_val const &val) {
|
||||
std::map<std::string, layermap_entry> &layermap = (*layermaps)[tiling_seg];
|
||||
if (layermap.count(layername) == 0) {
|
||||
layermap_entry lme = layermap_entry(layermap.size());
|
||||
lme.minzoom = z;
|
||||
lme.maxzoom = z;
|
||||
lme.retain = 1;
|
||||
|
||||
layermap.insert(std::pair<std::string, layermap_entry>(layername, lme));
|
||||
|
||||
if (lme.id >= (*layer_unmaps)[tiling_seg].size()) {
|
||||
(*layer_unmaps)[tiling_seg].resize(lme.id + 1);
|
||||
(*layer_unmaps)[tiling_seg][lme.id] = layername;
|
||||
}
|
||||
}
|
||||
auto fk = layermap.find(layername);
|
||||
if (fk == layermap.end()) {
|
||||
fprintf(stderr, "Internal error: layer %s not found\n", layername.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
type_and_string attrib;
|
||||
attrib.type = val.type;
|
||||
attrib.string = val.s;
|
||||
|
||||
add_to_file_keys(fk->second.file_keys, key, attrib);
|
||||
}
|
||||
|
||||
long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *stringpool, int z, unsigned tx, unsigned ty, int detail, int min_detail, sqlite3 *outdb, const char *outdir, int buffer, const char *fname, FILE **geomfile, int minzoom, int maxzoom, double todo, volatile long long *along, long long alongminus, double gamma, int child_shards, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, volatile int *running, double simplification, std::vector<std::map<std::string, layermap_entry>> *layermaps, std::vector<std::vector<std::string>> *layer_unmaps, size_t tiling_seg, size_t pass, size_t passes, unsigned long long mingap, long long minextent, double fraction, const char *prefilter, const char *postfilter, write_tile_args *arg) {
|
||||
int line_detail;
|
||||
double merge_fraction = 1;
|
||||
@@ -1429,6 +1457,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
double scale = (double) (1LL << (64 - 2 * (z + 8)));
|
||||
double gap = 0, density_gap = 0;
|
||||
double spacing = 0;
|
||||
size_t clustered = 0;
|
||||
|
||||
long long original_features = 0;
|
||||
long long unclipped_features = 0;
|
||||
@@ -1540,7 +1569,34 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
}
|
||||
}
|
||||
|
||||
if (additional[A_DROP_DENSEST_AS_NEEDED]) {
|
||||
if (additional[A_CLUSTER_DENSEST_AS_NEEDED]) {
|
||||
indices.push_back(sf.index);
|
||||
if (sf.index - merge_previndex < mingap) {
|
||||
clustered++;
|
||||
continue;
|
||||
} else {
|
||||
if (clustered > 0) {
|
||||
std::string layername = (*layer_unmaps)[sf.segment][sf.layer];
|
||||
serial_val sv, sv2;
|
||||
|
||||
sf.full_keys.push_back("clustered");
|
||||
sv.type = mvt_bool;
|
||||
sv.s = "true";
|
||||
sf.full_values.push_back(sv);
|
||||
|
||||
add_tilestats(layername, z, layermaps, tiling_seg, layer_unmaps, "clustered", sv);
|
||||
|
||||
sf.full_keys.push_back("point_count");
|
||||
sv2.type = mvt_double;
|
||||
sv2.s = std::to_string(clustered + 1);
|
||||
sf.full_values.push_back(sv2);
|
||||
|
||||
add_tilestats(layername, z, layermaps, tiling_seg, layer_unmaps, "point_count", sv2);
|
||||
}
|
||||
|
||||
clustered = 0;
|
||||
}
|
||||
} else if (additional[A_DROP_DENSEST_AS_NEEDED]) {
|
||||
indices.push_back(sf.index);
|
||||
if (sf.index - merge_previndex < mingap) {
|
||||
continue;
|
||||
@@ -1884,7 +1940,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
fprintf(stderr, "Is your data in the wrong projection? It should be in WGS84/EPSG:4326.\n");
|
||||
}
|
||||
|
||||
long long totalsize = 0;
|
||||
size_t totalsize = 0;
|
||||
for (auto layer_iterator = layers.begin(); layer_iterator != layers.end(); ++layer_iterator) {
|
||||
std::vector<coalesce> &layer_features = layer_iterator->second;
|
||||
totalsize += layer_features.size();
|
||||
@@ -1899,11 +1955,11 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
}
|
||||
|
||||
if (totalsize > 0 && tile.layers.size() > 0) {
|
||||
if (totalsize > 200000 && !prevent[P_FEATURE_LIMIT]) {
|
||||
fprintf(stderr, "tile %d/%u/%u has %lld features, >200000 \n", z, tx, ty, totalsize);
|
||||
if (totalsize > max_tile_features && !prevent[P_FEATURE_LIMIT]) {
|
||||
fprintf(stderr, "tile %d/%u/%u has %zu features, >%zu \n", z, tx, ty, totalsize, max_tile_features);
|
||||
|
||||
if (has_polygons && additional[A_MERGE_POLYGONS_AS_NEEDED] && merge_fraction > .05 && merge_successful) {
|
||||
merge_fraction = merge_fraction * 200000 / tile.layers.size() * 0.95;
|
||||
merge_fraction = merge_fraction * max_tile_features / tile.layers.size() * 0.95;
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "Going to try merging %0.2f%% of the polygons to make it fit\n", 100 - merge_fraction * 100);
|
||||
}
|
||||
@@ -1926,8 +1982,8 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
}
|
||||
line_detail++; // to keep it the same when the loop decrements it
|
||||
continue;
|
||||
} else if (additional[A_DROP_DENSEST_AS_NEEDED]) {
|
||||
mingap_fraction = mingap_fraction * 200000.0 / totalsize * 0.90;
|
||||
} else if (additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_CLUSTER_DENSEST_AS_NEEDED]) {
|
||||
mingap_fraction = mingap_fraction * max_tile_features / totalsize * 0.90;
|
||||
unsigned long long mg = choose_mingap(indices, mingap_fraction);
|
||||
if (mg <= mingap) {
|
||||
mg = mingap * 1.5;
|
||||
@@ -1943,7 +1999,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
line_detail++;
|
||||
continue;
|
||||
} else if (additional[A_DROP_SMALLEST_AS_NEEDED] || additional[A_COALESCE_SMALLEST_AS_NEEDED]) {
|
||||
minextent_fraction = minextent_fraction * 200000.0 / totalsize * 0.90;
|
||||
minextent_fraction = minextent_fraction * max_tile_features / totalsize * 0.90;
|
||||
long long m = choose_minextent(extents, minextent_fraction);
|
||||
if (m != minextent) {
|
||||
minextent = m;
|
||||
@@ -1958,7 +2014,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
continue;
|
||||
}
|
||||
} else if (prevent[P_DYNAMIC_DROP] || additional[A_DROP_FRACTION_AS_NEEDED]) {
|
||||
fraction = fraction * 200000 / totalsize * 0.95;
|
||||
fraction = fraction * max_tile_features / totalsize * 0.95;
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "Going to try keeping %0.2f%% of the features to make it fit\n", fraction * 100);
|
||||
}
|
||||
@@ -2010,7 +2066,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
||||
fprintf(stderr, "Going to try gamma of %0.3f to make it fit\n", gamma);
|
||||
}
|
||||
line_detail++; // to keep it the same when the loop decrements it
|
||||
} else if (additional[A_DROP_DENSEST_AS_NEEDED]) {
|
||||
} else if (additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_CLUSTER_DENSEST_AS_NEEDED]) {
|
||||
mingap_fraction = mingap_fraction * max_tile_size / compressed.size() * 0.90;
|
||||
unsigned long long mg = choose_mingap(indices, mingap_fraction);
|
||||
if (mg <= mingap) {
|
||||
@@ -2321,7 +2377,7 @@ int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpo
|
||||
int err = INT_MAX;
|
||||
|
||||
size_t start = 1;
|
||||
if (additional[A_INCREASE_GAMMA_AS_NEEDED] || additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_DROP_FRACTION_AS_NEEDED] || additional[A_DROP_SMALLEST_AS_NEEDED] || additional[A_COALESCE_SMALLEST_AS_NEEDED]) {
|
||||
if (additional[A_INCREASE_GAMMA_AS_NEEDED] || additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_CLUSTER_DENSEST_AS_NEEDED] || additional[A_DROP_FRACTION_AS_NEEDED] || additional[A_DROP_SMALLEST_AS_NEEDED] || additional[A_COALESCE_SMALLEST_AS_NEEDED]) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user