mirror of
https://github.com/mapbox/tippecanoe.git
synced 2025-02-23 02:22:34 +00:00
Merge pull request #180 from mapbox/coverage
Add a gamma-reduction test and base zoom/drop rate guessing tests
This commit is contained in:
commit
b7f3fcfc7f
@ -81,7 +81,7 @@ Options
|
||||
* -B _zoom_: Base zoom, the level at and above which all points are included in the tiles (default maxzoom).
|
||||
If you use -Bg, it will guess a zoom level that will keep at most 50,000 features in the densest tile.
|
||||
You can also specify a marker-width with -Bg*width* to allow fewer features in the densest tile to
|
||||
compensate for the larger marker.
|
||||
compensate for the larger marker, or -Bf*number* to allow at most *number* features in the densest tile.
|
||||
* -d _detail_: Detail at max zoom level (default 12, for tile resolution of 4096)
|
||||
* -D _detail_: Detail at lower zoom levels (default 12, for tile resolution of 4096)
|
||||
* -m _detail_: Minimum detail that it will try if tiles are too big at regular detail (default 7)
|
||||
@ -97,6 +97,8 @@ Options
|
||||
|
||||
* -r _rate_: Rate at which dots are dropped at zoom levels below basezoom (default 2.5).
|
||||
If you use -rg, it will guess a drop rate that will keep at most 50,000 features in the densest tile.
|
||||
You can also specify a marker-width with -rg*width* to allow fewer features in the densest tile to
|
||||
compensate for the larger marker, or -rf*number* to allow at most *number* features in the densest tile.
|
||||
* -g _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.
|
||||
|
||||
### Doing more
|
||||
|
53
geojson.c
53
geojson.c
@ -1583,33 +1583,8 @@ int read_json(int argc, char **argv, char *fname, const char *layername, int max
|
||||
|
||||
tile[z].fullcount++;
|
||||
|
||||
// Keep in sync with write_tile()
|
||||
if (gamma > 0) {
|
||||
if (tile[z].gap > 0) {
|
||||
if (map[i].index == tile[z].previndex) {
|
||||
continue; // Exact duplicate: can't fulfil the gap requirement
|
||||
}
|
||||
|
||||
if (exp(log((map[i].index - tile[z].previndex) / scale) * gamma) >= tile[z].gap) {
|
||||
// Dot is further from the previous than the nth root of the gap,
|
||||
// so produce it, and choose a new gap at the next point.
|
||||
tile[z].gap = 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
tile[z].gap = (map[i].index - tile[z].previndex) / scale;
|
||||
|
||||
if (tile[z].gap == 0) {
|
||||
continue; // Exact duplicate: skip
|
||||
} else if (tile[z].gap < 1) {
|
||||
continue; // Narrow dot spacing: need to stretch out
|
||||
} else {
|
||||
tile[z].gap = 0; // Wider spacing than minimum: so pass through unchanged
|
||||
}
|
||||
}
|
||||
|
||||
tile[z].previndex = map[i].index;
|
||||
if (manage_gap(map[i].index, &tile[z].previndex, scale, gamma, &tile[z].gap)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tile[z].count++;
|
||||
@ -2105,12 +2080,15 @@ int main(int argc, char **argv) {
|
||||
case 'B':
|
||||
if (strcmp(optarg, "g") == 0) {
|
||||
basezoom = -2;
|
||||
basezoom_marker_width = 1;
|
||||
} else if (optarg[0] == 'g') {
|
||||
} else if (optarg[0] == 'g' || optarg[0] == 'f') {
|
||||
basezoom = -2;
|
||||
basezoom_marker_width = atof(optarg + 1);
|
||||
if (basezoom_marker_width == 0) {
|
||||
fprintf(stderr, "%s: Must specify marker width >0 with -Bg\n", argv[0]);
|
||||
if (optarg[0] == 'g') {
|
||||
basezoom_marker_width = atof(optarg + 1);
|
||||
} else {
|
||||
basezoom_marker_width = sqrt(50000 / atof(optarg + 1));
|
||||
}
|
||||
if (basezoom_marker_width == 0 || atof(optarg + 1) == 0) {
|
||||
fprintf(stderr, "%s: Must specify value >0 with -B%c\n", argv[0], optarg[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
@ -2154,6 +2132,17 @@ int main(int argc, char **argv) {
|
||||
case 'r':
|
||||
if (strcmp(optarg, "g") == 0) {
|
||||
droprate = -2;
|
||||
} else if (optarg[0] == 'g' || optarg[0] == 'f') {
|
||||
droprate = -2;
|
||||
if (optarg[0] == 'g') {
|
||||
basezoom_marker_width = atof(optarg + 1);
|
||||
} else {
|
||||
basezoom_marker_width = sqrt(50000 / atof(optarg + 1));
|
||||
}
|
||||
if (basezoom_marker_width == 0 || atof(optarg + 1) == 0) {
|
||||
fprintf(stderr, "%s: Must specify value >0 with -r%c\n", argv[0], optarg[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
droprate = atof(optarg);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ rather than a stream that can only be read sequentially.
|
||||
\-B \fIzoom\fP: Base zoom, the level at and above which all points are included in the tiles (default maxzoom).
|
||||
If you use \-Bg, it will guess a zoom level that will keep at most 50,000 features in the densest tile.
|
||||
You can also specify a marker\-width with \-Bg\fIwidth\fP to allow fewer features in the densest tile to
|
||||
compensate for the larger marker.
|
||||
compensate for the larger marker, or \-Bf\fInumber\fP to allow at most \fInumber\fP features in the densest tile.
|
||||
.IP \(bu 2
|
||||
\-d \fIdetail\fP: Detail at max zoom level (default 12, for tile resolution of 4096)
|
||||
.IP \(bu 2
|
||||
@ -116,6 +116,8 @@ compensate for the larger marker.
|
||||
.IP \(bu 2
|
||||
\-r \fIrate\fP: Rate at which dots are dropped at zoom levels below basezoom (default 2.5).
|
||||
If you use \-rg, it will guess a drop rate that will keep at most 50,000 features in the densest tile.
|
||||
You can also specify a marker\-width with \-rg\fIwidth\fP to allow fewer features in the densest tile to
|
||||
compensate for the larger marker, or \-rf\fInumber\fP to allow at most \fInumber\fP features in the densest tile.
|
||||
.IP \(bu 2
|
||||
\-g \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
|
||||
|
4613
tests/muni/muni.json
Normal file
4613
tests/muni/muni.json
Normal file
File diff suppressed because it is too large
Load Diff
9744
tests/muni/out/-Z11_-z11.json
Normal file
9744
tests/muni/out/-Z11_-z11.json
Normal file
File diff suppressed because it is too large
Load Diff
6386
tests/muni/out/-Z11_-z11_-g2.json
Normal file
6386
tests/muni/out/-Z11_-z11_-g2.json
Normal file
File diff suppressed because it is too large
Load Diff
24028
tests/muni/out/-Z11_-z13_-Bf2000.json
Normal file
24028
tests/muni/out/-Z11_-z13_-Bf2000.json
Normal file
File diff suppressed because it is too large
Load Diff
21676
tests/muni/out/-Z11_-z13_-rf2000.json
Normal file
21676
tests/muni/out/-Z11_-z13_-rf2000.json
Normal file
File diff suppressed because it is too large
Load Diff
24756
tests/muni/out/-Z11_-z13_-rf2000_-Bg.json
Normal file
24756
tests/muni/out/-Z11_-z13_-rf2000_-Bg.json
Normal file
File diff suppressed because it is too large
Load Diff
21266
tests/muni/out/-Z11_-z13_-rf2000_-g2.json
Normal file
21266
tests/muni/out/-Z11_-z13_-rf2000_-g2.json
Normal file
File diff suppressed because it is too large
Load Diff
60
tile.cc
60
tile.cc
@ -563,6 +563,38 @@ void *partial_feature_worker(void *v) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int manage_gap(unsigned long long index, unsigned long long *previndex, double scale, double gamma, double *gap) {
|
||||
if (gamma > 0) {
|
||||
if (*gap > 0) {
|
||||
if (index == *previndex) {
|
||||
return 1; // Exact duplicate: can't fulfil the gap requirement
|
||||
}
|
||||
|
||||
if (exp(log((index - *previndex) / scale) * gamma) >= *gap) {
|
||||
// Dot is further from the previous than the nth root of the gap,
|
||||
// so produce it, and choose a new gap at the next point.
|
||||
*gap = 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
*gap = (index - *previndex) / scale;
|
||||
|
||||
if (*gap == 0) {
|
||||
return 1; // Exact duplicate: skip
|
||||
} else if (*gap < 1) {
|
||||
return 1; // Narrow dot spacing: need to stretch out
|
||||
} else {
|
||||
*gap = 0; // Wider spacing than minimum: so pass through unchanged
|
||||
}
|
||||
}
|
||||
|
||||
*previndex = index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsigned tx, unsigned ty, int detail, int min_detail, int basezoom, struct pool **file_keys, char **layernames, sqlite3 *outdb, double droprate, int buffer, const char *fname, FILE **geomfile, int minzoom, int maxzoom, double todo, char *geomstart, volatile long long *along, double gamma, int nlayers, char *prevent, char *additional, int child_shards, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, volatile int *running) {
|
||||
int line_detail;
|
||||
double fraction = 1;
|
||||
@ -767,32 +799,10 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi
|
||||
}
|
||||
|
||||
if (gamma > 0) {
|
||||
unsigned long long index = encode(bbox[0] / 2 + bbox[2] / 2, bbox[1] / 2 + bbox[3] / 2);
|
||||
if (gap > 0) {
|
||||
if (index == previndex) {
|
||||
continue; // Exact duplicate: can't fulfil the gap requirement
|
||||
}
|
||||
|
||||
if (exp(log((index - previndex) / scale) * gamma) >= gap) {
|
||||
// Dot is further from the previous than the nth root of the gap,
|
||||
// so produce it, and choose a new gap at the next point.
|
||||
gap = 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
gap = (index - previndex) / scale;
|
||||
|
||||
if (gap == 0) {
|
||||
continue; // Exact duplicate: skip
|
||||
} else if (gap < 1) {
|
||||
continue; // Narrow dot spacing: need to stretch out
|
||||
} else {
|
||||
gap = 0; // Wider spacing than minimum: so pass through unchanged
|
||||
}
|
||||
unsigned long long index = index = encode(bbox[0] / 2 + bbox[2] / 2, bbox[1] / 2 + bbox[3] / 2);
|
||||
if (manage_gap(index, &previndex, scale, gamma, &gap)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
previndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
|
2
tile.h
2
tile.h
@ -29,6 +29,8 @@ long long write_tile(char **geom, char *metabase, char *stringpool, unsigned *fi
|
||||
|
||||
int traverse_zooms(int *geomfd, off_t *geom_size, char *metabase, char *stringpool, struct pool **file_keys, unsigned *midx, unsigned *midy, char **layernames, int maxzoom, int minzoom, int basezoom, sqlite3 *outdb, double droprate, int buffer, const char *fname, const char *tmpdir, double gamma, int nlayers, char *prevent, char *additional, int full_detail, int low_detail, int min_detail, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y);
|
||||
|
||||
int manage_gap(unsigned long long index, unsigned long long *previndex, double scale, double gamma, double *gap);
|
||||
|
||||
extern unsigned initial_x, initial_y;
|
||||
extern int geometry_scale;
|
||||
extern int quiet;
|
||||
|
Loading…
x
Reference in New Issue
Block a user