summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2015-06-25 11:58:23 -0700
committerMinh Nguyễn <mxn@1ec5.org>2015-06-25 21:54:57 -0700
commit1d11624efdf2d73a8adb43310c481969ead18d46 (patch)
treec362981a8e2ff82e0cb00285de39565bae49588d
parent68e404c522d318ca87e5435a997a21a9604ad0e8 (diff)
downloadqtlocation-mapboxgl-1d11624efdf2d73a8adb43310c481969ead18d46.tar.gz
Test fit to bounds; added MGLCoordinateBounds functions
Added a bunch of functions to work with MGLCoordinateBounds in a separate header analogous to MKGeometry.h. Added resolution-independent tests for common fit to bounds scenarios.
-rw-r--r--gyp/platform-ios.gypi2
-rw-r--r--include/mbgl/ios/MGLGeometry.h85
-rw-r--r--include/mbgl/ios/MGLMapView.h2
-rw-r--r--include/mbgl/ios/MGLOverlay.h2
-rw-r--r--include/mbgl/ios/MGLTypes.h15
-rw-r--r--include/mbgl/ios/MapboxGL.h1
-rw-r--r--platform/ios/MGLGeometry.m3
-rw-r--r--platform/ios/MGLMultiPoint.mm2
-rw-r--r--test/ios/MapViewTests.m35
9 files changed, 131 insertions, 16 deletions
diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi
index 484135a2ec..52a66ea45f 100644
--- a/gyp/platform-ios.gypi
+++ b/gyp/platform-ios.gypi
@@ -36,6 +36,8 @@
'../platform/ios/MGLUserLocationAnnotationView.m',
'../include/mbgl/ios/MGLTypes.h',
'../platform/ios/MGLTypes.m',
+ '../include/mbgl/ios/MGLGeometry.h',
+ '../platform/ios/MGLGeometry.m',
'../include/mbgl/ios/MGLMultiPoint.h',
'../platform/ios/MGLMultiPoint_Private.h',
'../platform/ios/MGLMultiPoint.mm',
diff --git a/include/mbgl/ios/MGLGeometry.h b/include/mbgl/ios/MGLGeometry.h
new file mode 100644
index 0000000000..6226af1d08
--- /dev/null
+++ b/include/mbgl/ios/MGLGeometry.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#import "MGLTypes.h"
+
+#import <CoreLocation/CoreLocation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Defines the area spanned by an MGLCoordinateBounds. */
+typedef struct {
+ CLLocationDegrees latitudeDelta;
+ CLLocationDegrees longitudeDelta;
+} MGLCoordinateSpan;
+
+/** Creates a new MGLCoordinateSpan from the given latitudinal and longitudinal deltas. */
+NS_INLINE MGLCoordinateSpan MGLCoordinateSpanMake(CLLocationDegrees latitudeDelta, CLLocationDegrees longitudeDelta) {
+ MGLCoordinateSpan span;
+ span.latitudeDelta = latitudeDelta;
+ span.longitudeDelta = longitudeDelta;
+ return span;
+}
+
+/** Returns `YES` if the two coordinate spans represent the same latitudinal change and the same longitudinal change. */
+NS_INLINE BOOL MGLCoordinateSpanEqualToCoordinateSpan(MGLCoordinateSpan span1, MGLCoordinateSpan span2) {
+ return (span1.latitudeDelta == span2.latitudeDelta &&
+ span1.longitudeDelta == span2.longitudeDelta);
+}
+
+/** An area of zero width and zero height. */
+extern const MGLCoordinateSpan MGLCoordinateSpanZero;
+
+/** A rectangular area as measured on a two-dimensional map projection. */
+typedef struct {
+ CLLocationCoordinate2D sw;
+ CLLocationCoordinate2D ne;
+} MGLCoordinateBounds;
+
+/** Creates a new MGLCoordinateBounds structure from the given southwest and northeast coordinates. */
+NS_INLINE MGLCoordinateBounds MGLCoordinateBoundsMake(CLLocationCoordinate2D sw, CLLocationCoordinate2D ne) {
+ MGLCoordinateBounds bounds;
+ bounds.sw = sw;
+ bounds.ne = ne;
+ return bounds;
+}
+
+/** Returns `YES` if the two coordinate bounds are equal to each other. */
+NS_INLINE BOOL MGLCoordinateBoundsEqualToCoordinateBounds(MGLCoordinateBounds bounds1, MGLCoordinateBounds bounds2) {
+ return (bounds1.sw.latitude == bounds2.sw.latitude &&
+ bounds1.sw.longitude == bounds2.sw.longitude &&
+ bounds1.ne.latitude == bounds2.ne.latitude &&
+ bounds1.ne.longitude == bounds2.ne.longitude);
+}
+
+/** Returns the area spanned by the coordinate bounds. */
+NS_INLINE MGLCoordinateSpan MGLCoordinateBoundsGetCoordinateSpan(MGLCoordinateBounds bounds) {
+ return MGLCoordinateSpanMake(bounds.ne.latitude - bounds.sw.latitude,
+ bounds.ne.longitude - bounds.sw.longitude);
+}
+
+/** Returns a coordinate bounds with southwest and northeast coordinates that are offset from those of the source bounds. */
+NS_INLINE MGLCoordinateBounds MGLCoordinateBoundsOffset(MGLCoordinateBounds bounds, MGLCoordinateSpan offset) {
+ MGLCoordinateBounds offsetBounds = bounds;
+ offsetBounds.sw.latitude += offset.latitudeDelta;
+ offsetBounds.sw.longitude += offset.longitudeDelta;
+ offsetBounds.ne.latitude += offset.latitudeDelta;
+ offsetBounds.ne.longitude += offset.longitudeDelta;
+ return offsetBounds;
+}
+
+/** Returns `YES` if the coordinate bounds covers no area.
+*
+* Note that a bounds may be empty but have a non-zero coordinate span (e.g., when its northeast point lies due north of its southwest point). */
+NS_INLINE BOOL MGLCoordinateBoundsIsEmpty(MGLCoordinateBounds bounds) {
+ MGLCoordinateSpan span = MGLCoordinateBoundsGetCoordinateSpan(bounds);
+ return span.latitudeDelta == 0 || span.longitudeDelta == 0;
+}
+
+/** Returns a formatted string for the given coordinate bounds. */
+NS_INLINE NSString *MGLStringFromCoordinateBounds(MGLCoordinateBounds bounds) {
+ return [NSString stringWithFormat:@"{{%.1f, %.1f}, {%.1f, %.1f}}",
+ bounds.sw.latitude, bounds.sw.longitude,
+ bounds.ne.latitude, bounds.ne.longitude];
+}
+
+NS_ASSUME_NONNULL_END
diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h
index bf42f47e7f..1d4f5b4ac2 100644
--- a/include/mbgl/ios/MGLMapView.h
+++ b/include/mbgl/ios/MGLMapView.h
@@ -1,4 +1,4 @@
-#import "MGLTypes.h"
+#import "MGLGeometry.h"
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
diff --git a/include/mbgl/ios/MGLOverlay.h b/include/mbgl/ios/MGLOverlay.h
index 4a07339b29..104a5e608b 100644
--- a/include/mbgl/ios/MGLOverlay.h
+++ b/include/mbgl/ios/MGLOverlay.h
@@ -2,7 +2,7 @@
#import <CoreLocation/CoreLocation.h>
#import "MGLAnnotation.h"
-#import "MGLTypes.h"
+#import "MGLGeometry.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/include/mbgl/ios/MGLTypes.h b/include/mbgl/ios/MGLTypes.h
index 9213dafb37..75a0d4619f 100644
--- a/include/mbgl/ios/MGLTypes.h
+++ b/include/mbgl/ios/MGLTypes.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
-#import <CoreLocation/CoreLocation.h>
+
+#pragma once
#if !__has_feature(nullability)
#define NS_ASSUME_NONNULL_BEGIN
@@ -23,18 +24,6 @@ typedef NS_ENUM(NSUInteger, MGLUserTrackingMode) {
MGLUserTrackingModeFollowWithHeading
};
-typedef struct {
- CLLocationCoordinate2D sw;
- CLLocationCoordinate2D ne;
-} MGLCoordinateBounds;
-
-NS_INLINE MGLCoordinateBounds MGLCoordinateBoundsMake(CLLocationCoordinate2D sw, CLLocationCoordinate2D ne) {
- MGLCoordinateBounds bounds;
- bounds.sw = sw;
- bounds.ne = ne;
- return bounds;
-}
-
NS_ASSUME_NONNULL_END
#pragma clang diagnostic push
diff --git a/include/mbgl/ios/MapboxGL.h b/include/mbgl/ios/MapboxGL.h
index d3b032b9c9..bcdc5359bf 100644
--- a/include/mbgl/ios/MapboxGL.h
+++ b/include/mbgl/ios/MapboxGL.h
@@ -1,5 +1,6 @@
#import "MGLAccountManager.h"
#import "MGLAnnotation.h"
+#import "MGLGeometry.h"
#import "MGLMapView.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
diff --git a/platform/ios/MGLGeometry.m b/platform/ios/MGLGeometry.m
new file mode 100644
index 0000000000..9eab5565fa
--- /dev/null
+++ b/platform/ios/MGLGeometry.m
@@ -0,0 +1,3 @@
+#import "MGLGeometry.h"
+
+const MGLCoordinateSpan MGLCoordinateSpanZero = {0, 0};
diff --git a/platform/ios/MGLMultiPoint.mm b/platform/ios/MGLMultiPoint.mm
index 5721086e86..624c1658ad 100644
--- a/platform/ios/MGLMultiPoint.mm
+++ b/platform/ios/MGLMultiPoint.mm
@@ -1,5 +1,5 @@
#import "MGLMultiPoint.h"
-#import "MGLTypes.h"
+#import "MGLGeometry.h"
#import <mbgl/util/geo.hpp>
diff --git a/test/ios/MapViewTests.m b/test/ios/MapViewTests.m
index 90447680ae..de4095497a 100644
--- a/test/ios/MapViewTests.m
+++ b/test/ios/MapViewTests.m
@@ -150,6 +150,41 @@
@"disabling zoom gesture should disallow pinching");
}
+- (void)testFitToBounds {
+ // No-op
+ MGLCoordinateBounds initialBounds = tester.mapView.visibleCoordinateBounds;
+ [tester.mapView setVisibleCoordinateBounds:initialBounds animated:NO];
+ XCTAssertEqualObjects(MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds),
+ @"setting visible coordinate bounds to currently visible coordinate bounds should be a no-op");
+
+ // Roundtrip after zooming
+ tester.mapView.zoomLevel -= 3;
+ [tester.mapView setVisibleCoordinateBounds:initialBounds animated:NO];
+ XCTAssertEqualObjects(MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds),
+ @"after zooming out, setting visible coordinate bounds back to %@ should not leave them at %@",
+ MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds));
+ tester.mapView.zoomLevel += 3;
+ [tester.mapView setVisibleCoordinateBounds:initialBounds animated:NO];
+ XCTAssertEqualObjects(MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds),
+ @"after zooming in, setting visible coordinate bounds back to %@ should not leave them at %@",
+ MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds));
+
+ // Roundtrip after panning
+ MGLCoordinateBounds offsetBounds = MGLCoordinateBoundsOffset(initialBounds, MGLCoordinateSpanMake(0, 30));
+ [tester.mapView setVisibleCoordinateBounds:offsetBounds animated:NO];
+ [tester.mapView setVisibleCoordinateBounds:initialBounds animated:NO];
+ XCTAssertEqualObjects(MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds),
+ @"after panning 30° to the east, setting visible coordinate bounds back to %@ should not leave them at %@",
+ MGLStringFromCoordinateBounds(initialBounds),
+ MGLStringFromCoordinateBounds(tester.mapView.visibleCoordinateBounds));
+}
+
- (void)testPan {
CLLocationCoordinate2D centerCoordinate = tester.mapView.centerCoordinate;