Implement map projection functionality (#254)

* Implement map projection functionality

* Add missing MGL_EXPORT

* Remove the automatic copyright header
This commit is contained in:
Oleksandr Stepanov
2022-03-14 20:03:05 +06:00
committed by GitHub
parent ea234edf67
commit 6db27f50ad
15 changed files with 397 additions and 2 deletions

View File

@@ -134,6 +134,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/include/mbgl/map/map.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/map/map_observer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/map/map_options.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/map/map_projection.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/map/mode.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/map/projection_mode.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/math/clamp.hpp
@@ -375,6 +376,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/src/mbgl/map/map_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/map/map_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/map/map_options.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/map/map_projection.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/map/transform.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/map/transform.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/map/transform_state.cpp

View File

@@ -23,6 +23,7 @@
namespace mbgl {
class RendererFrontend;
class TransformState;
namespace style {
class Image;
@@ -110,6 +111,9 @@ public:
std::vector<ScreenCoordinate> pixelsForLatLngs(const std::vector<LatLng>&) const;
std::vector<LatLng> latLngsForPixels(const std::vector<ScreenCoordinate>&) const;
// Transform
TransformState getTransfromState() const;
// Annotations
void addAnnotationImage(std::unique_ptr<style::Image>);
void removeAnnotationImage(const std::string&);

View File

@@ -0,0 +1,30 @@
#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geo.hpp>
#include <memory>
namespace mbgl {
class Transform;
class MapProjection : private util::noncopyable {
public:
explicit MapProjection(const Map&);
~MapProjection();
ScreenCoordinate pixelForLatLng(const LatLng&) const;
LatLng latLngForPixel(const ScreenCoordinate&) const;
void setCamera(const CameraOptions&);
CameraOptions getCamera() const;
/// Set the underneath camera so the requested coordinates are visible with the inset.
void setVisibleCoordinates(const std::vector<LatLng>&, const EdgeInsets&);
private:
std::unique_ptr<Transform> transform;
};
} // namespace mbgl

View File

@@ -0,0 +1,92 @@
#import <Mapbox/Mapbox.h>
#import <XCTest/XCTest.h>
#import <TargetConditionals.h>
#if TARGET_OS_IPHONE
#define MGLEdgeInsets UIEdgeInsets
#define MGLEdgeInsetsMake UIEdgeInsetsMake
#else
#define MGLEdgeInsets NSEdgeInsets
#define MGLEdgeInsetsMake NSEdgeInsetsMake
#endif
@interface MGLMapProjectionTests : XCTestCase
@property (nonatomic, retain) MGLMapView *mapView;
@property (nonatomic, retain) MGLMapProjection *mapProjection;
@end
@implementation MGLMapProjectionTests
- (void)setUp {
[super setUp];
[MGLSettings setApiKey:@"pk.feedcafedeadbeefbadebede"];
NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
self.mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 200, 200) styleURL:styleURL];
[self.mapView setVisibleCoordinateBounds:MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(1.0, 1.0),
CLLocationCoordinate2DMake(2.0, 2.0))];
self.mapProjection = self.mapView.mapProjection;
}
- (void)tearDown {
self.mapView = nil;
self.mapProjection = nil;
[MGLSettings setApiKey:nil];
[super tearDown];
}
- (void)testMapProjectionCamera {
XCTAssertTrue([self.mapProjection.camera isEqualToMapCamera:self.mapView.camera],
@"Map projection camera must be equal to the map view's one");
}
- (void)testMapProjectionCameraSet {
MGLCoordinateBounds newBounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(3.0, 3.0),
CLLocationCoordinate2DMake(4.0, 4.0));
MGLEdgeInsets paddings = MGLEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
MGLMapCamera *newCamera = [self.mapView cameraThatFitsCoordinateBounds:newBounds edgePadding:paddings];
[self.mapProjection setCamera:newCamera withEdgeInsets:paddings];
XCTAssertTrue([self.mapProjection.camera isEqualToMapCamera:newCamera],
@"Map projection camera must be equal to the one just set");
CLLocationCoordinate2D topLeftCoordinate = [self.mapProjection convertPoint:CGPointMake(10.0, 10.0)];
XCTAssertEqualWithAccuracy(topLeftCoordinate.latitude, 4.0, 1e-3);
XCTAssertEqualWithAccuracy(topLeftCoordinate.longitude, 3.0, 1e-3);
CLLocationCoordinate2D bottomRightCoordinate = [self.mapProjection convertPoint:CGPointMake(190.0, 190.0)];
XCTAssertEqualWithAccuracy(bottomRightCoordinate.latitude, 3.0, 1e-3);
XCTAssertEqualWithAccuracy(bottomRightCoordinate.longitude, 4.0, 1e-3);
CLLocationCoordinate2D centerCoordinate = [self.mapProjection convertPoint:CGPointMake(100.0, 100.0)];
XCTAssertEqualWithAccuracy(centerCoordinate.latitude, 3.5, 1e-3);
XCTAssertEqualWithAccuracy(centerCoordinate.longitude, 3.5, 1e-3);
}
- (void)testMapProjectionVisibleBoundsSet {
MGLCoordinateBounds newBounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(3.0, 3.0),
CLLocationCoordinate2DMake(4.0, 4.0));
MGLEdgeInsets paddings = MGLEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
[self.mapProjection setVisibleCoordinateBounds:newBounds edgePadding:paddings];
CLLocationCoordinate2D topLeftCoordinate = [self.mapProjection convertPoint:CGPointMake(10.0, 10.0)];
XCTAssertEqualWithAccuracy(topLeftCoordinate.latitude, 4.0, 1e-3);
XCTAssertEqualWithAccuracy(topLeftCoordinate.longitude, 3.0, 1e-3);
CLLocationCoordinate2D bottomRightCoordinate = [self.mapProjection convertPoint:CGPointMake(190.0, 190.0)];
XCTAssertEqualWithAccuracy(bottomRightCoordinate.latitude, 3.0, 1e-3);
XCTAssertEqualWithAccuracy(bottomRightCoordinate.longitude, 4.0, 1e-3);
CLLocationCoordinate2D centerCoordinate = [self.mapProjection convertPoint:CGPointMake(100.0, 100.0)];
XCTAssertEqualWithAccuracy(centerCoordinate.latitude, 3.5, 1e-3);
XCTAssertEqualWithAccuracy(centerCoordinate.longitude, 3.5, 1e-3);
}
@end

