summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Hunter <adam@mapbox.com>2015-12-02 16:37:28 -0800
committerAdam Hunter <adam@mapbox.com>2015-12-09 17:14:22 -0800
commit095a8be3007c91a230996af2f566e0365cd7c4b9 (patch)
tree4ec64a3fbb145ca08bc51db5873e699348a3c9d2 /src
parent896245e510d672eb4c1f8101ba5953c02ad8713c (diff)
downloadqtlocation-mapboxgl-095a8be3007c91a230996af2f566e0365cd7c4b9.tar.gz
Implementation of flyTo.
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/map/map.cpp6
-rw-r--r--src/mbgl/map/transform.cpp101
-rw-r--r--src/mbgl/map/transform.hpp1
3 files changed, 108 insertions, 0 deletions
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 0d6bdf9c7e..1896e7d29b 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -156,6 +156,12 @@ void Map::easeTo(const CameraOptions& options) {
transform->easeTo(options);
update(options.zoom ? Update::Zoom : Update::Repaint);
}
+
+
+void Map::flyTo(const CameraOptions& options) {
+ transform->flyTo(options);
+ update(options.zoom ? Update::Zoom : Update::Repaint);
+}
#pragma mark - Position
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index 7f0363c709..8f5c1b0f58 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -313,6 +313,107 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
}
}
+void Transform::flyTo(const CameraOptions &options) {
+ CameraOptions flyOptions(options);
+ LatLng latLng = options.center ? *options.center : getLatLng();
+ LatLng startLatLng = getLatLng();
+ double zoom = flyOptions.zoom ? *flyOptions.zoom : getZoom();
+ double angle = flyOptions.angle ? *flyOptions.angle : getAngle();
+ if (std::isnan(latLng.latitude) || std::isnan(latLng.longitude) || std::isnan(zoom)) {
+ return;
+ }
+
+ double new_scale = std::pow(2.0, zoom);
+
+ const double scaled_tile_size = new_scale * util::tileSize;
+ state.Bc = scaled_tile_size / 360;
+ state.Cc = scaled_tile_size / util::M2PI;
+
+ const double m = 1 - 1e-15;
+ const double f = std::fmin(std::fmax(std::sin(util::DEG2RAD * latLng.latitude), -m), m);
+
+ double xn = -latLng.longitude * state.Bc;
+ double yn = 0.5 * state.Cc * std::log((1 + f) / (1 - f));
+
+ view.notifyMapChange(MapChangeRegionWillChangeAnimated);
+
+ const double startS = state.scale;
+ const double startA = state.angle;
+ state.panning = true;
+ state.scaling = true;
+ state.rotating = true;
+
+ const double rho = 1.42;
+ double w0 = std::max(state.width, state.height);
+ double w1 = w0 / new_scale;
+ double u1 = std::hypot(xn, yn);
+ double rho2 = rho * rho;
+
+ auto r = [=](double i) {
+ double b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);
+ return std::log(std::sqrt(b * b + 1) - b);
+ };
+
+ bool is_close = std::abs(u1) < 0.000001;
+ if (is_close && std::abs(w0 - w1) < 0.000001) {
+ return;
+ }
+
+ double r0 = r(0);
+ auto w = [=](double s) {
+ return (is_close ? std::exp((w1 < w0 ? -1 : 1) * rho * s)
+ : (std::cosh(r0) / std::cosh(r0 + rho * s)));
+ };
+ auto u = [=](double s) {
+ return (is_close ? 0.
+ : (w0 * ((std::cosh(r0) * std::tanh(r0 + rho * s) - std::sinh(r0)) / rho2) / u1));
+ };
+ double S = (is_close ? (std::abs(std::log(w1 / w0)) / rho)
+ : ((r(1) - r0) / rho));
+
+ if (!flyOptions.duration) {
+ flyOptions.duration = Duration::zero();
+ }
+ startTransition(
+ [=](double t) {
+ util::UnitBezier ease = flyOptions.easing ? *flyOptions.easing : util::UnitBezier(0, 0, 0.25, 1);
+ return ease.solve(t, 0.001);
+ },
+ [=](double k) {
+ double s = k * S;
+ double us = u(s);
+
+ //First calculate the desired latlng
+ double desiredLat = startLatLng.latitude + (latLng.latitude - startLatLng.latitude) * us;
+ double desiredLng = startLatLng.longitude + (latLng.longitude - startLatLng.longitude) * us;
+
+ //Now calculate desired zoom
+ state.scale = startS - w(s);
+
+ //Now set values
+ const double new_scaled_tile_size = state.scale * util::tileSize;
+ state.Bc = new_scaled_tile_size / 360;
+ state.Cc = new_scaled_tile_size / util::M2PI;
+
+ const double f2 = std::fmin(std::fmax(std::sin(util::DEG2RAD * desiredLat), -m), m);
+ state.x = -desiredLng * state.Bc;
+ state.y = 0.5 * state.Cc * std::log((1 + f2) / (1 - f2));
+
+ if (angle != startA) {
+ state.angle = util::wrap(util::interpolate(startA, angle, k), -M_PI, M_PI);
+ }
+
+ view.notifyMapChange(MapChangeRegionIsChanging);
+ return Update::Zoom;
+ },
+ [=] {
+ state.panning = false;
+ state.scaling = false;
+ state.rotating = false;
+ view.notifyMapChange(MapChangeRegionDidChangeAnimated);
+ }, *flyOptions.duration);
+};
+
#pragma mark - Angle
void Transform::rotateBy(const PrecisionPoint& first, const PrecisionPoint& second, const Duration& duration) {
diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp
index 914fa164da..391b8c8d65 100644
--- a/src/mbgl/map/transform.hpp
+++ b/src/mbgl/map/transform.hpp
@@ -26,6 +26,7 @@ public:
void jumpTo(const CameraOptions&);
void easeTo(const CameraOptions&);
+ void flyTo(const CameraOptions&);
// Position
void moveBy(const PrecisionPoint&, const Duration& = Duration::zero());