Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] Added padding option to CameraOptions
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
1ec5 committed Jan 15, 2016
1 parent a88e58e commit eaeef95
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 16 deletions.
4 changes: 4 additions & 0 deletions include/mbgl/map/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 2 additions & 8 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -106,8 +99,9 @@ class Map : private util::noncopyable {
// 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
Expand Down
29 changes: 29 additions & 0 deletions include/mbgl/util/geo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,35 @@ 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 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
12 changes: 8 additions & 4 deletions src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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() {
Expand Down Expand Up @@ -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 = {
Expand Down
40 changes: 39 additions & 1 deletion src/mbgl/map/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
state.latY(latLng.latitude),
};

EdgeInsets padding;
if (camera.padding) {
padding = *camera.padding;
padding.flip();
}

// Constrain camera options.
zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom());
const double scale = state.zoomScale(zoom);
Expand Down Expand Up @@ -141,6 +147,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);
}
Expand Down Expand Up @@ -175,6 +185,12 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
state.latY(latLng.latitude),
};

EdgeInsets padding;
if (camera.padding) {
padding = *camera.padding;
padding.flip();
}

// Constrain camera options.
zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom());
pitch = util::clamp(pitch, 0., util::PITCH_MAX);
Expand All @@ -189,7 +205,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);
Expand Down Expand Up @@ -304,6 +321,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);
}
Expand Down Expand Up @@ -340,12 +361,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);
}

Expand Down Expand Up @@ -381,6 +409,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

Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/map/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ class Transform : private util::noncopyable {
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

Expand Down
12 changes: 12 additions & 0 deletions src/mbgl/util/geo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

This comment has been minimized.

Copy link
@tmpsantos

tmpsantos Jan 18, 2016

Contributor

Do we need to flip the horizontal margins? On my tests the results seemed horizontally mirrored.

This comment has been minimized.

Copy link
@1ec5

1ec5 Jan 18, 2016

Author Contributor

Hm, it looks like I’m using flip() for two different things: this call is only intended to flip the origin from the bottom-left to the top-left, but all the other call sites are using it to apply a negative offset.

This comment has been minimized.

Copy link
@1ec5

1ec5 Jan 19, 2016

Author Contributor

Fixed in dc97d3f21c22ffae749f9307cb2aa5e87e492e4b.

}

} // end namespace mbgl
36 changes: 34 additions & 2 deletions test/miscellaneous/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "../fixtures/mock_view.hpp"

#include <mbgl/map/transform.hpp>
#include <mbgl/util/geo.hpp>

using namespace mbgl;

Expand Down Expand Up @@ -193,12 +194,43 @@ 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);

ASSERT_NEAR(M_PI_4, transform.getAngle(), 0.000001);
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);
}

0 comments on commit eaeef95

Please sign in to comment.