diff options
Diffstat (limited to 'src/mbgl/map/transform.cpp')
-rw-r--r-- | src/mbgl/map/transform.cpp | 92 |
1 files changed, 52 insertions, 40 deletions
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index e97f0da3f1..aa103c0208 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -57,6 +57,7 @@ void Transform::resize(const Size size) { state.size = size; state.constrain(state.scale, state.x, state.y); + recalculateViewport(); observer.onCameraDidChange(MapObserver::CameraChangeMode::Immediate); } @@ -77,13 +78,13 @@ void Transform::jumpTo(const CameraOptions& camera) { } /** - * Change any combination of center, zoom, bearing, and pitch, with a smooth animation - * between old and new values. The map will retain the current values for any options - * not included in `options`. + * Change any combination of center, zoom, bearing, pitch and edgeInsets, with a + * smooth animation between old and new values. The map will retain the current + * values for any options not included in `options`. */ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& animation) { - const EdgeInsets& padding = camera.padding; - LatLng startLatLng = getLatLng(padding, LatLng::Unwrapped); + const EdgeInsets& padding = camera.padding.value_or(state.edgeInsets); + LatLng startLatLng = getLatLng(LatLng::Unwrapped); const LatLng& unwrappedLatLng = camera.center.value_or(startLatLng); const LatLng& latLng = state.bounds != LatLngBounds::unbounded() ? unwrappedLatLng : unwrappedLatLng.wrapped(); double zoom = camera.zoom.value_or(getZoom()); @@ -110,9 +111,6 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim const Point<double> startPoint = Projection::project(startLatLng, state.scale); const Point<double> endPoint = Projection::project(latLng, state.scale); - ScreenCoordinate center = getScreenCoordinate(padding); - center.y = state.size.height - center.y; - // Constrain camera options. zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom()); const double scale = state.zoomScale(zoom); @@ -130,6 +128,7 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim state.panning = unwrappedLatLng != startLatLng; state.scaling = scale != startScale; state.rotating = bearing != startBearing; + const EdgeInsets startEdgeInsets = state.edgeInsets; startTransition(camera, animation, [=](double t) { Point<double> framePoint = util::interpolate(startPoint, endPoint, t); @@ -143,9 +142,15 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim if (pitch != startPitch) { state.pitch = util::interpolate(startPitch, pitch, t); } - - if (!padding.isFlush()) { - state.moveLatLng(frameLatLng, center); + if (padding != startEdgeInsets) { + // Interpolate edge insets + state.edgeInsets = { + util::interpolate(startEdgeInsets.top(), padding.top(), t), + util::interpolate(startEdgeInsets.left(), padding.left(), t), + util::interpolate(startEdgeInsets.bottom(), padding.bottom(), t), + util::interpolate(startEdgeInsets.right(), padding.right(), t) + }; + recalculateViewport(); } }, duration); } @@ -159,8 +164,8 @@ 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) { - const EdgeInsets& padding = camera.padding; - const LatLng& latLng = camera.center.value_or(getLatLng(padding, LatLng::Unwrapped)).wrapped(); + 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()); double bearing = camera.bearing ? -*camera.bearing * util::DEG2RAD : getBearing(); double pitch = camera.pitch ? *camera.pitch * util::DEG2RAD : getPitch(); @@ -170,14 +175,14 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima } // Determine endpoints. - LatLng startLatLng = getLatLng(padding, LatLng::Unwrapped).wrapped(); + LatLng startLatLng = getLatLng(LatLng::Unwrapped).wrapped(); startLatLng.unwrapForShortestPath(latLng); const Point<double> startPoint = Projection::project(startLatLng, state.scale); const Point<double> endPoint = Projection::project(latLng, state.scale); - ScreenCoordinate center = getScreenCoordinate(padding); - center.y = state.size.height - center.y; + // ScreenCoordinate center = getScreenCoordinate(padding); + // center.y = state.size.height - center.y; // Constrain camera options. zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom()); @@ -278,6 +283,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima state.panning = true; state.scaling = true; state.rotating = bearing != startBearing; + const EdgeInsets startEdgeInsets = state.edgeInsets; startTransition(camera, animation, [=](double k) { /// s: The distance traveled along the flight path, measured in @@ -304,9 +310,15 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima if (pitch != startPitch) { state.pitch = util::interpolate(startPitch, pitch, k); } - - if (!padding.isFlush()) { - state.moveLatLng(frameLatLng, center); + 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) + }; + recalculateViewport(); } }, duration); } @@ -314,28 +326,16 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima #pragma mark - Position void Transform::moveBy(const ScreenCoordinate& offset, const AnimationOptions& animation) { - ScreenCoordinate centerOffset = { offset.x, -offset.y, }; - ScreenCoordinate centerPoint = getScreenCoordinate() - centerOffset; - easeTo(CameraOptions().withCenter(state.screenCoordinateToLatLng(centerPoint)), animation); + ScreenCoordinate centerOffset = { offset.x, offset.y }; + ScreenCoordinate pointOnScreen = state.edgeInsets.getCenter(state.size.width, state.size.height) - centerOffset; + // Use unwrapped LatLng to carry information about moveBy direction. + easeTo(CameraOptions().withCenter(screenCoordinateToLatLng(pointOnScreen, LatLng::Unwrapped)), animation); } -LatLng Transform::getLatLng(const EdgeInsets& padding, LatLng::WrapMode wrap) const { - if (padding.isFlush()) { - return state.getLatLng(wrap); - } else { - return screenCoordinateToLatLng(padding.getCenter(state.size.width, state.size.height)); - } +LatLng Transform::getLatLng(LatLng::WrapMode wrap) const { + return state.getLatLng(wrap); } -ScreenCoordinate Transform::getScreenCoordinate(const EdgeInsets& padding) const { - if (padding.isFlush()) { - return { state.size.width / 2., state.size.height / 2. }; - } else { - return padding.getCenter(state.size.width, state.size.height); - } -} - - #pragma mark - Zoom double Transform::getZoom() const { @@ -364,7 +364,7 @@ void Transform::setMaxZoom(const double maxZoom) { #pragma mark - Bearing void Transform::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const AnimationOptions& animation) { - ScreenCoordinate center = getScreenCoordinate(); + ScreenCoordinate center = state.edgeInsets.getCenter(state.size.width, state.size.height); const ScreenCoordinate offset = first - center; const double distance = std::sqrt(std::pow(2, offset.x) + std::pow(2, offset.y)); @@ -438,6 +438,18 @@ ProjectionMode Transform::getProjectionMode() const { .withYSkew(state.ySkew); } +void Transform::recalculateViewport() { + auto size = state.size; + auto edgeInsets = state.edgeInsets; + ScreenCoordinate center = {0.5 * (size.width + edgeInsets.left() - edgeInsets.right()), + 0.5 * (size.height + edgeInsets.top() - edgeInsets.bottom())}; + double s = std::max(std::max(center.x, size.width - center.x) / size.width, + std::max(center.y, size.height - center.y) / size.height) * 2.0; + double width = s * size.width; + double height = s * size.height; + state.viewport = { center.x - 0.5 * width, size.height - height - (size.height - center.y - 0.5 * height), width, height, s }; +} + #pragma mark - Transition void Transform::startTransition(const CameraOptions& camera, @@ -576,10 +588,10 @@ ScreenCoordinate Transform::latLngToScreenCoordinate(const LatLng& latLng) const return point; } -LatLng Transform::screenCoordinateToLatLng(const ScreenCoordinate& point) const { +LatLng Transform::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const { ScreenCoordinate flippedPoint = point; flippedPoint.y = state.size.height - flippedPoint.y; - return state.screenCoordinateToLatLng(flippedPoint).wrapped(); + return state.screenCoordinateToLatLng(flippedPoint, wrapMode); } } // namespace mbgl |