summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby Sudekum <bobby@mapbox.com>2018-07-02 16:30:18 -0700
committerGitHub <noreply@github.com>2018-07-02 16:30:18 -0700
commit4286d5869c9af0513298b8b31d36744a3243bff4 (patch)
tree8db8172a0bc9320fb79d9060bddede7cca7ee1b3
parent29e25356e355d466a60297117f3e7c010825a7ff (diff)
downloadqtlocation-mapboxgl-4286d5869c9af0513298b8b31d36744a3243bff4.tar.gz
Add pitch argument to cameraThatFits functions (#12213)
-rw-r--r--include/mbgl/map/map.hpp6
-rw-r--r--platform/ios/CHANGELOG.md4
-rw-r--r--platform/ios/src/MGLMapView.h31
-rw-r--r--platform/ios/src/MGLMapView.mm31
-rw-r--r--platform/macos/CHANGELOG.md4
-rw-r--r--platform/macos/src/MGLMapView.h31
-rw-r--r--platform/macos/src/MGLMapView.mm26
-rw-r--r--src/mbgl/map/map.cpp37
-rw-r--r--test/map/map.test.cpp32
9 files changed, 181 insertions, 21 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 5ba23a76dd..3aee932070 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -67,9 +67,9 @@ public:
void jumpTo(const CameraOptions&);
void easeTo(const CameraOptions&, const AnimationOptions&);
void flyTo(const CameraOptions&, const AnimationOptions&);
- CameraOptions cameraForLatLngBounds(const LatLngBounds&, const EdgeInsets&, optional<double> bearing = {}) const;
- CameraOptions cameraForLatLngs(const std::vector<LatLng>&, const EdgeInsets&, optional<double> bearing = {}) const;
- CameraOptions cameraForGeometry(const Geometry<double>&, const EdgeInsets&, optional<double> bearing = {}) const;
+ CameraOptions cameraForLatLngBounds(const LatLngBounds&, const EdgeInsets&, optional<double> bearing = {}, optional<double> pitch = {}) const;
+ CameraOptions cameraForLatLngs(const std::vector<LatLng>&, const EdgeInsets&, optional<double> bearing = {}, optional<double> pitch = {}) const;
+ CameraOptions cameraForGeometry(const Geometry<double>&, const EdgeInsets&, optional<double> bearing = {}, optional<double> pitch = {}) const;
LatLngBounds latLngBoundsForCamera(const CameraOptions&) const;
// Position
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index c49dc4381f..9b377913de 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,6 +2,10 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
+# master
+
+* Added `-[MGLMapView camera:fittingShape:edgePadding:]` and `-[MGLMapView camera:fittingCoordinateBounds:edgePadding:]` allowing you specify the pitch and direction for the calculated camera. ([#12213](https://github.com/mapbox/mapbox-gl-native/pull/12213))
+
## 4.2.0
### Packaging
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index fd0ca19b26..04a7a06313 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -927,6 +927,37 @@ MGL_EXPORT IB_DESIGNABLE
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
/**
+ Returns the camera that best fits the given coordinate bounds, with the specified camera,
+ optionally with some additional padding on each side.
+
+ @param camera The camera that the return camera should adhere to. All values
+ on this camera will be manipulated except for pitch and direction.
+ @param bounds The coordinate bounds to fit to the receiver’s viewport.
+ @param insets The minimum padding (in screen points) that would be visible
+ around the returned camera object if it were set as the receiver’s camera.
+ @return A camera object centered on the same location as the coordinate bounds
+ with zoom level as high (close to the ground) as possible while still
+ including the entire coordinate bounds. The initial camera's pitch and
+ direction will be honored.
+ */
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
+
+/**
+ Returns the camera that best fits the given shape, with the specified camera,
+ optionally with some additional padding on each side.
+
+ @param camera The camera that the return camera should adhere to. All values
+ on this camera will be manipulated except for pitch and direction.
+ @param shape The shape to fit to the receiver’s viewport.
+ @param insets The minimum padding (in screen points) that would be visible
+ around the returned camera object if it were set as the receiver’s camera.
+ @return A camera object centered on the shape's center with zoom level as high
+ (close to the ground) as possible while still including the entire shape. The
+ initial camera's pitch and direction will be honored.
+ */
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingShape:(MGLShape *)shape edgePadding:(UIEdgeInsets)insets;
+
+/**
Returns the camera that best fits the given shape, with the specified direction,
optionally with some additional padding on each side.
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 7003f2e4b4..1bbda94387 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -3348,14 +3348,39 @@ public:
return [self cameraForCameraOptions:cameraOptions];
}
-- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape direction:(CLLocationDirection)direction edgePadding:(UIEdgeInsets)insets {
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets
+{
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
+
+ MGLMapCamera *currentCamera = self.camera;
+ CGFloat pitch = camera.pitch < 0 ? currentCamera.pitch : camera.pitch;
+ CLLocationDirection direction = camera.heading < 0 ? currentCamera.heading : camera.heading;
+
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), padding, direction, pitch);
+ return [self cameraForCameraOptions:cameraOptions];
+}
- mbgl::CameraOptions cameraOptions = _mbglMap->cameraForGeometry([shape geometryObject], padding, direction);
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingShape:(MGLShape *)shape edgePadding:(UIEdgeInsets)insets {
+ mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
+ padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
+
+ MGLMapCamera *currentCamera = self.camera;
+ CGFloat pitch = camera.pitch < 0 ? currentCamera.pitch : camera.pitch;
+ CLLocationDirection direction = camera.heading < 0 ? currentCamera.heading : camera.heading;
+
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForGeometry([shape geometryObject], padding, direction, pitch);
+
+ return [self cameraForCameraOptions: cameraOptions];
+}
+- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape direction:(CLLocationDirection)direction edgePadding:(UIEdgeInsets)insets {
+ mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
+ padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
+
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForGeometry([shape geometryObject], padding, direction);
+
return [self cameraForCameraOptions:cameraOptions];
-
}
- (MGLMapCamera *)cameraForCameraOptions:(const mbgl::CameraOptions &)cameraOptions
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 7767185c4e..f084552b68 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog for Mapbox Maps SDK for macOS
+# master
+
+* Added `-[MGLMapView camera:fittingShape:edgePadding:]` and `-[MGLMapView camera:fittingCoordinateBounds:edgePadding:]` allowing you specify the pitch and direction for the calculated camera. ([#12213](https://github.com/mapbox/mapbox-gl-native/pull/12213))
+
## 0.7.2 - June 22, 2018
* Fixed a crash in `-[MGLStyle localizeLabelsIntoLocale:]` on macOS 10.11. ([#12123](https://github.com/mapbox/mapbox-gl-native/pull/12123))
diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h
index 824df827ac..305a1348e4 100644
--- a/platform/macos/src/MGLMapView.h
+++ b/platform/macos/src/MGLMapView.h
@@ -486,6 +486,37 @@ MGL_EXPORT IB_DESIGNABLE
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets;
/**
+ Returns the camera that best fits the given coordinate bounds, with the specified camera,
+ optionally with some additional padding on each side.
+
+ @param camera The camera that the return camera should adhere to. All values
+ on this camera will be manipulated except for pitch and direction.
+ @param bounds The coordinate bounds to fit to the receiver’s viewport.
+ @param insets The minimum padding (in screen points) that would be visible
+ around the returned camera object if it were set as the receiver’s camera.
+ @return A camera object centered on the same location as the coordinate bounds
+ with zoom level as high (close to the ground) as possible while still
+ including the entire coordinate bounds. The initial camera's pitch and
+ direction will be honored.
+ */
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets;
+
+/**
+ Returns the camera that best fits the given shape, with the specified camera,
+ optionally with some additional padding on each side.
+
+ @param camera The camera that the return camera should adhere to. All values
+ on this camera will be manipulated except for pitch and direction.
+ @param shape The shape to fit to the receiver’s viewport.
+ @param insets The minimum padding (in screen points) that would be visible
+ around the returned camera object if it were set as the receiver’s camera.
+ @return A camera object centered on the shape's center with zoom level as high
+ (close to the ground) as possible while still including the entire shape. The
+ initial camera's pitch and direction will be honored.
+ */
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingShape:(MGLShape *)shape edgePadding:(NSEdgeInsets)insets;
+
+/**
Returns the camera that best fits the given shape, with the specified direction,
optionally with some additional padding on each side.
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index bc9ac1e641..154b716377 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -1275,6 +1275,32 @@ public:
return [self cameraForCameraOptions:cameraOptions];
}
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets
+{
+ mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
+ padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
+
+ MGLMapCamera *currentCamera = self.camera;
+ CGFloat pitch = camera.pitch < 0 ? currentCamera.pitch : camera.pitch;
+ CLLocationDirection direction = camera.heading < 0 ? currentCamera.heading : camera.heading;
+
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), padding, direction, pitch);
+ return [self cameraForCameraOptions:cameraOptions];
+}
+
+- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingShape:(MGLShape *)shape edgePadding:(NSEdgeInsets)insets {
+ mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
+ padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
+
+ MGLMapCamera *currentCamera = self.camera;
+ CGFloat pitch = camera.pitch < 0 ? currentCamera.pitch : camera.pitch;
+ CLLocationDirection direction = camera.heading < 0 ? currentCamera.heading : camera.heading;
+
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForGeometry([shape geometryObject], padding, direction, pitch);
+
+ return [self cameraForCameraOptions: cameraOptions];
+}
+
- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape direction:(CLLocationDirection)direction edgePadding:(NSEdgeInsets)insets {
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index ea35560e97..c177299485 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -364,13 +364,13 @@ void Map::setLatLngZoom(const LatLng& latLng, double zoom, const EdgeInsets& pad
impl->onUpdate();
}
-CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding, optional<double> bearing) const {
+CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding, optional<double> bearing, optional<double> pitch) const {
return cameraForLatLngs({
bounds.northwest(),
bounds.southwest(),
bounds.southeast(),
bounds.northeast(),
- }, padding, bearing);
+ }, padding, bearing, pitch);
}
CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs, const Transform& transform, const EdgeInsets& padding) {
@@ -426,26 +426,37 @@ CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs, const Transfo
return options;
}
-CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const EdgeInsets& padding, optional<double> bearing) const {
- if(bearing) {
- double angle = -*bearing * util::DEG2RAD; // Convert to radians
- Transform transform(impl->transform.getState());
- transform.setAngle(angle);
- CameraOptions options = mbgl::cameraForLatLngs(latLngs, transform, padding);
- options.angle = angle;
- return options;
- } else {
+CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const EdgeInsets& padding, optional<double> bearing, optional<double> pitch) const {
+
+ if (!bearing && !pitch) {
return mbgl::cameraForLatLngs(latLngs, impl->transform, padding);
}
+
+ Transform transform(impl->transform.getState());
+
+ if (bearing) {
+ double angle = -*bearing * util::DEG2RAD; // Convert to radians
+ transform.setAngle(angle);
+ }
+ if (pitch) {
+ double pitchAsRadian = *pitch * util::DEG2RAD; // Convert to radians
+ transform.setPitch(pitchAsRadian);
+ }
+
+ CameraOptions options = mbgl::cameraForLatLngs(latLngs, transform, padding);
+ options.angle = transform.getAngle();
+ options.pitch = transform.getPitch();
+
+ return options;
}
-CameraOptions Map::cameraForGeometry(const Geometry<double>& geometry, const EdgeInsets& padding, optional<double> bearing) const {
+CameraOptions Map::cameraForGeometry(const Geometry<double>& geometry, const EdgeInsets& padding, optional<double> bearing, optional<double> pitch) const {
std::vector<LatLng> latLngs;
forEachPoint(geometry, [&](const Point<double>& pt) {
latLngs.push_back({ pt.y, pt.x });
});
- return cameraForLatLngs(latLngs, padding, bearing);
+ return cameraForLatLngs(latLngs, padding, bearing, pitch);
}
LatLngBounds Map::latLngBoundsForCamera(const CameraOptions& camera) const {
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp
index f95e26fd82..4f7bd2df7b 100644
--- a/test/map/map.test.cpp
+++ b/test/map/map.test.cpp
@@ -84,7 +84,21 @@ TEST(Map, LatLngBoundsToCameraWithAngle) {
CameraOptions virtualCamera = test.map.cameraForLatLngBounds(bounds, {}, 35);
ASSERT_TRUE(bounds.contains(*virtualCamera.center));
EXPECT_NEAR(*virtualCamera.zoom, 1.21385, 1e-5);
- EXPECT_DOUBLE_EQ(virtualCamera.angle.value_or(0), -35 * util::DEG2RAD);
+ EXPECT_NEAR(virtualCamera.angle.value_or(0), -35 * util::DEG2RAD, 1e-5);
+}
+
+TEST(Map, LatLngBoundsToCameraWithAngleAndPitch) {
+ MapTest<> test;
+
+ test.map.setLatLngZoom({ 40.712730, -74.005953 }, 16.0);
+
+ LatLngBounds bounds = LatLngBounds::hull({15.68169,73.499857}, {53.560711, 134.77281});
+
+ CameraOptions virtualCamera = test.map.cameraForLatLngBounds(bounds, {}, 35, 20);
+ ASSERT_TRUE(bounds.contains(*virtualCamera.center));
+ EXPECT_NEAR(*virtualCamera.zoom, 13.66272, 1e-5);
+ ASSERT_DOUBLE_EQ(*virtualCamera.pitch, 20 * util::DEG2RAD);
+ EXPECT_NEAR(virtualCamera.angle.value_or(0), -35 * util::DEG2RAD, 1e-5);
}
TEST(Map, LatLngsToCamera) {
@@ -93,12 +107,26 @@ TEST(Map, LatLngsToCamera) {
std::vector<LatLng> latLngs{{ 40.712730, 74.005953 }, {15.68169,73.499857}, {30.82678, 83.4082}};
CameraOptions virtualCamera = test.map.cameraForLatLngs(latLngs, {}, 23);
- EXPECT_DOUBLE_EQ(virtualCamera.angle.value_or(0), -23 * util::DEG2RAD);
+ EXPECT_NEAR(virtualCamera.angle.value_or(0), -23 * util::DEG2RAD, 1e-5);
EXPECT_NEAR(virtualCamera.zoom.value_or(0), 2.75434, 1e-5);
EXPECT_NEAR(virtualCamera.center->latitude(), 28.49288, 1e-5);
EXPECT_NEAR(virtualCamera.center->longitude(), 74.97437, 1e-5);
}
+TEST(Map, LatLngsToCameraWithAngleAndPitch) {
+ MapTest<> test;
+
+ std::vector<LatLng> latLngs{{ 40.712730, 74.005953 }, {15.68169,73.499857}, {30.82678, 83.4082}};
+
+ CameraOptions virtualCamera = test.map.cameraForLatLngs(latLngs, {}, 23, 20);
+ EXPECT_NEAR(virtualCamera.angle.value_or(0), -23 * util::DEG2RAD, 1e-5);
+ EXPECT_NEAR(virtualCamera.zoom.value_or(0), 3.04378, 1e-5);
+ EXPECT_NEAR(virtualCamera.center->latitude(), 28.53718, 1e-5);
+ EXPECT_NEAR(virtualCamera.center->longitude(), 74.31746, 1e-5);
+ ASSERT_DOUBLE_EQ(*virtualCamera.pitch, 20 * util::DEG2RAD);
+}
+
+
TEST(Map, CameraToLatLngBounds) {
MapTest<> test;