diff options
author | Adam Hunter <adam@mapbox.com> | 2015-12-02 16:37:28 -0800 |
---|---|---|
committer | Adam Hunter <adam@mapbox.com> | 2015-12-09 17:14:22 -0800 |
commit | 095a8be3007c91a230996af2f566e0365cd7c4b9 (patch) | |
tree | 4ec64a3fbb145ca08bc51db5873e699348a3c9d2 /src | |
parent | 896245e510d672eb4c1f8101ba5953c02ad8713c (diff) | |
download | qtlocation-mapboxgl-095a8be3007c91a230996af2f566e0365cd7c4b9.tar.gz |
Implementation of flyTo.
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/map/map.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 101 | ||||
-rw-r--r-- | src/mbgl/map/transform.hpp | 1 |
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()); |