3#include <QtCore/QDebug>
4#include <QtCore/QtMath>
13 const QDebugStateSaver saver(debug);
14 debug.nospace() << key.
zoom <<
'/' << key.
x <<
'/' << key.
y;
26 const double x = qDegreesToRadians(coord.longitude()) *
kEarthRadius;
27 const double y = std::log(std::tan(M_PI_4 + qDegreesToRadians(lat) / 2.0)) *
kEarthRadius;
33 const double lon = qRadiansToDegrees(world.x() /
kEarthRadius);
34 const double lat = qRadiansToDegrees(2.0 * std::atan(std::exp(world.y() /
kEarthRadius)) - M_PI_2);
35 return QGeoCoordinate(lat, lon, 0);
41 return 1.0 / std::cos(qDegreesToRadians(lat));
49 const int tilesAtZoom = 1 << key.
zoom;
50 return (key.
x >= 0) && (key.
x < tilesAtZoom) && (key.
y >= 0) && (key.
y < tilesAtZoom);
62 const double minX = -half + (key.
x * span);
63 const double minY = half - ((key.
y + 1) * span);
64 return QPointF(minX, minY);
72 const int tileCount = 1 << clampedZoom;
74 const double x = std::clamp(world.x(), -half, half);
75 const double y = std::clamp(world.y(), -half, half);
78 key.
zoom = clampedZoom;
79 key.
x = std::clamp(
static_cast<int>(std::floor((x + half) / span)), 0, tileCount - 1);
80 key.
y = std::clamp(
static_cast<int>(std::floor((half - y) / span)), 0, tileCount - 1);
91 if (metersPerPixel <= 0.0) {
95 return std::clamp(
static_cast<int>(std::ceil(zoomExact)),
kMinZoom,
kMaxZoom);
constexpr double kMaxLatitude
Mercator latitude clamp (deg)
constexpr int kTilePixels
Nominal tile edge used for meters-per-pixel.
double worldSize()
Full mercator world extent (2*pi*R) in world meters.
constexpr double kEarthRadius
WGS84 equatorial radius (m)
QPointF geoToWorld(const QGeoCoordinate &coord)
Geo -> world meters. Latitude is clamped to +/-kMaxLatitude.
QPointF tileMinCorner(const TileKey &key)
South-west (minimum x/y) corner of a tile in world meters.
bool isValidKey(const TileKey &key)
True if zoom is within [kMinZoom, kMaxZoom] and x/y address a tile at that zoom.
QDebug operator<<(QDebug debug, const TileKey &key)
Streams as slippy "zoom/x/y" notation for logging.
int zoomForMetersPerPixel(double metersPerPixel)
Smallest zoom whose resolution is at least as fine as metersPerPixel (clamped to valid range)
double mercatorScale(double latitude)
double metersPerPixelAtZoom(int zoom)
World meters spanned by one pixel of a kTilePixels tile at zoom (equator)
QGeoCoordinate worldToGeo(const QPointF &world)
World meters -> geo (altitude 0)
double tileSpanAtZoom(int zoom)
Edge length of one tile at zoom, in world meters.
TileKey tileForWorld(const QPointF &world, int zoom)
Tile containing a world point. World coordinates are clamped to the world extent.