/MapView/Map/RMMarkerManager.m
Objective C | 205 lines | 130 code | 34 blank | 41 comment | 19 complexity | eb7c2aeebd887e8a1b67cfeac0a08829 MD5 | raw file
1// 2// RMMarkerManager.m 3// 4// Copyright (c) 2008-2009, Route-Me Contributors 5// All rights reserved. 6// 7// Redistribution and use in source and binary forms, with or without 8// modification, are permitted provided that the following conditions are met: 9// 10// * Redistributions of source code must retain the above copyright notice, this 11// list of conditions and the following disclaimer. 12// * Redistributions in binary form must reproduce the above copyright notice, 13// this list of conditions and the following disclaimer in the documentation 14// and/or other materials provided with the distribution. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26// POSSIBILITY OF SUCH DAMAGE. 27 28#import "RMMarkerManager.h" 29#import "RMMercatorToScreenProjection.h" 30#import "RMProjection.h" 31#import "RMLayerCollection.h" 32 33@implementation RMMarkerManager 34 35@synthesize contents; 36 37- (id)initWithContents:(RMMapContents *)mapContents 38{ 39 if (![super init]) 40 return nil; 41 42 contents = mapContents; 43 44 rotationTransform = CGAffineTransformIdentity; 45 46 return self; 47} 48 49- (void)dealloc 50{ 51 contents = nil; 52 [super dealloc]; 53} 54 55/////////////////////////////////////////////////////////////////////////////////////////////////// 56#pragma mark 57#pragma mark Adding / Removing / Displaying Markers 58 59/// place the (new created) marker onto the map at projected point and take ownership of it 60- (void)addMarker:(RMMarker *)marker atProjectedPoint:(RMProjectedPoint)projectedPoint { 61 62 // only set the AffineTransform if the marker has rotation enabled 63 if (marker.enableRotation) { 64 [marker setAffineTransform:rotationTransform]; 65 } else { 66 [marker setAffineTransform:CGAffineTransformMakeRotation(0.0f)]; 67 } 68 [marker setProjectedLocation:projectedPoint]; 69 [marker setPosition:[[contents mercatorToScreenProjection] projectXYPoint:projectedPoint]]; 70 [[contents overlay] addSublayer:marker]; 71} 72 73/// place the (newly created) marker onto the map and take ownership of it 74/// \bug should return the marker 75- (void) addMarker: (RMMarker*)marker AtLatLong:(CLLocationCoordinate2D)point 76{ 77 [self addMarker:marker atProjectedPoint:[[contents projection] latLongToPoint:point]]; 78} 79 80/// \bug see http://code.google.com/p/route-me/issues/detail?id=75 81/// (halmueller): I am skeptical about interactions of this code with paths 82- (void) removeMarkers 83{ 84 [[contents overlay] setSublayers:[NSArray arrayWithObjects:nil]]; 85} 86 87/// \bug this will hide path overlays too? 88/// \deprecated syntactic sugar. Might have a place on RMMapView, but not on RMMarkerManager. 89- (void) hideAllMarkers 90{ 91 [[contents overlay] setHidden:YES]; 92} 93 94/// \bug this will hide path overlays too? 95/// \deprecated syntactic sugar. Might have a place on RMMapView, but not on RMMarkerManager. 96- (void) unhideAllMarkers 97{ 98 [[contents overlay] setHidden:NO]; 99} 100 101/////////////////////////////////////////////////////////////////////////////////////////////////// 102#pragma mark 103#pragma mark Marker information 104 105- (NSArray *)markers 106{ 107 return [[contents overlay] sublayers]; 108} 109 110- (void) removeMarker:(RMMarker *)marker 111{ 112 [[contents overlay] removeSublayer:marker]; 113} 114 115- (void) removeMarkers:(NSArray *)markers 116{ 117 [[contents overlay] removeSublayers:markers]; 118} 119 120- (CGPoint) screenCoordinatesForMarker: (RMMarker *)marker 121{ 122 return [[contents mercatorToScreenProjection] projectXYPoint:[marker projectedLocation]]; 123} 124 125- (CLLocationCoordinate2D) latitudeLongitudeForMarker: (RMMarker *) marker 126{ 127 return [contents pixelToLatLong:[self screenCoordinatesForMarker:marker]]; 128} 129 130- (NSArray *) markersWithinScreenBounds 131{ 132 NSMutableArray *markersInScreenBounds = [NSMutableArray array]; 133 CGRect rect = [[contents mercatorToScreenProjection] screenBounds]; 134 135 for (RMMarker *marker in [self markers]) { 136 if ([self isMarker:marker withinBounds:rect]) { 137 [markersInScreenBounds addObject:marker]; 138 } 139 } 140 141 return markersInScreenBounds; 142} 143 144- (BOOL) isMarkerWithinScreenBounds:(RMMarker*)marker 145{ 146 return [self isMarker:marker withinBounds:[[contents mercatorToScreenProjection] screenBounds]]; 147} 148 149/// \deprecated violates Objective-C naming rules 150- (BOOL) isMarker:(RMMarker*)marker withinBounds:(CGRect)rect 151{ 152 if (![self managingMarker:marker]) { 153 return NO; 154 } 155 156 CGPoint markerCoord = [self screenCoordinatesForMarker:marker]; 157 158 if ( markerCoord.x > rect.origin.x 159 && markerCoord.x < rect.origin.x + rect.size.width 160 && markerCoord.y > rect.origin.y 161 && markerCoord.y < rect.origin.y + rect.size.height) 162 { 163 return YES; 164 } 165 return NO; 166} 167 168/// \deprecated violates Objective-C naming rules 169- (BOOL) managingMarker:(RMMarker*)marker 170{ 171 NSArray *markers = [self markers]; 172 if (marker != nil && markers != nil && [markers indexOfObject:marker] != NSNotFound) { 173 return YES; 174 } 175 return NO; 176} 177 178- (void) moveMarker:(RMMarker *)marker AtLatLon:(RMLatLong)point 179{ 180 [marker setProjectedLocation:[[contents projection]latLongToPoint:point]]; 181 [marker setPosition:[[contents mercatorToScreenProjection] projectXYPoint:[[contents projection] latLongToPoint:point]]]; 182} 183 184- (void) moveMarker:(RMMarker *)marker AtXY:(CGPoint)point 185{ 186 [marker setProjectedLocation:[[contents mercatorToScreenProjection] projectScreenPointToXY:point]]; 187 [marker setPosition:point]; 188} 189 190- (void)setRotation:(float)angle 191{ 192 rotationTransform = CGAffineTransformMakeRotation(angle); // store rotation transform for subsequent markers 193 194 for (RMMarker *marker in [self markers]) 195 { 196 // only apply rotation if the marker has it enabled 197 if (marker.enableRotation) { 198 [marker setAffineTransform:rotationTransform]; 199 } else { 200 [marker setAffineTransform:CGAffineTransformMakeRotation(0.0f)]; 201 } 202 } 203} 204 205@end