diff --git a/geometry.cc b/geometry.cc index 586bfa4..41f8087 100644 --- a/geometry.cc +++ b/geometry.cc @@ -206,6 +206,8 @@ drawvec shrink_lines(drawvec &geom, int z, int detail, int basezoom, long long * } #endif +#define CLIPPER_OFFSET 0x400000000LL + static void decode_clipped(ClipperLib::PolyNode *t, drawvec &out) { // To make the GeoJSON come out right, we need to do each of the // outer rings followed by its children if any, and then go back @@ -213,19 +215,19 @@ static void decode_clipped(ClipperLib::PolyNode *t, drawvec &out) { ClipperLib::Path p = t->Contour; for (unsigned i = 0; i < p.size(); i++) { - out.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X, p[i].Y)); + out.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X - CLIPPER_OFFSET, p[i].Y - CLIPPER_OFFSET)); } if (p.size() > 0) { - out.push_back(draw(VT_LINETO, p[0].X, p[0].Y)); + out.push_back(draw(VT_LINETO, p[0].X - CLIPPER_OFFSET, p[0].Y - CLIPPER_OFFSET)); } for (int n = 0; n < t->ChildCount(); n++) { ClipperLib::Path p = t->Childs[n]->Contour; for (unsigned i = 0; i < p.size(); i++) { - out.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X, p[i].Y)); + out.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X - CLIPPER_OFFSET, p[i].Y - CLIPPER_OFFSET)); } if (p.size() > 0) { - out.push_back(draw(VT_LINETO, p[0].X, p[0].Y)); + out.push_back(draw(VT_LINETO, p[0].X - CLIPPER_OFFSET, p[0].Y - CLIPPER_OFFSET)); } } @@ -252,7 +254,7 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool cl drawvec tmp; for (unsigned k = i; k < j; k++) { - path.push_back(ClipperLib::IntPoint(geom[k].x, geom[k].y)); + path.push_back(ClipperLib::IntPoint(geom[k].x + CLIPPER_OFFSET, geom[k].y + CLIPPER_OFFSET)); } if (!clipper.AddPath(path, ClipperLib::ptSubject, true)) { @@ -280,11 +282,11 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool cl long long clip_buffer = buffer * area / 256; ClipperLib::Path edge; - edge.push_back(ClipperLib::IntPoint(-clip_buffer, -clip_buffer)); - edge.push_back(ClipperLib::IntPoint(area + clip_buffer, -clip_buffer)); - edge.push_back(ClipperLib::IntPoint(area + clip_buffer, area + clip_buffer)); - edge.push_back(ClipperLib::IntPoint(-clip_buffer, area + clip_buffer)); - edge.push_back(ClipperLib::IntPoint(-clip_buffer, -clip_buffer)); + edge.push_back(ClipperLib::IntPoint(-clip_buffer + CLIPPER_OFFSET, -clip_buffer + CLIPPER_OFFSET)); + edge.push_back(ClipperLib::IntPoint(area + clip_buffer + CLIPPER_OFFSET, -clip_buffer + CLIPPER_OFFSET)); + edge.push_back(ClipperLib::IntPoint(area + clip_buffer + CLIPPER_OFFSET, area + clip_buffer + CLIPPER_OFFSET)); + edge.push_back(ClipperLib::IntPoint(-clip_buffer + CLIPPER_OFFSET, area + clip_buffer + CLIPPER_OFFSET)); + edge.push_back(ClipperLib::IntPoint(-clip_buffer + CLIPPER_OFFSET, -clip_buffer + CLIPPER_OFFSET)); clipper.AddPath(edge, ClipperLib::ptClip, true); } diff --git a/projection.c b/projection.c index 839370e..ccd4f00 100644 --- a/projection.c +++ b/projection.c @@ -3,6 +3,23 @@ // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames void latlon2tile(double lat, double lon, int zoom, long long *x, long long *y) { + // Must limit latitude somewhere to prevent overflow. + // 89.9 degrees latitude is 0.621 worlds beyond the edge of the flat earth, + // hopefully far enough out that there are few expectations about the shape. + if (lat < -89.9) { + lat = -89.9; + } + if (lat > 89.9) { + lat = 89.9; + } + + if (lon < -360) { + lon = -360; + } + if (lon > 360) { + lon = 360; + } + double lat_rad = lat * M_PI / 180; unsigned long long n = 1LL << zoom;