diff options
-rw-r--r-- | include/mbgl/map/map.hpp | 1 | ||||
-rw-r--r-- | platform/default/glfw_view.cpp | 5 | ||||
-rw-r--r-- | platform/ios/MGLMapView.mm | 11 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 60 | ||||
-rw-r--r-- | src/mbgl/map/transform.hpp | 1 |
6 files changed, 58 insertions, 25 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 6757691bb6..7ea803d310 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -104,6 +104,7 @@ public: // Position void moveBy(double dx, double dy, const Duration& = Duration::zero()); + void setLatLng(LatLng latLng, vec2<double> point, const Duration& = Duration::zero()); void setLatLng(LatLng latLng, const Duration& = Duration::zero()); LatLng getLatLng() const; void resetPosition(); diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index 8453845d1e..762521d207 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -332,7 +332,10 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) { double dx = x - view->lastX; double dy = y - view->lastY; if (dx || dy) { - view->map->moveBy(dx, dy); + double flippedY = view->height - y; + view->map->setLatLng( + view->map->latLngForPixel(mbgl::vec2<double>(x - dx, flippedY + dy)), + mbgl::vec2<double>(x, flippedY)); } } else if (view->rotating) { view->map->rotateBy(view->lastX, view->lastY, x, y); diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 5fcd045b74..29377bf2c8 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -892,7 +892,14 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) CGPoint delta = CGPointMake([pan translationInView:pan.view].x - self.centerPoint.x, [pan translationInView:pan.view].y - self.centerPoint.y); - _mbglMap->moveBy(delta.x, delta.y); + double flippedY = self.bounds.size.height - [pan locationInView:pan.view].y; + _mbglMap->setLatLng( + _mbglMap->latLngForPixel(mbgl::vec2<double>( + [pan locationInView:pan.view].x - delta.x, + flippedY + delta.y)), + mbgl::vec2<double>( + [pan locationInView:pan.view].x, + flippedY)); self.centerPoint = CGPointMake(self.centerPoint.x + delta.x, self.centerPoint.y + delta.y); @@ -1063,7 +1070,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) _mbglMap->setBearing(newDegrees, [rotate locationInView:rotate.view].x, - [rotate locationInView:rotate.view].y); + self.bounds.size.height - [rotate locationInView:rotate.view].y); } else if (rotate.state == UIGestureRecognizerStateEnded || rotate.state == UIGestureRecognizerStateCancelled) { diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index f102b4570a..6ad754d03c 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -140,6 +140,11 @@ void Map::setLatLng(LatLng latLng, const Duration& duration) { update(Update::Repaint); } +void Map::setLatLng(LatLng latLng, vec2<double> point, const Duration& duration) { + transform->setLatLng(latLng, point, duration); + update(Update::Repaint); +} + LatLng Map::getLatLng() const { return transform->getLatLng(); } diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 5d3ccfdf56..50970727c3 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -6,6 +6,7 @@ #include <mbgl/util/math.hpp> #include <mbgl/util/unitbezier.hpp> #include <mbgl/util/interpolate.hpp> +#include <mbgl/util/tile_coordinate.hpp> #include <mbgl/platform/platform.hpp> #include <cstdio> @@ -113,6 +114,27 @@ void Transform::setLatLng(const LatLng latLng, const Duration& duration) { easeTo(options); } +void Transform::setLatLng(const LatLng latLng, vec2<double> point, const Duration& duration) { + if (std::isnan(latLng.latitude) || std::isnan(latLng.longitude)) { + return; + } + + auto coord = state.latLngToCoordinate(latLng); + auto coordAtPoint = state.pointToCoordinate(point); + auto coordCenter = state.pointToCoordinate({ state.width / 2.0f, state.height / 2.0f }); + + float columnDiff = coordAtPoint.column - coord.column; + float rowDiff = coordAtPoint.row - coord.row; + + auto newLatLng = state.coordinateToLatLng({ + coordCenter.column - columnDiff, + coordCenter.row - rowDiff, + coordCenter.zoom + }); + + setLatLng(newLatLng, duration); +} + void Transform::setLatLngZoom(const LatLng latLng, const double zoom, const Duration& duration) { CameraOptions options; options.center = latLng; @@ -173,25 +195,20 @@ void Transform::_setScale(double new_scale, double cx, double cy, const Duration new_scale = state.max_scale; } - // Zoom in on the center if we don't have click or gesture anchor coordinates. - if (cx < 0 || cy < 0) { - cx = static_cast<double>(state.width) / 2.0; - cy = static_cast<double>(state.height) / 2.0; - } - - // Account for the x/y offset from the center (= where the user clicked or pinched) const double factor = new_scale / state.scale; - const double dx = (cx - static_cast<double>(state.width) / 2.0) * (1.0 - factor); - const double dy = (cy - static_cast<double>(state.height) / 2.0) * (1.0 - factor); - - // Account for angle - const double angle_sin = std::sin(-state.angle); - const double angle_cos = std::cos(-state.angle); - const double ax = angle_cos * dx - angle_sin * dy; - const double ay = angle_sin * dx + angle_cos * dy; + double dx = 0; + double dy = 0; + + if (cx > 0 || cy > 0) { + auto coord = state.pointToCoordinate({ cx, state.getHeight() - cy }).zoomTo(state.getZoom()); + auto centerCoord = state.pointToCoordinate({ state.width / 2.0f, state.height / 2.0f }).zoomTo(state.getZoom()); + auto coordDiff = centerCoord - coord; + dx = coordDiff.column * util::tileSize * (1.0 - factor); + dy = coordDiff.row * util::tileSize * (1.0 - factor); + } - const double xn = state.x * factor + ax; - const double yn = state.y * factor + ay; + const double xn = state.x * factor - dx; + const double yn = state.y * factor - dy; _setScaleXY(new_scale, xn, yn, duration); } @@ -318,18 +335,17 @@ void Transform::setAngle(const double new_angle, const double cx, const double c return; } - double dx = 0, dy = 0; + LatLng rotationCenter; if (cx >= 0 && cy >= 0) { - dx = (static_cast<double>(state.width) / 2.0) - cx; - dy = (static_cast<double>(state.height) / 2.0) - cy; - _moveBy(dx, dy, Duration::zero()); + rotationCenter = state.pointToLatLng({ cx, cy }); + setLatLng(rotationCenter, Duration::zero()); } _setAngle(new_angle); if (cx >= 0 && cy >= 0) { - _moveBy(-dx, -dy, Duration::zero()); + setLatLng(rotationCenter, { cx, cy }, Duration::zero()); } } diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index eead72f4b1..365d7af446 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -29,6 +29,7 @@ public: // Position void moveBy(double dx, double dy, const Duration& = Duration::zero()); void setLatLng(LatLng latLng, const Duration& = Duration::zero()); + void setLatLng(LatLng latLng, vec2<double> point, const Duration& duration = Duration::zero()); void setLatLngZoom(LatLng latLng, double zoom, const Duration& = Duration::zero()); inline const LatLng getLatLng() const { return state.getLatLng(); } |