View File

@@ -415,6 +415,11 @@
CAFB3C15234505D500399265 /* MGLMapSnapshotter_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAFB3C13234505D500399265 /* MGLMapSnapshotter_Private.h */; };
CF75A91522D85E860058A5C4 /* MGLLoggingConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */; };
CF75A91622D85E860058A5C4 /* MGLLoggingConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */; };
D42DE1E4275F7FEB00B4446E /* MGLMapProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = D42DE1E2275F7FEB00B4446E /* MGLMapProjection.h */; settings = {ATTRIBUTES = (Public, ); }; };
D42DE1E5275F7FEB00B4446E /* MGLMapProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = D42DE1E2275F7FEB00B4446E /* MGLMapProjection.h */; settings = {ATTRIBUTES = (Public, ); }; };
D42DE1E6275F7FEB00B4446E /* MGLMapProjection.mm in Sources */ = {isa = PBXBuildFile; fileRef = D42DE1E3275F7FEB00B4446E /* MGLMapProjection.mm */; };
D42DE1E7275F7FEB00B4446E /* MGLMapProjection.mm in Sources */ = {isa = PBXBuildFile; fileRef = D42DE1E3275F7FEB00B4446E /* MGLMapProjection.mm */; };
D4D7412E2760EEBA00102513 /* MGLMapProjectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D7412D2760EEBA00102513 /* MGLMapProjectionTests.m */; };
D717FE7A25F1955A0054E06E /* iosapp_UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717FE7925F1955A0054E06E /* iosapp_UITests.swift */; };
D717FECB25F19F520054E06E /* XCTestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717FECA25F19F520054E06E /* XCTestCase+Extensions.swift */; };
D7E7CE8825F2EF6A00C175FC /* bench_UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E7CE8725F2EF6A00C175FC /* bench_UITests.swift */; };
@@ -1069,6 +1074,9 @@
CAE7AD5420F46EF5003B6782 /* MGLMapSnapshotterSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MGLMapSnapshotterSwiftTests.swift; sourceTree = "<group>"; };
CAFB3C13234505D500399265 /* MGLMapSnapshotter_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLMapSnapshotter_Private.h; sourceTree = "<group>"; };
CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLoggingConfiguration.mm; sourceTree = "<group>"; };
D42DE1E2275F7FEB00B4446E /* MGLMapProjection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLMapProjection.h; sourceTree = "<group>"; };
D42DE1E3275F7FEB00B4446E /* MGLMapProjection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapProjection.mm; sourceTree = "<group>"; };
D4D7412D2760EEBA00102513 /* MGLMapProjectionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLMapProjectionTests.m; path = ../../darwin/test/MGLMapProjectionTests.m; sourceTree = "<group>"; };
D717FE7725F1955A0054E06E /* iosapp UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "iosapp UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
D717FE7925F1955A0054E06E /* iosapp_UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosapp_UITests.swift; sourceTree = "<group>"; };
D717FE7B25F1955A0054E06E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -1903,6 +1911,7 @@
96381C0122C6F3950053497D /* MGLMapViewPitchTests.m */,
9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */,
076171C22139C70900668A35 /* MGLMapViewTests.m */,
D4D7412D2760EEBA00102513 /* MGLMapProjectionTests.m */,
9686D1BC22D9357700194EA0 /* MGLMapViewZoomTests.mm */,
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */,
96036A0520059BBA00510F3D /* MGLNSOrthographyAdditionsTests.m */,
@@ -2016,6 +2025,8 @@
DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */,
4BC5769125E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.h */,
4BC5769225E3D3D6006E06EB /* MGLUserLocationAnnotationViewStyle.m */,
D42DE1E2275F7FEB00B4446E /* MGLMapProjection.h */,
D42DE1E3275F7FEB00B4446E /* MGLMapProjection.mm */,
);
name = Kit;
path = src;
@@ -2358,6 +2369,7 @@
DA17BE301CC4BAC300402C41 /* MGLMapView_Private.h in Headers */,
DAD165781CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */,
DAED38631D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */,
D42DE1E4275F7FEB00B4446E /* MGLMapProjection.h in Headers */,
DA88481E1CBAFA6200AB86E3 /* MGLMultiPoint_Private.h in Headers */,
3566C7661D4A77BA008152BC /* MGLShapeSource.h in Headers */,
35CE61821D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */,
@@ -2519,6 +2531,7 @@
DABFB8681CBE99E500D62B32 /* MGLPolyline.h in Headers */,
96E516DF200054FB00A02306 /* MGLShape_Private.h in Headers */,
DABFB86F1CBE9A0F00D62B32 /* MGLMapView.h in Headers */,
D42DE1E5275F7FEB00B4446E /* MGLMapProjection.h in Headers */,
DA6408DC1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */,
353933F31D3FB753003F57D7 /* MGLCircleStyleLayer.h in Headers */,
558DE7A11E5615E400C7916D /* MGLFoundation_Private.h in Headers */,
@@ -3160,6 +3173,7 @@
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */,
556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */,
4031ACFF1E9FD29F00A3EA26 /* MGLSDKTestHelpers.swift in Sources */,
D4D7412E2760EEBA00102513 /* MGLMapProjectionTests.m in Sources */,
16376B491FFEED010000563E /* MGLMapViewLayoutTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -3189,6 +3203,7 @@
967C864D210A9D3C004DF794 /* UIDevice+MGLAdditions.m in Sources */,
400533021DB0862B0069F638 /* NSArray+MGLAdditions.mm in Sources */,
6F018BAE220031B8003E7269 /* UIView+MGLAdditions.m in Sources */,
D42DE1E6275F7FEB00B4446E /* MGLMapProjection.mm in Sources */,
96036A03200565C700510F3D /* NSOrthography+MGLAdditions.m in Sources */,
35136D421D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */,
3538AA1F1D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */,
@@ -3288,6 +3303,7 @@
35136D431D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */,
967C864E210A9D3C004DF794 /* UIDevice+MGLAdditions.m in Sources */,
96036A04200565C700510F3D /* NSOrthography+MGLAdditions.m in Sources */,
D42DE1E7275F7FEB00B4446E /* MGLMapProjection.mm in Sources */,
6F018BB1220031C1003E7269 /* UIView+MGLAdditions.m in Sources */,
3538AA201D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */,
DA00FC911D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */,

