From 83e73e88408c16a2fef29e7b3f3e1affd92c80e7 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Mon, 24 Oct 2016 12:29:36 -0700 Subject: [PATCH] Add an option to dynamically increase gamma until tiles are small enough --- README.md | 1 + main.cpp | 1 + man/tippecanoe.1 | 2 ++ options.hpp | 1 + tile.cpp | 42 +++++++++++++++++++++++++++++++++++++++--- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6e0c925..845a451 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ resolution is obtained than by using a smaller _maxzoom_ or _detail_. * -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. * -ab or --detect-shared-borders: In the manner of [TopoJSON](https://github.com/mbostock/topojson/wiki/Introduction), detect borders that are shared between multiple polygons and simplify them identically in each polygon. This takes more time and memory than considering each polygon individually. + * -aG or --increase-gamma-as-needed: If a tile is too large, try to reduce it to under 500K by increasing the `-g` gamma ### Doing less diff --git a/main.cpp b/main.cpp index 3d1d5fd..7328187 100644 --- a/main.cpp +++ b/main.cpp @@ -1911,6 +1911,7 @@ int main(int argc, char **argv) { {"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 1}, {"calculate-feature-density", no_argument, &additional[A_CALCULATE_FEATURE_DENSITY], 1}, {"detect-shared-borders", no_argument, &additional[A_DETECT_SHARED_BORDERS], 1}, + {"increase-gamma-as-needed", no_argument, &additional[A_INCREASE_GAMMA_AS_NEEDED], 1}, {"no-line-simplification", no_argument, &prevent[P_SIMPLIFY], 1}, {"simplify-only-low-zooms", no_argument, &prevent[P_SIMPLIFY_LOW], 1}, diff --git a/man/tippecanoe.1 b/man/tippecanoe.1 index 10d7596..4a03e7e 100644 --- a/man/tippecanoe.1 +++ b/man/tippecanoe.1 @@ -150,6 +150,8 @@ which may not be what you want. \-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. .IP \(bu 2 \-ab or \-\-detect\-shared\-borders: In the manner of TopoJSON \[la]https://github.com/mbostock/topojson/wiki/Introduction\[ra], detect borders that are shared between multiple polygons and simplify them identically in each polygon. This takes more time and memory than considering each polygon individually. +.IP \(bu 2 +\-aG or \-\-increase\-gamma\-as\-needed: If a tile is too large, try to reduce it to under 500K by increasing the \fB\fC\-g\fR gamma .RE .SS Doing less .RS diff --git a/options.hpp b/options.hpp index 76c9545..c1013cf 100644 --- a/options.hpp +++ b/options.hpp @@ -7,6 +7,7 @@ #define A_DETECT_SHARED_BORDERS ((int) 'b') #define A_PREFER_RADIX_SORT ((int) 'R') #define A_CALCULATE_FEATURE_DENSITY ((int) 'g') +#define A_INCREASE_GAMMA_AS_NEEDED ((int) 'G') #define P_SIMPLIFY ((int) 's') #define P_SIMPLIFY_LOW ((int) 'S') diff --git a/tile.cpp b/tile.cpp index 44b4021..02b92a1 100644 --- a/tile.cpp +++ b/tile.cpp @@ -990,6 +990,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s static volatile double oprogress = 0; + 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. for (line_detail = detail; line_detail >= min_detail || line_detail == detail; line_detail--, oprogress = 0) { @@ -1177,7 +1178,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s unclipped_features++; } - if (line_detail == detail && fraction == 1) { /* only write out the next zoom once, even if we retry */ + if (first_time) { /* only write out the next zoom once, even if we retry */ rewrite(geom, z, nextzoom, maxzoom, bbox, tx, ty, buffer, line_detail, within, geompos, geomfile, fname, t, layer, metastart, feature_minzoom, child_shards, max_zoom_increment, original_seq, tippecanoe_minzoom, tippecanoe_maxzoom, segment, initial_x, initial_y, m, metakeys, metavals, has_id, id); } @@ -1253,6 +1254,8 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s } } + first_time = false; + if (additional[A_DETECT_SHARED_BORDERS]) { find_common_edges(partials, z, line_detail, simplification, maxzoom); } @@ -1473,8 +1476,30 @@ 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); - fprintf(stderr, "Try using -B to set a higher base zoom level.\n"); - return -1; + + if (prevent[P_DYNAMIC_DROP]) { + fraction = fraction * 200000 / totalsize * 0.95; + if (!quiet) { + fprintf(stderr, "Going to try keeping %0.2f%% of the features to make it fit\n", fraction * 100); + } + line_detail++; // to keep it the same when the loop decrements it + continue; + } else if (additional[A_INCREASE_GAMMA_AS_NEEDED]) { + if (gamma < 1) { + gamma = 1; + } else { + gamma = gamma * 1.25; + } + + 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 { + fprintf(stderr, "Try using -B (and --drop-lines or --drop-polygons if needed) to set a higher base zoom level.\n"); + return -1; + } } std::string compressed = tile.encode(); @@ -1493,6 +1518,17 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s fprintf(stderr, "Going to try keeping %0.2f%% of the features to make it fit\n", fraction * 100); } line_detail++; // to keep it the same when the loop decrements it + } else if (additional[A_INCREASE_GAMMA_AS_NEEDED]) { + if (gamma < 1) { + gamma = 1; + } else { + gamma = gamma * 1.25; + } + + 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 } } else { if (pthread_mutex_lock(&db_lock) != 0) {