[core] Add cameraForLatLngs() method with modified bearing

This commit is contained in:
Asheem Mamoowala
2017-10-02 13:42:26 -07:00
parent 9048d6cfd0
commit df20b0cbec
4 changed files with 71 additions and 14 deletions

View File

@@ -8,6 +8,7 @@
#include <mbgl/util/size.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/util/geometry.hpp>
#include <cstdint>
#include <string>
@@ -66,6 +67,10 @@ 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;
LatLngBounds latLngBoundsForCamera(const CameraOptions&) const;
// Position
void moveBy(const ScreenCoordinate&, const AnimationOptions& = {});
@@ -82,9 +87,6 @@ public:
double getZoom() const;
void setLatLngZoom(const LatLng&, double zoom, const AnimationOptions& = {});
void setLatLngZoom(const LatLng&, double zoom, const EdgeInsets&, const AnimationOptions& = {});
CameraOptions cameraForLatLngBounds(const LatLngBounds&, const EdgeInsets&) const;
CameraOptions cameraForLatLngs(const std::vector<LatLng>&, const EdgeInsets&) const;
LatLngBounds latLngBoundsForCamera(const CameraOptions&) const;
void resetZoom();
// Bounds

View File

@@ -2,6 +2,7 @@
#include <mapbox/geometry/geometry.hpp>
#include <mapbox/geometry/point_arithmetic.hpp>
#include <mapbox/geometry/for_each_point.hpp>
namespace mbgl {
@@ -58,4 +59,9 @@ struct ToFeatureType {
FeatureType operator()(const mapbox::geometry::geometry_collection<T> &) const { return FeatureType::Unknown; }
};
template <class T, typename F>
auto forEachPoint(const Geometry<T>& g, F f) {
mapbox::geometry::for_each_point(g, f);
}
} // namespace mbgl

View File

@@ -364,27 +364,27 @@ void Map::setLatLngZoom(const LatLng& latLng, double zoom, const EdgeInsets& pad
impl->onUpdate();
}
CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding) const {
CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding, optional<double> bearing) const {
return cameraForLatLngs({
bounds.northwest(),
bounds.southwest(),
bounds.southeast(),
bounds.northeast(),
}, padding);
}, padding, bearing);
}
CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const EdgeInsets& padding) const {
CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs, const Transform& transform, const EdgeInsets& padding) {
CameraOptions options;
if (latLngs.empty()) {
return options;
}
Size size = transform.getState().getSize();
// Calculate the bounds of the possibly rotated shape with respect to the viewport.
ScreenCoordinate nePixel = {-INFINITY, -INFINITY};
ScreenCoordinate swPixel = {INFINITY, INFINITY};
double viewportHeight = getSize().height;
double viewportHeight = size.height;
for (LatLng latLng : latLngs) {
ScreenCoordinate pixel = impl->transform.latLngToScreenCoordinate(latLng);
ScreenCoordinate pixel = transform.latLngToScreenCoordinate(latLng);
swPixel.x = std::min(swPixel.x, pixel.x);
nePixel.x = std::max(nePixel.x, pixel.x);
swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y);
@@ -396,14 +396,14 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed
// Calculate the zoom level.
double minScale = INFINITY;
if (width > 0 || height > 0) {
double scaleX = double(getSize().width) / width;
double scaleY = double(getSize().height) / height;
double scaleX = double(size.width) / width;
double scaleY = double(size.height) / height;
scaleX -= (padding.left() + padding.right()) / width;
scaleY -= (padding.top() + padding.bottom()) / height;
minScale = util::min(scaleX, scaleY);
}
double zoom = getZoom() + util::log2(minScale);
zoom = util::clamp(zoom, getMinZoom(), getMaxZoom());
double zoom = transform.getZoom() + util::log2(minScale);
zoom = util::clamp(zoom, transform.getState().getMinZoom(), transform.getState().getMaxZoom());
// Calculate the center point of a virtual bounds that is extended in all directions by padding.
ScreenCoordinate centerPixel = nePixel + swPixel;
@@ -421,11 +421,34 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed
// CameraOptions origin is at the top-left corner.
centerPixel.y = viewportHeight - centerPixel.y;
options.center = latLngForPixel(centerPixel);
options.center = transform.screenCoordinateToLatLng(centerPixel);
options.zoom = zoom;
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 {
return mbgl::cameraForLatLngs(latLngs, impl->transform, padding);
}
}
CameraOptions Map::cameraForGeometry(const Geometry<double>& geometry, const EdgeInsets& padding, optional<double> bearing) const {
std::vector<LatLng> latLngs;
forEachPoint(geometry, [&](const Point<double>& pt) {
latLngs.push_back({ pt.y, pt.x });
});
return cameraForLatLngs(latLngs, padding, bearing);
}
LatLngBounds Map::latLngBoundsForCamera(const CameraOptions& camera) const {
Transform shallow { impl->transform.getState() };
Size size = shallow.getState().getSize();

View File

@@ -109,6 +109,32 @@ TEST(Map, LatLngBoundsToCamera) {
CameraOptions virtualCamera = test.map.cameraForLatLngBounds(bounds, {});
ASSERT_TRUE(bounds.contains(*virtualCamera.center));
EXPECT_NEAR(*virtualCamera.zoom, 1.55467, 1e-5);
}
TEST(Map, LatLngBoundsToCameraWithAngle) {
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);
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);
}
TEST(Map, LatLngsToCamera) {
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);
EXPECT_DOUBLE_EQ(virtualCamera.angle.value_or(0), -23 * util::DEG2RAD);
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, CameraToLatLngBounds) {