From 31ef904b7a62100b95b88c06e8b173f0b9879eda Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Thu, 27 Jun 2024 14:09:32 -0700 Subject: [PATCH] Start to distinguish fixed cluster density setting from as-needed density --- serial.cpp | 3 +++ serial.hpp | 1 + tile.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/serial.cpp b/serial.cpp index af405a8b..2c9aa9c3 100644 --- a/serial.cpp +++ b/serial.cpp @@ -210,6 +210,7 @@ std::string serialize_feature(serial_feature *sf, long long wx, long long wy) { if (sf->index != 0) { serialize_ulong_long(s, sf->index); + serialize_ulong_long(s, sf->previndex); } if (sf->label_point != 0) { serialize_ulong_long(s, sf->label_point); @@ -258,6 +259,7 @@ serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigne deserialize_int(&cp, &sf.segment); sf.index = 0; + sf.previndex = 0; sf.label_point = 0; sf.extent = 0; @@ -265,6 +267,7 @@ serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigne if (sf.layer & (1 << FLAG_INDEX)) { deserialize_ulong_long(&cp, &sf.index); + deserialize_ulong_long(&cp, &sf.previndex); } if (sf.layer & (1 << FLAG_LABEL_POINT)) { deserialize_ulong_long(&cp, &sf.label_point); diff --git a/serial.hpp b/serial.hpp index 2d47f672..837500eb 100644 --- a/serial.hpp +++ b/serial.hpp @@ -66,6 +66,7 @@ struct serial_feature { int tippecanoe_maxzoom = -1; drawvec geometry = drawvec(); + unsigned long long previndex = 0; // filled in during z0 unsigned long long index = 0; unsigned long long label_point = 0; long long extent = 0; diff --git a/tile.cpp b/tile.cpp index 6e6899d2..8aa81291 100644 --- a/tile.cpp +++ b/tile.cpp @@ -1029,6 +1029,8 @@ struct multiplier_state { // from the input stream. If the stream is at an end, it returns a feature with the // geometry type set to -2. static serial_feature next_feature(decompressor *geoms, std::atomic *geompos_in, int z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y, long long *original_features, long long *unclipped_features, int nextzoom, int maxzoom, int minzoom, int max_zoom_increment, size_t pass, std::atomic *along, long long alongminus, int buffer, int *within, compressor **geomfile, std::atomic *geompos, std::atomic *oprogress, double todo, const char *fname, int child_shards, json_object *filter, const char *global_stringpool, long long *pool_off, std::vector> *layer_unmaps, bool first_time, bool compressed, multiplier_state *multiplier_state, std::shared_ptr &tile_stringpool, std::vector const &unidecode_data) { + unsigned long long previndex = 0; + while (1) { serial_feature sf; long long len; @@ -1072,6 +1074,11 @@ static serial_feature next_feature(decompressor *geoms, std::atomic * (*original_features)++; + if (sf.previndex == 0) { + sf.previndex = previndex; + } + previndex = sf.index; + if (clip_to_tile(sf, z, buffer)) { continue; } @@ -1519,6 +1526,9 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch } } + // only for -K + unsigned long long cluster_mingap = ((1LL << (32 - z)) / 256 * cluster_distance) * ((1LL << (32 - z)) / 256 * cluster_distance); + bool first_time = true; // This only loops if the tile data didn't fit, in which case the detail // goes down and the progress indicator goes backward for the next try. @@ -1745,11 +1755,16 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch // representative of the other features in the tile. const size_t MAX_INDICES = 100000; - if (z <= cluster_maxzoom && (additional[A_CLUSTER_DENSEST_AS_NEEDED] || cluster_distance != 0)) { + if (z <= cluster_maxzoom && cluster_distance != 0) { if (indices.size() < MAX_INDICES) { indices.push_back(sf.index); } - if ((sf.index < merge_previndex || sf.index - merge_previndex < mingap) && find_feature_to_accumulate_onto(features, sf, which_serial_feature, layer_unmaps, LLONG_MAX, multiplier_seq)) { + // This still uses merge_previndex instead of sf.previndex + // because the cluster size in -K is expecting to specify + // distances between points that are subject to dot-dropping, + // rather than wanting each feature to have a consistent + // idea of density between zooms. + if ((sf.index < merge_previndex || sf.index - merge_previndex < cluster_mingap) && find_feature_to_accumulate_onto(features, sf, which_serial_feature, layer_unmaps, LLONG_MAX, multiplier_seq)) { features[which_serial_feature].clustered++; if (features[which_serial_feature].t == VT_POINT && @@ -1777,7 +1792,31 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch continue; } } + } else if (z <= cluster_maxzoom && (additional[A_CLUSTER_DENSEST_AS_NEEDED])) { + // this is now just like coalesce-densest, except that instead of unioning the geometry, + // it averages the point locations + if (indices.size() < MAX_INDICES) { + indices.push_back(sf.index); + } + if (sf.index - merge_previndex < mingap && find_feature_to_accumulate_onto(features, sf, which_serial_feature, layer_unmaps, LLONG_MAX, multiplier_seq)) { + features[which_serial_feature].clustered++; + if (features[which_serial_feature].t == VT_POINT && + features[which_serial_feature].geometry.size() == 1 && + sf.geometry.size() == 1) { + double x = (double) features[which_serial_feature].geometry[0].x * features[which_serial_feature].clustered; + double y = (double) features[which_serial_feature].geometry[0].y * features[which_serial_feature].clustered; + x += sf.geometry[0].x; + y += sf.geometry[0].y; + features[which_serial_feature].geometry[0].x = x / (features[which_serial_feature].clustered + 1); + features[which_serial_feature].geometry[0].y = y / (features[which_serial_feature].clustered + 1); + } + + preserve_attributes(arg->attribute_accum, sf, features[which_serial_feature]); + strategy->coalesced_as_needed++; + drop_rest = true; + continue; + } } else if (additional[A_COALESCE_DENSEST_AS_NEEDED]) { if (indices.size() < MAX_INDICES) { indices.push_back(sf.index); @@ -2826,7 +2865,7 @@ int traverse_zooms(int *geomfd, off_t *geom_size, char *global_stringpool, std:: int err = INT_MAX; double zoom_gamma = gamma; - unsigned long long zoom_mingap = ((1LL << (32 - z)) / 256 * cluster_distance) * ((1LL << (32 - z)) / 256 * cluster_distance); + unsigned long long zoom_mingap = 0; long long zoom_minextent = 0; unsigned long long zoom_mindrop_sequence = 0; size_t zoom_tile_size = 0;