mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Add an option to limit geometry vertex count
This commit is contained in:
@@ -83,6 +83,7 @@ int cluster_distance = 0;
|
||||
int tiny_polygon_size = 2;
|
||||
long justx = -1, justy = -1;
|
||||
std::string attribute_for_id = "";
|
||||
size_t max_geometry_size = 0;
|
||||
|
||||
std::vector<order_field> order_by;
|
||||
bool order_reverse;
|
||||
@@ -2773,6 +2774,7 @@ int main(int argc, char **argv) {
|
||||
{"Setting or disabling tile size limits", 0, 0, 0},
|
||||
{"maximum-tile-bytes", required_argument, 0, 'M'},
|
||||
{"maximum-tile-features", required_argument, 0, 'O'},
|
||||
{"maximum-tile-geometry", required_argument, 0, '~'},
|
||||
{"no-feature-limit", no_argument, &prevent[P_FEATURE_LIMIT], 1},
|
||||
{"no-tile-size-limit", no_argument, &prevent[P_KILOBYTE_LIMIT], 1},
|
||||
{"no-tile-compression", no_argument, &prevent[P_TILE_COMPRESSION], 1},
|
||||
@@ -2897,12 +2899,14 @@ int main(int argc, char **argv) {
|
||||
order_by.push_back(order_field(ORDER_BY_SIZE, true));
|
||||
order_by_size = true;
|
||||
} else if (strcmp(opt, "simplification-at-maximum-zoom") == 0) {
|
||||
maxzoom_simplification = atof_require(optarg, "Mazoom simplification");
|
||||
maxzoom_simplification = atof_require(optarg, "Maxzoom simplification");
|
||||
if (maxzoom_simplification <= 0) {
|
||||
fprintf(stderr, "%s: --simplification-at-maximum-zoom must be > 0\n", argv[0]);
|
||||
exit(EXIT_ARGS);
|
||||
}
|
||||
break;
|
||||
} else if (strcmp(opt, "maximum-tile-geometry") == 0) {
|
||||
max_geometry_size = atoll_require(optarg, "Max tile geometry");
|
||||
} else {
|
||||
fprintf(stderr, "%s: Unrecognized option --%s\n", argv[0], opt);
|
||||
exit(EXIT_ARGS);
|
||||
|
||||
@@ -53,6 +53,7 @@ extern size_t max_tile_features;
|
||||
extern int cluster_distance;
|
||||
extern std::string attribute_for_id;
|
||||
extern int tiny_polygon_size;
|
||||
extern size_t max_geometry_size;
|
||||
|
||||
struct order_field {
|
||||
std::string name;
|
||||
|
||||
+950
File diff suppressed because one or more lines are too long
@@ -1836,7 +1836,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
||||
// goes down and the progress indicator goes backward for the next try.
|
||||
int line_detail;
|
||||
for (line_detail = detail; line_detail >= min_detail || line_detail == detail; line_detail--, oprogress = 0) {
|
||||
long long count = 0;
|
||||
long long total_geom_size = 0;
|
||||
double accum_area = 0;
|
||||
|
||||
double fraction_accum = 0;
|
||||
@@ -2413,7 +2413,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
||||
|
||||
feature.type = layer_features[x].type;
|
||||
feature.geometry = to_feature(layer_features[x].geom);
|
||||
count += layer_features[x].geom.size();
|
||||
total_geom_size += layer_features[x].geom.size();
|
||||
layer_features[x].geom.clear();
|
||||
|
||||
feature.id = layer_features[x].id;
|
||||
@@ -2482,6 +2482,92 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
||||
}
|
||||
|
||||
if (totalsize > 0 && tile.layers.size() > 0) {
|
||||
if (max_geometry_size > 0 && (size_t) total_geom_size > max_geometry_size) {
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "tile %d/%u/%u has %lld vertices, >%zu \n", z, tx, ty, total_geom_size, max_geometry_size);
|
||||
}
|
||||
|
||||
if (has_polygons && additional[A_MERGE_POLYGONS_AS_NEEDED] && merge_fraction > .05 && merge_successful) {
|
||||
merge_fraction = merge_fraction * max_geometry_size / total_geom_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);
|
||||
}
|
||||
line_detail++; // to keep it the same when the loop decrements it
|
||||
continue;
|
||||
} else if (additional[A_INCREASE_GAMMA_AS_NEEDED] && gamma < 10) {
|
||||
if (gamma < 1) {
|
||||
gamma = 1;
|
||||
} else {
|
||||
gamma = gamma * 1.25;
|
||||
}
|
||||
|
||||
if (gamma > arg->gamma_out) {
|
||||
arg->gamma_out = gamma;
|
||||
arg->still_dropping = true;
|
||||
}
|
||||
|
||||
if (!quiet) {
|
||||
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
|
||||
continue;
|
||||
} else if (mingap < ULONG_MAX && (additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_COALESCE_DENSEST_AS_NEEDED] || additional[A_CLUSTER_DENSEST_AS_NEEDED])) {
|
||||
mingap_fraction = mingap_fraction * max_geometry_size / total_geom_size * 0.90;
|
||||
unsigned long long mg = choose_mingap(indices, mingap_fraction);
|
||||
if (mg <= mingap) {
|
||||
mg = (mingap + 1) * 1.5;
|
||||
|
||||
if (mg <= mingap) {
|
||||
mg = ULONG_MAX;
|
||||
}
|
||||
}
|
||||
mingap = mg;
|
||||
if (mingap > arg->mingap_out) {
|
||||
arg->mingap_out = mingap;
|
||||
arg->still_dropping = true;
|
||||
}
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "Going to try keeping the sparsest %0.2f%% of the features to make it fit\n", mingap_fraction * 100.0);
|
||||
}
|
||||
line_detail++;
|
||||
continue;
|
||||
} else if (additional[A_DROP_SMALLEST_AS_NEEDED] || additional[A_COALESCE_SMALLEST_AS_NEEDED]) {
|
||||
minextent_fraction = minextent_fraction * max_geometry_size / total_geom_size * 0.75;
|
||||
long long m = choose_minextent(extents, minextent_fraction);
|
||||
if (m != minextent) {
|
||||
minextent = m;
|
||||
if (minextent > arg->minextent_out) {
|
||||
arg->minextent_out = minextent;
|
||||
arg->still_dropping = true;
|
||||
}
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "Going to try keeping the biggest %0.2f%% of the features to make it fit\n", minextent_fraction * 100.0);
|
||||
}
|
||||
line_detail++;
|
||||
continue;
|
||||
}
|
||||
} else if (totalsize > layers.size() && (prevent[P_DYNAMIC_DROP] || additional[A_DROP_FRACTION_AS_NEEDED] || additional[A_COALESCE_FRACTION_AS_NEEDED])) {
|
||||
// The 95% is a guess to avoid too many retries
|
||||
// and probably actually varies based on how much duplicated metadata there is
|
||||
|
||||
fraction = fraction * max_geometry_size / total_geom_size * 0.95;
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "Going to try keeping %0.2f%% of the features to make it fit\n", fraction * 100);
|
||||
}
|
||||
if ((additional[A_DROP_FRACTION_AS_NEEDED] || additional[A_COALESCE_FRACTION_AS_NEEDED]) && fraction < arg->fraction_out) {
|
||||
arg->fraction_out = fraction;
|
||||
arg->still_dropping = true;
|
||||
} else if (prevent[P_DYNAMIC_DROP]) {
|
||||
arg->still_dropping = true;
|
||||
}
|
||||
line_detail++; // to keep it the same when the loop decrements it
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr, "Try using --drop-fraction-as-needed or --drop-densest-as-needed.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalsize > max_tile_features && !prevent[P_FEATURE_LIMIT]) {
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "tile %d/%u/%u has %zu features, >%zu \n", z, tx, ty, totalsize, max_tile_features);
|
||||
@@ -2695,10 +2781,10 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return total_geom_size;
|
||||
}
|
||||
} else {
|
||||
return count;
|
||||
return total_geom_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user