From ea20dd58e66981e39da87e3dfea663494d746011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Thu, 6 Apr 2017 08:30:34 -0700 Subject: [PATCH] [ios, macos] Fail gracefully on invalid coordinates Invalid coordinates no longer cause an exception to be raised immediately when used in conversion methods and model objects. Instead, the appropriate invalid values are used, consistent with MapKit. Exceptions are still raised when invalid model objects are used with the map. --- platform/darwin/src/MGLMapCamera.mm | 26 +++++++++++++---------- platform/darwin/src/MGLMultiPoint.mm | 4 ++++ platform/darwin/src/MGLPointCollection.mm | 9 ++++++-- platform/ios/src/MGLMapView.mm | 8 +++++++ platform/macos/src/MGLMapView.mm | 6 ++++++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/platform/darwin/src/MGLMapCamera.mm b/platform/darwin/src/MGLMapCamera.mm index ecac2892b1d..49c7e70900f 100644 --- a/platform/darwin/src/MGLMapCamera.mm +++ b/platform/darwin/src/MGLMapCamera.mm @@ -24,17 +24,21 @@ + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCo fromEyeCoordinate:(CLLocationCoordinate2D)eyeCoordinate eyeAltitude:(CLLocationDistance)eyeAltitude { - mbgl::LatLng centerLatLng = MGLLatLngFromLocationCoordinate2D(centerCoordinate); - mbgl::LatLng eyeLatLng = MGLLatLngFromLocationCoordinate2D(eyeCoordinate); - - mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng); - mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng); - CLLocationDirection heading = std::atan((centerMeters.northing - eyeMeters.northing) / - (centerMeters.easting - eyeMeters.easting)); - - double groundDistance = std::hypot(centerMeters.northing - eyeMeters.northing, - centerMeters.easting - eyeMeters.easting); - CGFloat pitch = std::atan(eyeAltitude / groundDistance); + CLLocationDirection heading = -1; + CGFloat pitch = -1; + if (CLLocationCoordinate2DIsValid(centerCoordinate) && CLLocationCoordinate2DIsValid(eyeCoordinate)) { + mbgl::LatLng centerLatLng = MGLLatLngFromLocationCoordinate2D(centerCoordinate); + mbgl::LatLng eyeLatLng = MGLLatLngFromLocationCoordinate2D(eyeCoordinate); + + 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); + } return [[self alloc] initWithCenterCoordinate:centerCoordinate altitude:eyeAltitude diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm index 4ab4ceb0070..ef46bbb0fee 100644 --- a/platform/darwin/src/MGLMultiPoint.mm +++ b/platform/darwin/src/MGLMultiPoint.mm @@ -163,6 +163,10 @@ - (MGLCoordinateBounds)overlayBounds if (!_bounds) { mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); for (auto coordinate : _coordinates) { + if (!CLLocationCoordinate2DIsValid(coordinate)) { + bounds = mbgl::LatLngBounds::empty(); + break; + } bounds.extend(MGLLatLngFromLocationCoordinate2D(coordinate)); } _bounds = bounds; diff --git a/platform/darwin/src/MGLPointCollection.mm b/platform/darwin/src/MGLPointCollection.mm index d8f0f0d3dca..8f20d91a429 100644 --- a/platform/darwin/src/MGLPointCollection.mm +++ b/platform/darwin/src/MGLPointCollection.mm @@ -54,6 +54,10 @@ - (MGLCoordinateBounds)overlayBounds { if (!_bounds) { mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); for (auto coordinate : _coordinates) { + if (!CLLocationCoordinate2DIsValid(coordinate)) { + bounds = mbgl::LatLngBounds::empty(); + break; + } bounds.extend(MGLLatLngFromLocationCoordinate2D(coordinate)); } _bounds = bounds; @@ -119,8 +123,9 @@ - (NSDictionary *)geoJSONDictionary - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p; count = %lu>", - NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount]]; + return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>", + NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount], + MGLStringFromCoordinateBounds(self.overlayBounds)]; } @end diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index f5c3ce3ba6c..d80e741c000 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -2843,6 +2843,10 @@ - (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(null - (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(nullable UIView *)view { + if ( ! CLLocationCoordinate2DIsValid(coordinate)) + { + return CGPointMake(NAN, NAN); + } return [self convertLatLng:MGLLatLngFromLocationCoordinate2D(coordinate) toPointToView:view]; } @@ -2860,6 +2864,10 @@ - (MGLCoordinateBounds)convertRect:(CGRect)rect toCoordinateBoundsFromView:(null - (CGRect)convertCoordinateBounds:(MGLCoordinateBounds)bounds toRectToView:(nullable UIView *)view { + if ( ! CLLocationCoordinate2DIsValid(bounds.sw) || ! CLLocationCoordinate2DIsValid(bounds.ne)) + { + return CGRectNull; + } return [self convertLatLngBounds:MGLLatLngBoundsFromCoordinateBounds(bounds) toRectToView:view]; } diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 42f38cd99f0..e19755044b3 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -2618,6 +2618,9 @@ - (void)prepareForInterfaceBuilder { #pragma mark Geometric methods - (NSPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(nullable NSView *)view { + if (!CLLocationCoordinate2DIsValid(coordinate)) { + return NSMakePoint(NAN, NAN); + } return [self convertLatLng:MGLLatLngFromLocationCoordinate2D(coordinate) toPointToView:view]; } @@ -2644,6 +2647,9 @@ - (CLLocationCoordinate2D)convertPoint:(NSPoint)point toCoordinateFromView:(null } - (NSRect)convertCoordinateBounds:(MGLCoordinateBounds)bounds toRectToView:(nullable NSView *)view { + if (!CLLocationCoordinate2DIsValid(bounds.sw) || !CLLocationCoordinate2DIsValid(bounds.ne)) { + return CGRectNull; + } return [self convertLatLngBounds:MGLLatLngBoundsFromCoordinateBounds(bounds) toRectToView:view]; }