diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-01-15 08:23:10 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-01-18 16:54:57 -0800 |
commit | 143f8a78170065fc46afba1eaf987258e9c9f99b (patch) | |
tree | 854e6e55b5d08b4c524afb30c7f4c6ff2d8d3821 | |
parent | cb126eafe0e9b482162414d0fbbc0ae4d4f3cea9 (diff) | |
download | qtlocation-mapboxgl-143f8a78170065fc46afba1eaf987258e9c9f99b.tar.gz |
[core] Added padding option to CameraOptions
Moved EdgeInsets to geo.hpp so CameraOptions and Transform can refer to it. Added a padding option to CameraOptions that alters the frame of reference for the center option. Added optional padding parameters to LatLng getters and setters.
Working towards #2600.
-rw-r--r-- | include/mbgl/map/camera.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 10 | ||||
-rw-r--r-- | include/mbgl/util/geo.hpp | 34 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 12 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 42 | ||||
-rw-r--r-- | src/mbgl/map/transform.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/util/geo.cpp | 12 | ||||
-rw-r--r-- | test/miscellaneous/transform.cpp | 36 |
8 files changed, 135 insertions, 18 deletions
diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp index 80734b76fd..32ad8f019f 100644 --- a/include/mbgl/map/camera.hpp +++ b/include/mbgl/map/camera.hpp @@ -17,6 +17,10 @@ struct CameraOptions { /** Coordinate at the center of the map. */ mapbox::util::optional<LatLng> center; + /** Padding around the interior of the view that affects the frame of + reference for `center`. */ + mapbox::util::optional<EdgeInsets> padding; + /** Point of reference for `zoom` and `angle`, assuming an origin at the top-left corner of the view. */ mapbox::util::optional<PrecisionPoint> anchor; diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 3e52d57d19..3852bb7b6f 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -34,13 +34,6 @@ namespace util { template <class T> class Thread; } // namespace util -struct EdgeInsets { - double top = 0; - double left = 0; - double bottom = 0; - double right = 0; -}; - class Map : private util::noncopyable { friend class View; @@ -106,8 +99,9 @@ public: // Position void moveBy(const PrecisionPoint&, const Duration& = Duration::zero()); void setLatLng(const LatLng&, const PrecisionPoint&, const Duration& = Duration::zero()); + void setLatLng(const LatLng&, const EdgeInsets&, const Duration& = Duration::zero()); void setLatLng(const LatLng&, const Duration& = Duration::zero()); - LatLng getLatLng() const; + LatLng getLatLng(const EdgeInsets& = {}) const; void resetPosition(); // Scale diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp index e815456f22..db7d9c792e 100644 --- a/include/mbgl/util/geo.hpp +++ b/include/mbgl/util/geo.hpp @@ -108,6 +108,40 @@ enum class NorthOrientation : uint8_t { Leftwards, }; +/// The distance on each side between a rectangle and a rectangle within. +struct EdgeInsets { + double top = 0; ///< Number of pixels inset from the top edge. + double left = 0; ///< Number of pixels inset from the left edge. + double bottom = 0; ///< Number of pixels inset from the bottom edge. + double right = 0; ///< Number of pixels inset from the right edge. + + inline EdgeInsets() {} + + inline EdgeInsets(const double t, const double l, const double b, const double r) + : top(t), left(l), bottom(b), right(r) {} + + inline operator bool() const { + return top || left || bottom || right; + } + + inline void operator+=(const EdgeInsets& o) { + top += o.top; + left += o.left; + bottom += o.bottom; + right += o.right; + } + + inline EdgeInsets operator+(const EdgeInsets& o) const { + return { + top + o.top, left + o.left, bottom + o.bottom, right + o.right, + }; + } + + PrecisionPoint getCenter(uint16_t width, uint16_t height) const; + + void flip(); +}; + } // namespace mbgl #endif diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 50201ff949..f03915c953 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -172,7 +172,11 @@ void Map::moveBy(const PrecisionPoint& point, const Duration& duration) { } void Map::setLatLng(const LatLng& latLng, const Duration& duration) { - transform->setLatLng(latLng, duration); + setLatLng(latLng, EdgeInsets(), duration); +} + +void Map::setLatLng(const LatLng& latLng, const EdgeInsets& padding, const Duration& duration) { + transform->setLatLng(latLng, padding, duration); update(Update::Repaint); } @@ -181,8 +185,8 @@ void Map::setLatLng(const LatLng& latLng, const PrecisionPoint& point, const Dur update(Update::Repaint); } -LatLng Map::getLatLng() const { - return transform->getLatLng(); +LatLng Map::getLatLng(const EdgeInsets& padding) const { + return transform->getLatLng(padding); } void Map::resetPosition() { @@ -259,7 +263,7 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed double scaleY = (getHeight() - padding.top - padding.bottom) / height; double minScale = ::fmin(scaleX, scaleY); double zoom = ::log2(getScale() * minScale); - zoom = ::fmax(::fmin(zoom, getMaxZoom()), getMinZoom()); + zoom = util::clamp(zoom, getMinZoom(), getMaxZoom()); // Calculate the center point of a virtual bounds that is extended in all directions by padding. PrecisionPoint paddedNEPixel = { diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 98b0804482..7596d5d543 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -91,7 +91,12 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim } // Determine endpoints. - const LatLng startLatLng = getLatLng(); + EdgeInsets padding; + if (camera.padding) { + padding = *camera.padding; + } + const LatLng startLatLng = getLatLng(padding); + padding.flip(); const PrecisionPoint startPoint = { state.lngX(startLatLng.longitude), state.latY(startLatLng.latitude), @@ -141,6 +146,10 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim if (pitch != startPitch) { state.pitch = util::interpolate(startPitch, pitch, t); } + + if (padding) { + state.moveLatLng(frameLatLng, padding.getCenter(state.width, state.height)); + } return update; }, duration); } @@ -164,7 +173,12 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima } // Determine endpoints. - const LatLng startLatLng = getLatLng(); + EdgeInsets padding; + if (camera.padding) { + padding = *camera.padding; + } + const LatLng startLatLng = getLatLng(padding); + padding.flip(); const PrecisionPoint startPoint = { state.lngX(startLatLng.longitude), state.latY(startLatLng.latitude), @@ -189,7 +203,8 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima /// 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); + double w0 = std::max(state.width - padding.left - padding.right, + state.height - padding.top - padding.bottom); /// w₁: Final visible span, measured in pixels with respect to the initial /// scale. double w1 = w0 / state.zoomScale(zoom - startZoom); @@ -304,6 +319,10 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima if (pitch != startPitch) { state.pitch = util::interpolate(startPitch, pitch, k); } + + if (padding) { + state.moveLatLng(frameLatLng, padding.getCenter(state.width, state.height)); + } return Update::Zoom; }, duration); } @@ -340,12 +359,19 @@ void Transform::moveBy(const PrecisionPoint& offset, const Duration& duration) { } void Transform::setLatLng(const LatLng& latLng, const Duration& duration) { + setLatLng(latLng, EdgeInsets(), duration); +} + +void Transform::setLatLng(const LatLng& latLng, const EdgeInsets& padding, const Duration& duration) { if (!latLng) { return; } CameraOptions camera; camera.center = latLng; + if (padding) { + camera.padding = padding; + } easeTo(camera, duration); } @@ -381,6 +407,16 @@ void Transform::setLatLngZoom(const LatLng& latLng, double zoom, const Duration& easeTo(camera, duration); } +LatLng Transform::getLatLng(const EdgeInsets& padding) const { + if (padding) { + EdgeInsets flippedPadding = padding; + flippedPadding.flip(); + return state.pointToLatLng(flippedPadding.getCenter(state.width, state.height)); + } else { + return state.getLatLng(); + } +} + #pragma mark - Zoom diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index 6be0558f98..77c03e939d 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -43,9 +43,10 @@ public: top to bottom and from left to right. */ void moveBy(const PrecisionPoint& offset, const Duration& = Duration::zero()); void setLatLng(const LatLng&, const Duration& = Duration::zero()); + void setLatLng(const LatLng&, const EdgeInsets&, const Duration& = Duration::zero()); void setLatLng(const LatLng&, const PrecisionPoint&, const Duration& = Duration::zero()); void setLatLngZoom(const LatLng&, double zoom, const Duration& = Duration::zero()); - LatLng getLatLng() const { return state.getLatLng(); } + LatLng getLatLng(const EdgeInsets& = {}) const; // Zoom diff --git a/src/mbgl/util/geo.cpp b/src/mbgl/util/geo.cpp index e82f4afad2..a0ba44c4a9 100644 --- a/src/mbgl/util/geo.cpp +++ b/src/mbgl/util/geo.cpp @@ -28,4 +28,16 @@ LatLngBounds::LatLngBounds(const TileID& id) ne(TileID{ id.z, id.x + 1, id.y, id.sourceZ }) { } +PrecisionPoint EdgeInsets::getCenter(uint16_t width, uint16_t height) const { + return { + (width - left - right) / 2.0f + left, + (height - top - bottom) / 2.0f + top, + }; +} + +void EdgeInsets::flip() { + std::swap(top, bottom); + std::swap(left, right); +} + } // end namespace mbgl diff --git a/test/miscellaneous/transform.cpp b/test/miscellaneous/transform.cpp index f06fb56f14..4a8b685564 100644 --- a/test/miscellaneous/transform.cpp +++ b/test/miscellaneous/transform.cpp @@ -2,6 +2,7 @@ #include "../fixtures/mock_view.hpp" #include <mbgl/map/transform.hpp> +#include <mbgl/util/geo.hpp> using namespace mbgl; @@ -193,8 +194,7 @@ TEST(Transform, Anchor) { ASSERT_DOUBLE_EQ(10, transform.getZoom()); ASSERT_DOUBLE_EQ(0, transform.getAngle()); - const auto size = view.getSize(); - const PrecisionPoint anchorPoint = { size[0] * 0.8, size[1] * 0.3 }; + const PrecisionPoint anchorPoint = {0, 0}; const LatLng anchorLatLng = transform.getState().pointToLatLng(anchorPoint); transform.setAngle(M_PI_4, anchorPoint); @@ -202,3 +202,35 @@ TEST(Transform, Anchor) { ASSERT_NE(anchorLatLng, transform.getLatLng()); ASSERT_DOUBLE_EQ(anchorLatLng, transform.getState().pointToLatLng(anchorPoint)); } + +TEST(Transform, Padding) { + MockView view; + Transform transform(view, ConstrainMode::HeightOnly); + transform.resize({{ 1000, 1000 }}); + + ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude); + ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude); + + transform.setLatLngZoom({ 10, -100 }, 10); + + const LatLng trueCenter = transform.getLatLng(); + ASSERT_DOUBLE_EQ(10, trueCenter.latitude); + ASSERT_DOUBLE_EQ(-100, trueCenter.longitude); + ASSERT_DOUBLE_EQ(10, transform.getZoom()); + + const LatLng manualShiftedCenter = transform.getState().pointToLatLng({ + 1000.0 / 2.0, + 1000.0 / 4.0, + }); + + EdgeInsets padding; + padding.top = 1000.0 / 2.0; + ASSERT_GT(padding.top, 0); + ASSERT_TRUE(padding); + + const LatLng shiftedCenter = transform.getLatLng(padding); + ASSERT_NE(trueCenter.latitude, shiftedCenter.latitude); + ASSERT_DOUBLE_EQ(trueCenter.longitude, shiftedCenter.longitude); + ASSERT_DOUBLE_EQ(manualShiftedCenter.latitude, shiftedCenter.latitude); + ASSERT_DOUBLE_EQ(manualShiftedCenter.longitude, shiftedCenter.longitude); +} |