summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2015-12-14 23:11:37 -0800
committerMinh Nguyễn <mxn@1ec5.org>2015-12-15 12:52:13 -0800
commite1854f0f2628e4808b48e01231c1a3a3a6cf9b68 (patch)
treedde998bc54115ec14fa2c905f4a3be0d1df1b854
parentb75c6edbf75f6bb11f23e0d1330efee3ed3ff880 (diff)
downloadqtlocation-mapboxgl-e1854f0f2628e4808b48e01231c1a3a3a6cf9b68.tar.gz
[core] Corrected flying trajectory; pitched flight
Corrected some fairly opaque code that was incorrectly ported from GL JS the first time around in #3171, causing the trajectory to extend far into the Earth’s orbit. Also transition pitch while flying, call transition frame/finish callback functions, and recognize the same “speed” and “curve” parameters that GL JS does. Fixes #3296, fixes #3297.
-rw-r--r--CHANGELOG.md1
-rw-r--r--include/mbgl/map/camera.hpp2
-rw-r--r--src/mbgl/map/transform.cpp102
-rw-r--r--src/mbgl/map/transform_state.cpp4
-rw-r--r--src/mbgl/map/transform_state.hpp1
5 files changed, 69 insertions, 41 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8cfe553ad..fe9bcf339f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,7 @@ Known issues:
- `MGLMapView` methods that alter the viewport now accept optional completion handlers. ([#3090](https://github.com/mapbox/mapbox-gl-native/pull/3090))
- Tapping now selects annotations more reliably. Tapping near the top of a large annotation image now selects that annotation. An annotation image’s alignment insets influence how far away the user can tap and still select the annotation. For example, if your annotation image has a large shadow, you can keep that shadow from being tappable by excluding it from the image’s alignment rect. ([#3261](https://github.com/mapbox/mapbox-gl-native/pull/3261))
+- A new method on MGLMapView, `-flyToCamera:withDuration:completionHandler:`, lets you transition between viewpoints along an arc as if by aircraft. ([#3171](https://github.com/mapbox/mapbox-gl-native/pull/3171), [#3301](https://github.com/mapbox/mapbox-gl-native/pull/3301))
- The user dot’s callout view is now centered above the user dot. It was previously offset slightly to the left. ([#3261](https://github.com/mapbox/mapbox-gl-native/pull/3261))
## iOS 3.0.1
diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp
index 18e7dbf96c..dd9e0a0f56 100644
--- a/include/mbgl/map/camera.hpp
+++ b/include/mbgl/map/camera.hpp
@@ -17,6 +17,8 @@ struct CameraOptions {
mapbox::util::optional<double> angle;
mapbox::util::optional<double> pitch;
mapbox::util::optional<Duration> duration;
+ mapbox::util::optional<double> speed;
+ mapbox::util::optional<double> curve;
mapbox::util::optional<mbgl::util::UnitBezier> easing;
std::function<void(double)> transitionFrameFn;
std::function<void()> transitionFinishFn;
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index 4604fbb287..d08972d53f 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -319,6 +319,7 @@ void Transform::flyTo(const CameraOptions &options) {
LatLng startLatLng = getLatLng();
double zoom = flyOptions.zoom ? *flyOptions.zoom : getZoom();
double angle = flyOptions.angle ? *flyOptions.angle : getAngle();
+ double pitch = flyOptions.pitch ? *flyOptions.pitch : getPitch();
if (std::isnan(latLng.latitude) || std::isnan(latLng.longitude) || std::isnan(zoom)) {
return;
}
@@ -337,13 +338,14 @@ void Transform::flyTo(const CameraOptions &options) {
view.notifyMapChange(MapChangeRegionWillChangeAnimated);
- const double startS = state.scale;
+ const double startZ = state.scaleZoom(state.scale);
const double startA = state.angle;
+ const double startP = state.pitch;
state.panning = true;
state.scaling = true;
state.rotating = true;
- const double rho = 1.42;
+ double rho = flyOptions.curve ? *flyOptions.curve : 1.42;
double w0 = std::max(state.width, state.height);
double w1 = w0 / new_scale;
double u1 = ::hypot(xn, yn);
@@ -371,47 +373,65 @@ void Transform::flyTo(const CameraOptions &options) {
double S = (is_close ? (std::abs(std::log(w1 / w0)) / rho)
: ((r(1) - r0) / rho));
- if (!flyOptions.duration) {
- flyOptions.duration = Duration::zero();
+ Duration duration = flyOptions.duration ? *flyOptions.duration : Duration::zero();
+ if (flyOptions.duration) {
+ duration = *flyOptions.duration;
+ } else {
+ double speed = flyOptions.speed ? *flyOptions.speed : 1.2;
+ duration = std::chrono::duration_cast<std::chrono::steady_clock::duration>(
+ std::chrono::duration<double, std::chrono::seconds::period>(S / speed));
}
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 = ::fmin(::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);
+ [=](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
+ double desiredZoom = startZ + state.scaleZoom(1 / w(s));
+ double desiredScale = state.zoomScale(desiredZoom);
+ state.scale = ::fmax(::fmin(desiredScale, state.max_scale), state.min_scale);
+
+ //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 = ::fmin(::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);
+ }
+ if (pitch != startP) {
+ state.pitch = util::clamp(util::interpolate(startP, pitch, k), 0., 60.);
+ }
+ // At k = 1.0, a DidChangeAnimated notification should be sent from finish().
+ if (k < 1.0) {
+ if (options.transitionFrameFn) {
+ options.transitionFrameFn(k);
+ }
+ view.notifyMapChange(MapChangeRegionIsChanging);
+ }
+ return Update::Zoom;
+ },
+ [=] {
+ state.panning = false;
+ state.scaling = false;
+ state.rotating = false;
+ if (options.transitionFinishFn) {
+ options.transitionFinishFn();
+ }
+ view.notifyMapChange(MapChangeRegionDidChangeAnimated);
+ }, duration);
};
#pragma mark - Angle
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index 7153c2524b..a96f182534 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -243,6 +243,10 @@ double TransformState::zoomScale(double zoom) const {
return std::pow(2.0f, zoom);
}
+double TransformState::scaleZoom(double s) const {
+ return std::log2(s);
+}
+
float TransformState::worldSize() const {
return util::tileSize * scale;
}
diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp
index fd9a556eb9..fa6ed8b58b 100644
--- a/src/mbgl/map/transform_state.hpp
+++ b/src/mbgl/map/transform_state.hpp
@@ -95,6 +95,7 @@ private:
double lngX(double lon) const;
double latY(double lat) const;
double zoomScale(double zoom) const;
+ double scaleZoom(double scale) const;
float worldSize() const;
mat4 coordinatePointMatrix(double z) const;