View File

@@ -0,0 +1,75 @@
#import "MGLFoundation.h"
#import "MGLMapView.h"
NS_ASSUME_NONNULL_BEGIN
/**
The aim of this class is to provide the functionality of changing the camera state and
converting between map view screen coordinates and geographical coordinates without
changing the actual map view camera state.
*/
MGL_EXPORT
@interface MGLMapProjection : NSObject
/**
Initializes and returns the new projection object with the current
camera state from the provided map view.
@param mapView The map view the camera state to use for the initialization.
@return An initialized map projection.
*/
- (instancetype)initWithMapView:(MGLMapView*)mapView;
/**
A camera representing the current projection state
*/
@property (readonly, copy) MGLMapCamera *camera;
/**
Change the projection state with camera and padding values.
@param camera The new camera to be used in the projection calculation.
@param insets The insets applied on top of the camera be used in the projection calculation.
@note `MGLMapView` instance frame must not be changed since this projection is initialized,
otherwise the calculation may be wrong.
*/
- (void)setCamera:(MGLMapCamera * _Nonnull)camera withEdgeInsets:(UIEdgeInsets)insets;
/**
Change the projection state to make the provided bounds visible with the specified inset.
@param bounds The bounds that the viewport should fit.
@param insets The insets applied on top of the viewport to be used in the projection calculation.
@note `MGLMapView` instance frame must not be changed since this projection is initialized,
otherwise the calculation may be wrong.
*/
- (void)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
/**
Converts a point in the coordinate system of the map view the projection
was initialized with to the geographical coordinate.
@param point The point to convert.
@return The geographic coordinate at the given point.
*/
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point;
/**
Converts a geographic coordinate to a point in the map view's the projection
was initialized with coordinate system.
@param coordinate The geographic coordinate to convert.
@return The point corresponding to the given geographic coordinate.
*/
- (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate;
/**
The distance in meters spanned by a single point for the current camera.
*/
@property (readonly) CLLocationDistance metersPerPoint;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,113 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_projection.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/projection.hpp>
#import "MGLMapProjection.h"
#import "MGLMapView_Private.h"
#import "MGLGeometry_Private.h"
@interface MGLMapProjection ()
@property (nonatomic) CGSize mapFrameSize;
@end
@implementation MGLMapProjection
{
std::unique_ptr<mbgl::MapProjection> _mbglProjection;
}
- (instancetype)initWithMapView:(MGLMapView *)mapView
{
if (self = [super init])
{
_mbglProjection = std::make_unique<mbgl::MapProjection>([mapView mbglMap]);
self.mapFrameSize = mapView.frame.size;
}
return self;
}
- (MGLMapCamera*)camera
{
mbgl::CameraOptions cameraOptions = _mbglProjection->getCamera();
CLLocationCoordinate2D centerCoordinate = MGLLocationCoordinate2DFromLatLng(*cameraOptions.center);
double zoomLevel = *cameraOptions.zoom;
CLLocationDirection direction = mbgl::util::wrap(*cameraOptions.bearing, 0., 360.);
CGFloat pitch = *cameraOptions.pitch;
CLLocationDistance altitude = MGLAltitudeForZoomLevel(zoomLevel, pitch,
centerCoordinate.latitude, self.mapFrameSize);
return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate altitude:altitude
pitch:pitch heading:direction];
}
- (void)setCamera:(MGLMapCamera * _Nonnull)camera withEdgeInsets:(UIEdgeInsets)insets
{
mbgl::CameraOptions cameraOptions;
if (CLLocationCoordinate2DIsValid(camera.centerCoordinate))
{
cameraOptions.center = MGLLatLngFromLocationCoordinate2D(camera.centerCoordinate);
}
cameraOptions.padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
cameraOptions.zoom = MGLZoomLevelForAltitude(camera.altitude, camera.pitch,
camera.centerCoordinate.latitude,
self.mapFrameSize);
if (camera.heading >= 0)
{
cameraOptions.bearing = camera.heading;
}
if (camera.pitch >= 0)
{
cameraOptions.pitch = camera.pitch;
}
_mbglProjection->setCamera(cameraOptions);
}
- (void)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets {
CLLocationCoordinate2D coordinates[] = {
{bounds.ne.latitude, bounds.sw.longitude},
bounds.sw,
{bounds.sw.latitude, bounds.ne.longitude},
bounds.ne,
};
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
std::vector<mbgl::LatLng> latLngs;
latLngs.reserve(4);
for (NSUInteger i = 0; i < 4; i++)
{
latLngs.push_back({coordinates[i].latitude, coordinates[i].longitude});
}
_mbglProjection->setVisibleCoordinates(latLngs, padding);
}
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point
{
mbgl::ScreenCoordinate screenCoordinate = mbgl::ScreenCoordinate(point.x, point.y);
return MGLLocationCoordinate2DFromLatLng(_mbglProjection->latLngForPixel(screenCoordinate).wrapped());
}
- (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate
{
if ( !CLLocationCoordinate2DIsValid(coordinate))
{
return CGPointMake(NAN, NAN);
}
mbgl::LatLng latLng = MGLLatLngFromLocationCoordinate2D(coordinate);
mbgl::ScreenCoordinate pixel = _mbglProjection->pixelForLatLng(latLng);
return CGPointMake(pixel.x, pixel.y);
}
- (CLLocationDistance)metersPerPoint
{
mbgl::CameraOptions cameraOptions = _mbglProjection->getCamera();
return mbgl::Projection::getMetersPerPixelAtLatitude(cameraOptions.center->latitude(),
*cameraOptions.zoom);
}
@end

View File

@@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
@class MGLAnnotationView;
@class MGLAnnotationImage;
@class MGLUserLocation;
@class MGLMapProjection;
@class MGLPolyline;
@class MGLPolygon;
@class MGLShape;
@@ -1533,6 +1534,12 @@ MGL_EXPORT
*/
- (CLLocationDistance)metersPerPointAtLatitude:(CLLocationDegrees)latitude;
/**
Returns the new map projection instance initialized with the map view,
i.e. with the current camera state.
*/
- (MGLMapProjection*)mapProjection;
#pragma mark Annotating the Map
/**

View File

@@ -67,6 +67,7 @@
#import "MGLNetworkConfiguration_Private.h"
#import "MGLReachability.h"
#import "MGLSettings_Private.h"
#import "MGLMapProjection.h"
#include <algorithm>
#include <cstdlib>
@@ -4360,6 +4361,10 @@ static void *windowScreenContext = &windowScreenContext;
return mbgl::Projection::getMetersPerPixelAtLatitude(latitude, zoomLevel);
}
- (MGLMapProjection*)mapProjection {
return [[MGLMapProjection alloc] initWithMapView:self];
}
#pragma mark - Camera Change Reason -
- (void)resetCameraChangeReason

View File

@@ -54,6 +54,7 @@ FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const _Nonnull MGLUnderlyingMapUna
/// Synchronously render a frame of the map.
- (BOOL)renderSync;
- (mbgl::Map &)mbglMap;
- (nonnull mbgl::Renderer *)renderer;
/** Returns whether the map view is currently loading or processing any assets required to render the map */

View File

@@ -36,6 +36,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLLocationManager.h"
#import "MGLLoggingConfiguration.h"
#import "MGLMapCamera.h"
#import "MGLMapProjection.h"
#import "MGLMapSnapshotter.h"
#import "MGLMapView.h"
#import "MGLMapViewDelegate.h"

View File

@@ -3,14 +3,13 @@
#import "../../darwin/src/MGLGeometry_Private.h"
#import "MGLMockGestureRecognizers.h"
#import "MGLMapView_Private.h"
#include <mbgl/map/map.hpp>
#include <mbgl/map/camera.hpp>
@interface MGLMapView (MGLMapViewGestureRecognizerTests)
- (mbgl::Map &)mbglMap;
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch;
- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate;
- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap;

View File

@@ -426,6 +426,12 @@ std::vector<LatLng> Map::latLngsForPixels(const std::vector<ScreenCoordinate>& s
return ret;
}
#pragma mark - Transform
TransformState Map::getTransfromState() const {
return impl->transform.getState();
}
#pragma mark - Annotations
void Map::addAnnotationImage(std::unique_ptr<style::Image> image) {

View File

@@ -76,4 +76,9 @@ public:
std::unique_ptr<StillImageRequest> stillImageRequest;
};
// Forward declaration of this method is required for the MapProjection class
CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs,
const Transform& transform,
const EdgeInsets& padding);
} // namespace mbgl

