PageRenderTime 85ms CodeModel.GetById 13ms app.highlight 67ms RepoModel.GetById 1ms app.codeStats 0ms

/MapView/UnitTesting/RouteMeTests.m

http://github.com/route-me/route-me
Objective C | 409 lines | 338 code | 60 blank | 11 comment | 6 complexity | a7feb33e7225b89eac828cc4eaa11569 MD5 | raw file
  1//
  2//  RouteMeTests.m
  3//  MapView
  4//
  5//  Created by Hal Mueller on 4/6/09.
  6//  Copyright 2009 Route-Me Contributors. All rights reserved.
  7//
  8
  9#import "RouteMeTests.h"
 10#import "RMMapView.h"
 11#import "RMCloudMadeMapSource.h"
 12#import "RMGeoHash.h"
 13#import "RMMarker.h"
 14#import "RMMarkerManager.h"
 15
 16@implementation RouteMeTests
 17#define kAccuracyThreshold .0001
 18#define kAccuracyThresholdForGeographicCoordinates .00001
 19#define kAccuracyThresholdForPixelCoordinates kAccuracyThreshold
 20
 21- (void)setUp {
 22    [super setUp];
 23
 24	CGRect appRect = [[UIScreen mainScreen] applicationFrame];
 25	contentView = [[UIView alloc] initWithFrame:appRect];
 26	contentView.backgroundColor = [UIColor greenColor];
 27	
 28	initialCenter.latitude = 66.44;
 29	initialCenter.longitude = -178.0;
 30	
 31	mapView = [[RMMapView alloc] initWithFrame:CGRectMake(10,20,200,300)
 32								  WithLocation:initialCenter];
 33	[contentView addSubview:mapView];
 34}
 35
 36-(void)tearDown {
 37    [mapView release]; mapView = nil;
 38	[super tearDown];
 39}
 40
 41- (void)testObjectCreation 
 42{
 43	
 44	STAssertNotNil((mapView = [[RMMapView alloc] init]), @"mapView alloc/init failed");
 45	STAssertNoThrow([mapView release], @"mapView release failed");
 46	mapView = nil;
 47	
 48	id myTilesource;
 49	STAssertNotNil((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d6934" styleNumber:999]),
 50				   @"tilesource creation failed");
 51	STAssertNoThrow([myTilesource release], @"tilesource release failed");
 52	STAssertNil((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:nil styleNumber:999]),
 53				@"empty CloudMade key does not trigger error");
 54	STAssertNoThrow([myTilesource release], @"tilesource release failed");
 55	STAssertThrows((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d693" styleNumber:999]),
 56				@"bogus CloudMade key does not trigger error");
 57	STAssertNoThrow([myTilesource release], @"tilesource release failed");
 58}
 59
 60- (void)testGeohashing 
 61{
 62	CLLocationCoordinate2D location1, location2;
 63	location1.latitude = 38.89;
 64	location1.longitude = -77.0;
 65	STAssertEqualStrings([RMGeoHash fromLocation:location1 withPrecision:6], @"dqcjr2", @"6-digit geohash location1 failed");
 66	STAssertEqualStrings([RMGeoHash fromLocation:location1 withPrecision:4], @"dqcj", @"4-digit geohash location1 failed");
 67	
 68	location2.latitude = 38.89;
 69	location2.longitude = -77.1;
 70	STAssertEqualStrings([RMGeoHash fromLocation:location2 withPrecision:6], @"dqcjjx", @"geohash location2 failed");
 71	STAssertEqualStrings([RMGeoHash fromLocation:location2 withPrecision:4], @"dqcj", @"4-digit geohash location1 failed");
 72											  
 73}
 74
 75- (void)testProgrammaticViewCreation
 76{
 77	STAssertNotNil(mapView, @"mapview creation failed");
 78	STAssertNotNil([mapView contents], @"mapView contents should not be nil");
 79}
 80
 81- (void)testMarkerCreation
 82{
 83	// create markers from -183 to -169 longitude 
 84	initialCenter.longitude = -178.0;
 85
 86	CLLocationCoordinate2D markerPosition;
 87	NSUInteger nRows = 1;
 88	NSUInteger nColumns = 8;
 89	double columnSpacing = 2.0;
 90	
 91	UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"];
 92	STAssertNotNil(markerImage, @"testMarkerCreation marker image did not load");
 93	markerPosition.latitude = initialCenter.latitude - ((nRows - 1)/2.0 * columnSpacing);
 94	NSUInteger i, j;
 95	for (i = 0; i < nRows; i++) {
 96		markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing);
 97		for (j = 0; j < nColumns; j++) {
 98			markerPosition.longitude += columnSpacing;
 99			RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage];
100			STAssertNotNil(newMarker, @"testMarkerCreation marker creation failed");
101			[newMarker setData:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]];
102			[mapView.contents.markerManager addMarker:newMarker
103			 AtLatLong:markerPosition];
104		}
105		markerPosition.latitude += columnSpacing;
106	}
107}
108
109- (void)testMarkerCoordinatesFarEast
110{
111	[mapView.contents setZoom:3.0];
112
113	// create markers from +177 to +191 longitude 
114	initialCenter.longitude = +176.0;
115	CLLocationCoordinate2D markerPosition;
116	
117	NSUInteger nColumns = 8;
118	double columnSpacing = 2.0;
119	
120	UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"];
121	markerPosition.latitude = initialCenter.latitude;
122	markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing);
123	NSUInteger j;
124	NSMutableArray *testMarkers = [NSMutableArray arrayWithCapacity:nColumns];
125	for (j = 0; j < nColumns; j++) {
126		markerPosition.longitude += columnSpacing;
127		RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage];
128		[testMarkers addObject:newMarker];
129		[newMarker setData:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]];
130		[mapView.contents.markerManager addMarker:newMarker
131		 AtLatLong:markerPosition];
132	}
133	STAssertGreaterThan(columnSpacing, 0.0, @"this test requires positive columnSpacing");
134
135	RMMarkerManager *mangler = [[mapView contents] markerManager];
136	
137	[[mapView contents] moveBy:CGSizeMake(-5.0, 0.0)];
138#ifdef DEBUG
139	RMSphericalTrapezium screenLimitsDegrees = [[mapView contents] latitudeLongitudeBoundingBoxForScreen];
140	RMLog(@"screen limits west: %4.1f east %4.1f", screenLimitsDegrees.southwest.longitude, screenLimitsDegrees.northeast.longitude);
141	RMLog(@"screen limits south: %4.1f north %4.1f", screenLimitsDegrees.southwest.latitude, screenLimitsDegrees.northeast.latitude);
142#endif
143	
144	for (j = 1; j < nColumns; j++) {
145		RMMarker *leftMarker = [testMarkers objectAtIndex:j - 1];
146		RMMarker *rightMarker = [testMarkers objectAtIndex:j];
147		CGPoint leftScreenPosition = [mangler screenCoordinatesForMarker:leftMarker];
148		CGPoint rightScreenPosition = [mangler screenCoordinatesForMarker:rightMarker];
149		RMLatLong leftMarkerCoordinate, rightMarkerCoordinate;
150		leftMarkerCoordinate.longitude = [[(NSArray *)leftMarker.data objectAtIndex:0] doubleValue];
151		leftMarkerCoordinate.latitude = [[(NSArray *)leftMarker.data objectAtIndex:1] doubleValue];
152		rightMarkerCoordinate.longitude = [[(NSArray *)rightMarker.data objectAtIndex:0] doubleValue];
153		rightMarkerCoordinate.latitude = [[(NSArray *)rightMarker.data objectAtIndex:1] doubleValue];
154		STAssertLessThan(leftScreenPosition.x, rightScreenPosition.x, 
155						 @"screen position calculation failed (markers %d, %d): left (%f, %f) right (%f, %f) mapped to left (%f, %f) right (%f, %f)",
156						 j-1, j,
157// write these out as longitude/latitude instead of standard latitude/longitude to make comparisons easier
158						 leftMarkerCoordinate.longitude, leftMarkerCoordinate.latitude,
159						 rightMarkerCoordinate.longitude, rightMarkerCoordinate.latitude,
160						 leftScreenPosition.x, leftScreenPosition.y, rightScreenPosition.x, rightScreenPosition.y);
161		CLLocationCoordinate2D computedLatitudeLongitude = 
162		[mangler latitudeLongitudeForMarker:leftMarker];
163		STAssertEqualsWithAccuracy(leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude, kAccuracyThresholdForGeographicCoordinates,
164								   @"round-trip computation of longitude failed %f %f",
165								   leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude);
166		STAssertEqualsWithAccuracy(leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude, kAccuracyThresholdForGeographicCoordinates,
167								   @"round-trip computation of latitude failed %f %f",
168								   leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude);
169	}
170	
171}
172
173- (void)testMarkerCoordinatesFarWest
174{
175	[mapView.contents setZoom:3.0];
176
177	// create markers from -177 to -169 longitude
178	initialCenter.longitude = -178.0;
179	CLLocationCoordinate2D markerPosition;
180	
181	NSUInteger nColumns = 8;
182	double columnSpacing = 2.0;
183	
184	UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"];
185	markerPosition.latitude = initialCenter.latitude;
186	markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing);
187	NSUInteger j;
188	NSMutableArray *testMarkers = [NSMutableArray arrayWithCapacity:nColumns];
189	for (j = 0; j < nColumns; j++) {
190		markerPosition.longitude += columnSpacing;
191		RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage];
192		[testMarkers addObject:newMarker];
193		[newMarker setData:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]];
194		[mapView.contents.markerManager addMarker:newMarker
195		 AtLatLong:markerPosition];
196	}
197	STAssertGreaterThan(columnSpacing, 0.0, @"this test requires positive columnSpacing");
198
199	RMMarkerManager *mangler = [[mapView contents] markerManager];
200	
201	[[mapView contents] moveBy:CGSizeMake(-5.0, 0.0)];
202#ifdef DEBUG
203	RMSphericalTrapezium screenLimitsDegrees = [[mapView contents] latitudeLongitudeBoundingBoxForScreen];
204	RMLog(@"screen limits west: %4.1f east %4.1f", screenLimitsDegrees.southwest.longitude, screenLimitsDegrees.northeast.longitude);
205	RMLog(@"screen limits south: %4.1f north %4.1f", screenLimitsDegrees.southwest.latitude, screenLimitsDegrees.northeast.latitude);
206#endif
207	
208	for (j = 1; j < nColumns; j++) {
209		RMMarker *leftMarker = [testMarkers objectAtIndex:j - 1];
210		RMMarker *rightMarker = [testMarkers objectAtIndex:j];
211		CGPoint leftScreenPosition = [mangler screenCoordinatesForMarker:leftMarker];
212		CGPoint rightScreenPosition = [mangler screenCoordinatesForMarker:rightMarker];
213		RMLatLong leftMarkerCoordinate, rightMarkerCoordinate;
214		leftMarkerCoordinate.longitude = [[(NSArray *)leftMarker.data objectAtIndex:0] doubleValue];
215		leftMarkerCoordinate.latitude = [[(NSArray *)leftMarker.data objectAtIndex:1] doubleValue];
216		rightMarkerCoordinate.longitude = [[(NSArray *)rightMarker.data objectAtIndex:0] doubleValue];
217		rightMarkerCoordinate.latitude = [[(NSArray *)rightMarker.data objectAtIndex:1] doubleValue];
218		STAssertLessThan(leftScreenPosition.x, rightScreenPosition.x, 
219						 @"screen position calculation failed (markers %d, %d): left (%f, %f) right (%f, %f) mapped to left (%f, %f) right (%f, %f)",
220						 j-1, j,
221						 leftMarkerCoordinate.longitude, leftMarkerCoordinate.latitude,
222						 rightMarkerCoordinate.longitude, rightMarkerCoordinate.latitude,
223						 leftScreenPosition.x, leftScreenPosition.y, rightScreenPosition.x, rightScreenPosition.y);
224		CLLocationCoordinate2D computedLatitudeLongitude = 
225		[mangler latitudeLongitudeForMarker:leftMarker];
226		STAssertEqualsWithAccuracy(leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude, kAccuracyThresholdForGeographicCoordinates,
227								   @"round-trip computation of longitude failed %f %f",
228								   leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude);
229		STAssertEqualsWithAccuracy(leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude, kAccuracyThresholdForGeographicCoordinates,
230								   @"round-trip computation of latitude failed %f %f",
231								   leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude);
232	}
233	
234}
235
236- (void)testScreenCoordinatesPacificNorthwest
237{
238	[[mapView contents] setZoom: 10];
239	CLLocationCoordinate2D coord = {45.5,-121};
240	[mapView moveToLatLong:coord];
241	
242	CGPoint point1 = [mapView latLongToPixel:coord];
243	
244	coord.longitude -= .125;
245	CGPoint point2 = [mapView latLongToPixel:coord];
246	
247	coord.longitude -= .125;
248	CGPoint point3 = [mapView latLongToPixel:coord];
249	
250	STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates,
251							   @"Y pixel values should be equal");
252	STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates,
253							   @"Y pixel values should be equal");
254	STAssertLessThan(point3.x, point2.x,
255					 @"X pixel coordinates should be increasing left to right");
256	STAssertLessThan(point2.x, point1.x,
257					 @"X pixel coordinates should be increasing left to right");
258}
259
260- (void)testScreenCoordinatesFarEast
261{
262	[[mapView contents] setZoom: 10];
263	CLLocationCoordinate2D coord = {45.5,179.9};
264	[mapView moveToLatLong:coord];
265	
266	CGPoint point1 = [mapView latLongToPixel:coord];
267	
268	coord.longitude += .125;
269	CGPoint point2 = [mapView latLongToPixel:coord];
270	
271	coord.longitude += .125;
272	CGPoint point3 = [mapView latLongToPixel:coord];
273	
274	STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates,
275							   @"Y pixel values should be equal");
276	STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates,
277							   @"Y pixel values should be equal");
278	STAssertLessThan(point1.x, point2.x,
279					 @"X pixel coordinates should be increasing left to right");
280	STAssertLessThan(point2.x, point3.x,
281					 @"X pixel coordinates should be increasing left to right");
282}
283
284- (void)testScreenCoordinatesFarWest
285{
286	[[mapView contents] setZoom: 10];
287	CLLocationCoordinate2D coord = {45.5,-179.9};
288	[mapView moveToLatLong:coord];
289	
290	CGPoint point1 = [mapView latLongToPixel:coord];
291	
292	coord.longitude -= .125;
293	CGPoint point2 = [mapView latLongToPixel:coord];
294	
295	coord.longitude -= .125;
296	CGPoint point3 = [mapView latLongToPixel:coord];
297	
298	STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates,
299							   @"Y pixel values should be equal");
300	STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates,
301							   @"Y pixel values should be equal");
302	STAssertLessThan(point3.x, point2.x,
303					 @"X pixel coordinates should be increasing left to right");
304	STAssertLessThan(point2.x, point1.x,
305					 @"X pixel coordinates should be increasing left to right");
306}
307
308- (void)testZoomBounds
309{
310	double contentsMaxZoom, tilesourceMaxZoom, contentsZoom;
311	contentsMaxZoom = [[mapView contents] maxZoom];
312	tilesourceMaxZoom = [[[mapView contents] tileSource] maxZoom];
313	contentsZoom = [[mapView contents] zoom];
314	STAssertLessThanOrEqual(contentsMaxZoom, tilesourceMaxZoom, @"map's maxZoom exceeds tilesource's maxZoom");
315	STAssertLessThanOrEqual(contentsZoom, tilesourceMaxZoom, @"map's zoom exceeds tilesource's maxZoom");
316	
317	double targetZoom = tilesourceMaxZoom + 0.4;
318	[[mapView contents] setZoom:targetZoom]; // try to exceed tilesource limit
319	contentsZoom = [[mapView contents] zoom];
320	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, @"map's zoom wrong after trying to exceed tilesource's maxZoom");
321	
322	targetZoom = tilesourceMaxZoom + 0.5;
323	[[mapView contents] setZoom:targetZoom]; // try to exceed tilesource limit
324	contentsZoom = [[mapView contents] zoom];
325	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, @"map's zoom wrong after trying to exceed tilesource's maxZoom");
326	
327	targetZoom = tilesourceMaxZoom - 1.6;
328	[[mapView contents] setZoom:targetZoom];
329	CGPoint pivotPoint = CGPointMake(5., 5.);
330	[[mapView contents] zoomInToNextNativeZoomAt:pivotPoint];
331	contentsZoom = [[mapView contents] zoom];
332	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom - 1.0, kAccuracyThreshold, 
333							   @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom-1 %f",
334							   contentsZoom, tilesourceMaxZoom);
335	[[mapView contents] zoomInToNextNativeZoomAt:pivotPoint];
336	contentsZoom = [[mapView contents] zoom];
337	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 
338							   @"map's zoom [%f] wrong after zoomInToNextNativeZoomAt: for maxZoom %f (first)",
339							   contentsZoom, tilesourceMaxZoom);
340	[[mapView contents] zoomInToNextNativeZoomAt:pivotPoint];
341	contentsZoom = [[mapView contents] zoom];
342	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 
343							   @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom %f (second)",
344							   contentsZoom, tilesourceMaxZoom);
345	
346	
347	targetZoom = tilesourceMaxZoom - 1.5;
348	[[mapView contents] setZoom:targetZoom];
349	pivotPoint = CGPointMake(5., 5.);
350	[[mapView contents] zoomInToNextNativeZoomAt:pivotPoint];
351	contentsZoom = [[mapView contents] zoom];
352	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom - 1.0, kAccuracyThreshold, 
353							   @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom-1 %f",
354							   contentsZoom, tilesourceMaxZoom);
355	[[mapView contents] zoomInToNextNativeZoomAt:pivotPoint];
356	contentsZoom = [[mapView contents] zoom];
357	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 
358							   @"map's zoom [%f] wrong after zoomInToNextNativeZoomAt: for maxZoom %f (first)",
359							   contentsZoom, tilesourceMaxZoom);
360	[[mapView contents] zoomInToNextNativeZoomAt:pivotPoint];
361	contentsZoom = [[mapView contents] zoom];
362	STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 
363							   @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom %f (second)",
364							   contentsZoom, tilesourceMaxZoom);
365	
366	
367	double contentsMinZoom = 3.0;
368	[[mapView contents] setMinZoom:contentsMinZoom];
369	targetZoom = contentsMinZoom + 0.6;	
370	[[mapView contents] setZoom:targetZoom];
371	contentsZoom = [[mapView contents] zoom];
372	NSLog(@"zoom: %f minZoom: %f", contentsZoom, [[mapView contents] minZoom]);
373	[[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint];
374	contentsZoom = [[mapView contents] zoom];
375	STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 
376							   @"map's zoom %f wrong after first zoomOutToNextNativeZoomAt: for minZoom %f",
377							   contentsZoom, contentsMinZoom);
378	[[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint];
379	contentsZoom = [[mapView contents] zoom];
380	STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 
381							   @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f",
382							   contentsZoom, contentsMinZoom);
383	
384	contentsMinZoom = 3.0;
385	[[mapView contents] setMinZoom:contentsMinZoom];
386	targetZoom = contentsMinZoom + 1.6;	
387	[[mapView contents] setZoom:targetZoom];
388	contentsZoom = [[mapView contents] zoom];
389	NSLog(@"zoom: %f minZoom: %f", contentsZoom, [[mapView contents] minZoom]);
390	[[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint];
391	contentsZoom = [[mapView contents] zoom];
392	STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom+1.0, kAccuracyThreshold, 
393							   @"map's zoom %f wrong after first zoomOutToNextNativeZoomAt: for minZoom %f",
394							   contentsZoom, contentsMinZoom);
395	[[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint];
396	contentsZoom = [[mapView contents] zoom];
397	STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 
398							   @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f",
399							   contentsZoom, contentsMinZoom);
400	[[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint];
401	contentsZoom = [[mapView contents] zoom];
402	STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 
403							   @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f",
404							   contentsZoom, contentsMinZoom);
405	
406	
407}
408
409@end