[ios, macos] Fixed camera initialization with eye coordinate
Rewrote the code that calculates the heading and pitch of the camera when given an eye coordinate.
This commit is contained in:
committed by
Minh Nguyễn
parent
85a474e275
commit
a9dc1b5294
@@ -1,7 +1,9 @@
|
||||
#import "MGLMapCamera.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
|
||||
#include <mbgl/util/projection.hpp>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
#include <mbgl/math/wrap.hpp>
|
||||
|
||||
BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
|
||||
{
|
||||
@@ -27,17 +29,15 @@ BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
|
||||
CLLocationDirection heading = -1;
|
||||
CGFloat pitch = -1;
|
||||
if (CLLocationCoordinate2DIsValid(centerCoordinate) && CLLocationCoordinate2DIsValid(eyeCoordinate)) {
|
||||
mbgl::LatLng centerLatLng = MGLLatLngFromLocationCoordinate2D(centerCoordinate);
|
||||
mbgl::LatLng eyeLatLng = MGLLatLngFromLocationCoordinate2D(eyeCoordinate);
|
||||
heading = MGLDirectionBetweenCoordinates(eyeCoordinate, centerCoordinate);
|
||||
|
||||
mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng);
|
||||
mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng);
|
||||
heading = std::atan((centerMeters.northing() - eyeMeters.northing()) /
|
||||
(centerMeters.easting() - eyeMeters.easting()));
|
||||
|
||||
double groundDistance = std::hypot(centerMeters.northing() - eyeMeters.northing(),
|
||||
centerMeters.easting() - eyeMeters.easting());
|
||||
pitch = std::atan(eyeAltitude / groundDistance);
|
||||
CLLocation *centerLocation = [[CLLocation alloc] initWithLatitude:centerCoordinate.latitude
|
||||
longitude:centerCoordinate.longitude];
|
||||
CLLocation *eyeLocation = [[CLLocation alloc] initWithLatitude:eyeCoordinate.latitude
|
||||
longitude:eyeCoordinate.longitude];
|
||||
CLLocationDistance groundDistance = [eyeLocation distanceFromLocation:centerLocation];
|
||||
CGFloat radianPitch = atan2(eyeAltitude, groundDistance);
|
||||
pitch = mbgl::util::wrap(90 - MGLDegreesFromRadians(radianPitch), 0.0, 360.0);
|
||||
}
|
||||
|
||||
return [[self alloc] initWithCenterCoordinate:centerCoordinate
|
||||
|
||||
@@ -9,6 +9,45 @@
|
||||
|
||||
@implementation MGLMapCameraTests
|
||||
|
||||
- (void)testEyeCoordinateInitialization {
|
||||
CLLocationCoordinate2D fountainSquare = CLLocationCoordinate2DMake(39.10152215, -84.5124439696089);
|
||||
CLLocationCoordinate2D unionTerminal = CLLocationCoordinate2DMake(39.10980955, -84.5352778794236);
|
||||
|
||||
MGLMapCamera *camera = [MGLMapCamera cameraLookingAtCenterCoordinate:fountainSquare
|
||||
fromEyeCoordinate:fountainSquare
|
||||
eyeAltitude:1000];
|
||||
MKMapCamera *mkCamera = [MKMapCamera cameraLookingAtCenterCoordinate:fountainSquare
|
||||
fromEyeCoordinate:fountainSquare
|
||||
eyeAltitude:1000];
|
||||
XCTAssertEqual(camera.centerCoordinate.latitude, fountainSquare.latitude);
|
||||
XCTAssertEqual(camera.centerCoordinate.longitude, fountainSquare.longitude);
|
||||
XCTAssertEqual(camera.centerCoordinate.latitude, mkCamera.centerCoordinate.latitude);
|
||||
XCTAssertEqual(camera.centerCoordinate.longitude, mkCamera.centerCoordinate.longitude);
|
||||
XCTAssertEqual(camera.altitude, 1000, @"Eye altitude should be equivalent to altitude in untilted camera.");
|
||||
XCTAssertEqual(camera.altitude, mkCamera.altitude, @"Eye altitude in untilted camera should match MapKit.");
|
||||
XCTAssertEqual(camera.pitch, 0, @"Camera directly over center coordinate should be untilted.");
|
||||
XCTAssertEqual(camera.pitch, mkCamera.pitch, @"Camera directly over center coordinate should have same pitch as MapKit.");
|
||||
XCTAssertEqual(camera.heading, 0, @"Camera directly over center coordinate should be unrotated.");
|
||||
XCTAssertEqual(camera.heading, mkCamera.heading, @"Camera directly over center coordinate should have same heading as MapKit.");
|
||||
|
||||
camera = [MGLMapCamera cameraLookingAtCenterCoordinate:fountainSquare
|
||||
fromEyeCoordinate:unionTerminal
|
||||
eyeAltitude:1000];
|
||||
mkCamera = [MKMapCamera cameraLookingAtCenterCoordinate:fountainSquare
|
||||
fromEyeCoordinate:unionTerminal
|
||||
eyeAltitude:1000];
|
||||
XCTAssertEqual(camera.centerCoordinate.latitude, fountainSquare.latitude);
|
||||
XCTAssertEqual(camera.centerCoordinate.longitude, fountainSquare.longitude);
|
||||
XCTAssertEqual(camera.centerCoordinate.latitude, mkCamera.centerCoordinate.latitude);
|
||||
XCTAssertEqual(camera.centerCoordinate.longitude, mkCamera.centerCoordinate.longitude);
|
||||
XCTAssertEqual(camera.altitude, 1000);
|
||||
XCTAssertEqual(camera.altitude, mkCamera.altitude, @"Eye altitude in tilted camera should match MapKit.");
|
||||
XCTAssertEqualWithAccuracy(camera.pitch, 65.3469146074, 0.01);
|
||||
XCTAssertEqual(camera.pitch, mkCamera.pitch);
|
||||
XCTAssertEqualWithAccuracy(camera.heading, 115.066396383, 0.01);
|
||||
XCTAssertEqualWithAccuracy(camera.heading, mkCamera.heading, 0.01);
|
||||
}
|
||||
|
||||
- (void)testViewingDistanceInitialization {
|
||||
CLLocationCoordinate2D fountainSquare = CLLocationCoordinate2DMake(39.10152215, -84.5124439696089);
|
||||
MGLMapCamera *camera = [MGLMapCamera cameraLookingAtCenterCoordinate:fountainSquare
|
||||
|
||||
Reference in New Issue
Block a user