summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/map/camera.hpp17
-rw-r--r--src/mbgl/map/transform.cpp59
2 files changed, 49 insertions, 27 deletions
diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp
index 626ccac353..73d7d5e7d2 100644
--- a/include/mbgl/map/camera.hpp
+++ b/include/mbgl/map/camera.hpp
@@ -38,15 +38,16 @@ struct CameraOptions {
/** Time to animate to the viewpoint defined herein. */
mapbox::util::optional<Duration> duration;
- /** Average velocity of a flyTo() transition, measured in distance units per
- second. */
- mapbox::util::optional<double> speed;
+ /** Average velocity of a flyTo() transition, measured in screenfuls per
+ second, assuming a linear timing curve.
+
+ A <i>screenful</i> is the visible span in pixels. It does not correspond
+ to a fixed physical distance but rather varies by zoom level. */
+ mapbox::util::optional<double> velocity;
- /** The relative amount of zooming that takes place along the flight path of
- a flyTo() transition. A high value maximizes zooming for an exaggerated
- animation, while a low value minimizes zooming for something closer to
- easeTo(). */
- mapbox::util::optional<double> curve;
+ /** Zero-based zoom level at the peak of the flyTo() transition’s flight
+ path. */
+ mapbox::util::optional<double> minZoom;
/** The easing timing curve of the transition. */
mapbox::util::optional<mbgl::util::UnitBezier> easing;
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index badd5d89a3..3da31d64b5 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -371,24 +371,38 @@ void Transform::flyTo(const CameraOptions &options) {
const double startAngle = state.angle;
const double startPitch = state.pitch;
+ /// w₀: Initial visible span, measured in pixels at the initial scale.
+ /// Known henceforth as a <i>screenful</i>.
+ double w0 = std::max(state.width, state.height);
+ /// w₁: Final visible span, measured in pixels with respect to the initial
+ /// scale.
+ double w1 = w0 / state.zoomScale(zoom - startZoom);
+ /// Length of the flight path as projected onto the ground plane, measured
+ /// in pixels from the world image origin at the initial scale.
+ double u1 = ::hypot((endPoint - startPoint).x, (endPoint - startPoint).y);
+
/** ρ: The relative amount of zooming that takes place along the flight
path. A high value maximizes zooming for an exaggerated animation, while
a low value minimizes zooming for something closer to easeTo().
1.42 is the average value selected by participants in the user study in
van Wijk (2003). A value of 6<sup>¼</sup> would be equivalent to the
- root mean squared average velocity, V<sub>RMS</sub>. */
- double rho = flyOptions.curve ? *flyOptions.curve : 1.42;
- /// w₀: Initial visible range.
- double w0 = std::max(state.width, state.height);
- /// w₁: Target visible range.
- double w1 = w0 / state.zoomScale(zoom - startZoom);
- /// Length of the flight path as projected onto the ground plane.
- double u1 = ::hypot((endPoint - startPoint).x, (endPoint - startPoint).y);
+ root mean squared average velocity, V<sub>RMS</sub>. A value of 1 would
+ produce a circular motion. */
+ double rho = 1.42;
+ if (flyOptions.minZoom) {
+ double minZoom = util::min(*flyOptions.minZoom, startZoom, zoom);
+ /// w<sub>m</sub>: 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);
+ }
/// ρ²
double rho2 = rho * rho;
- /// rᵢ
+ /** rᵢ: Returns the zoom-out factor at one end of the animation.
+
+ @param i 0 for the ascent or 1 for the descent. */
auto r = [=](double i) {
/// bᵢ
double b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);
@@ -397,27 +411,30 @@ void Transform::flyTo(const CameraOptions &options) {
// When u₀ = u₁, the optimal path doesn’t require both ascent and descent.
bool isClose = std::abs(u1) < 0.000001;
- // Bail if the path is too short.
+ // Perform a more or less instantaneous transition if the path is too short.
if (isClose && std::abs(w0 - w1) < 0.000001) {
+ easeTo(options);
return;
}
- /// r₀: rᵢ where i = 0.
+ /// r₀: Zoom-out factor during ascent.
double r0 = r(0);
- /** w(s): Visible range on the ground, proportional to the scale, measured
- in world coordinates.
+ /** w(s): Returns the visible span on the ground, measured in pixels with
+ respect to the initial scale.
Assumes an angular field of view of 2 arctan ½ ≈ 53°. */
auto w = [=](double s) {
return (isClose ? std::exp((w1 < w0 ? -1 : 1) * rho * s)
: (std::cosh(r0) / std::cosh(r0 + rho * s)));
};
- /// u(s): Distance along the flight path as projected onto the ground plane.
+ /// u(s): Returns the distance along the flight path as projected onto the
+ /// ground plane, measured in pixels from the world image origin at the
+ /// initial scale.
auto u = [=](double s) {
return (isClose ? 0.
: (w0 * (std::cosh(r0) * std::tanh(r0 + rho * s) - std::sinh(r0)) / rho2 / u1));
};
- /// S: Total length of the flight path.
+ /// S: Total length of the flight path, measured in ρ-screenfuls.
double S = (isClose ? (std::abs(std::log(w1 / w0)) / rho)
: ((r(1) - r0) / rho));
@@ -425,13 +442,16 @@ void Transform::flyTo(const CameraOptions &options) {
if (flyOptions.duration) {
duration = *flyOptions.duration;
} else {
- /// V: Average velocity.
- double velocity = flyOptions.speed ? *flyOptions.speed : 1.2;
+ /// V: Average velocity, measured in ρ-screenfuls per second.
+ double velocity = 1.2;
+ if (flyOptions.velocity) {
+ velocity = *flyOptions.velocity / rho;
+ }
duration = std::chrono::duration_cast<std::chrono::steady_clock::duration>(
std::chrono::duration<double, std::chrono::seconds::period>(S / velocity));
}
if (duration == Duration::zero()) {
- // Atomic transition.
+ // Perform an instantaneous transition.
jumpTo(options);
return;
}
@@ -452,7 +472,8 @@ void Transform::flyTo(const CameraOptions &options) {
return ease.solve(t, 0.001);
},
[=](double k) {
- /// s: The distance traveled along the flight path.
+ /// s: The distance traveled along the flight path, measured in
+ /// ρ-screenfuls.
double s = k * S;
double us = u(s);