Authored by Thomas Rasch

o RMMapView major cleanup

... ... @@ -38,19 +38,6 @@
#import "RMMapScrollView.h"
#import "RMTileSourcesContainer.h"
// constants for boundingMask
enum : NSUInteger {
RMMapNoMinBound = 0, // Map can be zoomed out past view limits
RMMapMinHeightBound = 1, // Minimum map height when zooming out restricted to view height
RMMapMinWidthBound = 2 // Minimum map width when zooming out restricted to view width (default)
};
typedef enum : NSUInteger {
RMMapDecelerationNormal,
RMMapDecelerationFast,
RMMapDecelerationOff
} RMMapDecelerationMode;
@class RMProjection;
@class RMFractalTileProjection;
@class RMTileCache;
... ... @@ -61,86 +48,47 @@ typedef enum : NSUInteger {
@class RMAnnotation;
@class RMQuadTree;
@protocol RMMercatorToTileProjection;
@protocol RMTileSource;
@protocol RMMapScrollViewDelegate;
@interface RMMapView : UIView <UIScrollViewDelegate, RMMapOverlayViewDelegate,
RMMapTiledLayerViewDelegate, RMMapScrollViewDelegate>
{
id <RMMapViewDelegate> delegate;
RMProjection *projection;
RMFractalTileProjection *mercatorToTileProjection;
UIView *backgroundView;
RMMapScrollView *mapScrollView;
RMMapOverlayView *overlayView;
double metersPerPixel;
BOOL adjustTilesForRetinaDisplay;
NSMutableSet *annotations;
NSMutableSet *visibleAnnotations;
RMQuadTree *quadTree;
BOOL enableClustering, positionClusterMarkersAtTheGravityCenter;
CGSize clusterMarkerSize, clusterAreaSize;
// constants for boundingMask
enum : NSUInteger {
RMMapNoMinBound = 0, // Map can be zoomed out past view limits
RMMapMinHeightBound = 1, // Minimum map height when zooming out restricted to view height
RMMapMinWidthBound = 2 // Minimum map width when zooming out restricted to view width (default)
};
RMTileCache *tileCache; // Generic tile cache
// constants for the scrollview deceleration mode
typedef enum : NSUInteger {
RMMapDecelerationNormal = 0, // default
RMMapDecelerationFast = 1,
RMMapDecelerationOff = 2
} RMMapDecelerationMode;
float minZoom, maxZoom, zoom;
float screenScale;
NSUInteger missingTilesDepth;
NSUInteger boundingMask;
}
@interface RMMapView : UIView <UIScrollViewDelegate, RMMapOverlayViewDelegate,
RMMapTiledLayerViewDelegate, RMMapScrollViewDelegate>
@property (nonatomic, assign) id <RMMapViewDelegate> delegate;
// View properties
#pragma mark - View properties
@property (nonatomic, assign) BOOL enableDragging;
@property (nonatomic, assign) BOOL enableBouncing;
@property (nonatomic, assign) RMMapDecelerationMode decelerationMode;
@property (nonatomic, assign) CLLocationCoordinate2D centerCoordinate;
@property (nonatomic, assign) RMProjectedPoint centerProjectedPoint;
@property (nonatomic, assign) RMProjectedRect projectedBounds;
@property (nonatomic, readonly) RMProjectedPoint projectedOrigin;
@property (nonatomic, readonly) RMProjectedSize projectedViewSize;
@property (nonatomic, assign) double metersPerPixel;
@property (nonatomic, readonly) double scaledMetersPerPixel;
@property (nonatomic, readonly) double scaleDenominator; /// The denominator in a cartographic scale like 1/24000, 1/50000, 1/2000000.
@property (nonatomic, readonly) double scaleDenominator; // The denominator in a cartographic scale like 1/24000, 1/50000, 1/2000000.
@property (nonatomic, readonly) float screenScale;
@property (nonatomic, assign) BOOL adjustTilesForRetinaDisplay;
@property (nonatomic, readonly) float adjustedZoomForRetinaDisplay; // takes adjustTilesForRetinaDisplay and screen scale into account
/// minimum and maximum zoom number allowed for the view. #minZoom and #maxZoom must be within the limits of #tileSource but can be stricter; they are clamped to tilesource limits (minZoom, maxZoom) if needed.
@property (nonatomic, assign) float zoom;
@property (nonatomic, assign) float minZoom;
@property (nonatomic, assign) float maxZoom;
/// take missing tiles from lower zoom levels, up to #missingTilesDepth zoom levels (defaults to 0, which disables this feature)
// take missing tiles from lower zoom levels, up to #missingTilesDepth zoom levels (defaults to 0, which disables this feature)
@property (nonatomic, assign) NSUInteger missingTilesDepth;
@property (nonatomic, assign) NSUInteger boundingMask;
@property (nonatomic, retain) RMQuadTree *quadTree;
@property (nonatomic, assign) BOOL enableClustering;
@property (nonatomic, assign) BOOL positionClusterMarkersAtTheGravityCenter;
@property (nonatomic, assign) CGSize clusterMarkerSize;
@property (nonatomic, assign) CGSize clusterAreaSize;
/// projection objects to convert from latitude/longitude to meters, from projected meters to tile coordinates
@property (nonatomic, readonly) RMProjection *projection;
@property (nonatomic, readonly) id <RMMercatorToTileProjection> mercatorToTileProjection;
@property (nonatomic, assign) NSUInteger boundingMask;
@property (nonatomic, retain) RMTileCache *tileCache;
@property (nonatomic, readonly) RMTileSourcesContainer *tileSourcesContainer;
/// subview for the background image displayed while tiles are loading.
// subview for the background image displayed while tiles are loading.
@property (nonatomic, retain) UIView *backgroundView;
@property (nonatomic, assign) BOOL debugTiles;
... ... @@ -149,7 +97,7 @@ typedef enum : NSUInteger {
- (id)initWithFrame:(CGRect)frame andTilesource:(id <RMTileSource>)newTilesource;
/// designated initializer
// designated initializer
- (id)initWithFrame:(CGRect)frame
andTilesource:(id <RMTileSource>)newTilesource
centerCoordinate:(CLLocationCoordinate2D)initialCenterCoordinate
... ... @@ -162,17 +110,29 @@ typedef enum : NSUInteger {
#pragma mark - Movement
/// recenter the map on #coordinate, expressed as CLLocationCoordinate2D (latitude/longitude)
@property (nonatomic, assign) CLLocationCoordinate2D centerCoordinate;
@property (nonatomic, assign) RMProjectedPoint centerProjectedPoint;
// recenter the map on #coordinate, expressed as CLLocationCoordinate2D (latitude/longitude)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
/// recenter the map on #aPoint, expressed in projected meters
// recenter the map on #aPoint, expressed in projected meters
- (void)setCenterProjectedPoint:(RMProjectedPoint)aPoint animated:(BOOL)animated;
- (void)moveBy:(CGSize)delta;
#pragma mark - Zoom
/// recenter the map on #boundsRect, expressed in projected meters
// minimum and maximum zoom number allowed for the view. #minZoom and #maxZoom must be within the limits of #tileSource but can be stricter; they are clamped to tilesource limits (minZoom, maxZoom) if needed.
@property (nonatomic, assign) float zoom;
@property (nonatomic, assign) float minZoom;
@property (nonatomic, assign) float maxZoom;
@property (nonatomic, assign) RMProjectedRect projectedBounds;
@property (nonatomic, readonly) RMProjectedPoint projectedOrigin;
@property (nonatomic, readonly) RMProjectedSize projectedViewSize;
// recenter the map on #boundsRect, expressed in projected meters
- (void)setProjectedBounds:(RMProjectedRect)boundsRect animated:(BOOL)animated;
- (void)zoomByFactor:(float)zoomFactor near:(CGPoint)center animated:(BOOL)animated;
... ... @@ -187,38 +147,26 @@ typedef enum : NSUInteger {
- (void)setMetersPerPixel:(double)newMetersPerPixel animated:(BOOL)animated;
#pragma mark - Conversions
- (CGPoint)projectedPointToPixel:(RMProjectedPoint)projectedPoint;
- (CGPoint)coordinateToPixel:(CLLocationCoordinate2D)coordinate;
- (RMProjectedPoint)pixelToProjectedPoint:(CGPoint)pixelCoordinate;
- (CLLocationCoordinate2D)pixelToCoordinate:(CGPoint)pixelCoordinate;
- (RMProjectedPoint)coordinateToProjectedPoint:(CLLocationCoordinate2D)coordinate;
- (CLLocationCoordinate2D)projectedPointToCoordinate:(RMProjectedPoint)projectedPoint;
- (RMProjectedSize)viewSizeToProjectedSize:(CGSize)screenSize;
- (CGSize)projectedSizeToViewSize:(RMProjectedSize)projectedSize;
- (CLLocationCoordinate2D)normalizeCoordinate:(CLLocationCoordinate2D)coordinate;
- (RMTile)tileWithCoordinate:(CLLocationCoordinate2D)coordinate andZoom:(int)zoom;
#pragma mark - Bounds
/// returns the smallest bounding box containing the entire view
// returns the smallest bounding box containing the entire view
- (RMSphericalTrapezium)latitudeLongitudeBoundingBox;
/// returns the smallest bounding box containing a rectangular region of the view
// returns the smallest bounding box containing a rectangular region of the view
- (RMSphericalTrapezium)latitudeLongitudeBoundingBoxFor:(CGRect) rect;
#pragma mark - Bounds
- (BOOL)tileSourceBoundsContainProjectedPoint:(RMProjectedPoint)point;
- (void)setConstraintsSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast;
- (void)setProjectedConstraintsSouthWest:(RMProjectedPoint)southWest northEast:(RMProjectedPoint)northEast;
#pragma mark - Snapshots
- (UIImage *)takeSnapshot;
- (UIImage *)takeSnapshotAndIncludeOverlay:(BOOL)includeOverlay;
#pragma mark - Annotations
- (NSArray *)annotations;
@property (nonatomic, readonly) NSArray *annotations;
- (void)addAnnotation:(RMAnnotation *)annotation;
- (void)addAnnotations:(NSArray *)annotations;
... ... @@ -231,8 +179,18 @@ typedef enum : NSUInteger {
#pragma mark - TileSources
- (id <RMTileSource>)tileSource; // the first tile source, for backwards compatibility
- (NSArray *)tileSources;
@property (nonatomic, retain) RMQuadTree *quadTree;
@property (nonatomic, assign) BOOL enableClustering;
@property (nonatomic, assign) BOOL positionClusterMarkersAtTheGravityCenter;
@property (nonatomic, assign) CGSize clusterMarkerSize;
@property (nonatomic, assign) CGSize clusterAreaSize;
@property (nonatomic, retain) RMTileCache *tileCache;
@property (nonatomic, readonly) RMTileSourcesContainer *tileSourcesContainer;
@property (nonatomic, readonly) id <RMTileSource> tileSource; // the first tile source, for backwards compatibility
@property (nonatomic, readonly) NSArray *tileSources;
- (BOOL)setTileSource:(id <RMTileSource>)tileSource; // replaces all tilesources with the new tilesource
... ... @@ -249,12 +207,28 @@ typedef enum : NSUInteger {
#pragma mark - Cache
/// Clear all images from the #tileSource's caching system.
// Clear all images from the #tileSource's caching system.
-(void)removeAllCachedImages;
#pragma mark - Snapshots
#pragma mark - Conversions
- (UIImage *)takeSnapshot;
- (UIImage *)takeSnapshotAndIncludeOverlay:(BOOL)includeOverlay;
// projections to convert from latitude/longitude to meters, from projected meters to tile coordinates
@property (nonatomic, readonly) RMProjection *projection;
@property (nonatomic, readonly) id <RMMercatorToTileProjection> mercatorToTileProjection;
- (CGPoint)projectedPointToPixel:(RMProjectedPoint)projectedPoint;
- (CGPoint)coordinateToPixel:(CLLocationCoordinate2D)coordinate;
- (RMProjectedPoint)pixelToProjectedPoint:(CGPoint)pixelCoordinate;
- (CLLocationCoordinate2D)pixelToCoordinate:(CGPoint)pixelCoordinate;
- (RMProjectedPoint)coordinateToProjectedPoint:(CLLocationCoordinate2D)coordinate;
- (CLLocationCoordinate2D)projectedPointToCoordinate:(RMProjectedPoint)projectedPoint;
- (RMProjectedSize)viewSizeToProjectedSize:(CGSize)screenSize;
- (CGSize)projectedSizeToViewSize:(RMProjectedSize)projectedSize;
- (CLLocationCoordinate2D)normalizeCoordinate:(CLLocationCoordinate2D)coordinate;
- (RMTile)tileWithCoordinate:(CLLocationCoordinate2D)coordinate andZoom:(int)zoom;
@end
... ...
//
// RMMapView.m
//
// Copyright (c) 2008-2009, Route-Me Contributors
// Copyright (c) 2008-2012, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
... ... @@ -61,8 +61,6 @@
@interface RMMapView (PrivateMethods)
@property (nonatomic, retain) RMMapLayer *overlay;
- (void)createMapView;
- (void)correctPositionOfAllAnnotations;
... ... @@ -76,6 +74,8 @@
@implementation RMMapView
{
id <RMMapViewDelegate> _delegate;
BOOL _delegateHasBeforeMapMove;
BOOL _delegateHasAfterMapMove;
BOOL _delegateHasBeforeMapZoom;
... ... @@ -97,13 +97,23 @@
BOOL _delegateHasWillHideLayerForAnnotation;
BOOL _delegateHasDidHideLayerForAnnotation;
RMTileSourcesContainer *_tileSourcesContainer;
UIView *_backgroundView;
RMMapScrollView *_mapScrollView;
RMMapOverlayView *_overlayView;
UIView *_tiledLayersSuperview;
RMProjection *_projection;
RMFractalTileProjection *_mercatorToTileProjection;
RMTileSourcesContainer *_tileSourcesContainer;
NSMutableSet *_annotations;
NSMutableSet *_visibleAnnotations;
BOOL _constrainMovement;
RMProjectedRect _constrainingProjectedBounds;
float _lastZoom;
double _metersPerPixel;
float _zoom, _lastZoom;
CGPoint _lastContentOffset, _accumulatedDelta;
CGSize _lastContentSize;
BOOL _mapScrollViewIsZooming;
... ... @@ -111,17 +121,19 @@
BOOL _enableDragging, _enableBouncing;
}
@synthesize decelerationMode;
@synthesize decelerationMode = _decelerationMode;
@synthesize boundingMask;
@synthesize minZoom, maxZoom;
@synthesize screenScale;
@synthesize tileCache;
@synthesize quadTree;
@synthesize enableClustering, positionClusterMarkersAtTheGravityCenter, clusterMarkerSize, clusterAreaSize;
@synthesize adjustTilesForRetinaDisplay;
@synthesize missingTilesDepth;
@synthesize debugTiles;
@synthesize boundingMask = _boundingMask;
@synthesize minZoom = _minZoom, maxZoom = _maxZoom;
@synthesize screenScale = _screenScale;
@synthesize tileCache = _tileCache;
@synthesize quadTree = _quadTree;
@synthesize enableClustering = _enableClustering;
@synthesize positionClusterMarkersAtTheGravityCenter = _positionClusterMarkersAtTheGravityCenter;
@synthesize clusterMarkerSize = _clusterMarkerSize, clusterAreaSize = _clusterAreaSize;
@synthesize adjustTilesForRetinaDisplay = _adjustTilesForRetinaDisplay;
@synthesize missingTilesDepth = _missingTilesDepth;
@synthesize debugTiles = _debugTiles;
#pragma mark -
#pragma mark Initialization
... ... @@ -141,23 +153,24 @@
_tileSourcesContainer = [RMTileSourcesContainer new];
_tiledLayersSuperview = nil;
projection = nil;
mercatorToTileProjection = nil;
mapScrollView = nil;
overlayView = nil;
_projection = nil;
_mercatorToTileProjection = nil;
_mapScrollView = nil;
_overlayView = nil;
screenScale = [UIScreen mainScreen].scale;
_screenScale = [UIScreen mainScreen].scale;
boundingMask = RMMapMinWidthBound;
adjustTilesForRetinaDisplay = NO;
missingTilesDepth = 0;
_boundingMask = RMMapMinWidthBound;
_adjustTilesForRetinaDisplay = NO;
_missingTilesDepth = 0;
_debugTiles = NO;
annotations = [NSMutableSet new];
visibleAnnotations = [NSMutableSet new];
_annotations = [NSMutableSet new];
_visibleAnnotations = [NSMutableSet new];
[self setQuadTree:[[[RMQuadTree alloc] initWithMapView:self] autorelease]];
enableClustering = positionClusterMarkersAtTheGravityCenter = NO;
clusterMarkerSize = CGSizeMake(100.0, 100.0);
clusterAreaSize = CGSizeMake(150.0, 150.0);
_enableClustering = _positionClusterMarkersAtTheGravityCenter = NO;
_clusterMarkerSize = CGSizeMake(100.0, 100.0);
_clusterAreaSize = CGSizeMake(150.0, 150.0);
[self setTileCache:[[[RMTileCache alloc] init] autorelease]];
... ... @@ -179,7 +192,7 @@
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
RMLog(@"Map initialised. tileSource:%@, minZoom:%f, maxZoom:%f, zoom:%f at {%f,%f}", newTilesource, [self minZoom], [self maxZoom], [self zoom], [self centerCoordinate].longitude, [self centerCoordinate].latitude);
RMLog(@"Map initialised. tileSource:%@, minZoom:%f, maxZoom:%f, zoom:%f at {%f,%f}", newTilesource, self.minZoom, self.maxZoom, self.zoom, initialCenterCoordinate.longitude, initialCenterCoordinate.latitude);
}
- (id)initWithCoder:(NSCoder *)aDecoder
... ... @@ -256,14 +269,14 @@
[super setFrame:frame];
// only change if the frame changes and not during initialization
if (!CGRectEqualToRect(r, frame))
if ( ! CGRectEqualToRect(r, frame))
{
RMProjectedPoint centerPoint = [self centerProjectedPoint];
RMProjectedPoint centerPoint = self.centerProjectedPoint;
CGRect bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
backgroundView.frame = bounds;
mapScrollView.frame = bounds;
overlayView.frame = bounds;
_backgroundView.frame = bounds;
_mapScrollView.frame = bounds;
_overlayView.frame = bounds;
[self setCenterProjectedPoint:centerPoint animated:NO];
... ... @@ -279,16 +292,16 @@
[self setDelegate:nil];
[self setBackgroundView:nil];
[self setQuadTree:nil];
[annotations release]; annotations = nil;
[visibleAnnotations release]; visibleAnnotations = nil;
[_annotations release]; _annotations = nil;
[_visibleAnnotations release]; _visibleAnnotations = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[mapScrollView removeObserver:self forKeyPath:@"contentOffset"];
[_mapScrollView removeObserver:self forKeyPath:@"contentOffset"];
[_tiledLayersSuperview release]; _tiledLayersSuperview = nil;
[mapScrollView release]; mapScrollView = nil;
[overlayView release]; overlayView = nil;
[_mapScrollView release]; _mapScrollView = nil;
[_overlayView release]; _overlayView = nil;
[_tileSourcesContainer cancelAllDownloads]; [_tileSourcesContainer release]; _tileSourcesContainer = nil;
[projection release]; projection = nil;
[mercatorToTileProjection release]; mercatorToTileProjection = nil;
[_projection release]; _projection = nil;
[_mercatorToTileProjection release]; _mercatorToTileProjection = nil;
[self setTileCache:nil];
[super dealloc];
}
... ... @@ -297,8 +310,8 @@
{
LogMethod();
[_tileSourcesContainer didReceiveMemoryWarning];
[tileCache didReceiveMemoryWarning];
[self.tileCache didReceiveMemoryWarning];
[self.tileSourcesContainer didReceiveMemoryWarning];
}
- (void)handleMemoryWarningNotification:(NSNotification *)notification
... ... @@ -308,54 +321,52 @@
- (NSString *)description
{
CGRect bounds = [self bounds];
CGRect bounds = self.bounds;
return [NSString stringWithFormat:@"MapView at {%.0f,%.0f}-{%.0f,%.0f}", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height];
return [NSString stringWithFormat:@"MapView at {%.0f,%.0f}-{%.0fx%.0f}", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height];
}
#pragma mark -
#pragma mark Delegate
@dynamic delegate;
- (id <RMMapViewDelegate>)delegate
{
return _delegate;
}
- (void)setDelegate:(id <RMMapViewDelegate>)aDelegate
{
if (delegate == aDelegate)
if (_delegate == aDelegate)
return;
delegate = aDelegate;
_delegate = aDelegate;
_delegateHasBeforeMapMove = [delegate respondsToSelector:@selector(beforeMapMove:)];
_delegateHasAfterMapMove = [delegate respondsToSelector:@selector(afterMapMove:)];
_delegateHasBeforeMapMove = [_delegate respondsToSelector:@selector(beforeMapMove:)];
_delegateHasAfterMapMove = [_delegate respondsToSelector:@selector(afterMapMove:)];
_delegateHasBeforeMapZoom = [delegate respondsToSelector:@selector(beforeMapZoom:)];
_delegateHasAfterMapZoom = [delegate respondsToSelector:@selector(afterMapZoom:)];
_delegateHasBeforeMapZoom = [_delegate respondsToSelector:@selector(beforeMapZoom:)];
_delegateHasAfterMapZoom = [_delegate respondsToSelector:@selector(afterMapZoom:)];
_delegateHasMapViewRegionDidChange = [delegate respondsToSelector:@selector(mapViewRegionDidChange:)];
_delegateHasMapViewRegionDidChange = [_delegate respondsToSelector:@selector(mapViewRegionDidChange:)];
_delegateHasDoubleTapOnMap = [delegate respondsToSelector:@selector(doubleTapOnMap:at:)];
_delegateHasDoubleTapTwoFingersOnMap = [delegate respondsToSelector:@selector(doubleTapTwoFingersOnMap:at:)];
_delegateHasSingleTapOnMap = [delegate respondsToSelector:@selector(singleTapOnMap:at:)];
_delegateHasSingleTapTwoFingersOnMap = [delegate respondsToSelector:@selector(singleTapTwoFingersOnMap:at:)];
_delegateHasLongSingleTapOnMap = [delegate respondsToSelector:@selector(longSingleTapOnMap:at:)];
_delegateHasDoubleTapOnMap = [_delegate respondsToSelector:@selector(doubleTapOnMap:at:)];
_delegateHasDoubleTapTwoFingersOnMap = [_delegate respondsToSelector:@selector(doubleTapTwoFingersOnMap:at:)];
_delegateHasSingleTapOnMap = [_delegate respondsToSelector:@selector(singleTapOnMap:at:)];
_delegateHasSingleTapTwoFingersOnMap = [_delegate respondsToSelector:@selector(singleTapTwoFingersOnMap:at:)];
_delegateHasLongSingleTapOnMap = [_delegate respondsToSelector:@selector(longSingleTapOnMap:at:)];
_delegateHasTapOnAnnotation = [delegate respondsToSelector:@selector(tapOnAnnotation:onMap:)];
_delegateHasDoubleTapOnAnnotation = [delegate respondsToSelector:@selector(doubleTapOnAnnotation:onMap:)];
_delegateHasTapOnLabelForAnnotation = [delegate respondsToSelector:@selector(tapOnLabelForAnnotation:onMap:)];
_delegateHasDoubleTapOnLabelForAnnotation = [delegate respondsToSelector:@selector(doubleTapOnLabelForAnnotation:onMap:)];
_delegateHasTapOnAnnotation = [_delegate respondsToSelector:@selector(tapOnAnnotation:onMap:)];
_delegateHasDoubleTapOnAnnotation = [_delegate respondsToSelector:@selector(doubleTapOnAnnotation:onMap:)];
_delegateHasTapOnLabelForAnnotation = [_delegate respondsToSelector:@selector(tapOnLabelForAnnotation:onMap:)];
_delegateHasDoubleTapOnLabelForAnnotation = [_delegate respondsToSelector:@selector(doubleTapOnLabelForAnnotation:onMap:)];
_delegateHasShouldDragMarker = [delegate respondsToSelector:@selector(mapView:shouldDragAnnotation:)];
_delegateHasDidDragMarker = [delegate respondsToSelector:@selector(mapView:didDragAnnotation:withDelta:)];
_delegateHasDidEndDragMarker = [delegate respondsToSelector:@selector(mapView:didEndDragAnnotation:)];
_delegateHasShouldDragMarker = [_delegate respondsToSelector:@selector(mapView:shouldDragAnnotation:)];
_delegateHasDidDragMarker = [_delegate respondsToSelector:@selector(mapView:didDragAnnotation:withDelta:)];
_delegateHasDidEndDragMarker = [_delegate respondsToSelector:@selector(mapView:didEndDragAnnotation:)];
_delegateHasLayerForAnnotation = [delegate respondsToSelector:@selector(mapView:layerForAnnotation:)];
_delegateHasWillHideLayerForAnnotation = [delegate respondsToSelector:@selector(mapView:willHideLayerForAnnotation:)];
_delegateHasDidHideLayerForAnnotation = [delegate respondsToSelector:@selector(mapView:didHideLayerForAnnotation:)];
}
- (id <RMMapViewDelegate>)delegate
{
return delegate;
_delegateHasLayerForAnnotation = [_delegate respondsToSelector:@selector(mapView:layerForAnnotation:)];
_delegateHasWillHideLayerForAnnotation = [_delegate respondsToSelector:@selector(mapView:willHideLayerForAnnotation:)];
_delegateHasDidHideLayerForAnnotation = [_delegate respondsToSelector:@selector(mapView:didHideLayerForAnnotation:)];
}
#pragma mark -
... ... @@ -388,6 +399,7 @@
- (RMProjectedRect)projectedRectFromLatitudeLongitudeBounds:(RMSphericalTrapezium)bounds
{
float pixelBuffer = kZoomRectPixelBuffer;
CLLocationCoordinate2D southWest = bounds.southWest;
CLLocationCoordinate2D northEast = bounds.northEast;
CLLocationCoordinate2D midpoint = {
... ... @@ -395,9 +407,9 @@
.longitude = (northEast.longitude + southWest.longitude) / 2
};
RMProjectedPoint myOrigin = [projection coordinateToProjectedPoint:midpoint];
RMProjectedPoint southWestPoint = [projection coordinateToProjectedPoint:southWest];
RMProjectedPoint northEastPoint = [projection coordinateToProjectedPoint:northEast];
RMProjectedPoint myOrigin = [_projection coordinateToProjectedPoint:midpoint];
RMProjectedPoint southWestPoint = [_projection coordinateToProjectedPoint:southWest];
RMProjectedPoint northEastPoint = [_projection coordinateToProjectedPoint:northEast];
RMProjectedPoint myPoint = {
.x = northEastPoint.x - southWestPoint.x,
.y = northEastPoint.y - southWestPoint.y
... ... @@ -430,7 +442,7 @@
myOrigin.x = myOrigin.x - (zoomRect.size.width / 2);
myOrigin.y = myOrigin.y - (zoomRect.size.height / 2);
RMLog(@"Origin is calculated at: %f, %f", [projection projectedPointToCoordinate:myOrigin].longitude, [projection projectedPointToCoordinate:myOrigin].latitude);
RMLog(@"Origin is calculated at: %f, %f", [_projection projectedPointToCoordinate:myOrigin].longitude, [_projection projectedPointToCoordinate:myOrigin].latitude);
zoomRect.origin = myOrigin;
... ... @@ -443,8 +455,8 @@
{
RMSphericalTrapezium bounds = [self.tileSourcesContainer latitudeLongitudeBoundingBox];
if (bounds.northEast.latitude == 90 && bounds.northEast.longitude == 180 &&
bounds.southWest.latitude == -90 && bounds.southWest.longitude == -180)
if (bounds.northEast.latitude == 90.0 && bounds.northEast.longitude == 180.0 &&
bounds.southWest.latitude == -90.0 && bounds.southWest.longitude == -180.0)
{
return YES;
}
... ... @@ -463,8 +475,8 @@
- (void)setConstraintsSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast
{
RMProjectedPoint projectedSouthWest = [projection coordinateToProjectedPoint:southWest];
RMProjectedPoint projectedNorthEast = [projection coordinateToProjectedPoint:northEast];
RMProjectedPoint projectedSouthWest = [_projection coordinateToProjectedPoint:southWest];
RMProjectedPoint projectedNorthEast = [_projection coordinateToProjectedPoint:northEast];
[self setProjectedConstraintsSouthWest:projectedSouthWest northEast:projectedNorthEast];
}
... ... @@ -473,8 +485,6 @@
{
_constrainMovement = YES;
_constrainingProjectedBounds = RMProjectedRectMake(southWest.x, southWest.y, northEast.x - southWest.x, northEast.y - southWest.y);
mapScrollView.mapScrollViewDelegate = self;
}
#pragma mark -
... ... @@ -482,29 +492,29 @@
- (CLLocationCoordinate2D)centerCoordinate
{
return [projection projectedPointToCoordinate:[self centerProjectedPoint]];
return [_projection projectedPointToCoordinate:[self centerProjectedPoint]];
}
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
{
[self setCenterProjectedPoint:[projection coordinateToProjectedPoint:centerCoordinate]];
[self setCenterProjectedPoint:[_projection coordinateToProjectedPoint:centerCoordinate]];
}
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate animated:(BOOL)animated
{
[self setCenterProjectedPoint:[projection coordinateToProjectedPoint:centerCoordinate] animated:animated];
[self setCenterProjectedPoint:[_projection coordinateToProjectedPoint:centerCoordinate] animated:animated];
}
// ===
- (RMProjectedPoint)centerProjectedPoint
{
CGPoint center = CGPointMake(mapScrollView.contentOffset.x + mapScrollView.bounds.size.width/2.0, mapScrollView.contentSize.height - (mapScrollView.contentOffset.y + mapScrollView.bounds.size.height/2.0));
CGPoint center = CGPointMake(_mapScrollView.contentOffset.x + _mapScrollView.bounds.size.width/2.0, _mapScrollView.contentSize.height - (_mapScrollView.contentOffset.y + _mapScrollView.bounds.size.height/2.0));
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = (center.x * metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = (center.y * metersPerPixel) - fabs(planetBounds.origin.y);
normalizedProjectedPoint.x = (center.x * _metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = (center.y * _metersPerPixel) - fabs(planetBounds.origin.y);
// RMLog(@"centerProjectedPoint: {%f,%f}", normalizedProjectedPoint.x, normalizedProjectedPoint.y);
... ... @@ -519,23 +529,23 @@
- (void)setCenterProjectedPoint:(RMProjectedPoint)centerProjectedPoint animated:(BOOL)animated
{
if (_delegateHasBeforeMapMove)
[delegate beforeMapMove:self];
[_delegate beforeMapMove:self];
// RMLog(@"Current contentSize: {%.0f,%.0f}, zoom: %f", mapScrollView.contentSize.width, mapScrollView.contentSize.height, self.zoom);
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = centerProjectedPoint.x + fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = centerProjectedPoint.y + fabs(planetBounds.origin.y);
[mapScrollView setContentOffset:CGPointMake(normalizedProjectedPoint.x / metersPerPixel - mapScrollView.bounds.size.width/2.0,
mapScrollView.contentSize.height - ((normalizedProjectedPoint.y / metersPerPixel) + mapScrollView.bounds.size.height/2.0))
[_mapScrollView setContentOffset:CGPointMake(normalizedProjectedPoint.x / _metersPerPixel - _mapScrollView.bounds.size.width/2.0,
_mapScrollView.contentSize.height - ((normalizedProjectedPoint.y / _metersPerPixel) + _mapScrollView.bounds.size.height/2.0))
animated:animated];
// RMLog(@"setMapCenterProjectedPoint: {%f,%f} -> {%.0f,%.0f}", centerProjectedPoint.x, centerProjectedPoint.y, mapScrollView.contentOffset.x, mapScrollView.contentOffset.y);
if (_delegateHasAfterMapMove && !animated)
[delegate afterMapMove:self];
[_delegate afterMapMove:self];
[self correctPositionOfAllAnnotations];
}
... ... @@ -545,15 +555,15 @@
- (void)moveBy:(CGSize)delta
{
if (_delegateHasBeforeMapMove)
[delegate beforeMapMove:self];
[_delegate beforeMapMove:self];
CGPoint contentOffset = mapScrollView.contentOffset;
CGPoint contentOffset = _mapScrollView.contentOffset;
contentOffset.x += delta.width;
contentOffset.y += delta.height;
mapScrollView.contentOffset = contentOffset;
_mapScrollView.contentOffset = contentOffset;
if (_delegateHasAfterMapMove)
[delegate afterMapMove:self];
[_delegate afterMapMove:self];
}
#pragma mark -
... ... @@ -561,7 +571,7 @@
- (void)setBoundingMask:(NSUInteger)mask
{
boundingMask = mask;
_boundingMask = mask;
[self correctMinZoomScaleForBoundingMask];
}
... ... @@ -575,25 +585,25 @@
CGFloat newMinZoomScale = (self.boundingMask == RMMapMinWidthBound ? self.bounds.size.width : self.bounds.size.height) / ((CATiledLayer *)((RMMapTiledLayerView *)[_tiledLayersSuperview.subviews objectAtIndex:0]).layer).tileSize.width;
if (mapScrollView.minimumZoomScale > 0 && newMinZoomScale > mapScrollView.minimumZoomScale)
if (_mapScrollView.minimumZoomScale > 0 && newMinZoomScale > _mapScrollView.minimumZoomScale)
{
RMLog(@"clamping min zoom of %f to %f due to %@", log2f(mapScrollView.minimumZoomScale), log2f(newMinZoomScale), (self.boundingMask == RMMapMinWidthBound ? @"RMMapMinWidthBound" : @"RMMapMinHeightBound"));
RMLog(@"clamping min zoom of %f to %f due to %@", log2f(_mapScrollView.minimumZoomScale), log2f(newMinZoomScale), (self.boundingMask == RMMapMinWidthBound ? @"RMMapMinWidthBound" : @"RMMapMinHeightBound"));
mapScrollView.minimumZoomScale = newMinZoomScale;
_mapScrollView.minimumZoomScale = newMinZoomScale;
}
}
}
- (RMProjectedRect)projectedBounds
{
CGPoint bottomLeft = CGPointMake(mapScrollView.contentOffset.x, mapScrollView.contentSize.height - (mapScrollView.contentOffset.y + mapScrollView.bounds.size.height));
CGPoint bottomLeft = CGPointMake(_mapScrollView.contentOffset.x, _mapScrollView.contentSize.height - (_mapScrollView.contentOffset.y + _mapScrollView.bounds.size.height));
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedRect normalizedProjectedRect;
normalizedProjectedRect.origin.x = (bottomLeft.x * metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedRect.origin.y = (bottomLeft.y * metersPerPixel) - fabs(planetBounds.origin.y);
normalizedProjectedRect.size.width = mapScrollView.bounds.size.width * metersPerPixel;
normalizedProjectedRect.size.height = mapScrollView.bounds.size.height * metersPerPixel;
normalizedProjectedRect.origin.x = (bottomLeft.x * _metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedRect.origin.y = (bottomLeft.y * _metersPerPixel) - fabs(planetBounds.origin.y);
normalizedProjectedRect.size.width = _mapScrollView.bounds.size.width * _metersPerPixel;
normalizedProjectedRect.size.height = _mapScrollView.bounds.size.height * _metersPerPixel;
return normalizedProjectedRect;
}
... ... @@ -608,30 +618,30 @@
if (_constrainMovement)
boundsRect = [self fitProjectedRect:boundsRect intoRect:_constrainingProjectedBounds];
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = boundsRect.origin.x + fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = boundsRect.origin.y + fabs(planetBounds.origin.y);
float zoomScale = mapScrollView.zoomScale;
CGRect zoomRect = CGRectMake((normalizedProjectedPoint.x / metersPerPixel) / zoomScale,
((planetBounds.size.height - normalizedProjectedPoint.y - boundsRect.size.height) / metersPerPixel) / zoomScale,
(boundsRect.size.width / metersPerPixel) / zoomScale,
(boundsRect.size.height / metersPerPixel) / zoomScale);
[mapScrollView zoomToRect:zoomRect animated:animated];
float zoomScale = _mapScrollView.zoomScale;
CGRect zoomRect = CGRectMake((normalizedProjectedPoint.x / _metersPerPixel) / zoomScale,
((planetBounds.size.height - normalizedProjectedPoint.y - boundsRect.size.height) / _metersPerPixel) / zoomScale,
(boundsRect.size.width / _metersPerPixel) / zoomScale,
(boundsRect.size.height / _metersPerPixel) / zoomScale);
[_mapScrollView zoomToRect:zoomRect animated:animated];
}
- (float)adjustedZoomForCurrentBoundingMask:(float)zoomFactor
{
if (boundingMask == RMMapNoMinBound)
if (_boundingMask == RMMapNoMinBound)
return zoomFactor;
double newMetersPerPixel = metersPerPixel / zoomFactor;
double newMetersPerPixel = _metersPerPixel / zoomFactor;
RMProjectedRect mercatorBounds = [projection planetBounds];
RMProjectedRect mercatorBounds = [_projection planetBounds];
// Check for MinWidthBound
if (boundingMask & RMMapMinWidthBound)
if (_boundingMask & RMMapMinWidthBound)
{
double newMapContentsWidth = mercatorBounds.size.width / newMetersPerPixel;
double screenBoundsWidth = [self bounds].size.width;
... ... @@ -640,13 +650,13 @@
if (newMapContentsWidth < screenBoundsWidth)
{
// Calculate new zoom facter so that it does not shrink the map any further.
mapContentWidth = mercatorBounds.size.width / metersPerPixel;
mapContentWidth = mercatorBounds.size.width / _metersPerPixel;
zoomFactor = screenBoundsWidth / mapContentWidth;
}
}
// Check for MinHeightBound
if (boundingMask & RMMapMinHeightBound)
if (_boundingMask & RMMapMinHeightBound)
{
double newMapContentsHeight = mercatorBounds.size.height / newMetersPerPixel;
double screenBoundsHeight = [self bounds].size.height;
... ... @@ -655,7 +665,7 @@
if (newMapContentsHeight < screenBoundsHeight)
{
// Calculate new zoom facter so that it does not shrink the map any further.
mapContentHeight = mercatorBounds.size.height / metersPerPixel;
mapContentHeight = mercatorBounds.size.height / _metersPerPixel;
zoomFactor = screenBoundsHeight / mapContentHeight;
}
}
... ... @@ -709,16 +719,16 @@
if ([self shouldZoomToTargetZoom:targetZoom withZoomFactor:zoomFactor])
{
float zoomScale = mapScrollView.zoomScale;
CGSize newZoomSize = CGSizeMake(mapScrollView.bounds.size.width / zoomFactor,
mapScrollView.bounds.size.height / zoomFactor);
CGFloat factorX = pivot.x / mapScrollView.bounds.size.width,
factorY = pivot.y / mapScrollView.bounds.size.height;
CGRect zoomRect = CGRectMake(((mapScrollView.contentOffset.x + pivot.x) - (newZoomSize.width * factorX)) / zoomScale,
((mapScrollView.contentOffset.y + pivot.y) - (newZoomSize.height * factorY)) / zoomScale,
float zoomScale = _mapScrollView.zoomScale;
CGSize newZoomSize = CGSizeMake(_mapScrollView.bounds.size.width / zoomFactor,
_mapScrollView.bounds.size.height / zoomFactor);
CGFloat factorX = pivot.x / _mapScrollView.bounds.size.width,
factorY = pivot.y / _mapScrollView.bounds.size.height;
CGRect zoomRect = CGRectMake(((_mapScrollView.contentOffset.x + pivot.x) - (newZoomSize.width * factorX)) / zoomScale,
((_mapScrollView.contentOffset.y + pivot.y) - (newZoomSize.height * factorY)) / zoomScale,
newZoomSize.width / zoomScale,
newZoomSize.height / zoomScale);
[mapScrollView zoomToRect:zoomRect animated:animated];
[_mapScrollView zoomToRect:zoomRect animated:animated];
}
else
{
... ... @@ -801,26 +811,30 @@
if (northEast.latitude == southWest.latitude && northEast.longitude == southWest.longitude) // There are no bounds, probably only one marker.
{
RMProjectedRect zoomRect;
RMProjectedPoint myOrigin = [projection coordinateToProjectedPoint:southWest];
RMProjectedPoint myOrigin = [_projection coordinateToProjectedPoint:southWest];
// Default is with scale = 2.0 * mercators/pixel
zoomRect.size.width = [self bounds].size.width * 2.0;
zoomRect.size.height = [self bounds].size.height * 2.0;
myOrigin.x = myOrigin.x - (zoomRect.size.width / 2.0);
myOrigin.y = myOrigin.y - (zoomRect.size.height / 2.0);
zoomRect.origin = myOrigin;
[self setProjectedBounds:zoomRect animated:animated];
}
else
{
// Convert northEast/southWest into RMMercatorRect and call zoomWithBounds
float pixelBuffer = kZoomRectPixelBuffer;
CLLocationCoordinate2D midpoint = {
.latitude = (northEast.latitude + southWest.latitude) / 2,
.longitude = (northEast.longitude + southWest.longitude) / 2
};
RMProjectedPoint myOrigin = [projection coordinateToProjectedPoint:midpoint];
RMProjectedPoint southWestPoint = [projection coordinateToProjectedPoint:southWest];
RMProjectedPoint northEastPoint = [projection coordinateToProjectedPoint:northEast];
RMProjectedPoint myOrigin = [_projection coordinateToProjectedPoint:midpoint];
RMProjectedPoint southWestPoint = [_projection coordinateToProjectedPoint:southWest];
RMProjectedPoint northEastPoint = [_projection coordinateToProjectedPoint:northEast];
RMProjectedPoint myPoint = {
.x = northEastPoint.x - southWestPoint.x,
.y = northEastPoint.y - southWestPoint.y
... ... @@ -855,7 +869,7 @@
zoomRect.origin = myOrigin;
RMProjectedPoint topRight = RMProjectedPointMake(myOrigin.x + zoomRect.size.width, myOrigin.y + zoomRect.size.height);
RMLog(@"zoomWithBoundingBox: {%f,%f} - {%f,%f}", [projection projectedPointToCoordinate:myOrigin].longitude, [projection projectedPointToCoordinate:myOrigin].latitude, [projection projectedPointToCoordinate:topRight].longitude, [projection projectedPointToCoordinate:topRight].latitude);
RMLog(@"zoomWithBoundingBox: {%f,%f} - {%f,%f}", [_projection projectedPointToCoordinate:myOrigin].longitude, [_projection projectedPointToCoordinate:myOrigin].latitude, [_projection projectedPointToCoordinate:topRight].longitude, [_projection projectedPointToCoordinate:topRight].latitude);
[self setProjectedBounds:zoomRect animated:animated];
}
... ... @@ -866,7 +880,7 @@
- (void)removeAllCachedImages
{
[tileCache removeAllCachedImages];
[self.tileCache removeAllCachedImages];
}
#pragma mark -
... ... @@ -874,7 +888,7 @@
- (void)createMapView
{
[overlayView removeFromSuperview]; [overlayView release]; overlayView = nil;
[_overlayView removeFromSuperview]; [_overlayView release]; _overlayView = nil;
for (RMMapTiledLayerView *tiledLayerView in _tiledLayersSuperview.subviews)
{
... ... @@ -884,37 +898,37 @@
[_tiledLayersSuperview removeFromSuperview]; [_tiledLayersSuperview release]; _tiledLayersSuperview = nil;
[mapScrollView removeObserver:self forKeyPath:@"contentOffset"];
[mapScrollView removeFromSuperview]; [mapScrollView release]; mapScrollView = nil;
[_mapScrollView removeObserver:self forKeyPath:@"contentOffset"];
[_mapScrollView removeFromSuperview]; [_mapScrollView release]; _mapScrollView = nil;
_mapScrollViewIsZooming = NO;
int tileSideLength = [_tileSourcesContainer tileSideLength];
CGSize contentSize = CGSizeMake(tileSideLength, tileSideLength); // zoom level 1
mapScrollView = [[RMMapScrollView alloc] initWithFrame:[self bounds]];
mapScrollView.delegate = self;
mapScrollView.opaque = NO;
mapScrollView.backgroundColor = [UIColor clearColor];
mapScrollView.showsVerticalScrollIndicator = NO;
mapScrollView.showsHorizontalScrollIndicator = NO;
mapScrollView.scrollsToTop = NO;
mapScrollView.scrollEnabled = _enableDragging;
mapScrollView.bounces = _enableBouncing;
mapScrollView.bouncesZoom = _enableBouncing;
mapScrollView.contentSize = contentSize;
mapScrollView.minimumZoomScale = exp2f([self minZoom]);
mapScrollView.maximumZoomScale = exp2f([self maxZoom]);
mapScrollView.contentOffset = CGPointMake(0.0, 0.0);
_mapScrollView = [[RMMapScrollView alloc] initWithFrame:[self bounds]];
_mapScrollView.delegate = self;
_mapScrollView.opaque = NO;
_mapScrollView.backgroundColor = [UIColor clearColor];
_mapScrollView.showsVerticalScrollIndicator = NO;
_mapScrollView.showsHorizontalScrollIndicator = NO;
_mapScrollView.scrollsToTop = NO;
_mapScrollView.scrollEnabled = _enableDragging;
_mapScrollView.bounces = _enableBouncing;
_mapScrollView.bouncesZoom = _enableBouncing;
_mapScrollView.contentSize = contentSize;
_mapScrollView.minimumZoomScale = exp2f([self minZoom]);
_mapScrollView.maximumZoomScale = exp2f([self maxZoom]);
_mapScrollView.contentOffset = CGPointMake(0.0, 0.0);
_tiledLayersSuperview = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height)];
for (id <RMTileSource> tileSource in _tileSourcesContainer.tileSources)
{
RMMapTiledLayerView *tiledLayerView = [[RMMapTiledLayerView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) mapView:self forTileSource:tileSource];
RMMapTiledLayerView *tiledLayerView = [[[RMMapTiledLayerView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) mapView:self forTileSource:tileSource] autorelease];
tiledLayerView.delegate = self;
if (self.adjustTilesForRetinaDisplay && screenScale > 1.0)
if (self.adjustTilesForRetinaDisplay && _screenScale > 1.0)
((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength * 2.0, tileSideLength * 2.0);
else
((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength, tileSideLength);
... ... @@ -922,31 +936,31 @@
[_tiledLayersSuperview addSubview:tiledLayerView];
}
[mapScrollView addSubview:_tiledLayersSuperview];
[_mapScrollView addSubview:_tiledLayersSuperview];
_lastZoom = [self zoom];
_lastContentOffset = mapScrollView.contentOffset;
_lastContentOffset = _mapScrollView.contentOffset;
_accumulatedDelta = CGPointMake(0.0, 0.0);
_lastContentSize = mapScrollView.contentSize;
_lastContentSize = _mapScrollView.contentSize;
[mapScrollView addObserver:self forKeyPath:@"contentOffset" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:NULL];
mapScrollView.mapScrollViewDelegate = self;
[_mapScrollView addObserver:self forKeyPath:@"contentOffset" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:NULL];
_mapScrollView.mapScrollViewDelegate = self;
mapScrollView.zoomScale = exp2f([self zoom]);
_mapScrollView.zoomScale = exp2f([self zoom]);
[self setDecelerationMode:decelerationMode];
[self setDecelerationMode:_decelerationMode];
if (backgroundView)
[self insertSubview:mapScrollView aboveSubview:backgroundView];
if (_backgroundView)
[self insertSubview:_mapScrollView aboveSubview:_backgroundView];
else
[self insertSubview:mapScrollView atIndex:0];
[self insertSubview:_mapScrollView atIndex:0];
overlayView = [[RMMapOverlayView alloc] initWithFrame:[self bounds]];
overlayView.delegate = self;
_overlayView = [[RMMapOverlayView alloc] initWithFrame:[self bounds]];
_overlayView.delegate = self;
[self insertSubview:overlayView aboveSubview:mapScrollView];
[self insertSubview:_overlayView aboveSubview:_mapScrollView];
[visibleAnnotations removeAllObjects];
[_visibleAnnotations removeAllObjects];
[self correctPositionOfAllAnnotations];
}
... ... @@ -958,31 +972,31 @@
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if (_delegateHasBeforeMapMove)
[delegate beforeMapMove:self];
[_delegate beforeMapMove:self];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate && _delegateHasAfterMapMove)
[delegate afterMapMove:self];
[_delegate afterMapMove:self];
}
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
if (decelerationMode == RMMapDecelerationOff)
if (_decelerationMode == RMMapDecelerationOff)
[scrollView setContentOffset:scrollView.contentOffset animated:NO];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if (_delegateHasAfterMapMove)
[delegate afterMapMove:self];
[_delegate afterMapMove:self];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
if (_delegateHasAfterMapMove)
[delegate afterMapMove:self];
[_delegate afterMapMove:self];
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
... ... @@ -990,7 +1004,7 @@
_mapScrollViewIsZooming = YES;
if (_delegateHasBeforeMapZoom)
[delegate beforeMapZoom:self];
[_delegate beforeMapZoom:self];
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
... ... @@ -1005,7 +1019,7 @@
[self correctPositionOfAllAnnotations];
if (_delegateHasAfterMapZoom)
[delegate afterMapZoom:self];
[_delegate afterMapZoom:self];
}
// Overlay
... ... @@ -1014,12 +1028,12 @@
{
if (_delegateHasTapOnAnnotation && anAnnotation)
{
[delegate tapOnAnnotation:anAnnotation onMap:self];
[_delegate tapOnAnnotation:anAnnotation onMap:self];
}
else
{
if (_delegateHasSingleTapOnMap)
[delegate singleTapOnMap:self at:aPoint];
[_delegate singleTapOnMap:self at:aPoint];
}
}
... ... @@ -1027,7 +1041,7 @@
{
if (_delegateHasDoubleTapOnAnnotation && anAnnotation)
{
[delegate doubleTapOnAnnotation:anAnnotation onMap:self];
[_delegate doubleTapOnAnnotation:anAnnotation onMap:self];
}
else
{
... ... @@ -1039,16 +1053,16 @@
{
if (_delegateHasTapOnLabelForAnnotation && anAnnotation)
{
[delegate tapOnLabelForAnnotation:anAnnotation onMap:self];
[_delegate tapOnLabelForAnnotation:anAnnotation onMap:self];
}
else if (_delegateHasTapOnAnnotation && anAnnotation)
{
[delegate tapOnAnnotation:anAnnotation onMap:self];
[_delegate tapOnAnnotation:anAnnotation onMap:self];
}
else
{
if (_delegateHasSingleTapOnMap)
[delegate singleTapOnMap:self at:aPoint];
[_delegate singleTapOnMap:self at:aPoint];
}
}
... ... @@ -1056,11 +1070,11 @@
{
if (_delegateHasDoubleTapOnLabelForAnnotation && anAnnotation)
{
[delegate doubleTapOnLabelForAnnotation:anAnnotation onMap:self];
[_delegate doubleTapOnLabelForAnnotation:anAnnotation onMap:self];
}
else if (_delegateHasDoubleTapOnAnnotation && anAnnotation)
{
[delegate doubleTapOnAnnotation:anAnnotation onMap:self];
[_delegate doubleTapOnAnnotation:anAnnotation onMap:self];
}
else
{
... ... @@ -1071,7 +1085,7 @@
- (BOOL)mapOverlayView:(RMMapOverlayView *)aMapOverlayView shouldDragAnnotation:(RMAnnotation *)anAnnotation
{
if (_delegateHasShouldDragMarker)
return [delegate mapView:self shouldDragAnnotation:anAnnotation];
return [_delegate mapView:self shouldDragAnnotation:anAnnotation];
else
return NO;
}
... ... @@ -1079,13 +1093,13 @@
- (void)mapOverlayView:(RMMapOverlayView *)aMapOverlayView didDragAnnotation:(RMAnnotation *)anAnnotation withDelta:(CGPoint)delta
{
if (_delegateHasDidDragMarker)
[delegate mapView:self didDragAnnotation:anAnnotation withDelta:delta];
[_delegate mapView:self didDragAnnotation:anAnnotation withDelta:delta];
}
- (void)mapOverlayView:(RMMapOverlayView *)aMapOverlayView didEndDragAnnotation:(RMAnnotation *)anAnnotation
{
if (_delegateHasDidEndDragMarker)
[delegate mapView:self didEndDragAnnotation:anAnnotation];
[_delegate mapView:self didEndDragAnnotation:anAnnotation];
}
// Tiled layer
... ... @@ -1093,7 +1107,7 @@
- (void)mapTiledLayerView:(RMMapTiledLayerView *)aTiledLayerView singleTapAtPoint:(CGPoint)aPoint
{
if (_delegateHasSingleTapOnMap)
[delegate singleTapOnMap:self at:aPoint];
[_delegate singleTapOnMap:self at:aPoint];
}
- (void)mapTiledLayerView:(RMMapTiledLayerView *)aTiledLayerView doubleTapAtPoint:(CGPoint)aPoint
... ... @@ -1101,7 +1115,7 @@
[self zoomInToNextNativeZoomAt:aPoint animated:YES];
if (_delegateHasDoubleTapOnMap)
[delegate doubleTapOnMap:self at:aPoint];
[_delegate doubleTapOnMap:self at:aPoint];
}
- (void)mapTiledLayerView:(RMMapTiledLayerView *)aTiledLayerView twoFingerDoubleTapAtPoint:(CGPoint)aPoint
... ... @@ -1109,7 +1123,7 @@
[self zoomOutToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES];
if (_delegateHasDoubleTapTwoFingersOnMap)
[delegate doubleTapTwoFingersOnMap:self at:aPoint];
[_delegate doubleTapTwoFingersOnMap:self at:aPoint];
}
- (void)mapTiledLayerView:(RMMapTiledLayerView *)aTiledLayerView twoFingerSingleTapAtPoint:(CGPoint)aPoint
... ... @@ -1117,13 +1131,13 @@
[self zoomOutToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES];
if (_delegateHasSingleTapTwoFingersOnMap)
[delegate singleTapTwoFingersOnMap:self at:aPoint];
[_delegate singleTapTwoFingersOnMap:self at:aPoint];
}
- (void)mapTiledLayerView:(RMMapTiledLayerView *)aTiledLayerView longPressAtPoint:(CGPoint)aPoint
{
if (_delegateHasLongSingleTapOnMap)
[delegate longSingleTapOnMap:self at:aPoint];
[_delegate longSingleTapOnMap:self at:aPoint];
}
// Detect dragging/zooming
... ... @@ -1138,14 +1152,14 @@
// The first offset during zooming out (animated) is always garbage
if (_mapScrollViewIsZooming == YES &&
mapScrollView.zooming == NO &&
_lastContentSize.width > mapScrollView.contentSize.width &&
_mapScrollView.zooming == NO &&
_lastContentSize.width > _mapScrollView.contentSize.width &&
((*aContentOffset).y - _lastContentOffset.y) == 0.0)
{
return;
}
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
double currentMetersPerPixel = planetBounds.size.width / aScrollView.contentSize.width;
CGPoint bottomLeft = CGPointMake((*aContentOffset).x,
... ... @@ -1176,7 +1190,7 @@
if ( ! _constrainMovement)
return;
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
double currentMetersPerPixel = planetBounds.size.width / (*aContentSize).width;
RMProjectedSize projectedSize;
... ... @@ -1208,12 +1222,12 @@
// The first offset during zooming out (animated) is always garbage
if (_mapScrollViewIsZooming == YES &&
mapScrollView.zooming == NO &&
_lastContentSize.width > mapScrollView.contentSize.width &&
_mapScrollView.zooming == NO &&
_lastContentSize.width > _mapScrollView.contentSize.width &&
(newContentOffset.y - oldContentOffset.y) == 0.0)
{
_lastContentOffset = mapScrollView.contentOffset;
_lastContentSize = mapScrollView.contentSize;
_lastContentOffset = _mapScrollView.contentOffset;
_lastContentSize = _mapScrollView.contentSize;
return;
}
... ... @@ -1222,25 +1236,25 @@
// RMLog(@"contentSize: {%.0f,%.0f} -> {%.0f,%.0f}", _lastContentSize.width, _lastContentSize.height, mapScrollView.contentSize.width, mapScrollView.contentSize.height);
// RMLog(@"isZooming: %d, scrollview.zooming: %d", _mapScrollViewIsZooming, mapScrollView.zooming);
RMProjectedRect planetBounds = projection.planetBounds;
metersPerPixel = planetBounds.size.width / mapScrollView.contentSize.width;
RMProjectedRect planetBounds = _projection.planetBounds;
_metersPerPixel = planetBounds.size.width / _mapScrollView.contentSize.width;
zoom = log2f(mapScrollView.zoomScale);
zoom = (zoom > maxZoom) ? maxZoom : zoom;
zoom = (zoom < minZoom) ? minZoom : zoom;
_zoom = log2f(_mapScrollView.zoomScale);
_zoom = (_zoom > _maxZoom) ? _maxZoom : _zoom;
_zoom = (_zoom < _minZoom) ? _minZoom : _zoom;
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(correctPositionOfAllAnnotations) object:nil];
if (zoom == _lastZoom)
if (_zoom == _lastZoom)
{
CGPoint contentOffset = mapScrollView.contentOffset;
CGPoint contentOffset = _mapScrollView.contentOffset;
CGPoint delta = CGPointMake(_lastContentOffset.x - contentOffset.x, _lastContentOffset.y - contentOffset.y);
_accumulatedDelta.x += delta.x;
_accumulatedDelta.y += delta.y;
if (fabsf(_accumulatedDelta.x) < kZoomRectPixelBuffer && fabsf(_accumulatedDelta.y) < kZoomRectPixelBuffer)
{
[overlayView moveLayersBy:_accumulatedDelta];
[_overlayView moveLayersBy:_accumulatedDelta];
[self performSelector:@selector(correctPositionOfAllAnnotations) withObject:nil afterDelay:0.1];
}
else
... ... @@ -1253,16 +1267,16 @@
}
else
{
[self correctPositionOfAllAnnotationsIncludingInvisibles:NO animated:(_mapScrollViewIsZooming && !mapScrollView.zooming)];
_lastZoom = zoom;
[self correctPositionOfAllAnnotationsIncludingInvisibles:NO animated:(_mapScrollViewIsZooming && !_mapScrollView.zooming)];
_lastZoom = _zoom;
}
_lastContentOffset = mapScrollView.contentOffset;
_lastContentSize = mapScrollView.contentSize;
_lastContentOffset = _mapScrollView.contentOffset;
_lastContentSize = _mapScrollView.contentSize;
// Don't do anything stupid here or your scrolling experience will suck
if (_delegateHasMapViewRegionDidChange)
[delegate mapViewRegionDidChange:self];
[_delegate mapViewRegionDidChange:self];
}
#pragma mark -
... ... @@ -1270,7 +1284,7 @@
- (UIImage *)takeSnapshotAndIncludeOverlay:(BOOL)includeOverlay
{
overlayView.hidden = !includeOverlay;
_overlayView.hidden = !includeOverlay;
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, [[UIScreen mainScreen] scale]);
... ... @@ -1286,7 +1300,7 @@
UIGraphicsEndImageContext();
overlayView.hidden = NO;
_overlayView.hidden = NO;
return image;
}
... ... @@ -1339,11 +1353,11 @@
RMProjectedPoint centerPoint = [self centerProjectedPoint];
[projection release];
projection = [[_tileSourcesContainer projection] retain];
[_projection release];
_projection = [[_tileSourcesContainer projection] retain];
[mercatorToTileProjection release];
mercatorToTileProjection = [[_tileSourcesContainer mercatorToTileProjection] retain];
[_mercatorToTileProjection release];
_mercatorToTileProjection = [[_tileSourcesContainer mercatorToTileProjection] retain];
RMSphericalTrapezium bounds = [_tileSourcesContainer latitudeLongitudeBoundingBox];
... ... @@ -1352,7 +1366,7 @@
if (_constrainMovement)
_constrainingProjectedBounds = (RMProjectedRect)[self projectedRectFromLatitudeLongitudeBounds:bounds];
else
_constrainingProjectedBounds = projection.planetBounds;
_constrainingProjectedBounds = _projection.planetBounds;
[self setMinZoom:_tileSourcesContainer.minZoom];
[self setMaxZoom:_tileSourcesContainer.maxZoom];
... ... @@ -1374,8 +1388,8 @@
if ([_tileSourcesContainer.tileSources count] == 0)
{
[projection release];
[mercatorToTileProjection release];
[_projection release];
[_mercatorToTileProjection release];
_constrainMovement = NO;
}
... ... @@ -1393,8 +1407,8 @@
if ([_tileSourcesContainer.tileSources count] == 0)
{
[projection release];
[mercatorToTileProjection release];
[_projection release];
[_mercatorToTileProjection release];
_constrainMovement = NO;
}
... ... @@ -1442,32 +1456,32 @@
- (UIView *)backgroundView
{
return [[backgroundView retain] autorelease];
return [[_backgroundView retain] autorelease];
}
- (void)setBackgroundView:(UIView *)aView
{
if (backgroundView == aView)
if (_backgroundView == aView)
return;
if (backgroundView != nil)
if (_backgroundView != nil)
{
[backgroundView removeFromSuperview];
[backgroundView release];
[_backgroundView removeFromSuperview];
[_backgroundView release];
}
backgroundView = [aView retain];
if (backgroundView == nil)
_backgroundView = [aView retain];
if (_backgroundView == nil)
return;
backgroundView.frame = [self bounds];
_backgroundView.frame = [self bounds];
[self insertSubview:backgroundView atIndex:0];
[self insertSubview:_backgroundView atIndex:0];
}
- (double)metersPerPixel
{
return metersPerPixel;
return _metersPerPixel;
}
- (void)setMetersPerPixel:(double)newMetersPerPixel
... ... @@ -1484,7 +1498,7 @@
- (double)scaledMetersPerPixel
{
return metersPerPixel / screenScale;
return _metersPerPixel / _screenScale;
}
// From http://stackoverflow.com/questions/610193/calculating-pixel-size-on-an-iphone
... ... @@ -1499,62 +1513,62 @@
double iphoneMillimetersPerPixel;
BOOL deviceIsIPhone = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone);
BOOL deviceHasRetinaDisplay = (screenScale > 1.0);
BOOL deviceHasRetinaDisplay = (_screenScale > 1.0);
if (deviceHasRetinaDisplay)
iphoneMillimetersPerPixel = (deviceIsIPhone ? kiPhone4MillimetersPerPixel : iPad3MillimetersPerPixel);
else
iphoneMillimetersPerPixel = (deviceIsIPhone ? kiPhone3MillimeteresPerPixel : iPad1MillimetersPerPixel);
return ((metersPerPixel * 1000.0) / iphoneMillimetersPerPixel);
return ((_metersPerPixel * 1000.0) / iphoneMillimetersPerPixel);
}
- (void)setMinZoom:(float)newMinZoom
{
minZoom = newMinZoom;
_minZoom = newMinZoom;
// RMLog(@"New minZoom:%f", newMinZoom);
mapScrollView.minimumZoomScale = exp2f(newMinZoom);
_mapScrollView.minimumZoomScale = exp2f(newMinZoom);
[self correctMinZoomScaleForBoundingMask];
}
- (void)setMaxZoom:(float)newMaxZoom
{
maxZoom = newMaxZoom;
_maxZoom = newMaxZoom;
// RMLog(@"New maxZoom:%f", newMaxZoom);
mapScrollView.maximumZoomScale = exp2f(newMaxZoom);
_mapScrollView.maximumZoomScale = exp2f(newMaxZoom);
}
- (float)zoom
{
return zoom;
return _zoom;
}
// if #zoom is outside of range #minZoom to #maxZoom, zoom level is clamped to that range.
- (void)setZoom:(float)newZoom
{
zoom = (newZoom > maxZoom) ? maxZoom : newZoom;
zoom = (zoom < minZoom) ? minZoom : zoom;
_zoom = (newZoom > _maxZoom) ? _maxZoom : newZoom;
_zoom = (_zoom < _minZoom) ? _minZoom : _zoom;
// RMLog(@"New zoom:%f", zoom);
mapScrollView.zoomScale = exp2f(zoom);
_mapScrollView.zoomScale = exp2f(_zoom);
}
- (void)setEnableClustering:(BOOL)doEnableClustering
{
enableClustering = doEnableClustering;
_enableClustering = doEnableClustering;
[self correctPositionOfAllAnnotations];
}
- (void)setDecelerationMode:(RMMapDecelerationMode)aDecelerationMode
{
decelerationMode = aDecelerationMode;
_decelerationMode = aDecelerationMode;
float decelerationRate = 0.0;
... ... @@ -1563,7 +1577,7 @@
else if (aDecelerationMode == RMMapDecelerationFast)
decelerationRate = UIScrollViewDecelerationRateFast;
[mapScrollView setDecelerationRate:decelerationRate];
[_mapScrollView setDecelerationRate:decelerationRate];
}
- (BOOL)enableDragging
... ... @@ -1574,7 +1588,7 @@
- (void)setEnableDragging:(BOOL)enableDragging
{
_enableDragging = enableDragging;
mapScrollView.scrollEnabled = enableDragging;
_mapScrollView.scrollEnabled = enableDragging;
}
- (BOOL)enableBouncing
... ... @@ -1585,16 +1599,16 @@
- (void)setEnableBouncing:(BOOL)enableBouncing
{
_enableBouncing = enableBouncing;
mapScrollView.bounces = enableBouncing;
mapScrollView.bouncesZoom = enableBouncing;
_mapScrollView.bounces = enableBouncing;
_mapScrollView.bouncesZoom = enableBouncing;
}
- (void)setAdjustTilesForRetinaDisplay:(BOOL)doAdjustTilesForRetinaDisplay
{
if (adjustTilesForRetinaDisplay == doAdjustTilesForRetinaDisplay)
if (_adjustTilesForRetinaDisplay == doAdjustTilesForRetinaDisplay)
return;
adjustTilesForRetinaDisplay = doAdjustTilesForRetinaDisplay;
_adjustTilesForRetinaDisplay = doAdjustTilesForRetinaDisplay;
RMProjectedPoint centerPoint = [self centerProjectedPoint];
... ... @@ -1605,7 +1619,7 @@
- (float)adjustedZoomForRetinaDisplay
{
if (!self.adjustTilesForRetinaDisplay && screenScale > 1.0)
if (!self.adjustTilesForRetinaDisplay && _screenScale > 1.0)
return [self zoom] + 1.0;
return [self zoom];
... ... @@ -1613,17 +1627,17 @@
- (RMProjection *)projection
{
return [[projection retain] autorelease];
return [[_projection retain] autorelease];
}
- (RMFractalTileProjection *)mercatorToTileProjection
{
return [[mercatorToTileProjection retain] autorelease];
return [[_mercatorToTileProjection retain] autorelease];
}
- (void)setDebugTiles:(BOOL)shouldDebug;
{
debugTiles = shouldDebug;
_debugTiles = shouldDebug;
for (RMMapTiledLayerView *tiledLayerView in _tiledLayersSuperview.subviews)
{
... ... @@ -1637,13 +1651,13 @@
- (CGPoint)projectedPointToPixel:(RMProjectedPoint)projectedPoint
{
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = projectedPoint.x + fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = projectedPoint.y + fabs(planetBounds.origin.y);
// \bug: There is a rounding error here for high zoom levels
CGPoint projectedPixel = CGPointMake((normalizedProjectedPoint.x / metersPerPixel) - mapScrollView.contentOffset.x, (mapScrollView.contentSize.height - (normalizedProjectedPoint.y / metersPerPixel)) - mapScrollView.contentOffset.y);
CGPoint projectedPixel = CGPointMake((normalizedProjectedPoint.x / _metersPerPixel) - _mapScrollView.contentOffset.x, (_mapScrollView.contentSize.height - (normalizedProjectedPoint.y / _metersPerPixel)) - _mapScrollView.contentOffset.y);
// RMLog(@"pointToPixel: {%f,%f} -> {%f,%f}", projectedPoint.x, projectedPoint.y, projectedPixel.x, projectedPixel.y);
... ... @@ -1652,15 +1666,15 @@
- (CGPoint)coordinateToPixel:(CLLocationCoordinate2D)coordinate
{
return [self projectedPointToPixel:[projection coordinateToProjectedPoint:coordinate]];
return [self projectedPointToPixel:[_projection coordinateToProjectedPoint:coordinate]];
}
- (RMProjectedPoint)pixelToProjectedPoint:(CGPoint)pixelCoordinate
{
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = ((pixelCoordinate.x + mapScrollView.contentOffset.x) * metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = ((mapScrollView.contentSize.height - mapScrollView.contentOffset.y - pixelCoordinate.y) * metersPerPixel) - fabs(planetBounds.origin.y);
normalizedProjectedPoint.x = ((pixelCoordinate.x + _mapScrollView.contentOffset.x) * _metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = ((_mapScrollView.contentSize.height - _mapScrollView.contentOffset.y - pixelCoordinate.y) * _metersPerPixel) - fabs(planetBounds.origin.y);
// RMLog(@"pixelToPoint: {%f,%f} -> {%f,%f}", pixelCoordinate.x, pixelCoordinate.y, normalizedProjectedPoint.x, normalizedProjectedPoint.y);
... ... @@ -1669,37 +1683,37 @@
- (CLLocationCoordinate2D)pixelToCoordinate:(CGPoint)pixelCoordinate
{
return [projection projectedPointToCoordinate:[self pixelToProjectedPoint:pixelCoordinate]];
return [_projection projectedPointToCoordinate:[self pixelToProjectedPoint:pixelCoordinate]];
}
- (RMProjectedPoint)coordinateToProjectedPoint:(CLLocationCoordinate2D)coordinate
{
return [projection coordinateToProjectedPoint:coordinate];
return [_projection coordinateToProjectedPoint:coordinate];
}
- (CLLocationCoordinate2D)projectedPointToCoordinate:(RMProjectedPoint)projectedPoint
{
return [projection projectedPointToCoordinate:projectedPoint];
return [_projection projectedPointToCoordinate:projectedPoint];
}
- (RMProjectedSize)viewSizeToProjectedSize:(CGSize)screenSize
{
return RMProjectedSizeMake(screenSize.width * metersPerPixel, screenSize.height * metersPerPixel);
return RMProjectedSizeMake(screenSize.width * _metersPerPixel, screenSize.height * _metersPerPixel);
}
- (CGSize)projectedSizeToViewSize:(RMProjectedSize)projectedSize
{
return CGSizeMake(projectedSize.width / metersPerPixel, projectedSize.height / metersPerPixel);
return CGSizeMake(projectedSize.width / _metersPerPixel, projectedSize.height / _metersPerPixel);
}
- (RMProjectedPoint)projectedOrigin
{
CGPoint origin = CGPointMake(mapScrollView.contentOffset.x, mapScrollView.contentSize.height - mapScrollView.contentOffset.y);
CGPoint origin = CGPointMake(_mapScrollView.contentOffset.x, _mapScrollView.contentSize.height - _mapScrollView.contentOffset.y);
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = (origin.x * metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = (origin.y * metersPerPixel) - fabs(planetBounds.origin.y);
normalizedProjectedPoint.x = (origin.x * _metersPerPixel) - fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = (origin.y * _metersPerPixel) - fabs(planetBounds.origin.y);
// RMLog(@"projectedOrigin: {%f,%f}", normalizedProjectedPoint.x, normalizedProjectedPoint.y);
... ... @@ -1708,7 +1722,7 @@
- (RMProjectedSize)projectedViewSize
{
return RMProjectedSizeMake(self.bounds.size.width * metersPerPixel, self.bounds.size.height * metersPerPixel);
return RMProjectedSizeMake(self.bounds.size.width * _metersPerPixel, self.bounds.size.height * _metersPerPixel);
}
- (CLLocationCoordinate2D)normalizeCoordinate:(CLLocationCoordinate2D)coordinate
... ... @@ -1737,7 +1751,7 @@
}
#pragma mark -
#pragma mark Markers and overlays
#pragma mark Bounds
- (RMSphericalTrapezium)latitudeLongitudeBoundingBox
{
... ... @@ -1789,13 +1803,13 @@
- (void)correctScreenPosition:(RMAnnotation *)annotation animated:(BOOL)animated
{
RMProjectedRect planetBounds = projection.planetBounds;
RMProjectedRect planetBounds = _projection.planetBounds;
RMProjectedPoint normalizedProjectedPoint;
normalizedProjectedPoint.x = annotation.projectedLocation.x + fabs(planetBounds.origin.x);
normalizedProjectedPoint.y = annotation.projectedLocation.y + fabs(planetBounds.origin.y);
CGPoint newPosition = CGPointMake((normalizedProjectedPoint.x / metersPerPixel) - mapScrollView.contentOffset.x,
mapScrollView.contentSize.height - (normalizedProjectedPoint.y / metersPerPixel) - mapScrollView.contentOffset.y);
CGPoint newPosition = CGPointMake((normalizedProjectedPoint.x / _metersPerPixel) - _mapScrollView.contentOffset.x,
_mapScrollView.contentSize.height - (normalizedProjectedPoint.y / _metersPerPixel) - _mapScrollView.contentOffset.y);
// RMLog(@"Change annotation at {%f,%f} in mapView {%f,%f}", annotation.position.x, annotation.position.y, mapScrollView.contentSize.width, mapScrollView.contentSize.height);
... ... @@ -1808,7 +1822,7 @@
[CATransaction begin];
// Synchronize marker movement with the map scroll view
if (animated && !mapScrollView.isZooming)
if (animated && !_mapScrollView.isZooming)
{
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setAnimationDuration:0.30];
... ... @@ -1820,13 +1834,13 @@
_accumulatedDelta.x = 0.0;
_accumulatedDelta.y = 0.0;
[overlayView moveLayersBy:_accumulatedDelta];
[_overlayView moveLayersBy:_accumulatedDelta];
if (self.quadTree)
{
if (!correctAllAnnotations || _mapScrollViewIsZooming)
{
for (RMAnnotation *annotation in visibleAnnotations)
for (RMAnnotation *annotation in _visibleAnnotations)
[self correctScreenPosition:annotation animated:animated];
// RMLog(@"%d annotations corrected", [visibleAnnotations count]);
... ... @@ -1836,32 +1850,33 @@
return;
}
RMProjectedRect boundingBox = [self projectedBounds];
double boundingBoxBuffer = kZoomRectPixelBuffer * metersPerPixel;
double boundingBoxBuffer = (kZoomRectPixelBuffer * _metersPerPixel);
RMProjectedRect boundingBox = self.projectedBounds;
boundingBox.origin.x -= boundingBoxBuffer;
boundingBox.origin.y -= boundingBoxBuffer;
boundingBox.size.width += 2*boundingBoxBuffer;
boundingBox.size.height += 2*boundingBoxBuffer;
boundingBox.size.width += (2.0 * boundingBoxBuffer);
boundingBox.size.height += (2.0 * boundingBoxBuffer);
NSArray *annotationsToCorrect = [quadTree annotationsInProjectedRect:boundingBox
createClusterAnnotations:self.enableClustering
withProjectedClusterSize:RMProjectedSizeMake(self.clusterAreaSize.width * metersPerPixel, self.clusterAreaSize.height * metersPerPixel)
andProjectedClusterMarkerSize:RMProjectedSizeMake(self.clusterMarkerSize.width * metersPerPixel, self.clusterMarkerSize.height * metersPerPixel)
findGravityCenter:self.positionClusterMarkersAtTheGravityCenter];
NSMutableSet *previousVisibleAnnotations = [[NSMutableSet alloc] initWithSet:visibleAnnotations];
NSArray *annotationsToCorrect = [self.quadTree annotationsInProjectedRect:boundingBox
createClusterAnnotations:self.enableClustering
withProjectedClusterSize:RMProjectedSizeMake(self.clusterAreaSize.width * _metersPerPixel, self.clusterAreaSize.height * _metersPerPixel)
andProjectedClusterMarkerSize:RMProjectedSizeMake(self.clusterMarkerSize.width * _metersPerPixel, self.clusterMarkerSize.height * _metersPerPixel)
findGravityCenter:self.positionClusterMarkersAtTheGravityCenter];
NSMutableSet *previousVisibleAnnotations = [[NSMutableSet alloc] initWithSet:_visibleAnnotations];
for (RMAnnotation *annotation in annotationsToCorrect)
{
if (annotation.layer == nil && _delegateHasLayerForAnnotation)
annotation.layer = [delegate mapView:self layerForAnnotation:annotation];
annotation.layer = [_delegate mapView:self layerForAnnotation:annotation];
if (annotation.layer == nil)
continue;
// Use the zPosition property to order the layer hierarchy
if (![visibleAnnotations containsObject:annotation])
if ( ! [_visibleAnnotations containsObject:annotation])
{
[overlayView addSublayer:annotation.layer];
[visibleAnnotations addObject:annotation];
[_overlayView addSublayer:annotation.layer];
[_visibleAnnotations addObject:annotation];
}
[self correctScreenPosition:annotation animated:animated];
... ... @@ -1872,14 +1887,14 @@
for (RMAnnotation *annotation in previousVisibleAnnotations)
{
if (_delegateHasWillHideLayerForAnnotation)
[delegate mapView:self willHideLayerForAnnotation:annotation];
[_delegate mapView:self willHideLayerForAnnotation:annotation];
annotation.layer = nil;
if (_delegateHasDidHideLayerForAnnotation)
[delegate mapView:self didHideLayerForAnnotation:annotation];
[_delegate mapView:self didHideLayerForAnnotation:annotation];
[visibleAnnotations removeObject:annotation];
[_visibleAnnotations removeObject:annotation];
}
[previousVisibleAnnotations release];
... ... @@ -1890,29 +1905,29 @@
{
CALayer *lastLayer = nil;
@synchronized (annotations)
@synchronized (_annotations)
{
if (correctAllAnnotations)
{
for (RMAnnotation *annotation in annotations)
for (RMAnnotation *annotation in _annotations)
{
[self correctScreenPosition:annotation animated:animated];
if ([annotation isAnnotationWithinBounds:[self bounds]])
{
if (annotation.layer == nil && _delegateHasLayerForAnnotation)
annotation.layer = [delegate mapView:self layerForAnnotation:annotation];
annotation.layer = [_delegate mapView:self layerForAnnotation:annotation];
if (annotation.layer == nil)
continue;
if (![visibleAnnotations containsObject:annotation])
if (![_visibleAnnotations containsObject:annotation])
{
if (!lastLayer)
[overlayView insertSublayer:annotation.layer atIndex:0];
[_overlayView insertSublayer:annotation.layer atIndex:0];
else
[overlayView insertSublayer:annotation.layer above:lastLayer];
[_overlayView insertSublayer:annotation.layer above:lastLayer];
[visibleAnnotations addObject:annotation];
[_visibleAnnotations addObject:annotation];
}
lastLayer = annotation.layer;
... ... @@ -1920,20 +1935,20 @@
else
{
if (_delegateHasWillHideLayerForAnnotation)
[delegate mapView:self willHideLayerForAnnotation:annotation];
[_delegate mapView:self willHideLayerForAnnotation:annotation];
annotation.layer = nil;
[visibleAnnotations removeObject:annotation];
[_visibleAnnotations removeObject:annotation];
if (_delegateHasDidHideLayerForAnnotation)
[delegate mapView:self didHideLayerForAnnotation:annotation];
[_delegate mapView:self didHideLayerForAnnotation:annotation];
}
}
// RMLog(@"%d annotations on screen, %d total", [overlayView sublayersCount], [annotations count]);
}
else
{
for (RMAnnotation *annotation in visibleAnnotations)
for (RMAnnotation *annotation in _visibleAnnotations)
[self correctScreenPosition:annotation animated:animated];
// RMLog(@"%d annotations corrected", [visibleAnnotations count]);
... ... @@ -1951,18 +1966,18 @@
- (NSArray *)annotations
{
return [annotations allObjects];
return [_annotations allObjects];
}
- (void)addAnnotation:(RMAnnotation *)annotation
{
@synchronized (annotations)
@synchronized (_annotations)
{
[annotations addObject:annotation];
[_annotations addObject:annotation];
[self.quadTree addAnnotation:annotation];
}
if (enableClustering)
if (_enableClustering)
{
[self correctPositionOfAllAnnotations];
}
... ... @@ -1971,21 +1986,21 @@
[self correctScreenPosition:annotation animated:NO];
if (annotation.layer == nil && [annotation isAnnotationOnScreen] && _delegateHasLayerForAnnotation)
annotation.layer = [delegate mapView:self layerForAnnotation:annotation];
annotation.layer = [_delegate mapView:self layerForAnnotation:annotation];
if (annotation.layer)
{
[overlayView addSublayer:annotation.layer];
[visibleAnnotations addObject:annotation];
[_overlayView addSublayer:annotation.layer];
[_visibleAnnotations addObject:annotation];
}
}
}
- (void)addAnnotations:(NSArray *)newAnnotations
{
@synchronized (annotations)
@synchronized (_annotations)
{
[annotations addObjectsFromArray:newAnnotations];
[_annotations addObjectsFromArray:newAnnotations];
[self.quadTree addAnnotations:newAnnotations];
}
... ... @@ -1994,10 +2009,10 @@
- (void)removeAnnotation:(RMAnnotation *)annotation
{
@synchronized (annotations)
@synchronized (_annotations)
{
[annotations removeObject:annotation];
[visibleAnnotations removeObject:annotation];
[_annotations removeObject:annotation];
[_visibleAnnotations removeObject:annotation];
}
[self.quadTree removeAnnotation:annotation];
... ... @@ -2008,12 +2023,12 @@
- (void)removeAnnotations:(NSArray *)annotationsToRemove
{
@synchronized (annotations)
@synchronized (_annotations)
{
for (RMAnnotation *annotation in annotationsToRemove)
{
[annotations removeObject:annotation];
[visibleAnnotations removeObject:annotation];
[_annotations removeObject:annotation];
[_visibleAnnotations removeObject:annotation];
[self.quadTree removeAnnotation:annotation];
annotation.layer = nil;
}
... ... @@ -2024,18 +2039,18 @@
- (void)removeAllAnnotations
{
@synchronized (annotations)
@synchronized (_annotations)
{
for (RMAnnotation *annotation in annotations)
for (RMAnnotation *annotation in _annotations)
{
// Remove the layer from the screen
annotation.layer = nil;
}
}
[annotations removeAllObjects];
[visibleAnnotations removeAllObjects];
[quadTree removeAllObjects];
[_annotations removeAllObjects];
[_visibleAnnotations removeAllObjects];
[self.quadTree removeAllObjects];
[self correctPositionOfAllAnnotations];
}
... ...