diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index cdd3044dcf1..cdfa7793505 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -1621,10 +1621,6 @@ - (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(null { CGPoint convertedPoint = [self convertPoint:point fromView:view]; - // flip y coordinate for iOS view origin top left - // - convertedPoint.y = self.bounds.size.height - convertedPoint.y; - return MGLLocationCoordinate2DFromLatLng(_mbglMap->latLngForPixel(mbgl::vec2(convertedPoint.x, convertedPoint.y))); } @@ -1632,10 +1628,6 @@ - (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(n { mbgl::vec2 pixel = _mbglMap->pixelForLatLng(MGLLatLngFromLocationCoordinate2D(coordinate)); - // flip y coordinate for iOS view origin in top left - // - pixel.y = self.bounds.size.height - pixel.y; - return [self convertPoint:CGPointMake(pixel.x, pixel.y) toView:view]; } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index e70972a13fb..065c33ce5f3 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -304,11 +304,11 @@ const LatLng Map::latLngForProjectedMeters(const ProjectedMeters projectedMeters } const vec2 Map::pixelForLatLng(const LatLng latLng) const { - return transform->getState().pixelForLatLng(latLng); + return transform->getState().latLngToPoint(latLng); } const LatLng Map::latLngForPixel(const vec2 pixel) const { - return transform->getState().latLngForPixel(pixel); + return transform->getState().pointToLatLng(pixel); } #pragma mark - Annotations diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index f60ddce5730..9aedf26a652 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -333,7 +333,7 @@ std::forward_list Source::coveringTiles(const TransformState& state) con // Map four viewport corners to pixel coordinates box points = state.cornersToBox(z); - const TileCoordinate center = state.pointCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z); + const TileCoordinate center = state.pointToCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z); std::forward_list covering_tiles = tileCover(z, points, reparseOverscaled ? actualZ : z); diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 2f62318281e..9e4ea457eb2 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -46,10 +45,10 @@ box TransformState::cornersToBox(uint32_t z) const { double w = width; double h = height; box b( - pointCoordinate({ 0, 0 }).zoomTo(z), - pointCoordinate({ w, 0 }).zoomTo(z), - pointCoordinate({ w, h }).zoomTo(z), - pointCoordinate({ 0, h }).zoomTo(z)); + pointToCoordinate({ 0, 0 }).zoomTo(z), + pointToCoordinate({ w, 0 }).zoomTo(z), + pointToCoordinate({ w, h }).zoomTo(z), + pointToCoordinate({ 0, h }).zoomTo(z)); return b; } @@ -158,94 +157,73 @@ float TransformState::getPitch() const { #pragma mark - Projection -const vec2 TransformState::pixelForLatLng(const LatLng latLng) const { - LatLng ll = getLatLng(); - double zoom = getZoom(); - - const double centerX = static_cast(width) / 2.0; - const double centerY = static_cast(height) / 2.0; - - const double m = Projection::getMetersPerPixelAtLatitude(0, zoom); - - const double angle_sin = std::sin(-angle); - const double angle_cos = std::cos(-angle); - - const ProjectedMeters givenMeters = Projection::projectedMetersForLatLng(latLng); - - const double givenAbsoluteX = givenMeters.easting / m; - const double givenAbsoluteY = givenMeters.northing / m; - - const ProjectedMeters centerMeters = Projection::projectedMetersForLatLng(ll); - - const double centerAbsoluteX = centerMeters.easting / m; - const double centerAbsoluteY = centerMeters.northing / m; - - const double deltaX = givenAbsoluteX - centerAbsoluteX; - const double deltaY = givenAbsoluteY - centerAbsoluteY; - - const double translatedX = deltaX + centerX; - const double translatedY = deltaY + centerY; - - const double rotatedX = translatedX * angle_cos - translatedY * angle_sin; - const double rotatedY = translatedX * angle_sin + translatedY * angle_cos; - - const double rotatedCenterX = centerX * angle_cos - centerY * angle_sin; - const double rotatedCenterY = centerX * angle_sin + centerY * angle_cos; - - double x_ = rotatedX + (centerX - rotatedCenterX); - double y_ = rotatedY + (centerY - rotatedCenterY); - - return vec2(x_, y_); +float TransformState::lngX(float lng) const { + return (180.0f + lng) * worldSize() / 360.0f; } -const LatLng TransformState::latLngForPixel(const vec2 pixel) const { - LatLng ll = getLatLng(); - double zoom = getZoom(); - - const double centerX = static_cast(width) / 2.0; - const double centerY = static_cast(height) / 2.0; - - const double m = Projection::getMetersPerPixelAtLatitude(0, zoom); - - const double angle_sin = std::sin(angle); - const double angle_cos = std::cos(angle); - - const double unrotatedCenterX = centerX * angle_cos - centerY * angle_sin; - const double unrotatedCenterY = centerX * angle_sin + centerY * angle_cos; +float TransformState::latY(float lat) const { + float y_ = 180.0f / M_PI * std::log(std::tan(M_PI / 4 + lat * M_PI / 360.0f)); + return (180.0f - y_) * worldSize() / 360.0f; +} - const double unrotatedX = pixel.x * angle_cos - pixel.y * angle_sin; - const double unrotatedY = pixel.x * angle_sin + pixel.y * angle_cos; +float TransformState::xLng(float x_, float worldSize_) const { + return x_ * 360.0f / worldSize_ - 180.0f; +} - const double givenX = unrotatedX + (centerX - unrotatedCenterX); - const double givenY = unrotatedY + (centerY - unrotatedCenterY); +float TransformState::yLat(float y_, float worldSize_) const { + float y2 = 180.0f - y_ * 360.0f / worldSize_; + return 360.0f / M_PI * std::atan(std::exp(y2 * M_PI / 180.0f)) - 90.0f; +} - const ProjectedMeters centerMeters = Projection::projectedMetersForLatLng(ll); +float TransformState::zoomScale(float zoom) const { + return std::pow(2.0f, zoom); +} - const double centerAbsoluteX = centerMeters.easting / m; - const double centerAbsoluteY = centerMeters.northing / m; +float TransformState::worldSize() const { + return util::tileSize * scale; +} - const double givenAbsoluteX = givenX + centerAbsoluteX - centerX; - const double givenAbsoluteY = givenY + centerAbsoluteY - centerY; +vec2 TransformState::latLngToPoint(const LatLng& latLng) const { + return coordinateToPoint(latLngToCoordinate(latLng)); +} - ProjectedMeters givenMeters = ProjectedMeters(givenAbsoluteY * m, givenAbsoluteX * m); +LatLng TransformState::pointToLatLng(const vec2 point) const { + return coordinateToLatLng(pointToCoordinate(point)); +} - // adjust for date line - ProjectedMeters sw, ne; - Projection::getWorldBoundsMeters(sw, ne); - double d = ne.easting - sw.easting; - if (ll.longitude > 0 && givenMeters.easting > centerMeters.easting) givenMeters.easting -= d; +TileCoordinate TransformState::latLngToCoordinate(const LatLng& latLng) const { + const float tileZoom = getIntegerZoom(); + const float k = zoomScale(tileZoom) / worldSize(); + return { + lngX(latLng.longitude) * k, + latY(latLng.latitude) * k, + tileZoom + }; +} - // adjust for world wrap - while (givenMeters.easting < sw.easting) givenMeters.easting += d; - while (givenMeters.easting > ne.easting) givenMeters.easting -= d; +LatLng TransformState::coordinateToLatLng(const TileCoordinate& coord) const { + const float worldSize_ = zoomScale(coord.zoom); + LatLng latLng = { + yLat(coord.row, worldSize_), + xLng(coord.column, worldSize_) + }; + while (latLng.longitude < 180.0f) latLng.longitude += 360.0f; + while (latLng.longitude > 180.0f) latLng.longitude -= 360.0f; + return latLng; +} - return Projection::latLngForProjectedMeters(givenMeters); +vec2 TransformState::coordinateToPoint(const TileCoordinate& coord) const { + mat4 mat = coordinatePointMatrix(coord.zoom); + matrix::vec4 p; + matrix::vec4 c = {{ coord.column, coord.row, 0, 1 }}; + matrix::transformMat4(p, c, mat); + return { p[0] / p[3], p[1] / p[3] }; } -TileCoordinate TransformState::pointCoordinate(const vec2 point) const { +TileCoordinate TransformState::pointToCoordinate(const vec2 point) const { float targetZ = 0; - float tileZoom = std::floor(getZoom()); + const float tileZoom = getIntegerZoom(); mat4 mat = coordinatePointMatrix(tileZoom); diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 521131b33ae..d4b46f04b18 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -31,9 +31,6 @@ class TransformState { uint16_t getWidth() const; uint16_t getHeight() const; - float worldSize() const; - float lngX(float lon) const; - float latY(float lat) const; std::array locationCoordinate(float lon, float lat) const; void getLonLat(double &lon, double &lat) const; @@ -55,18 +52,22 @@ class TransformState { float getAltitude() const; float getPitch() const; - // Projection - const vec2 pixelForLatLng(const LatLng latLng) const; - const LatLng latLngForPixel(const vec2 pixel) const; - // Changing bool isChanging() const; double pixel_x() const; double pixel_y() const; - // Conversions - TileCoordinate pointCoordinate(const vec2 point) const; + // Conversion and projection + + vec2 latLngToPoint(const LatLng& latLng) const; + LatLng pointToLatLng(const vec2 point) const; + + TileCoordinate latLngToCoordinate(const LatLng& latLng) const; + LatLng coordinateToLatLng(const TileCoordinate& coord) const; + + vec2 coordinateToPoint(const TileCoordinate& coord) const; + TileCoordinate pointToCoordinate(const vec2 point) const; private: void constrain(double& scale, double& y) const; @@ -78,6 +79,13 @@ class TransformState { // logical dimensions uint16_t width = 0, height = 0; + float xLng(float x, float worldSize) const; + float yLat(float y, float worldSize) const; + float lngX(float lon) const; + float latY(float lat) const; + float zoomScale(float zoom) const; + float worldSize() const; + mat4 coordinatePointMatrix(float z) const; mat4 getPixelMatrix() const; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 6b78ca40d30..9ea75efb886 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -379,7 +379,7 @@ void Painter::renderBackground(const StyleLayer &layer_desc) { patternShader->u_opacity = properties.opacity; LatLng latLng = state.getLatLng(); - vec2 center = state.pixelForLatLng(latLng); + vec2 center = state.latLngToPoint(latLng); float scale = 1 / std::pow(2, zoomFraction); std::array sizeA = imagePosA.size;