summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/map/camera.hpp4
-rw-r--r--include/mbgl/map/map.hpp10
-rw-r--r--include/mbgl/util/geo.hpp34
-rw-r--r--src/mbgl/map/map.cpp12
-rw-r--r--src/mbgl/map/transform.cpp42
-rw-r--r--src/mbgl/map/transform.hpp3
-rw-r--r--src/mbgl/util/geo.cpp12
-rw-r--r--test/miscellaneous/transform.cpp36
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);
+}