Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios, macos] Fixed camera initialization with eye coordinate
Browse files Browse the repository at this point in the history
Rewrote the code that calculates the heading and pitch of the camera when given an eye coordinate.
  • Loading branch information
1ec5 committed Sep 27, 2018
1 parent 8577a32 commit f42bbd4
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 5 deletions.
18 changes: 13 additions & 5 deletions platform/darwin/src/MGLMapCamera.mm
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#import "MGLMapCamera.h"
#import "MGLGeometry_Private.h"

#import <CoreLocation/CoreLocation.h>

#include <mbgl/util/projection.hpp>
#include <mbgl/math/wrap.hpp>

BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
{
Expand Down Expand Up @@ -32,12 +35,17 @@ + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCo

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()));
CGFloat radianHeading = atan2(centerMeters.easting() - eyeMeters.easting(),
centerMeters.northing() - eyeMeters.northing());
heading = mbgl::util::wrap(MGLDegreesFromRadians(radianHeading), 0.0, 360.0);

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
Expand Down
39 changes: 39 additions & 0 deletions platform/darwin/test/MGLMapCameraTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,45 @@ @interface MGLMapCameraTests : XCTestCase

@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
Expand Down
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
### Other changes

* Deprecated the `+[MGLMapCamera cameraLookingAtCenterCoordinate:fromDistance:pitch:heading:]` method in favor of `+[MGLMapCamera cameraLookingAtCenterCoordinate:altitude:pitch:heading:]` and a temporarily named `+[MGLMapCamera cameraLookingAtCenterCoordinate:correctlyFromDistance:pitch:heading:]`. ([#12966](https://github.com/mapbox/mapbox-gl-native/pull/12966))
* Fixed an issue where `+[MGLMapCamera cameraLookingAtCenterCoordinate:fromEyeCoordinate:eyeAltitude:]` created a camera looking from the wrong eye coordinate. ([#12966](https://github.com/mapbox/mapbox-gl-native/pull/12966))
* Added an `MGLMapCamera.viewingDistance` property based on the existing `MGLMapCamera.altitude` property. ([#12966](https://github.com/mapbox/mapbox-gl-native/pull/12966))
* Fixed an issue where `-[MGLMapSnapshotter startWithQueue:completionHandler:]` failed to call its completion handler in some cases. ([#12355](https://github.com/mapbox/mapbox-gl-native/pull/12355))
* Fixed bugs in coercion expression operators ("to-array" applied to empty arrays, "to-color" applied to colors, and "to-number" applied to null) [#12864](https://github.com/mapbox/mapbox-gl-native/pull/12864)
Expand Down
1 change: 1 addition & 0 deletions platform/macos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
### Other changes

* Deprecated the `+[MGLMapCamera cameraLookingAtCenterCoordinate:fromDistance:pitch:heading:]` method in favor of `+[MGLMapCamera cameraLookingAtCenterCoordinate:altitude:pitch:heading:]` and a temporarily named `+[MGLMapCamera cameraLookingAtCenterCoordinate:correctlyFromDistance:pitch:heading:]`. ([#12966](https://github.com/mapbox/mapbox-gl-native/pull/12966))
* Fixed an issue where `+[MGLMapCamera cameraLookingAtCenterCoordinate:fromEyeCoordinate:eyeAltitude:]` created a camera looking from the wrong eye coordinate. ([#12966](https://github.com/mapbox/mapbox-gl-native/pull/12966))
* Added an `MGLMapCamera.viewingDistance` property based on the existing `MGLMapCamera.altitude` property. ([#12966](https://github.com/mapbox/mapbox-gl-native/pull/12966))
* Fixed an issue where `-[MGLMapSnapshotter startWithQueue:completionHandler:]` failed to call its completion handler in some cases. ([#12355](https://github.com/mapbox/mapbox-gl-native/pull/12355))
* Fixed an issue where `MGLMapView` produced a designable error in Interface Builder storyboards in Xcode 10. ([#12883](https://github.com/mapbox/mapbox-gl-native/pull/12883))
Expand Down

0 comments on commit f42bbd4

Please sign in to comment.