[core] Group Map LatLngBounds, min and max zoom methods
Group bounds, minimum and maximum zoom related methods together using the new BoundOptions. v2: Document that getBounds() initializes all optional fields. - Add test for getBounds() on a map with default values.
This commit is contained in:
30
include/mbgl/map/bound_options.hpp
Normal file
30
include/mbgl/map/bound_options.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
* @brief Holds options to limit what parts of a map are visible. All fields are
|
||||
* optional.
|
||||
*/
|
||||
struct BoundOptions {
|
||||
/// Sets the latitude and longitude bounds to which the camera center are constrained
|
||||
BoundOptions& withLatLngBounds(LatLngBounds b) { bounds = b; return *this; }
|
||||
/// Sets the minimum zoom level
|
||||
BoundOptions& withMinZoom(double z) { minZoom = z; return *this; }
|
||||
/// Sets the maximum zoom level
|
||||
BoundOptions& withMaxZoom(double z) { maxZoom = z; return *this; }
|
||||
|
||||
/// Constrain the center of the camera to be within these bounds.
|
||||
optional<LatLngBounds> bounds;
|
||||
|
||||
/// Maximum zoom level allowed.
|
||||
optional<double> maxZoom;
|
||||
|
||||
/// Minimum zoom level allowed.
|
||||
optional<double> minZoom;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/map/bound_options.hpp>
|
||||
#include <mbgl/map/map_observer.hpp>
|
||||
#include <mbgl/map/map_options.hpp>
|
||||
#include <mbgl/map/mode.hpp>
|
||||
@@ -76,13 +77,15 @@ public:
|
||||
CameraOptions cameraForGeometry(const Geometry<double>&, const EdgeInsets&, optional<double> bearing = {}, optional<double> pitch = {}) const;
|
||||
LatLngBounds latLngBoundsForCamera(const CameraOptions&) const;
|
||||
|
||||
// Bounds
|
||||
void setLatLngBounds(LatLngBounds);
|
||||
LatLngBounds getLatLngBounds() const;
|
||||
void setMinZoom(double);
|
||||
double getMinZoom() const;
|
||||
void setMaxZoom(double);
|
||||
double getMaxZoom() const;
|
||||
/// @name Bounds
|
||||
/// @{
|
||||
|
||||
void setBounds(const BoundOptions& options);
|
||||
|
||||
/// Returns the current map bound options. All optional fields in BoundOptions are set.
|
||||
BoundOptions getBounds() const;
|
||||
|
||||
/// @}
|
||||
|
||||
// North Orientation
|
||||
void setNorthOrientation(NorthOrientation);
|
||||
|
||||
@@ -287,11 +287,13 @@ void NativeMapView::setStyleJson(jni::JNIEnv& env, const jni::String& json) {
|
||||
}
|
||||
|
||||
void NativeMapView::setLatLngBounds(jni::JNIEnv& env, const jni::Object<mbgl::android::LatLngBounds>& jBounds) {
|
||||
mbgl::BoundOptions bounds;
|
||||
if (jBounds) {
|
||||
map->setLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds));
|
||||
bounds.withLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds));
|
||||
} else {
|
||||
map->setLatLngBounds(mbgl::LatLngBounds::world());
|
||||
bounds.withLatLngBounds(mbgl::LatLngBounds::world());
|
||||
}
|
||||
map->setBounds(bounds);
|
||||
}
|
||||
|
||||
void NativeMapView::cancelTransitions(jni::JNIEnv&) {
|
||||
@@ -424,19 +426,19 @@ void NativeMapView::resetZoom(jni::JNIEnv&) {
|
||||
}
|
||||
|
||||
void NativeMapView::setMinZoom(jni::JNIEnv&, jni::jdouble zoom) {
|
||||
map->setMinZoom(zoom);
|
||||
map->setBounds(BoundOptions().withMinZoom(zoom));
|
||||
}
|
||||
|
||||
jni::jdouble NativeMapView::getMinZoom(jni::JNIEnv&) {
|
||||
return map->getMinZoom();
|
||||
return *map->getBounds().minZoom;
|
||||
}
|
||||
|
||||
void NativeMapView::setMaxZoom(jni::JNIEnv&, jni::jdouble zoom) {
|
||||
map->setMaxZoom(zoom);
|
||||
map->setBounds(BoundOptions().withMaxZoom(zoom));
|
||||
}
|
||||
|
||||
jni::jdouble NativeMapView::getMaxZoom(jni::JNIEnv&) {
|
||||
return map->getMaxZoom();
|
||||
return *map->getBounds().maxZoom;
|
||||
}
|
||||
|
||||
void NativeMapView::rotateBy(jni::JNIEnv&, jni::jdouble sx, jni::jdouble sy, jni::jdouble ex, jni::jdouble ey, jni::jlong duration) {
|
||||
|
||||
@@ -296,7 +296,7 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
|
||||
mbgl::LatLngBounds bound = bounds[nextBound++];
|
||||
nextBound = nextBound % bounds.size();
|
||||
|
||||
view->map->setLatLngBounds(bound);
|
||||
view->map->setBounds(mbgl::BoundOptions().withLatLngBounds(bound));
|
||||
|
||||
if (bound == mbgl::LatLngBounds::unbounded()) {
|
||||
view->map->removeAnnotation(boundAnnotationID);
|
||||
|
||||
@@ -1661,7 +1661,7 @@ public:
|
||||
newScale += scale / (velocity * duration) * 0.1;
|
||||
}
|
||||
|
||||
if (newScale <= 0 || log2(newScale) < self.mbglMap.getMinZoom())
|
||||
if (newScale <= 0 || log2(newScale) < *self.mbglMap.getBounds().minZoom)
|
||||
{
|
||||
velocity = 0;
|
||||
}
|
||||
@@ -1927,7 +1927,7 @@ public:
|
||||
|
||||
if ( ! self.isZoomEnabled) return;
|
||||
|
||||
if ([self zoomLevel] == self.mbglMap.getMinZoom()) return;
|
||||
if ([self zoomLevel] == *self.mbglMap.getBounds().minZoom) return;
|
||||
|
||||
[self cancelTransitions];
|
||||
|
||||
@@ -1979,7 +1979,7 @@ public:
|
||||
{
|
||||
CGFloat distance = [quickZoom locationInView:quickZoom.view].y - self.quickZoomStart;
|
||||
|
||||
CGFloat newZoom = MAX(log2f(self.scale) + (distance / 75), self.mbglMap.getMinZoom());
|
||||
CGFloat newZoom = MAX(log2f(self.scale) + (distance / 75), *self.mbglMap.getBounds().minZoom);
|
||||
|
||||
if ([self zoomLevel] == newZoom) return;
|
||||
|
||||
@@ -3251,23 +3251,23 @@ public:
|
||||
- (void)setMinimumZoomLevel:(double)minimumZoomLevel
|
||||
{
|
||||
MGLLogDebug(@"Setting minimumZoomLevel: %f", minimumZoomLevel);
|
||||
self.mbglMap.setMinZoom(minimumZoomLevel);
|
||||
self.mbglMap.setBounds(mbgl::BoundOptions().withMinZoom(minimumZoomLevel));
|
||||
}
|
||||
|
||||
- (double)minimumZoomLevel
|
||||
{
|
||||
return self.mbglMap.getMinZoom();
|
||||
return *self.mbglMap.getBounds().minZoom;
|
||||
}
|
||||
|
||||
- (void)setMaximumZoomLevel:(double)maximumZoomLevel
|
||||
{
|
||||
MGLLogDebug(@"Setting maximumZoomLevel: %f", maximumZoomLevel);
|
||||
self.mbglMap.setMaxZoom(maximumZoomLevel);
|
||||
self.mbglMap.setBounds(mbgl::BoundOptions().withMaxZoom(maximumZoomLevel));
|
||||
}
|
||||
|
||||
- (double)maximumZoomLevel
|
||||
{
|
||||
return self.mbglMap.getMaxZoom();
|
||||
return *self.mbglMap.getBounds().maxZoom;
|
||||
}
|
||||
|
||||
- (MGLCoordinateBounds)visibleCoordinateBounds
|
||||
@@ -5847,7 +5847,7 @@ public:
|
||||
|
||||
- (CGFloat)currentMinimumZoom
|
||||
{
|
||||
return fmaxf(self.mbglMap.getMinZoom(), MGLMinimumZoom);
|
||||
return fmaxf(*self.mbglMap.getBounds().minZoom, MGLMinimumZoom);
|
||||
}
|
||||
|
||||
- (BOOL)isRotationAllowed
|
||||
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
mbgl::CameraOptions options;
|
||||
options.center = mbgl::LatLng(0, 0);
|
||||
options.padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
|
||||
options.zoom = _mbglMap->getMinZoom();
|
||||
options.zoom = *_mbglMap->getBounds().minZoom;
|
||||
_mbglMap->jumpTo(options);
|
||||
_pendingLatitude = NAN;
|
||||
_pendingLongitude = NAN;
|
||||
@@ -1094,21 +1094,21 @@ public:
|
||||
- (void)setMinimumZoomLevel:(double)minimumZoomLevel
|
||||
{
|
||||
MGLLogDebug(@"Setting minimumZoomLevel: %f", minimumZoomLevel);
|
||||
_mbglMap->setMinZoom(minimumZoomLevel);
|
||||
_mbglMap->setBounds(mbgl::BoundOptions().withMinZoom(minimumZoomLevel));
|
||||
}
|
||||
|
||||
- (void)setMaximumZoomLevel:(double)maximumZoomLevel
|
||||
{
|
||||
MGLLogDebug(@"Setting maximumZoomLevel: %f", maximumZoomLevel);
|
||||
_mbglMap->setMaxZoom(maximumZoomLevel);
|
||||
_mbglMap->setBounds(mbgl::BoundOptions().withMaxZoom(maximumZoomLevel));
|
||||
}
|
||||
|
||||
- (double)maximumZoomLevel {
|
||||
return _mbglMap->getMaxZoom();
|
||||
return *_mbglMap->getBounds().maxZoom;
|
||||
}
|
||||
|
||||
- (double)minimumZoomLevel {
|
||||
return _mbglMap->getMinZoom();
|
||||
return *_mbglMap->getBounds().minZoom;
|
||||
}
|
||||
|
||||
/// Respond to a click on the zoom control.
|
||||
|
||||
@@ -765,7 +765,7 @@ void QMapboxGL::setZoom(double zoom_)
|
||||
*/
|
||||
double QMapboxGL::minimumZoom() const
|
||||
{
|
||||
return d_ptr->mapObj->getMinZoom();
|
||||
return *d_ptr->mapObj->getBounds().minZoom;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -775,7 +775,7 @@ double QMapboxGL::minimumZoom() const
|
||||
*/
|
||||
double QMapboxGL::maximumZoom() const
|
||||
{
|
||||
return d_ptr->mapObj->getMaxZoom();
|
||||
return *d_ptr->mapObj->getBounds().maxZoom;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -328,6 +328,7 @@
|
||||
"mbgl/layermanager/line_layer_factory.hpp": "include/mbgl/layermanager/line_layer_factory.hpp",
|
||||
"mbgl/layermanager/raster_layer_factory.hpp": "include/mbgl/layermanager/raster_layer_factory.hpp",
|
||||
"mbgl/layermanager/symbol_layer_factory.hpp": "include/mbgl/layermanager/symbol_layer_factory.hpp",
|
||||
"mbgl/map/bound_options.hpp": "include/mbgl/map/bound_options.hpp",
|
||||
"mbgl/map/camera.hpp": "include/mbgl/map/camera.hpp",
|
||||
"mbgl/map/change.hpp": "include/mbgl/map/change.hpp",
|
||||
"mbgl/map/map.hpp": "include/mbgl/map/map.hpp",
|
||||
|
||||
@@ -275,36 +275,41 @@ LatLngBounds Map::latLngBoundsForCamera(const CameraOptions& camera) const {
|
||||
|
||||
#pragma mark - Bounds
|
||||
|
||||
LatLngBounds Map::getLatLngBounds() const {
|
||||
return impl->transform.getState().getLatLngBounds();
|
||||
}
|
||||
void Map::setBounds(const BoundOptions& options) {
|
||||
bool changeCamera = false;
|
||||
CameraOptions cameraOptions;
|
||||
|
||||
void Map::setLatLngBounds(LatLngBounds bounds) {
|
||||
impl->cameraMutated = true;
|
||||
impl->transform.setLatLngBounds(std::move(bounds));
|
||||
impl->onUpdate();
|
||||
}
|
||||
if (options.bounds) {
|
||||
changeCamera = true;
|
||||
impl->transform.setLatLngBounds(*options.bounds);
|
||||
}
|
||||
|
||||
void Map::setMinZoom(const double minZoom) {
|
||||
impl->transform.setMinZoom(minZoom);
|
||||
if (impl->transform.getZoom() < minZoom) {
|
||||
jumpTo(CameraOptions().withZoom(minZoom));
|
||||
if (options.minZoom) {
|
||||
impl->transform.setMinZoom(*options.minZoom);
|
||||
if (impl->transform.getZoom() < *options.minZoom) {
|
||||
changeCamera = true;
|
||||
cameraOptions.withZoom(*options.minZoom);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.maxZoom) {
|
||||
impl->transform.setMaxZoom(*options.maxZoom);
|
||||
if (impl->transform.getZoom() > *options.maxZoom) {
|
||||
changeCamera = true;
|
||||
cameraOptions.withZoom(*options.maxZoom);
|
||||
}
|
||||
}
|
||||
|
||||
if (changeCamera) {
|
||||
jumpTo(cameraOptions);
|
||||
}
|
||||
}
|
||||
|
||||
double Map::getMinZoom() const {
|
||||
return impl->transform.getState().getMinZoom();
|
||||
}
|
||||
|
||||
void Map::setMaxZoom(const double maxZoom) {
|
||||
impl->transform.setMaxZoom(maxZoom);
|
||||
if (impl->transform.getZoom() > maxZoom) {
|
||||
jumpTo(CameraOptions().withZoom(maxZoom));
|
||||
}
|
||||
}
|
||||
|
||||
double Map::getMaxZoom() const {
|
||||
return impl->transform.getState().getMaxZoom();
|
||||
BoundOptions Map::getBounds() const {
|
||||
return BoundOptions()
|
||||
.withLatLngBounds(impl->transform.getState().getLatLngBounds())
|
||||
.withMinZoom(impl->transform.getState().getMinZoom())
|
||||
.withMaxZoom(impl->transform.getState().getMaxZoom());
|
||||
}
|
||||
|
||||
#pragma mark - Size
|
||||
|
||||
@@ -85,7 +85,7 @@ TEST(Annotations, LineAnnotation) {
|
||||
test.map.addAnnotation(annotation);
|
||||
test.checkRendering("line_annotation");
|
||||
|
||||
test.map.jumpTo(CameraOptions().withZoom(test.map.getMaxZoom()));
|
||||
test.map.jumpTo(CameraOptions().withZoom(*test.map.getBounds().maxZoom));
|
||||
test.checkRendering("line_annotation_max_zoom");
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ TEST(Annotations, FillAnnotation) {
|
||||
test.map.addAnnotation(annotation);
|
||||
test.checkRendering("fill_annotation");
|
||||
|
||||
test.map.jumpTo(CameraOptions().withZoom(test.map.getMaxZoom()));
|
||||
test.map.jumpTo(CameraOptions().withZoom(*test.map.getBounds().maxZoom));
|
||||
test.checkRendering("fill_annotation_max_zoom");
|
||||
}
|
||||
|
||||
@@ -481,11 +481,11 @@ TEST(Annotations, ChangeMaxZoom) {
|
||||
annotation.color = Color::red();
|
||||
annotation.width = { 5 };
|
||||
|
||||
test.map.setMaxZoom(6);
|
||||
test.map.setBounds(BoundOptions().withMaxZoom(6));
|
||||
test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
|
||||
test.map.addAnnotation(annotation);
|
||||
test.map.setMaxZoom(14);
|
||||
test.map.jumpTo(CameraOptions().withZoom(test.map.getMaxZoom()));
|
||||
test.map.setBounds(BoundOptions().withMaxZoom(14));
|
||||
test.map.jumpTo(CameraOptions().withZoom(*test.map.getBounds().maxZoom));
|
||||
test.checkRendering("line_annotation_max_zoom");
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,32 @@ TEST(Map, ProjectionMode) {
|
||||
EXPECT_EQ(*options.ySkew, 0.0);
|
||||
}
|
||||
|
||||
TEST(Map, BoundOptions) {
|
||||
MapTest<> test;
|
||||
|
||||
LatLngBounds llb = LatLngBounds::hull({-10, -10}, {10, 10});
|
||||
test.map.setBounds(BoundOptions().withMinZoom(4).withMaxZoom(10).withLatLngBounds(llb));
|
||||
auto bounds = test.map.getBounds();
|
||||
|
||||
EXPECT_EQ(*bounds.minZoom, 4);
|
||||
EXPECT_EQ(*bounds.maxZoom, 10);
|
||||
EXPECT_EQ(*bounds.bounds, llb);
|
||||
}
|
||||
|
||||
TEST(Map, DefaultBoundOptions) {
|
||||
MapTest<> test;
|
||||
|
||||
auto bounds = test.map.getBounds();
|
||||
|
||||
EXPECT_TRUE(bounds.minZoom);
|
||||
EXPECT_TRUE(bounds.maxZoom);
|
||||
EXPECT_TRUE(bounds.bounds);
|
||||
|
||||
EXPECT_EQ(*bounds.minZoom, util::MIN_ZOOM);
|
||||
EXPECT_EQ(*bounds.maxZoom, util::DEFAULT_MAX_ZOOM);
|
||||
EXPECT_EQ(*bounds.bounds, LatLngBounds::unbounded());
|
||||
}
|
||||
|
||||
TEST(Map, SetStyleInvalidJSON) {
|
||||
Log::setObserver(std::make_unique<FixtureLogObserver>());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user