Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
improve gestures in perspective view
Browse files Browse the repository at this point in the history
The location under your finger stays under your finger as you pan.
The location you double tap to zoom stays at the same point.
The location at the center of a pinch zoom stays at the center.
The location at the center of a rotation stays at the center.
  • Loading branch information
ansis committed Oct 23, 2015
1 parent 46e2f13 commit db0bb1b
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 26 deletions.
2 changes: 1 addition & 1 deletion android/cpp/jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, j
return;
}

nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration));
nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), mbgl::Duration(duration));
}

jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class Map : private util::noncopyable {

// 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();
Expand Down
5 changes: 4 additions & 1 deletion platform/default/glfw_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,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);
Expand Down
11 changes: 9 additions & 2 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,14 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan
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);

Expand Down Expand Up @@ -1052,7 +1059,7 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate

_mbglMap->setBearing(newDegrees,
[rotate locationInView:rotate.view].x,
[rotate locationInView:rotate.view].y);
self.bounds.size.height - [rotate locationInView:rotate.view].y);

[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
}
Expand Down
5 changes: 5 additions & 0 deletions src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,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();
}
Expand Down
60 changes: 38 additions & 22 deletions src/mbgl/map/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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());
}
}

Expand Down
1 change: 1 addition & 0 deletions src/mbgl/map/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Transform : private util::noncopyable {
// 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(); }

Expand Down

0 comments on commit db0bb1b

Please sign in to comment.