diff options
author | Bobby Sudekum <bobby@mapbox.com> | 2018-07-02 16:30:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-02 16:30:18 -0700 |
commit | 4286d5869c9af0513298b8b31d36744a3243bff4 (patch) | |
tree | 8db8172a0bc9320fb79d9060bddede7cca7ee1b3 | |
parent | 29e25356e355d466a60297117f3e7c010825a7ff (diff) | |
download | qtlocation-mapboxgl-4286d5869c9af0513298b8b31d36744a3243bff4.tar.gz |
Add pitch argument to cameraThatFits functions (#12213)
-rw-r--r-- | include/mbgl/map/map.hpp | 6 | ||||
-rw-r--r-- | platform/ios/CHANGELOG.md | 4 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.h | 31 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 31 | ||||
-rw-r--r-- | platform/macos/CHANGELOG.md | 4 | ||||
-rw-r--r-- | platform/macos/src/MGLMapView.h | 31 | ||||
-rw-r--r-- | platform/macos/src/MGLMapView.mm | 26 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 37 | ||||
-rw-r--r-- | test/map/map.test.cpp | 32 |
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; |