diff --git a/main.cpp b/main.cpp index 9a912dbd..9acb8727 100644 --- a/main.cpp +++ b/main.cpp @@ -93,6 +93,7 @@ size_t limit_tile_feature_count_at_maxzoom = 0; unsigned int drop_denser = 0; std::map set_attributes; unsigned long long preserve_point_density_threshold = 0; +unsigned long long preserve_multiplier_density_threshold = 0; long long extend_zooms_max = 0; int retain_points_multiplier = 1; std::vector unidecode_data; @@ -3109,6 +3110,7 @@ int main(int argc, char **argv) { {"cluster-distance", required_argument, 0, 'K'}, {"cluster-maxzoom", required_argument, 0, 'k'}, {"preserve-point-density-threshold", required_argument, 0, '~'}, + {"preserve-multiplier-density-threshold", required_argument, 0, '~'}, {"Dropping or merging a fraction of features to keep under tile size limits", 0, 0, 0}, {"drop-densest-as-needed", no_argument, &additional[A_DROP_DENSEST_AS_NEEDED], 1}, @@ -3320,6 +3322,8 @@ int main(int argc, char **argv) { } } else if (strcmp(opt, "preserve-point-density-threshold") == 0) { preserve_point_density_threshold = atoll_require(optarg, "Preserve point density threshold"); + } else if (strcmp(opt, "preserve-multiplier-density-threshold") == 0) { + preserve_multiplier_density_threshold = atoll_require(optarg, "Preserve multiplier density threshold"); } else if (strcmp(opt, "extend-zooms-if-still-dropping-maximum") == 0) { extend_zooms_max = atoll_require(optarg, "Maximum number by which to extend zooms"); } else if (strcmp(opt, "retain-points-multiplier") == 0) { diff --git a/main.hpp b/main.hpp index b5844d91..cc28df3c 100644 --- a/main.hpp +++ b/main.hpp @@ -65,6 +65,7 @@ extern long long extend_zooms_max; extern int retain_points_multiplier; extern size_t maximum_string_attribute_length; extern std::string accumulate_numeric; +extern unsigned long long preserve_multiplier_density_threshold; struct order_field { std::string name; diff --git a/serial.hpp b/serial.hpp index 91479a4a..61cd5515 100644 --- a/serial.hpp +++ b/serial.hpp @@ -94,6 +94,7 @@ struct serial_feature { #define FEATURE_DROPPED -1 #define FEATURE_KEPT 0 +#define FEATURE_NO_REALLY_KEEP_IT_AROUND INT_MAX // <0: dropped // 0: kept // >0: sequence number of additional feature kept by retain-points-multiplier diff --git a/tile.cpp b/tile.cpp index d31e17d7..0244f120 100644 --- a/tile.cpp +++ b/tile.cpp @@ -1237,6 +1237,9 @@ static serial_feature next_feature(decompressor *geoms, std::atomic * } else if (z + extra_multiplier_zooms >= feature_minzoom && count->second + 1 < retain_points_multiplier) { count->second++; sf.dropped = count->second; + } else if (preserve_multiplier_density_threshold > 0 && + sf.gap > ((1LL << (32 - z)) / preserve_multiplier_density_threshold) * ((1LL << (32 - z)) / preserve_multiplier_density_threshold)) { + sf.dropped = FEATURE_NO_REALLY_KEEP_IT_AROUND; } else { sf.dropped = FEATURE_DROPPED; } @@ -1898,8 +1901,11 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch } else { can_stop_early = false; - if (sf.dropped != FEATURE_DROPPED) { + if (sf.dropped != FEATURE_DROPPED && sf.dropped != FEATURE_NO_REALLY_KEEP_IT_AROUND) { // Does the current multiplier cluster already have too many features? + // (Because we are dropping dynamically, and we have already filled the + // cluster with features that were dynamically dropped from being + // primary features) // If so, we have to drop this one, even if it would potentially qualify // as a secondary feature to be exposed by filtering if (layer.multiplier_cluster_size >= (size_t) retain_points_multiplier) { @@ -2146,6 +2152,8 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch if (sf.dropped == FEATURE_KEPT) { layer.multiplier_cluster_size = 1; lead_features_count++; + } else if (sf.dropped == FEATURE_NO_REALLY_KEEP_IT_AROUND) { + other_multiplier_cluster_features_count++; } else { layer.multiplier_cluster_size++; other_multiplier_cluster_features_count++;