View File

@@ -0,0 +1,39 @@
#include <mbgl/map/map_projection.hpp>
#include <mbgl/map/map_impl.hpp>
#include <mbgl/map/transform.hpp>
namespace mbgl {
MapProjection::MapProjection(const Map& map)
: transform(std::make_unique<Transform>(map.getTransfromState())) {}
MapProjection::~MapProjection() = default;
ScreenCoordinate MapProjection::pixelForLatLng(const LatLng& latLng) const {
// The implementation is just a copy from map.cpp
LatLng unwrappedLatLng = latLng.wrapped();
unwrappedLatLng.unwrapForShortestPath(transform->getLatLng());
return transform->latLngToScreenCoordinate(unwrappedLatLng);
}
LatLng MapProjection::latLngForPixel(const ScreenCoordinate& pixel) const {
// The implementation is just a copy from map.cpp
return transform->screenCoordinateToLatLng(pixel);
}
void MapProjection::setCamera(const CameraOptions& camera) {
transform->jumpTo(camera);
}
CameraOptions MapProjection::getCamera() const {
return transform->getCameraOptions(nullopt);
}
void MapProjection::setVisibleCoordinates(const std::vector<LatLng>& latLngs,
const EdgeInsets& padding) {
transform->jumpTo(mbgl::cameraForLatLngs(latLngs, *transform, padding)
.withBearing(-transform->getBearing() * util::RAD2DEG)
.withPitch(transform->getPitch() * util::RAD2DEG));
}
} // namespace mbgl