diff --git a/geojson.c b/geojson.c index cc9d499..2d347e8 100644 --- a/geojson.c +++ b/geojson.c @@ -160,7 +160,7 @@ void parse_geometry(int t, json_object *j, unsigned *bbox, long long *fpos, FILE } } else { if (j->length >= 2 && j->array[0]->type == JSON_NUMBER && j->array[1]->type == JSON_NUMBER) { - unsigned x, y; + long long x, y; double lon = j->array[0]->number; double lat = j->array[1]->number; latlon2tile(lat, lon, 32, &x, &y); diff --git a/projection.c b/projection.c index effb347..839370e 100644 --- a/projection.c +++ b/projection.c @@ -2,39 +2,19 @@ #include "projection.h" // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames -void latlon2tile(double lat, double lon, int zoom, unsigned int *x, unsigned int *y) { +void latlon2tile(double lat, double lon, int zoom, long long *x, long long *y) { double lat_rad = lat * M_PI / 180; unsigned long long n = 1LL << zoom; long long llx = n * ((lon + 180) / 360); long long lly = n * (1 - (log(tan(lat_rad) + 1 / cos(lat_rad)) / M_PI)) / 2; - if (lat >= 85.0511) { - lly = 0; - } - if (lat <= -85.0511) { - lly = n - 1; - } - - if (llx < 0) { - llx = 0; - } - if (lly < 0) { - lly = 0; - } - if (llx >= n) { - llx = n - 1; - } - if (lly >= n) { - lly = n - 1; - } - *x = llx; *y = lly; } // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames -void tile2latlon(unsigned int x, unsigned int y, int zoom, double *lat, double *lon) { +void tile2latlon(long long x, long long y, int zoom, double *lat, double *lon) { unsigned long long n = 1LL << zoom; *lon = 360.0 * x / n - 180.0; *lat = atan(sinh(M_PI * (1 - 2.0 * y / n))) * 180.0 / M_PI; diff --git a/projection.h b/projection.h index af7002e..20d67ec 100644 --- a/projection.h +++ b/projection.h @@ -1,4 +1,4 @@ -void latlon2tile(double lat, double lon, int zoom, unsigned int *x, unsigned int *y); -void tile2latlon(unsigned int x, unsigned int y, int zoom, double *lat, double *lon); +void latlon2tile(double lat, double lon, int zoom, long long *x, long long *y); +void tile2latlon(long long x, long long y, int zoom, double *lat, double *lon); unsigned long long encode(unsigned int wx, unsigned int wy); void decode(unsigned long long index, unsigned *wx, unsigned *wy); diff --git a/tile.cc b/tile.cc index bdd95a6..6daa00a 100644 --- a/tile.cc +++ b/tile.cc @@ -544,6 +544,26 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi continue; } + if (z == 0) { + if (bbox[0] < 0 || bbox[2] > 1LL << 32) { + // If the geometry extends off the edge of the world, concatenate on another copy + // shifted by 360 degrees, and then make sure both copies get clipped down to size. + + unsigned n = geom.size(); + for (unsigned i = 0; i < n; i++) { + geom.push_back(draw(geom[i].op, geom[i].x - (1LL << 32), geom[i].y)); + } + for (unsigned i = 0; i < n; i++) { + geom.push_back(draw(geom[i].op, geom[i].x + (1LL << 32), geom[i].y)); + } + + bbox[0] = 0; + bbox[2] = 1LL << 32; + + quick = -1; + } + } + if (quick != 1) { if (t == VT_LINE) { geom = clip_lines(geom, z, line_detail, buffer);