From ab8675ffc4726e1fb882dfac56919bf73c2eb23d Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Mon, 18 Dec 2017 17:11:43 -0800 Subject: [ios, macos] Projection Matrix and LatLng projection to Mercator methods --- platform/darwin/src/MGLGeometry.h | 13 +++++++++++++ platform/darwin/src/MGLGeometry.mm | 9 +++++++++ platform/darwin/src/MGLOpenGLStyleLayer.h | 2 ++ platform/darwin/src/MGLOpenGLStyleLayer.mm | 12 ++++++++++++ platform/darwin/src/NSValue+MGLAdditions.h | 13 +++++++++++++ platform/darwin/src/NSValue+MGLAdditions.m | 10 ++++++++++ platform/darwin/test/MGLGeometryTests.mm | 9 +++++++++ 7 files changed, 68 insertions(+) diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h index 7c68033abf..5d8e7eccd5 100644 --- a/platform/darwin/src/MGLGeometry.h +++ b/platform/darwin/src/MGLGeometry.h @@ -14,6 +14,16 @@ typedef struct __attribute__((objc_boxable)) MGLCoordinateSpan { CLLocationDegrees longitudeDelta; } MGLCoordinateSpan; +/* Defines a point on the map in Mercator projection for a specific zoom level. */ +typedef struct __attribute__((objc_boxable)) MGLMapPoint { + /** X coordinate representing a longitude in Mercator projection. */ + CGFloat x; + /** Y coordinate representing a latitide in Mercator projection. */ + CGFloat y; + /** Zoom level at which the X and Y coordinates are valid. */ + CGFloat zoomLevel; +} MGLMapPoint; + /** Creates a new `MGLCoordinateSpan` from the given latitudinal and longitudinal deltas. @@ -181,4 +191,7 @@ NS_INLINE CLLocationDegrees MGLDegreesFromRadians(CGFloat radians) { return radians * 180 / M_PI; } +/** Returns Mercator projection of a WGS84 coordinate at the specified zoom level. */ +extern MGL_EXPORT MGLMapPoint MGLMapPointMake(CLLocationCoordinate2D coordinate, double zoomLevel); + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm index 715a70f0b8..63886b6474 100644 --- a/platform/darwin/src/MGLGeometry.mm +++ b/platform/darwin/src/MGLGeometry.mm @@ -106,3 +106,12 @@ CGPoint MGLPointRounded(CGPoint point) { #endif return CGPointMake(round(point.x * scaleFactor) / scaleFactor, round(point.y * scaleFactor) / scaleFactor); } + +MGLMapPoint MGLMapPointMake(CLLocationCoordinate2D coordinate, double zoomLevel) { + mbgl::Point projectedCoordinate = mbgl::Projection::project(MGLLatLngFromLocationCoordinate2D(coordinate), std::pow(2.0, zoomLevel)); + MGLMapPoint point; + point.x = projectedCoordinate.x; + point.y = projectedCoordinate.y; + point.zoomLevel = zoomLevel; + return point; +} diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h index 0b494e8062..50d226457f 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.h +++ b/platform/darwin/src/MGLOpenGLStyleLayer.h @@ -1,5 +1,6 @@ #import #import +#import #import "MGLFoundation.h" #import "MGLStyleValue.h" @@ -17,6 +18,7 @@ typedef struct MGLStyleLayerDrawingContext { CLLocationDirection direction; CGFloat pitch; CGFloat fieldOfView; + CATransform3D projectionMatrix; } MGLStyleLayerDrawingContext; MGL_EXPORT diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm index bbd7422c74..2389888632 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.mm +++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm @@ -7,6 +7,17 @@ #include #include + +CATransform3D CATransform3DMake(std::array array) { + CATransform3D t = { + .m11 = array[0], .m12 = array[1], .m13 = array[2], .m14 = array[3], + .m21 = array[4], .m22 = array[5], .m23 = array[6], .m24 = array[7], + .m31 = array[8], .m32 = array[9], .m33 = array[10], .m34 = array[11], + .m41 = array[12], .m42 = array[13], .m43 = array[14], .m44 = array[15] + }; + return t; +} + class MGLOpenGLLayerHost : public mbgl::style::CustomLayerHost { public: MGLOpenGLLayerHost(MGLOpenGLStyleLayer *styleLayer) { @@ -31,6 +42,7 @@ public: .direction = mbgl::util::wrap(params.bearing, 0., 360.), .pitch = static_cast(params.pitch), .fieldOfView = static_cast(params.fieldOfView), + .projectionMatrix = CATransform3DMake(params.projectionMatrix) }; [layer drawInMapView:layer.style.mapView withContext:drawingContext]; } diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h index f3026a389f..9222f04620 100644 --- a/platform/darwin/src/NSValue+MGLAdditions.h +++ b/platform/darwin/src/NSValue+MGLAdditions.h @@ -28,6 +28,19 @@ NS_ASSUME_NONNULL_BEGIN */ @property (readonly) CLLocationCoordinate2D MGLCoordinateValue; +/** + Creates a new value object containing the specified Mapbox map point structure. + + @param point The value for the new object. + @return A new value object that contains the coordinate and zoom level information. + */ ++ (instancetype)valueWithMGLMapPoint:(MGLMapPoint)point; + +/** + The Mapbox map point structure representation of the value. + */ +@property (readonly) MGLMapPoint MGLMapPointValue; + /** Creates a new value object containing the specified Mapbox coordinate span structure. diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m index 1383056944..b32445dab7 100644 --- a/platform/darwin/src/NSValue+MGLAdditions.m +++ b/platform/darwin/src/NSValue+MGLAdditions.m @@ -14,6 +14,16 @@ return coordinate; } ++ (instancetype)valueWithMGLMapPoint:(MGLMapPoint)point { + return [self valueWithBytes:&point objCType:@encode(MGLMapPoint)]; +} + +-(MGLMapPoint) MGLMapPointValue { + MGLMapPoint point; + [self getValue:&point]; + return point; +} + + (instancetype)valueWithMGLCoordinateSpan:(MGLCoordinateSpan)span { return [self valueWithBytes:&span objCType:@encode(MGLCoordinateSpan)]; } diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm index 1c85470188..57840d9953 100644 --- a/platform/darwin/test/MGLGeometryTests.mm +++ b/platform/darwin/test/MGLGeometryTests.mm @@ -163,4 +163,13 @@ [NSValue valueWithMGLCoordinate:quad.bottomRight], @"Quad bottom right should be computed correctly."); } + +- (void)testMGLMapPoint { + MGLMapPoint point = MGLMapPointMake(CLLocationCoordinate2DMake(37.936, -80.425), 0.0); + + MGLMapPoint roundTrippedPoint = [NSValue valueWithMGLMapPoint:point].MGLMapPointValue; + XCTAssertEqual(point.x, roundTrippedPoint.x); + XCTAssertEqual(point.y, roundTrippedPoint.y); + XCTAssertEqual(point.zoomLevel, roundTrippedPoint.zoomLevel); +} @end -- cgit v1.2.1