Add an option to vary the level of line and polygon simplification

This commit is contained in:
Eric Fischer 2016-07-12 16:51:56 -07:00
parent cb45f1c3bd
commit 9908db5e56
9 changed files with 4059 additions and 11 deletions

View File

@ -1,5 +1,6 @@
## 1.12.5
* Add an option to vary the level of line and polygon simplification
* Be careful not to produce an empty tile if there was a feature with
empty geometry.

View File

@ -110,6 +110,11 @@ resolution is obtained than by using a smaller _maxzoom_ or _detail_.
compensate for the larger marker, or -rf*number* to allow at most *number* features in the densest tile.
* -g _gamma_ or --gamma=_gamma_: Rate at which especially dense dots are dropped (default 0, for no effect). A gamma of 2 reduces the number of dots less than a pixel apart to the square root of their original number.
### Line and polygon simplification
* -S _scale_ or --simplify=_scale_: Multiply the tolerance for line and polygon simplification by _scale_. The standard tolerance tries to keep
the line or polygon within one tile unit of its proper location. You can probably go up to about 10 without too much visible difference.
### Doing more
* -ac or --coalesce: Coalesce adjacent line and polygon features that have the same properties.

View File

@ -1050,7 +1050,7 @@ drawvec impose_tile_boundaries(drawvec &geom, long long extent) {
return out;
}
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds) {
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification) {
int res = 1 << (32 - detail - z);
long long area = 1LL << (32 - z);
@ -1081,7 +1081,7 @@ drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds)
geom[j - 1].necessary = 1;
if (j - i > 1) {
douglas_peucker(geom, i, j - i, res);
douglas_peucker(geom, i, j - i, res * simplification);
}
i = j - 1;
}

View File

@ -43,7 +43,7 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
drawvec clip_lines(drawvec &geom, int z, int detail, long long buffer);
bool point_within_tile(long long x, long long y, int z, int detail, long long buffer);
int quick_check(long long *bbox, int z, int detail, long long buffer);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification);
drawvec reorder_lines(drawvec &geom);
drawvec fix_polygon(drawvec &geom);
std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms);

View File

