From 372df88c614a60a5fea8c53178785eba9b463d99 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Thu, 30 Mar 2017 16:25:12 +0300 Subject: [PATCH] [core] Added Map::{get,set}LatLngBounds --- include/mbgl/map/map.hpp | 2 ++ src/mbgl/map/map.cpp | 9 ++++++++ src/mbgl/map/transform.cpp | 6 +++++ src/mbgl/map/transform.hpp | 1 + src/mbgl/map/transform_state.cpp | 15 ++++++++++-- src/mbgl/map/transform_state.hpp | 4 ++++ test/map/transform.test.cpp | 39 ++++++++++++++++++++++++++++++++ 7 files changed, 74 insertions(+), 2 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index b740c3462e8..908beb6b298 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -111,6 +111,8 @@ class Map : private util::noncopyable { void resetZoom(); // Bounds + void setLatLngBounds(const LatLngBounds&); + LatLngBounds getLatLngBounds() const; void setMinZoom(double); double getMinZoom() const; void setMaxZoom(double); diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index ffcb83503a5..0f082ec8498 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -666,6 +666,15 @@ void Map::resetZoom() { #pragma mark - Bounds +LatLngBounds Map::getLatLngBounds() const { + return impl->transform.getState().getLatLngBounds(); +} + +void Map::setLatLngBounds(const LatLngBounds& bounds) { + impl->cameraMutated = true; + impl->transform.setLatLngBounds(bounds); + impl->onUpdate(Update::Repaint); +} void Map::setMinZoom(const double minZoom) { impl->transform.setMinZoom(minZoom); diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 50e0ec5cd0d..24c58dedd05 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -440,6 +440,12 @@ void Transform::setScale(double scale, optional padding, const Anima #pragma mark - Bounds +void Transform::setLatLngBounds(const LatLngBounds& bounds) { + if (bounds.valid()) { + state.setLatLngBounds(bounds); + } +} + void Transform::setMinZoom(const double minZoom) { if (std::isnan(minZoom)) return; state.setMinZoom(minZoom); diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index 2597e5ae549..558a150168f 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -57,6 +57,7 @@ class Transform : private util::noncopyable { // Bounds + void setLatLngBounds(const LatLngBounds&); void setMinZoom(double); void setMaxZoom(double); diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 742d269ed42..7b8a4d850b8 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -139,6 +139,15 @@ double TransformState::getScale() const { #pragma mark - Bounds +void TransformState::setLatLngBounds(const LatLngBounds& bounds_) { + bounds = bounds_; + setLatLngZoom(getLatLng(LatLng::Unwrapped), getZoom()); +} + +LatLngBounds TransformState::getLatLngBounds() const { + return bounds; +} + void TransformState::setMinZoom(const double minZoom) { if (minZoom <= getMaxZoom()) { min_scale = zoomScale(util::clamp(minZoom, util::MIN_ZOOM, util::MAX_ZOOM)); @@ -321,16 +330,18 @@ void TransformState::moveLatLng(const LatLng& latLng, const ScreenCoordinate& an } void TransformState::setLatLngZoom(const LatLng &latLng, double zoom) { + const LatLng constrained = bounds.constrain(latLng); + double newScale = zoomScale(zoom); const double newWorldSize = newScale * util::tileSize; Bc = newWorldSize / util::DEGREES_MAX; Cc = newWorldSize / util::M2PI; const double m = 1 - 1e-15; - const double f = util::clamp(std::sin(util::DEG2RAD * latLng.latitude), -m, m); + const double f = util::clamp(std::sin(util::DEG2RAD * constrained.latitude), -m, m); ScreenCoordinate point = { - -latLng.longitude * Bc, + -constrained.longitude * Bc, 0.5 * Cc * std::log((1 + f) / (1 - f)), }; setScalePoint(newScale, point); diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index d7691bcb052..2e0ddf5a1d5 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -51,6 +51,8 @@ class TransformState { double getZoomFraction() const; // Bounds + void setLatLngBounds(const LatLngBounds&); + LatLngBounds getLatLngBounds() const; void setMinZoom(double); double getMinZoom() const; void setMaxZoom(double); @@ -80,6 +82,8 @@ class TransformState { bool rotatedNorth() const; void constrain(double& scale, double& x, double& y) const; + LatLngBounds bounds = LatLngBounds::world(); + // Limit the amount of zooming possible on the map. double min_scale = std::pow(2, 0); double max_scale = std::pow(2, 20); diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp index 5bff4ee5efe..68706305dd9 100644 --- a/test/map/transform.test.cpp +++ b/test/map/transform.test.cpp @@ -543,3 +543,42 @@ TEST(Transform, DefaultTransform) { ASSERT_FALSE(transform.resize({ max, max })); testConversions(nullIsland, center); } + +TEST(Transform, LatLngBounds) { + const LatLng nullIsland {}; + const LatLng sanFrancisco { 37.7749, -122.4194 }; + + Transform transform; + transform.resize({ 1000, 1000 }); + transform.setLatLngZoom({ 0, 0 }, transform.getState().getMaxZoom()); + + // Default bounds. + ASSERT_EQ(transform.getState().getLatLngBounds(), LatLngBounds::world()); + ASSERT_EQ(transform.getLatLng(), nullIsland); + + // Invalid bounds. + transform.setLatLngBounds(LatLngBounds::empty()); + ASSERT_EQ(transform.getState().getLatLngBounds(), LatLngBounds::world()); + + transform.setLatLng(sanFrancisco); + ASSERT_EQ(transform.getLatLng(), sanFrancisco); + + // Single location. + transform.setLatLngBounds(LatLngBounds::singleton(sanFrancisco)); + ASSERT_EQ(transform.getLatLng(), sanFrancisco); + + transform.setLatLngBounds(LatLngBounds::hull({ -90.0, -180.0 }, { 0.0, 180.0 })); + transform.setLatLng(sanFrancisco); + ASSERT_EQ(transform.getLatLng().latitude, 0.0); + ASSERT_EQ(transform.getLatLng().longitude, sanFrancisco.longitude); + + transform.setLatLngBounds(LatLngBounds::hull({ -90.0, 0.0 }, { 90.0, 180.0 })); + transform.setLatLng(sanFrancisco); + ASSERT_EQ(transform.getLatLng().latitude, sanFrancisco.latitude); + ASSERT_EQ(transform.getLatLng().longitude, 0.0); + + transform.setLatLngBounds(LatLngBounds::hull({ -90.0, 0.0 }, { 0.0, 180.0 })); + transform.setLatLng(sanFrancisco); + ASSERT_EQ(transform.getLatLng().latitude, 0.0); + ASSERT_EQ(transform.getLatLng().longitude, 0.0); +}