diff options
author | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2018-07-17 18:42:55 +0300 |
---|---|---|
committer | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2018-07-30 13:32:43 +0300 |
commit | 91ce4840ad7ee0d5d41b79edf97b6c98cae5671c (patch) | |
tree | 4b665e8a7ab35175a79a22188cba93e8af8aa148 | |
parent | a8f146cc35d062c27bff1301cb0f82e1c88d4031 (diff) | |
download | qtlocation-mapboxgl-91ce4840ad7ee0d5d41b79edf97b6c98cae5671c.tar.gz |
[core] Refactor TransformState::constrain()
-rw-r--r-- | src/mbgl/map/transform_state.cpp | 88 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.hpp | 6 |
2 files changed, 44 insertions, 50 deletions
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 9e20ad96a5..c740e6e87d 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -108,7 +108,7 @@ Size TransformState::getSize() const { void TransformState::setSize(const Size& size_) { size = size_; - constrain(scale, position.x, position.y); + constrainToViewport(); } #pragma mark - North Orientation @@ -119,17 +119,17 @@ NorthOrientation TransformState::getNorthOrientation() const { void TransformState::setNorthOrientation(NorthOrientation orientation_) { orientation = orientation_; - constrain(scale, position.x, position.y); + constrainToViewport(); } double TransformState::getNorthOrientationAngle() const { double angleOrientation = 0; if (orientation == NorthOrientation::Rightwards) { - angleOrientation += M_PI / 2.0f; + angleOrientation += M_PI / 2.0; } else if (orientation == NorthOrientation::Downwards) { angleOrientation += M_PI; } else if (orientation == NorthOrientation::Leftwards) { - angleOrientation -= M_PI / 2.0f; + angleOrientation -= M_PI / 2.0; } return angleOrientation; } @@ -142,7 +142,7 @@ ConstrainMode TransformState::getConstrainMode() const { void TransformState::setConstrainMode(ConstrainMode constrainMode_) { constrainMode = constrainMode_; - constrain(scale, position.x, position.y); + constrainToViewport(); } #pragma mark - ViewportMode @@ -225,12 +225,7 @@ void TransformState::setMinZoom(const double minZoom) { } double TransformState::getMinZoom() const { - double test_scale = min_scale; - double unused_x = position.x; - double unused_y = position.y; - constrain(test_scale, unused_x, unused_y); - - return scaleZoom(test_scale); + return scaleZoom(minimumScaleAtCurrentSize()); } void TransformState::setMaxZoom(const double maxZoom) { @@ -334,12 +329,11 @@ ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) return { p[0] / p[3], size.height - p[1] / p[3] }; } -LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const { +Point<double> TransformState::screenCoordinateToMapPosition(const ScreenCoordinate& point) const { if (size.isEmpty()) { return {}; } - float targetZ = 0; mat4 mat = coordinatePointMatrix(getZoom()); mat4 inverted; @@ -368,9 +362,13 @@ LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, L double z0 = coord0[2] / w0; double z1 = coord1[2] / w1; - double t = z0 == z1 ? 0 : (targetZ - z0) / (z1 - z0); + double t = z0 == z1 ? 0 : -z0 / (z1 - z0); - return Projection::unproject(util::interpolate(p0, p1, t), scale / util::tileSize, wrapMode); + return util::interpolate(p0, p1, t); +} + +LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const { + return Projection::unproject(screenCoordinateToMapPosition(point), scale / util::tileSize, wrapMode); } mat4 TransformState::coordinatePointMatrix(double z) const { @@ -399,21 +397,32 @@ bool TransformState::rotatedNorth() const { return (orientation == NO::Leftwards || orientation == NO::Rightwards); } -void TransformState::constrain(double& scale_, double& x_, double& y_) const { +double TransformState::minimumScaleAtCurrentSize() const { + const bool rotated = rotatedNorth(); + return util::max(min_scale, + static_cast<double>(rotated ? size.height : size.width) / util::tileSize, + static_cast<double>(rotated ? size.width : size.height) / util::tileSize); +} + +void TransformState::constrainToViewport() { // Constrain minimum scale to avoid zooming out far enough to show off-world areas. - scale_ = util::max(scale_, - static_cast<double>(rotatedNorth() ? size.height : size.width) / util::tileSize, - static_cast<double>(rotatedNorth() ? size.width : size.height) / util::tileSize); + scale = util::max(scale, minimumScaleAtCurrentSize()); + + const bool rotated = rotatedNorth(); + const double worldSize = Projection::worldSize(scale); + + Bc = worldSize / util::DEGREES_MAX; + Cc = worldSize / util::M2PI; // Constrain min/max pan to avoid showing off-world areas. if (constrainMode == ConstrainMode::WidthAndHeight) { - double max_x = (scale_ * util::tileSize - (rotatedNorth() ? size.height : size.width)) / 2; - x_ = std::max(-max_x, std::min(x_, max_x)); + double max_x = (worldSize - (rotated ? size.height : size.width)) / 2.0; + position.x = std::max(-max_x, std::min(position.x, max_x)); } if (constrainMode != ConstrainMode::None) { - double max_y = (scale_ * util::tileSize - (rotatedNorth() ? size.width : size.height)) / 2; - y_ = std::max(-max_y, std::min(y_, max_y)); + double max_y = (worldSize - (rotated ? size.width : size.height)) / 2.0; + position.y = std::max(-max_y, std::min(position.y, max_y)); } } @@ -425,36 +434,19 @@ void TransformState::moveLatLng(const LatLng& latLng, const ScreenCoordinate& an } void TransformState::setLatLngZoom(const LatLng& latLng, double zoom) { - LatLng constrained = latLng; - if (bounds) { - constrained = bounds->constrain(latLng); - } - - double newScale = util::clamp(zoomScale(zoom), min_scale, max_scale); - const double newWorldSize = newScale * util::tileSize; - Bc = newWorldSize / util::DEGREES_MAX; - Cc = newWorldSize / util::M2PI; + const LatLng constrained = bounds ? bounds->constrain(latLng) : latLng; - const double m = 1 - 1e-15; + constexpr double m = 1 - 1e-15; const double f = util::clamp(std::sin(util::DEG2RAD * constrained.latitude()), -m, m); - ScreenCoordinate point = { - -constrained.longitude() * Bc, - 0.5 * Cc * std::log((1 + f) / (1 - f)), - }; - setScalePoint(newScale, point); -} - -void TransformState::setScalePoint(const double newScale, const ScreenCoordinate &point) { - double constrainedScale = newScale; - ScreenCoordinate constrainedPoint = point; - constrain(constrainedScale, constrainedPoint.x, constrainedPoint.y); - - scale = constrainedScale; - position.x = constrainedPoint.x; - position.y = constrainedPoint.y; + scale = util::clamp(zoomScale(zoom), min_scale, max_scale); Bc = Projection::worldSize(scale) / util::DEGREES_MAX; Cc = Projection::worldSize(scale) / util::M2PI; + + position.x = -constrained.longitude() * Bc; + position.y = 0.5 * Cc * std::log((1 + f) / (1 - f)); + + constrainToViewport(); } float TransformState::getCameraToTileDistance(const UnwrappedTileID& tileID) const { diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 11fb9cd99e..f30e551a97 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -110,12 +110,14 @@ public: /** Recenter the map so that the given coordinate is located at the given point on screen. */ void moveLatLng(const LatLng&, const ScreenCoordinate&); - void setScalePoint(const double scale, const ScreenCoordinate& point); void setLatLngZoom(const LatLng &latLng, double zoom); private: bool rotatedNorth() const; - void constrain(double& scale, double& x, double& y) const; + double minimumScaleAtCurrentSize() const; + void constrainToViewport(); + + Point<double> screenCoordinateToMapPosition(const ScreenCoordinate& point) const; optional<LatLngBounds> bounds; |