diff --git a/geojson.c b/geojson.c index 2c170206..c3d2023d 100644 --- a/geojson.c +++ b/geojson.c @@ -448,39 +448,52 @@ void read_json(FILE *f, char *fname, char *layername, int maxzoom, int minzoom, ix.maxzoom = z; fwrite_check(&ix, sizeof(struct index), 1, indexfile, fname, jp); } else { - for (z = maxzoom; z >= 1; z--) { - unsigned x, y; - for (x = (bbox[0] - (buffer << (32 - z - 8))) >> (32 - z); x <= (bbox[2] + (buffer << (32 - z - 8))) >> (32 - z); x++) { - for (y = (bbox[1] - (buffer << (32 - z - 8))) >> (32 - z); y <= (bbox[3] + (buffer << (32 - z - 8))) >> (32 - z); y++) { - if (z != maxzoom) { - // There must be a clearer way to write this, but the intent is - // not to add an additional index for a low-zoom tile - // if one of its children was already part of the - // buffered bounding box for the child's zoom. + int pass; + int instances = 0; - // So we are comparing this tile's x and y to the edges of the - // bounding box at the next zoom down, but divided by two - // to get it back into this zoom's tile coordinate scheme + for (pass = 0; pass < 2; pass++) { + for (z = maxzoom; z >= 1; z--) { + unsigned x, y; + for (x = (bbox[0] - (buffer << (32 - z - 8))) >> (32 - z); x <= (bbox[2] + (buffer << (32 - z - 8))) >> (32 - z); x++) { + for (y = (bbox[1] - (buffer << (32 - z - 8))) >> (32 - z); y <= (bbox[3] + (buffer << (32 - z - 8))) >> (32 - z); y++) { + if (z != maxzoom) { + // There must be a clearer way to write this, but the intent is + // not to add an additional index for a low-zoom tile + // if one of its children was already part of the + // buffered bounding box for the child's zoom. - if ((x >= ((bbox[0] - (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1)) && - (x <= ((bbox[2] + (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1)) && - (y >= ((bbox[1] - (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1)) && - (y <= ((bbox[3] + (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1))) { - continue; + // So we are comparing this tile's x and y to the edges of the + // bounding box at the next zoom down, but divided by two + // to get it back into this zoom's tile coordinate scheme + + if ((x >= ((bbox[0] - (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1)) && + (x <= ((bbox[2] + (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1)) && + (y >= ((bbox[1] - (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1)) && + (y <= ((bbox[3] + (buffer << (32 - (z + 1) - 8))) >> (32 - (z + 1)) >> 1))) { + continue; + } + } + + if (pass == 0) { + instances++; + if (instances > 1) { + break; + } + } else { + struct index ix; + + if (x == cx >> (32 - z) && y == cy >> (32 - z)) { + ix.index = encode(cx, cy); + } else { + ix.index = encode(x << (32 - z), y << (32 - z)); + } + ix.fpos = start; + ix.type = mb_geometry[t]; + ix.maxzoom = z; + ix.candup = (instances > 1); + fwrite_check(&ix, sizeof(struct index), 1, indexfile, fname, jp); } } - - struct index ix; - - if (x == cx >> (32 - z) && y == cy >> (32 - z)) { - ix.index = encode(cx, cy); - } else { - ix.index = encode(x << (32 - z), y << (32 - z)); - } - ix.fpos = start; - ix.type = mb_geometry[t]; - ix.maxzoom = z; - fwrite_check(&ix, sizeof(struct index), 1, indexfile, fname, jp); } } } diff --git a/tile.cc b/tile.cc index 1ed706fb..f86719db 100644 --- a/tile.cc +++ b/tile.cc @@ -371,10 +371,12 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns continue; } - if (dup.count(i->fpos) != 0) { - continue; + if (i->candup) { + if (dup.count(i->fpos) != 0) { + continue; + } + dup.insert(std::pair(i->fpos, 1)); } - dup.insert(std::pair(i->fpos, 1)); int t = i->type; if (t == VT_POINT) { diff --git a/tile.h b/tile.h index 2141590b..7ae1a72b 100644 --- a/tile.h +++ b/tile.h @@ -22,7 +22,8 @@ struct index { unsigned long long index; long long fpos : 48; int maxzoom : 8; - int type : 8; + int type : 7; + int candup : 1; }; long long write_tile(struct index *start, struct index *end, char *metabase, unsigned *file_bbox, int z, unsigned x, unsigned y, int detail, int basezoom, struct pool *file_keys, char *layername, sqlite3 *outdb, double droprate, int buffer);