diff --git a/main.cpp b/main.cpp index e5e16f5a..4fbec677 100644 --- a/main.cpp +++ b/main.cpp @@ -3140,7 +3140,7 @@ 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, "extend-zooms-if-still-dropping-maximum") == 0) { + } 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 { fprintf(stderr, "%s: Unrecognized option --%s\n", argv[0], opt); diff --git a/overzoom.cpp b/overzoom.cpp index b22399ce..a4b18b83 100644 --- a/overzoom.cpp +++ b/overzoom.cpp @@ -11,7 +11,7 @@ extern char *optarg; extern int optind; int detail = 12; // tippecanoe-style: mvt extent == 1 << detail -int buffer = 5; // tippecanoe-style: mvt buffer == extent * buffer / 256; +int buffer = 5; // tippecanoe-style: mvt buffer == extent * buffer / 256; std::set keep; diff --git a/tile-join.cpp b/tile-join.cpp index d393e2be..8940d400 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -80,7 +80,7 @@ void aprintf(std::string *buf, const char *format, ...) { free(tmp); } -void handle(std::string message, int z, unsigned x, unsigned y, std::map &layermap, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, std::set &keep_layers, std::set &remove_layers, int ifmatched, mvt_tile &outtile, json_object *filter) { +void append_tile(std::string message, int z, unsigned x, unsigned y, std::map &layermap, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, std::set &keep_layers, std::set &remove_layers, int ifmatched, mvt_tile &outtile, json_object *filter) { mvt_tile tile; int features_added = 0; bool was_compressed; @@ -378,6 +378,7 @@ struct reader { long long sorty = 0; long long y = 0; int z_flag = 0; + int maxzoom_so_far = 0; std::string data = ""; @@ -530,6 +531,7 @@ struct arg { std::set *remove_layers = NULL; int ifmatched = 0; json_object *filter = NULL; + struct reader *readers = NULL; }; void *join_worker(void *v) { @@ -538,8 +540,19 @@ void *join_worker(void *v) { for (auto ai = a->inputs.begin(); ai != a->inputs.end(); ++ai) { mvt_tile tile; + for (struct reader *r = a->readers; r != NULL; r = r->next) { + if (r->maxzoom_so_far < ai->first.z) { + // if this reader did not produce any tiles at this zoom level, + // and is not ready to produce any tiles at this zoom level, + // it is a candidate for overzooming this tile from whatever + // zoom level it did produce last. + + printf("overzooming %lld/%lld/%lld from zoom %d\n", ai->first.z, ai->first.x, ai->first.y, r->maxzoom_so_far); + } + } + for (size_t i = 0; i < ai->second.size(); i++) { - handle(ai->second[i], ai->first.z, ai->first.x, ai->first.y, *(a->layermap), *(a->header), *(a->mapping), *(a->exclude), *(a->include), *(a->keep_layers), *(a->remove_layers), a->ifmatched, tile, a->filter); + append_tile(ai->second[i], ai->first.z, ai->first.x, ai->first.y, *(a->layermap), *(a->header), *(a->mapping), *(a->exclude), *(a->include), *(a->keep_layers), *(a->remove_layers), a->ifmatched, tile, a->filter); } ai->second.clear(); @@ -574,7 +587,7 @@ void *join_worker(void *v) { return NULL; } -void handle_tasks(std::map> &tasks, std::vector> &layermaps, sqlite3 *outdb, const char *outdir, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, int ifmatched, std::set &keep_layers, std::set &remove_layers, json_object *filter) { +void dispatch_tasks(std::map> &tasks, std::vector> &layermaps, sqlite3 *outdb, const char *outdir, std::vector &header, std::map> &mapping, std::set &exclude, std::set &include, int ifmatched, std::set &keep_layers, std::set &remove_layers, json_object *filter, struct reader *readers) { pthread_t pthreads[CPUS]; std::vector args; @@ -590,6 +603,7 @@ void handle_tasks(std::map> &tasks, std::vector &layer int zoom_for_bbox = -1; while (readers != NULL && readers->zoom < 32) { + // pull a reader off the front of the queue, + // process whatever tile it has ready to read reader *r = readers; readers = readers->next; r->next = NULL; + if (r->zoom != zoom_for_bbox) { // Only use highest zoom for bbox calculation // to avoid z0 always covering the world @@ -749,6 +766,10 @@ void decode(struct reader *readers, std::map &layer zoom_for_bbox = r->zoom; } + if (r->zoom > r->maxzoom_so_far) { + r->maxzoom_so_far = r->zoom; + } + double lat1, lon1, lat2, lon2; tile2lonlat(r->x, r->y, r->zoom, &lon1, &lat1); tile2lonlat(r->x + 1, r->y + 1, r->zoom, &lon2, &lat2); @@ -776,7 +797,7 @@ void decode(struct reader *readers, std::map &layer if (readers == NULL || readers->zoom != r->zoom || readers->x != r->x || readers->y != r->y) { if (tasks.size() > 100 * CPUS) { - handle_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, include, ifmatched, keep_layers, remove_layers, filter); + dispatch_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, include, ifmatched, keep_layers, remove_layers, filter, readers); tasks.clear(); } } @@ -820,8 +841,10 @@ void decode(struct reader *readers, std::map &layer } } - struct reader **rr; + // put the reader back onto the queue, + // in whatever sequence its next tile calls for + struct reader **rr; for (rr = &readers; *rr != NULL; rr = &((*rr)->next)) { if (*r < **rr) { break; @@ -842,7 +865,7 @@ void decode(struct reader *readers, std::map &layer st->minlat2 = min(minlat, st->minlat2); st->maxlat2 = max(maxlat, st->maxlat2); - handle_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, include, ifmatched, keep_layers, remove_layers, filter); + dispatch_tasks(tasks, layermaps, outdb, outdir, header, mapping, exclude, include, ifmatched, keep_layers, remove_layers, filter, readers); layermap = merge_layermaps(layermaps); struct reader *next; diff --git a/tile.cpp b/tile.cpp index 52e5f185..1ce4ead0 100644 --- a/tile.cpp +++ b/tile.cpp @@ -3238,14 +3238,14 @@ int traverse_zooms(int *geomfd, off_t *geom_size, char *stringpool, std::atomic< z = args[thread].wrote_zoom; } - if (args[thread].still_dropping) { - if (additional[A_EXTEND_ZOOMS] && z == maxzoom && maxzoom < MAX_ZOOM) { - maxzoom++; - } else if (extend_zooms_max > 0 && z == maxzoom && maxzoom < MAX_ZOOM) { - maxzoom++; - extend_zooms_max--; - } - } + if (args[thread].still_dropping) { + if (additional[A_EXTEND_ZOOMS] && z == maxzoom && maxzoom < MAX_ZOOM) { + maxzoom++; + } else if (extend_zooms_max > 0 && z == maxzoom && maxzoom < MAX_ZOOM) { + maxzoom++; + extend_zooms_max--; + } + } } if ((size_t) z >= strategies.size()) {