@ -55,6 +55,7 @@ static int min_detail = 7;
int quiet = 0;
int geometry_scale = 0;
double simplification = 1;
int prevent[256];
int additional[256];
@ -1606,7 +1607,7 @@ int read_input(std::vector<source> &sources, char *fname, const char *layername,
}
unsigned midx = 0, midy = 0;
int written = traverse_zooms(fd, size, meta, stringpool, &midx, &midy, layernames, maxzoom, minzoom, basezoom, outdb, droprate, buffer, fname, tmpdir, gamma, nlayers, full_detail, low_detail, min_detail, meta_off, pool_off, initial_x, initial_y);
int written = traverse_zooms(fd, size, meta, stringpool, &midx, &midy, layernames, maxzoom, minzoom, basezoom, outdb, droprate, buffer, fname, tmpdir, gamma, nlayers, full_detail, low_detail, min_detail, meta_off, pool_off, initial_x, initial_y, simplification);
if (maxzoom != written) {
fprintf(stderr, "\n\n\n*** NOTE TILES ONLY COMPLETE THROUGH ZOOM %d ***\n\n\n", written);
@ -1764,6 +1765,7 @@ int main(int argc, char **argv) {
{"prevent", required_argument, 0, 'p'},
{"additional", required_argument, 0, 'a'},
{"projection", required_argument, 0, 's'},
{"simplification", required_argument, 0, 'S'},
{"exclude-all", no_argument, 0, 'X'},
{"force", no_argument, 0, 'f'},
@ -1812,7 +1814,7 @@ int main(int argc, char **argv) {
}
}
while ((i = getopt_long(argc, argv, "n:l:z:Z:B:d:D:m:o:x:y:r:b:t:g:p:a:XfFqvPL:A:s:", long_options, NULL)) != -1) {
while ((i = getopt_long(argc, argv, "n:l:z:Z:B:d:D:m:o:x:y:r:b:t:g:p:a:XfFqvPL:A:s:S:", long_options, NULL)) != -1) {
switch (i) {
case 0:
break;
@ -1983,6 +1985,14 @@ int main(int argc, char **argv) {
set_projection_or_exit(optarg);
break;
case 'S':
simplification = atof(optarg);
if (simplification <= 0) {
fprintf(stderr, "%s: --simplification must be > 0\n", argv[0]);
exit(EXIT_FAILURE);
}
break;
default: {
int width = 7 + strlen(argv[0]);
fprintf(stderr, "Usage: %s", argv[0]);

View File

@ -126,6 +126,12 @@ compensate for the larger marker, or \-rf\fInumber\fP to allow at most \fInumber
.IP \(bu 2
\-g \fIgamma\fP or \-\-gamma=\fIgamma\fP: Rate at which especially dense dots are dropped (default 0, for no effect). A gamma of 2 reduces the number of dots less than a pixel apart to the square root of their original number.
.RE
.SS Line and polygon simplification
.RS
.IP \(bu 2
\-S \fIscale\fP or \-\-simplify=\fIscale\fP: Multiply the tolerance for line and polygon simplification by \fIscale\fP\&. The standard tolerance tries to keep
the line or polygon within one tile unit of its proper location. You can probably go up to about 10 without too much visible difference.
.RE
.SS Doing more
.RS
.IP \(bu 2

File diff suppressed because one or more lines are too long

View File

@ -389,6 +389,7 @@ struct partial {
int line_detail;
int maxzoom;
double spacing;
double simplification;
signed char t;
};
@ -462,7 +463,7 @@ void *partial_feature_worker(void *v) {
geom = remove_noop(geom, t, 32 - z - line_detail);
}
drawvec ngeom = simplify_lines(geom, z, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]));
drawvec ngeom = simplify_lines(geom, z, line_detail, !(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), (*partials)[i].simplification);
if (t != VT_POLYGON || ngeom.size() >= 3) {
geom = ngeom;
@ -559,7 +560,7 @@ int manage_gap(unsigned long long index, unsigned long long *previndex, double s
return 0;
}
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, int basezoom, std::vector<std::string> *layernames, sqlite3 *outdb, double droprate, int buffer, const char *fname, FILE **geomfile, int minzoom, int maxzoom, double todo, volatile long long *along, long long alongminus, double gamma, int nlayers, int child_shards, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, volatile int *running) {
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, int basezoom, std::vector<std::string> *layernames, sqlite3 *outdb, double droprate, int buffer, const char *fname, FILE **geomfile, int minzoom, int maxzoom, double todo, volatile long long *along, long long alongminus, double gamma, int nlayers, int child_shards, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, volatile int *running, double simplification) {
int line_detail;
double fraction = 1;
@ -860,6 +861,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
p.keys = metakeys;
p.values = metavals;
p.spacing = spacing;
p.simplification = simplification;
partials.push_back(p);
}
}
@ -972,7 +974,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
if (features[j][x].coalesced && features[j][x].type == VT_LINE) {
features[j][x].geom = remove_noop(features[j][x].geom, features[j][x].type, 0);
features[j][x].geom = simplify_lines(features[j][x].geom, 32, 0,
!(prevent[P_CLIPPING] || prevent[P_DUPLICATION]));
!(prevent[P_CLIPPING] || prevent[P_DUPLICATION]), simplification);
}
if (features[j][x].type == VT_POLYGON) {
@ -1139,6 +1141,7 @@ struct write_tile_args {
int minzoom;
int full_detail;
int low_detail;
double simplification;
volatile long long *most;
long long *meta_off;
long long *pool_off;
@ -1186,7 +1189,7 @@ void *run_thread(void *vargs) {
// fprintf(stderr, "%d/%u/%u\n", z, x, y);
long long len = write_tile(geom, &geompos, arg->metabase, arg->stringpool, z, x, y, z == arg->maxzoom ? arg->full_detail : arg->low_detail, arg->min_detail, arg->basezoom, arg->layernames, arg->outdb, arg->droprate, arg->buffer, arg->fname, arg->geomfile, arg->minzoom, arg->maxzoom, arg->todo, arg->along, geompos, arg->gamma, arg->nlayers, arg->child_shards, arg->meta_off, arg->pool_off, arg->initial_x, arg->initial_y, arg->running);
long long len = write_tile(geom, &geompos, arg->metabase, arg->stringpool, z, x, y, z == arg->maxzoom ? arg->full_detail : arg->low_detail, arg->min_detail, arg->basezoom, arg->layernames, arg->outdb, arg->droprate, arg->buffer, arg->fname, arg->geomfile, arg->minzoom, arg->maxzoom, arg->todo, arg->along, geompos, arg->gamma, arg->nlayers, arg->child_shards, arg->meta_off, arg->pool_off, arg->initial_x, arg->initial_y, arg->running, arg->simplification);
if (len < 0) {
int *err = &arg->err;
@ -1237,7 +1240,7 @@ void *run_thread(void *vargs) {
return NULL;
}
int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpool, unsigned *midx, unsigned *midy, std::vector<std::string> &layernames, int maxzoom, int minzoom, int basezoom, sqlite3 *outdb, double droprate, int buffer, const char *fname, const char *tmpdir, double gamma, int nlayers, int full_detail, int low_detail, int min_detail, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y) {
int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpool, unsigned *midx, unsigned *midy, std::vector<std::string> &layernames, int maxzoom, int minzoom, int basezoom, sqlite3 *outdb, double droprate, int buffer, const char *fname, const char *tmpdir, double gamma, int nlayers, int full_detail, int low_detail, int min_detail, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, double simplification) {
int i;
for (i = 0; i <= maxzoom; i++) {
long long most = 0;
@ -1358,6 +1361,7 @@ int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpo
args[thread].gamma = gamma;
args[thread].nlayers = nlayers;
args[thread].child_shards = TEMP_FILES / threads;
args[thread].simplification = simplification;
args[thread].geomfd = geomfd;
args[thread].geom_size = geom_size;

View File

@ -1,5 +1,5 @@
long long write_tile(char **geom, char *metabase, char *stringpool, unsigned *file_bbox, int z, unsigned x, unsigned y, int detail, int min_detail, int basezoom, char **layernames, sqlite3 *outdb, double droprate, int buffer, const char *fname, FILE **geomfile, int file_minzoom, int file_maxzoom, double todo, char *geomstart, long long along, double gamma, int nlayers);
int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpool, unsigned *midx, unsigned *midy, std::vector<std::string> &layernames, int maxzoom, int minzoom, int basezoom, sqlite3 *outdb, double droprate, int buffer, const char *fname, const char *tmpdir, double gamma, int nlayers, int full_detail, int low_detail, int min_detail, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y);
int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpool, unsigned *midx, unsigned *midy, std::vector<std::string> &layernames, int maxzoom, int minzoom, int basezoom, sqlite3 *outdb, double droprate, int buffer, const char *fname, const char *tmpdir, double gamma, int nlayers, int full_detail, int low_detail, int min_detail, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, double simplification);
int manage_gap(unsigned long long index, unsigned long long *previndex, double scale, double gamma, double *gap);