[core] Add cameraForLatLngs() method with modified bearing
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user