From 685e83622fe2348e28cee7d44257acbac92a7df8 Mon Sep 17 00:00:00 2001 From: Aleksandar Stojiljkovic Date: Fri, 2 Aug 2019 12:13:46 +0300 Subject: [core] Reuse flyTo constant screen velocity calculation for easeTo implementation. When using flyTo for easeTo: Limit zoom out to min(startZoom, targetZoom). Reduce cinematic zoom in animation at the end of transition, Linear zoom interpolation. The patch also sets linear interpolation for flyTo edgeInsets animation, as it looks more appropriate to follow the approach taken for pitch and bearing. Fixes: #15144 --- src/mbgl/map/transform.cpp | 34 +++++++++++++++++++--------------- src/mbgl/map/transform.hpp | 10 +++++++--- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 4004b29431..462d2462fb 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -82,6 +82,11 @@ void Transform::jumpTo(const CameraOptions& camera) { * values for any options not included in `options`. */ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& animation) { + Duration duration = animation.duration ? *animation.duration : Duration::zero(); + if (state.bounds == LatLngBounds::unbounded() && !isGestureInProgress() && duration != Duration::zero()) { + // reuse flyTo, without exaggerated animation, to achieve constant ground speed. + return flyTo(camera, animation, true); + } const EdgeInsets& padding = camera.padding.value_or(state.edgeInsets); LatLng startLatLng = getLatLng(LatLng::Unwrapped); const LatLng& unwrappedLatLng = camera.center.value_or(startLatLng); @@ -118,8 +123,6 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim bearing = _normalizeAngle(bearing, state.bearing); state.bearing = _normalizeAngle(state.bearing, bearing); - Duration duration = animation.duration ? *animation.duration : Duration::zero(); - const double startZoom = state.getZoom(); const double startBearing = state.bearing; const double startPitch = state.pitch; @@ -161,7 +164,7 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim Where applicable, local variable documentation begins with the associated variable or function in van Wijk (2003). */ -void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &animation) { +void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &animation, bool linearZoomInterpolation) { const EdgeInsets& padding = camera.padding.value_or(state.edgeInsets); const LatLng& latLng = camera.center.value_or(getLatLng(LatLng::Unwrapped)).wrapped(); double zoom = camera.zoom.value_or(getZoom()); @@ -208,16 +211,16 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima 1.42 is the average value selected by participants in the user study in van Wijk (2003). A value of 6¼ would be equivalent to the - root mean squared average velocity, VRMS. A value of 1 would - produce a circular motion. */ + root mean squared average velocity, VRMS. A value of 1 + produces a circular motion. */ double rho = 1.42; - if (animation.minZoom) { - double minZoom = util::min(*animation.minZoom, startZoom, zoom); + if (animation.minZoom || linearZoomInterpolation) { + double minZoom = util::min(animation.minZoom.value_or(startZoom), startZoom, zoom); minZoom = util::clamp(minZoom, state.getMinZoom(), state.getMaxZoom()); /// wm: Maximum visible span, measured in pixels with respect /// to the initial scale. double wMax = w0 / state.zoomScale(minZoom - startZoom); - rho = std::sqrt(wMax / u1 * 2); + rho = u1 != 0 ? std::sqrt(wMax / u1 * 2) : 1.0; } /// ρ² double rho2 = rho * rho; @@ -232,8 +235,8 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima }; /// r₀: Zoom-out factor during ascent. - double r0 = r(0); - double r1 = r(1); + double r0 = u1 != 0 ? r(0) : INFINITY; // Silence division by 0 on sanitize bot. + double r1 = u1 != 0 ? r(1) : INFINITY; // When u₀ = u₁, the optimal path doesn’t require both ascent and descent. bool isClose = std::abs(u1) < 0.000001 || !std::isfinite(r0) || !std::isfinite(r1); @@ -288,7 +291,8 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima // Calculate the current point and zoom level along the flight path. Point framePoint = util::interpolate(startPoint, endPoint, us); - double frameZoom = startZoom + state.scaleZoom(1 / w(s)); + double frameZoom = linearZoomInterpolation ? util::interpolate(startZoom, zoom, k) + : startZoom + state.scaleZoom(1 / w(s)); // Zoom can be NaN if size is empty. if (std::isnan(frameZoom)) { @@ -305,10 +309,10 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima if (padding != startEdgeInsets) { // Interpolate edge insets state.edgeInsets = { - util::interpolate(startEdgeInsets.top(), padding.top(), us), - util::interpolate(startEdgeInsets.left(), padding.left(), us), - util::interpolate(startEdgeInsets.bottom(), padding.bottom(), us), - util::interpolate(startEdgeInsets.right(), padding.right(), us) + util::interpolate(startEdgeInsets.top(), padding.top(), k), + util::interpolate(startEdgeInsets.left(), padding.left(), k), + util::interpolate(startEdgeInsets.bottom(), padding.bottom(), k), + util::interpolate(startEdgeInsets.right(), padding.right(), k) }; } auto maxPitch = getMaxPitchForEdgeInsets(state.edgeInsets); diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index 75dfeff645..ffeff3859c 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -34,12 +34,16 @@ public: /** Instantaneously, synchronously applies the given camera options. */ void jumpTo(const CameraOptions&); /** Asynchronously transitions all specified camera options linearly along - an optional time curve. */ + an optional time curve. However, center coordinate is not transitioned + linearly as, instead, ground speed is kept linear.*/ void easeTo(const CameraOptions&, const AnimationOptions& = {}); /** Asynchronously zooms out, pans, and zooms back into the given camera along a great circle, as though the viewer is riding a supersonic - jetcopter. */ - void flyTo(const CameraOptions&, const AnimationOptions& = {}); + jetcopter. + Parameter linearZoomInterpolation: when true, there is no additional + zooming out as zoom is linearly interpolated from current to given + camera zoom. This is used for easeTo.*/ + void flyTo(const CameraOptions&, const AnimationOptions& = {}, bool linearZoomInterpolation = false); // Position -- cgit v1.2.1