Toggle navigation
Toggle navigation
This project
Loading...
Sign in
尹诚
/
Mapbox-iOS-SDK
·
Commits
Go to a project
GitLab
Go to dashboard
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
0
Merge Requests
0
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Email Patches
Plain Diff
Browse Files
Authored by
Thomas Rasch
13 years ago
Commit
6f64e50c7e3953a2edc54a105281fe8e7130723d
1 parent
22de7a38
o Some random code cleanup
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
563 additions
and
285 deletions
MapView/Map/RMAbstractMercatorTileSource.h
MapView/Map/RMAbstractWebMapSource.h
MapView/Map/RMAbstractWebMapSource.m
MapView/Map/RMAnnotation.m
MapView/Map/RMCacheObject.h
MapView/Map/RMCircle.m
MapView/Map/RMConfiguration.h
MapView/Map/RMConfiguration.m
MapView/Map/RMDBMapSource.m
MapView/Map/RMFoundation.c
MapView/Map/RMFractalTileProjection.h
MapView/Map/RMFractalTileProjection.m
MapView/Map/RMMapOverlayView.h
MapView/Map/RMMapOverlayView.m
MapView/Map/RMMapTiledLayerView.h
MapView/Map/RMMapTiledLayerView.m
MapView/Map/RMMapView.h
MapView/Map/RMMapView.m
MapView/Map/RMMarker.m
MapView/Map/RMMemoryCache.h
MapView/Map/RMMemoryCache.m
MapView/Map/RMOpenCycleMapSource.h
MapView/Map/RMOpenCycleMapSource.m
MapView/Map/RMOpenStreetMapSource.h
MapView/Map/RMOpenStreetMapSource.m
MapView/Map/RMPath.m
MapView/Map/RMPixel.c
MapView/Map/RMProjection.m
MapView/Map/RMQuadTree.m
MapView/Map/RMTile.c
MapView/Map/RMTileCache.m
MapView/Map/RouteMe.h
MapView/MapView.xcodeproj/project.pbxproj
MapView/Map/RMAbstractMercatorTileSource.h
View file @
6f64e50
...
...
@@ -37,7 +37,8 @@
#pragma mark --- end constants ---
@interface
RMAbstractMercatorTileSource
:
NSObject
<
RMTileSource
>
{
@interface
RMAbstractMercatorTileSource
:
NSObject
<
RMTileSource
>
{
RMFractalTileProjection
*
tileProjection
;
// supported zoom levels
...
...
MapView/Map/RMAbstractWebMapSource.h
View file @
6f64e50
...
...
@@ -28,8 +28,7 @@
#import "RMAbstractMercatorTileSource.h"
#import "RMProjection.h"
@interface
RMAbstractWebMapSource
:
RMAbstractMercatorTileSource
{
}
@interface
RMAbstractWebMapSource
:
RMAbstractMercatorTileSource
-
(
NSURL
*
)
URLForTile
:(
RMTile
)
tile
;
...
...
MapView/Map/RMAbstractWebMapSource.m
View file @
6f64e50
...
...
@@ -60,77 +60,88 @@
tile
=
[[
self
mercatorToTileProjection
]
normaliseTile
:
tile
];
image
=
[
tileCache
cachedImage
:
tile
withCacheKey
:[
self
uniqueTilecacheKey
]];
if
(
image
)
return
image
;
if
(
image
)
return
image
;
[[
NSNotificationCenter
defaultCenter
]
postNotificationName
:
RMTileRequested
object
:
nil
];
[
tileCache
retain
];
NSArray
*
URLs
=
[
self
URLsForTile
:
tile
];
// fill up collection array with placeholders
//
NSMutableArray
*
tilesData
=
[
NSMutableArray
arrayWithCapacity
:[
URLs
count
]];
for
(
int
p
=
0
;
p
<
[
URLs
count
];
p
++
)
[
tilesData
addObject
:[
NSNull
null
]];
dispatch_group_t
fetchGroup
=
dispatch_group_create
();
for
(
int
u
=
0
;
u
<
[
URLs
count
];
u
++
)
{
NSURL
*
currentURL
=
[
URLs
objectAtIndex
:
u
];
dispatch_group_async
(
fetchGroup
,
dispatch_get_global_queue
(
DISPATCH_QUEUE_PRIORITY_DEFAULT
,
0
),
^
(
void
)
{
NSData
*
tileData
=
nil
;
for
(
int
try
=
0
;
try
<
RMAbstractWebMapSourceRetryCount
;
try
++
)
{
if
(
!
tileData
)
// Beware: dataWithContentsOfURL is leaking like hell. Better use AFNetwork or ASIHTTPRequest
tileData
=
[
NSData
dataWithContentsOfURL
:
currentURL
options
:
NSDataReadingUncached
error
:
NULL
];
}
if
(
tileData
)
{
dispatch_sync
(
dispatch_get_main_queue
(),
^
(
void
)
{
// safely put into collection array in proper order
//
[
tilesData
replaceObjectAtIndex
:
u
withObject
:
tileData
];
[
tilesData
replaceObjectAtIndex
:
u
withObject
:
tileData
];
});
}
});
}
// wait for whole group of fetches (with retries) to finish, then clean up
//
dispatch_group_wait
(
fetchGroup
,
dispatch_time
(
DISPATCH_TIME_NOW
,
NSEC_PER_SEC
*
RMAbstractWebMapSourceWaitSeconds
));
dispatch_release
(
fetchGroup
);
// composite the collected images together
//
for
(
NSData
*
tileData
in
tilesData
)
{
if
(
tileData
&&
[
tileData
isKindOfClass
:[
NSData
class
]]
&&
[
tileData
length
])
{
if
(
image
!=
nil
)
{
if
(
tileData
&&
[
tileData
isKindOfClass
:[
NSData
class
]]
&&
[
tileData
length
])
{
if
(
image
!=
nil
)
{
UIGraphicsBeginImageContext
(
image
.
size
);
[
image
drawAtPoint
:
CGPointMake
(
0
,
0
)];
[[
UIImage
imageWithData
:
tileData
]
drawAtPoint
:
CGPointMake
(
0
,
0
)];
image
=
UIGraphicsGetImageFromCurrentImageContext
();
UIGraphicsEndImageContext
();
}
else
{
}
else
{
image
=
[
UIImage
imageWithData
:
tileData
];
}
}
}
if
(
image
)
[
tileCache
addImage
:
image
forTile
:
tile
withCacheKey
:[
self
uniqueTilecacheKey
]];
if
(
image
)
[
tileCache
addImage
:
image
forTile
:
tile
withCacheKey
:[
self
uniqueTilecacheKey
]];
[
tileCache
release
];
[[
NSNotificationCenter
defaultCenter
]
postNotificationName
:
RMTileRetrieved
object
:
nil
];
if
(
!
image
)
return
[
RMTileImage
errorTile
];
if
(
!
image
)
return
[
RMTileImage
errorTile
];
return
image
;
}
...
...
MapView/Map/RMAnnotation.m
View file @
6f64e50
...
...
@@ -112,15 +112,17 @@
{
[
mapView
autorelease
];
mapView
=
[
aMapView
retain
];
if
(
!
aMapView
)
{
if
(
!
aMapView
)
self
.
layer
=
nil
;
}
}
-
(
void
)
setPosition
:
(
CGPoint
)
aPosition
{
position
=
aPosition
;
if
(
layer
)
layer
.
position
=
aPosition
;
if
(
layer
)
layer
.
position
=
aPosition
;
}
-
(
RMMapLayer
*
)
layer
...
...
@@ -130,12 +132,16 @@
-
(
void
)
setLayer
:
(
RMMapLayer
*
)
aLayer
{
if
(
layer
!=
aLayer
)
{
if
(
layer
.
superlayer
)
[
layer
removeFromSuperlayer
];
if
(
layer
!=
aLayer
)
{
if
(
layer
.
superlayer
)
[
layer
removeFromSuperlayer
];
[
layer
release
];
layer
=
nil
;
}
if
(
aLayer
)
{
if
(
aLayer
)
{
layer
=
aLayer
;
[
layer
retain
];
layer
.
annotation
=
self
;
...
...
@@ -145,10 +151,13 @@
-
(
BOOL
)
isAnnotationWithinBounds
:
(
CGRect
)
bounds
{
if
(
self
.
hasBoundingBox
)
{
if
(
self
.
hasBoundingBox
)
{
RMProjectedRect
projectedScreenBounds
=
[
mapView
projectedBounds
];
return
RMProjectedRectIntersectsProjectedRect
(
projectedScreenBounds
,
projectedBoundingBox
);
}
else
{
}
else
{
return
CGRectContainsPoint
(
bounds
,
self
.
position
);
}
}
...
...
@@ -176,15 +185,15 @@
max
.
latitude
=
kRMMinLatitude
;
max
.
longitude
=
kRMMinLongitude
;
CLLocationDegrees
currentLatitude
,
currentLongitude
;
for
(
CLLocation
*
currentLocation
in
locations
)
{
currentLatitude
=
currentLocation
.
coordinate
.
latitude
;
currentLongitude
=
currentLocation
.
coordinate
.
longitude
;
// POIs outside of the world...
if
(
currentLatitude
<
kRMMinLatitude
||
currentLatitude
>
kRMMaxLatitude
||
currentLongitude
<
kRMMinLongitude
||
currentLongitude
>
kRMMaxLongitude
)
{
if
(
currentLatitude
<
kRMMinLatitude
||
currentLatitude
>
kRMMaxLatitude
||
currentLongitude
<
kRMMinLongitude
||
currentLongitude
>
kRMMaxLongitude
)
continue
;
}
max
.
latitude
=
fmax
(
currentLatitude
,
max
.
latitude
);
max
.
longitude
=
fmax
(
currentLongitude
,
max
.
longitude
);
...
...
MapView/Map/RMCacheObject.h
View file @
6f64e50
...
...
@@ -27,7 +27,8 @@
#import "RMTile.h"
@interface
RMCacheObject
:
NSObject
{
@interface
RMCacheObject
:
NSObject
{
id
cachedObject
;
NSString
*
cacheKey
;
...
...
MapView/Map/RMCircle.m
View file @
6f64e50
...
...
@@ -34,9 +34,13 @@
#define kDefaultFillColor [UIColor blueColor]
@interface
RMCircle
()
-
(
void
)
updateCirclePath
;
@end
#pragma mark -
@implementation
RMCircle
@synthesize
shapeLayer
;
...
...
@@ -116,7 +120,8 @@
-
(
void
)
setLineColor
:
(
UIColor
*
)
newLineColor
{
if
(
lineColor
!=
newLineColor
)
{
if
(
lineColor
!=
newLineColor
)
{
[
lineColor
release
];
lineColor
=
[
newLineColor
retain
];
[
self
updateCirclePath
];
...
...
@@ -125,7 +130,8 @@
-
(
void
)
setFillColor
:
(
UIColor
*
)
newFillColor
{
if
(
fillColor
!=
newFillColor
)
{
if
(
fillColor
!=
newFillColor
)
{
[
fillColor
release
];
fillColor
=
[
newFillColor
retain
];
[
self
updateCirclePath
];
...
...
MapView/Map/RMConfiguration.h
View file @
6f64e50
...
...
@@ -27,9 +27,7 @@
#import <UIKit/UIKit.h>
@interface
RMConfiguration
:
NSObject
{
id
propertyList
;
}
@interface
RMConfiguration
:
NSObject
+
(
RMConfiguration
*
)
configuration
;
...
...
MapView/Map/RMConfiguration.m
View file @
6f64e50
...
...
@@ -30,14 +30,19 @@
static
RMConfiguration
*
RMConfigurationSharedInstance
=
nil
;
@implementation
RMConfiguration
{
id
propertyList
;
}
+
(
RMConfiguration
*
)
configuration
{
@synchronized
(
RMConfigurationSharedInstance
)
{
@synchronized
(
RMConfigurationSharedInstance
)
{
if
(
RMConfigurationSharedInstance
!=
nil
)
return
RMConfigurationSharedInstance
;
RMConfigurationSharedInstance
=
[[
RMConfiguration
alloc
]
initWithPath
:[[
NSBundle
mainBundle
]
pathForResource
:
@"routeme"
ofType
:
@"plist"
]];
return
RMConfigurationSharedInstance
;
}
...
...
@@ -53,12 +58,14 @@ static RMConfiguration *RMConfigurationSharedInstance = nil;
NSString
*
error
;
NSPropertyListFormat
format
;
if
(
path
==
nil
)
{
if
(
path
==
nil
)
{
propertyList
=
nil
;
return
self
;
}
RMLog
(
@"reading configuration from %@"
,
path
);
plistData
=
[
NSData
dataWithContentsOfFile
:
path
];
propertyList
=
[[
NSPropertyListSerialization
propertyListFromData
:
plistData
...
...
@@ -66,7 +73,8 @@ static RMConfiguration *RMConfigurationSharedInstance = nil;
format
:
&
format
errorDescription
:
&
error
]
retain
];
if
(
!
propertyList
)
{
if
(
!
propertyList
)
{
RMLog
(
@"problem reading from %@: %@"
,
path
,
error
);
[
error
release
];
}
...
...
MapView/Map/RMDBMapSource.m
View file @
6f64e50
...
...
@@ -75,9 +75,7 @@
#import "FMDatabase.h"
#import "FMDatabaseQueue.h"
#define kDefaultLatLonBoundingBox ((RMSphericalTrapezium){.northEast = {.latitude = 90, .longitude = 180}, .southWest = {.latitude = -90, .longitude = -180}})
#define FMDBErrorCheck(db) { if ([db hadError]) { NSLog(@"DB error %d on line %d: %@", [db lastErrorCode], __LINE__, [db lastErrorMessage]); } }
#pragma mark --- begin constants ----
// mandatory preference keys
#define kMinZoomKey @"map.minZoom"
...
...
@@ -98,6 +96,7 @@
#define kShortAttributionKey @"map.shortAttribution"
#define kLongAttributionKey @"map.longAttribution"
#pragma mark --- end constants ----
@interface
RMDBMapSource
(
Preferences
)
...
...
@@ -219,7 +218,8 @@
{
// fetch the image from the db
FMResultSet
*
result
=
[
db
executeQuery
:
@"SELECT image FROM tiles WHERE tilekey = ?"
,
key
]
;
FMDBErrorCheck
(
db
)
;
if
([
db
hadError
])
NSLog
(
@"DB error %d on line %d: %@"
,
[
db
lastErrorCode
],
__LINE__
,
[
db
lastErrorMessage
])
;
if
([
result
next
])
image
=
[[[
UIImage
alloc
]
initWithData
:[
result
dataForColumnIndex
:
0
]]
autorelease
]
;
...
...
MapView/Map/RMFoundation.c
View file @
6f64e50
...
...
@@ -67,6 +67,7 @@ RMProjectedPoint RMScaleProjectedPointAboutPoint(RMProjectedPoint point, float f
{
point
.
x
=
(
point
.
x
-
pivot
.
x
)
*
factor
+
pivot
.
x
;
point
.
y
=
(
point
.
y
-
pivot
.
y
)
*
factor
+
pivot
.
y
;
return
point
;
}
...
...
@@ -75,6 +76,7 @@ RMProjectedRect RMScaleProjectedRectAboutPoint(RMProjectedRect rect, float facto
rect
.
origin
=
RMScaleProjectedPointAboutPoint
(
rect
.
origin
,
factor
,
pivot
);
rect
.
size
.
width
*=
factor
;
rect
.
size
.
height
*=
factor
;
return
rect
;
}
...
...
@@ -82,18 +84,21 @@ RMProjectedPoint RMTranslateProjectedPointBy(RMProjectedPoint point, RMProjected
{
point
.
x
+=
delta
.
width
;
point
.
y
+=
delta
.
height
;
return
point
;
}
RMProjectedRect
RMTranslateProjectedRectBy
(
RMProjectedRect
rect
,
RMProjectedSize
delta
)
{
rect
.
origin
=
RMTranslateProjectedPointBy
(
rect
.
origin
,
delta
);
return
rect
;
}
RMProjectedPoint
RMProjectedPointMake
(
double
x
,
double
y
)
{
RMProjectedPoint
point
=
{
x
,
y
};
return
point
;
}
...
...
@@ -103,6 +108,7 @@ RMProjectedRect RMProjectedRectMake(double x, double y, double width, double hei
{
x
,
y
},
{
width
,
height
}
};
return
rect
;
}
...
...
@@ -111,6 +117,7 @@ RMProjectedSize RMProjectedSizeMake(double width, double heigth)
RMProjectedSize
size
=
{
width
,
heigth
};
return
size
;
}
...
...
MapView/Map/RMFractalTileProjection.h
View file @
6f64e50
...
...
@@ -32,7 +32,8 @@
@class
RMProjection
;
@interface
RMFractalTileProjection
:
NSObject
{
@interface
RMFractalTileProjection
:
NSObject
{
// Maximum zoom for which our tile server stores images
NSUInteger
maxZoom
,
minZoom
;
...
...
MapView/Map/RMFractalTileProjection.m
View file @
6f64e50
...
...
@@ -97,11 +97,10 @@
{
// The mask contains a 1 for every valid x-coordinate bit.
uint32_t
mask
=
1
;
for
(
int
i
=
0
;
i
<
tile
.
zoom
;
i
++
)
{
mask
<<=
1
;
}
mask
-=
1
;
tile
.
x
&=
mask
;
...
...
MapView/Map/RMMapOverlayView.h
View file @
6f64e50
...
...
@@ -24,12 +24,9 @@
@end
@interface
RMMapOverlayView
:
UIView
{
@interface
RMMapOverlayView
:
UIView
{
id
<
RMMapOverlayViewDelegate
>
delegate
;
BOOL
_trackPanGesture
;
CGPoint
_lastTranslation
;
RMAnnotation
*
_draggedAnnotation
;
}
@property
(
nonatomic
,
assign
)
id
<
RMMapOverlayViewDelegate
>
delegate
;
...
...
MapView/Map/RMMapOverlayView.m
View file @
6f64e50
...
...
@@ -19,10 +19,15 @@
@end
@implementation
RMMapOverlayView
{
BOOL
_trackPanGesture
;
CGPoint
_lastTranslation
;
RMAnnotation
*
_draggedAnnotation
;
}
@synthesize
delegate
;
+
+
layerClass
+
(
Class
)
layerClass
{
return
[
CAScrollLayer
class
];
}
...
...
@@ -100,9 +105,9 @@
return
NO
;
CALayer
*
hit
=
[
self
.
layer
hitTest
:
point
];
if
(
!
hit
||
!
[
hit
isKindOfClass
:[
RMMarker
class
]])
{
if
(
!
hit
||
!
[
hit
isKindOfClass
:[
RMMarker
class
]])
return
NO
;
}
return
((
RMMarker
*
)
hit
).
annotation
.
enabled
;
}
...
...
@@ -124,46 +129,54 @@
-
(
void
)
handleSingleTap
:
(
UIGestureRecognizer
*
)
recognizer
{
CALayer
*
hit
=
[
self
.
layer
hitTest
:[
recognizer
locationInView
:
self
]];
if
(
!
hit
)
return
;
if
(
!
hit
)
return
;
CALayer
*
superlayer
=
[
hit
superlayer
];
// See if tap was on a marker or marker label and send delegate protocol method
if
([
hit
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
tapOnAnnotation
:
atPoint
:)])
{
if
([
hit
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
tapOnAnnotation
:
atPoint
:)])
[
delegate
mapOverlayView
:
self
tapOnAnnotation
:[((
RMMarker
*
)
hit
)
annotation
]
atPoint
:[
recognizer
locationInView
:
self
]];
}
}
else
if
(
superlayer
!=
nil
&&
[
superlayer
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
tapOnLabelForAnnotation
:
atPoint
:)])
{
}
else
if
(
superlayer
!=
nil
&&
[
superlayer
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
tapOnLabelForAnnotation
:
atPoint
:)])
[
delegate
mapOverlayView
:
self
tapOnLabelForAnnotation
:[((
RMMarker
*
)
superlayer
)
annotation
]
atPoint
:[
recognizer
locationInView
:
self
]];
}
}
else
if
([
superlayer
superlayer
]
!=
nil
&&
[[
superlayer
superlayer
]
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
tapOnLabelForAnnotation
:
atPoint
:)])
{
}
else
if
([
superlayer
superlayer
]
!=
nil
&&
[[
superlayer
superlayer
]
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
tapOnLabelForAnnotation
:
atPoint
:)])
[
delegate
mapOverlayView
:
self
tapOnLabelForAnnotation
:[((
RMMarker
*
)[
superlayer
superlayer
])
annotation
]
atPoint
:[
recognizer
locationInView
:
self
]];
}
}
}
-
(
void
)
handleDoubleTap
:
(
UIGestureRecognizer
*
)
recognizer
{
CALayer
*
hit
=
[
self
.
layer
hitTest
:[
recognizer
locationInView
:
self
]];
if
(
!
hit
)
return
;
if
(
!
hit
)
return
;
CALayer
*
superlayer
=
[
hit
superlayer
];
// See if tap was on a marker or marker label and send delegate protocol method
if
([
hit
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
doubleTapOnAnnotation
:
atPoint
:)])
{
if
([
hit
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
doubleTapOnAnnotation
:
atPoint
:)])
[
delegate
mapOverlayView
:
self
doubleTapOnAnnotation
:[((
RMMarker
*
)
hit
)
annotation
]
atPoint
:[
recognizer
locationInView
:
self
]];
}
}
else
if
(
superlayer
!=
nil
&&
[
superlayer
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
doubleTapOnLabelForAnnotation
:
atPoint
:)])
{
}
else
if
(
superlayer
!=
nil
&&
[
superlayer
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
doubleTapOnLabelForAnnotation
:
atPoint
:)])
[
delegate
mapOverlayView
:
self
doubleTapOnLabelForAnnotation
:[((
RMMarker
*
)
superlayer
)
annotation
]
atPoint
:[
recognizer
locationInView
:
self
]];
}
}
else
if
([
superlayer
superlayer
]
!=
nil
&&
[[
superlayer
superlayer
]
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
doubleTapOnLabelForAnnotation
:
atPoint
:)])
{
}
else
if
([
superlayer
superlayer
]
!=
nil
&&
[[
superlayer
superlayer
]
isKindOfClass
:[
RMMarker
class
]])
{
if
([
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
doubleTapOnLabelForAnnotation
:
atPoint
:)])
[
delegate
mapOverlayView
:
self
doubleTapOnLabelForAnnotation
:[((
RMMarker
*
)[
superlayer
superlayer
])
annotation
]
atPoint
:[
recognizer
locationInView
:
self
]];
}
}
}
...
...
@@ -172,8 +185,12 @@
if
(
recognizer
.
state
==
UIGestureRecognizerStateBegan
)
{
CALayer
*
hit
=
[
self
.
layer
hitTest
:[
recognizer
locationInView
:
self
]];
if
(
!
hit
)
return
;
if
([
hit
respondsToSelector
:
@selector
(
enableDragging
)]
&&
!
[(
RMMarker
*
)
hit
enableDragging
])
return
;
if
(
!
hit
)
return
;
if
([
hit
respondsToSelector
:
@selector
(
enableDragging
)]
&&
!
[(
RMMarker
*
)
hit
enableDragging
])
return
;
_lastTranslation
=
CGPointZero
;
[
_draggedAnnotation
release
];
...
...
@@ -185,15 +202,18 @@
_trackPanGesture
=
NO
;
}
if
(
!
_trackPanGesture
)
return
;
if
(
!
_trackPanGesture
)
return
;
if
(
recognizer
.
state
==
UIGestureRecognizerStateChanged
&&
[
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
didDragAnnotation
:
withDelta
:)])
{
if
(
recognizer
.
state
==
UIGestureRecognizerStateChanged
&&
[
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
didDragAnnotation
:
withDelta
:)])
{
CGPoint
translation
=
[
recognizer
translationInView
:
self
];
CGPoint
delta
=
CGPointMake
(
_lastTranslation
.
x
-
translation
.
x
,
_lastTranslation
.
y
-
translation
.
y
);
_lastTranslation
=
translation
;
[
delegate
mapOverlayView
:
self
didDragAnnotation
:
_draggedAnnotation
withDelta
:
delta
];
}
else
if
(
recognizer
.
state
==
UIGestureRecognizerStateEnded
&&
[
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
didEndDragAnnotation
:)])
{
}
else
if
(
recognizer
.
state
==
UIGestureRecognizerStateEnded
&&
[
delegate
respondsToSelector
:
@selector
(
mapOverlayView
:
didEndDragAnnotation
:)])
{
[
delegate
mapOverlayView
:
self
didEndDragAnnotation
:
_draggedAnnotation
];
_trackPanGesture
=
NO
;
[
_draggedAnnotation
release
];
_draggedAnnotation
=
nil
;
...
...
MapView/Map/RMMapTiledLayerView.h
View file @
6f64e50
...
...
@@ -20,7 +20,8 @@
@end
@interface
RMMapTiledLayerView
:
UIView
{
@interface
RMMapTiledLayerView
:
UIView
{
id
<
RMMapTiledLayerViewDelegate
>
delegate
;
RMMapView
*
mapView
;
}
...
...
MapView/Map/RMMapTiledLayerView.m
View file @
6f64e50
...
...
@@ -22,7 +22,7 @@
@synthesize
delegate
;
+
+
layerClass
+
(
Class
)
layerClass
{
return
[
CATiledLayer
class
];
}
...
...
MapView/Map/RMMapView.h
View file @
6f64e50
//
// RMMapView.h
//
// Copyright (c) 2008-20
09
, Route-Me Contributors
// Copyright (c) 2008-20
12
, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
...
...
@@ -57,6 +57,7 @@ typedef enum {
@class
RMMarker
;
@class
RMAnnotation
;
@class
RMQuadTree
;
@protocol
RMMercatorToTileProjection
;
@protocol
RMTileSource
;
@protocol
RMMapTiledLayerViewDelegate
;
...
...
@@ -94,34 +95,6 @@ typedef enum {
NSUInteger
boundingMask
;
RMProjectedRect
tileSourceProjectedBounds
;
@private
BOOL
_delegateHasBeforeMapMove
;
BOOL
_delegateHasAfterMapMove
;
BOOL
_delegateHasBeforeMapZoom
;
BOOL
_delegateHasAfterMapZoom
;
BOOL
_delegateHasMapViewRegionDidChange
;
BOOL
_delegateHasDoubleTapOnMap
;
BOOL
_delegateHasDoubleTapTwoFingersOnMap
;
BOOL
_delegateHasSingleTapOnMap
;
BOOL
_delegateHasSingleTapTwoFingersOnMap
;
BOOL
_delegateHasLongSingleTapOnMap
;
BOOL
_delegateHasTapOnAnnotation
;
BOOL
_delegateHasDoubleTapOnAnnotation
;
BOOL
_delegateHasTapOnLabelForAnnotation
;
BOOL
_delegateHasDoubleTapOnLabelForAnnotation
;
BOOL
_delegateHasShouldDragMarker
;
BOOL
_delegateHasDidDragMarker
;
BOOL
_delegateHasDidEndDragMarker
;
BOOL
_delegateHasLayerForAnnotation
;
BOOL
_delegateHasWillHideLayerForAnnotation
;
BOOL
_delegateHasDidHideLayerForAnnotation
;
BOOL
_constrainMovement
;
RMProjectedPoint
_northEastConstraint
,
_southWestConstraint
;
float
_lastZoom
;
CGPoint
_lastContentOffset
,
_accumulatedDelta
;
}
@property
(
nonatomic
,
assign
)
id
<
RMMapViewDelegate
>
delegate
;
...
...
MapView/Map/RMMapView.m
View file @
6f64e50
...
...
@@ -73,6 +73,34 @@
#pragma mark -
@implementation
RMMapView
{
BOOL
_delegateHasBeforeMapMove
;
BOOL
_delegateHasAfterMapMove
;
BOOL
_delegateHasBeforeMapZoom
;
BOOL
_delegateHasAfterMapZoom
;
BOOL
_delegateHasMapViewRegionDidChange
;
BOOL
_delegateHasDoubleTapOnMap
;
BOOL
_delegateHasDoubleTapTwoFingersOnMap
;
BOOL
_delegateHasSingleTapOnMap
;
BOOL
_delegateHasSingleTapTwoFingersOnMap
;
BOOL
_delegateHasLongSingleTapOnMap
;
BOOL
_delegateHasTapOnAnnotation
;
BOOL
_delegateHasDoubleTapOnAnnotation
;
BOOL
_delegateHasTapOnLabelForAnnotation
;
BOOL
_delegateHasDoubleTapOnLabelForAnnotation
;
BOOL
_delegateHasShouldDragMarker
;
BOOL
_delegateHasDidDragMarker
;
BOOL
_delegateHasDidEndDragMarker
;
BOOL
_delegateHasLayerForAnnotation
;
BOOL
_delegateHasWillHideLayerForAnnotation
;
BOOL
_delegateHasDidHideLayerForAnnotation
;
BOOL
_constrainMovement
;
RMProjectedPoint
_northEastConstraint
,
_southWestConstraint
;
float
_lastZoom
;
CGPoint
_lastContentOffset
,
_accumulatedDelta
;
}
@synthesize
decelerationMode
;
...
...
@@ -147,6 +175,7 @@
-
(
id
)
initWithCoder
:(
NSCoder
*
)
aDecoder
{
LogMethod
();
if
(
!
(
self
=
[
super
initWithCoder
:
aDecoder
]))
return
nil
;
...
...
@@ -167,12 +196,14 @@
-
(
id
)
initWithFrame
:(
CGRect
)
frame
{
LogMethod
();
return
[
self
initWithFrame
:
frame
andTilesource
:[[
RMOpenStreetMapSource
new
]
autorelease
]];
}
-
(
id
)
initWithFrame
:(
CGRect
)
frame
andTilesource
:(
id
<
RMTileSource
>
)
newTilesource
{
LogMethod
();
CLLocationCoordinate2D
coordinate
;
coordinate
.
latitude
=
kDefaultInitialLatitude
;
coordinate
.
longitude
=
kDefaultInitialLongitude
;
...
...
@@ -195,6 +226,7 @@
backgroundImage
:(
UIImage
*
)
backgroundImage
{
LogMethod
();
if
(
!
(
self
=
[
super
initWithFrame
:
frame
]))
return
nil
;
...
...
@@ -214,7 +246,8 @@
[
super
setFrame
:
frame
];
// only change if the frame changes and not during initialization
if
(
!
CGRectEqualToRect
(
r
,
frame
))
{
if
(
!
CGRectEqualToRect
(
r
,
frame
))
{
CGRect
bounds
=
CGRectMake
(
0
,
0
,
frame
.
size
.
width
,
frame
.
size
.
height
);
backgroundView
.
frame
=
bounds
;
mapScrollView
.
frame
=
bounds
;
...
...
@@ -226,6 +259,7 @@
-
(
void
)
dealloc
{
LogMethod
();
[
self
setDelegate
:
nil
];
[
self
setBackgroundView
:
nil
];
[
self
setQuadTree
:
nil
];
...
...
@@ -246,6 +280,7 @@
-
(
void
)
didReceiveMemoryWarning
{
LogMethod
();
[
tileSource
didReceiveMemoryWarning
];
[
tileCache
didReceiveMemoryWarning
];
}
...
...
@@ -258,6 +293,7 @@
-
(
NSString
*
)
description
{
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
];
}
...
...
@@ -346,6 +382,7 @@
// 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
;
if
((
myPoint
.
x
/
self
.
bounds
.
size
.
width
)
<
(
myPoint
.
y
/
self
.
bounds
.
size
.
height
))
{
if
((
myPoint
.
y
/
(
self
.
bounds
.
size
.
height
-
pixelBuffer
))
>
1
)
...
...
@@ -362,6 +399,7 @@
zoomRect
.
size
.
height
=
self
.
bounds
.
size
.
height
*
(
myPoint
.
x
/
(
self
.
bounds
.
size
.
width
-
pixelBuffer
));
}
}
myOrigin
.
x
=
myOrigin
.
x
-
(
zoomRect
.
size
.
width
/
2
);
myOrigin
.
y
=
myOrigin
.
y
-
(
zoomRect
.
size
.
height
/
2
);
...
...
@@ -377,16 +415,20 @@
-
(
BOOL
)
tileSourceBoundsContainProjectedPoint
:
(
RMProjectedPoint
)
point
{
RMSphericalTrapezium
bounds
=
[
self
.
tileSource
latitudeLongitudeBoundingBox
];
if
(
bounds
.
northEast
.
latitude
==
90
&&
bounds
.
northEast
.
longitude
==
180
&&
bounds
.
southWest
.
latitude
==
-
90
&&
bounds
.
southWest
.
longitude
==
-
180
)
{
bounds
.
southWest
.
latitude
==
-
90
&&
bounds
.
southWest
.
longitude
==
-
180
)
{
return
YES
;
}
return
[
self
projectedBounds
:
tileSourceProjectedBounds
containsPoint
:
point
];
}
-
(
BOOL
)
tileSourceBoundsContainScreenPoint
:
(
CGPoint
)
pixelCoordinate
{
RMProjectedPoint
projectedPoint
=
[
self
pixelToProjectedPoint
:
pixelCoordinate
];
return
[
self
tileSourceBoundsContainProjectedPoint
:
projectedPoint
];
}
...
...
@@ -451,7 +493,8 @@
if
(
!
[
self
tileSourceBoundsContainProjectedPoint
:
centerProjectedPoint
])
return
;
if
(
_delegateHasBeforeMapMove
)
[
delegate
beforeMapMove
:
self
];
if
(
_delegateHasBeforeMapMove
)
[
delegate
beforeMapMove
:
self
];
// RMLog(@"Current contentSize: {%.0f,%.0f}, zoom: %f", mapScrollView.contentSize.width, mapScrollView.contentSize.height, self.zoom);
...
...
@@ -466,7 +509,8 @@
// RMLog(@"setMapCenterProjectedPoint: {%f,%f} -> {%.0f,%.0f}", centerProjectedPoint.x, centerProjectedPoint.y, mapScrollView.contentOffset.x, mapScrollView.contentOffset.y);
if
(
_delegateHasAfterMapMove
)
[
delegate
afterMapMove
:
self
];
if
(
_delegateHasAfterMapMove
)
[
delegate
afterMapMove
:
self
];
[
self
correctPositionOfAllAnnotations
];
}
...
...
@@ -490,19 +534,24 @@
// see if new bounds are within constrained bounds, and constrain if necessary
BOOL
constrained
=
NO
;
if
(
newBounds
.
origin
.
y
<
_southWestConstraint
.
y
)
{
if
(
newBounds
.
origin
.
y
<
_southWestConstraint
.
y
)
{
newBounds
.
origin
.
y
=
_southWestConstraint
.
y
;
constrained
=
YES
;
}
if
(
newBounds
.
origin
.
y
+
newBounds
.
size
.
height
>
_northEastConstraint
.
y
)
{
if
(
newBounds
.
origin
.
y
+
newBounds
.
size
.
height
>
_northEastConstraint
.
y
)
{
newBounds
.
origin
.
y
=
_northEastConstraint
.
y
-
newBounds
.
size
.
height
;
constrained
=
YES
;
}
if
(
newBounds
.
origin
.
x
<
_southWestConstraint
.
x
)
{
if
(
newBounds
.
origin
.
x
<
_southWestConstraint
.
x
)
{
newBounds
.
origin
.
x
=
_southWestConstraint
.
x
;
constrained
=
YES
;
}
if
(
newBounds
.
origin
.
x
+
newBounds
.
size
.
width
>
_northEastConstraint
.
x
)
{
if
(
newBounds
.
origin
.
x
+
newBounds
.
size
.
width
>
_northEastConstraint
.
x
)
{
newBounds
.
origin
.
x
=
_northEastConstraint
.
x
-
newBounds
.
size
.
width
;
constrained
=
YES
;
}
...
...
@@ -517,12 +566,16 @@
}
}
if
(
_delegateHasBeforeMapMove
)
[
delegate
beforeMapMove
:
self
];
if
(
_delegateHasBeforeMapMove
)
[
delegate
beforeMapMove
:
self
];
CGPoint
contentOffset
=
mapScrollView
.
contentOffset
;
contentOffset
.
x
+=
delta
.
width
;
contentOffset
.
y
+=
delta
.
height
;
mapScrollView
.
contentOffset
=
contentOffset
;
if
(
_delegateHasAfterMapMove
)
[
delegate
afterMapMove
:
self
];
if
(
_delegateHasAfterMapMove
)
[
delegate
afterMapMove
:
self
];
}
#pragma mark -
...
...
@@ -614,11 +667,10 @@
//zooming in zoomFactor > 1
//zooming out zoomFactor < 1
if
((
zoomGreaterMin
&&
zoomLessMax
)
||
(
zoomAtMax
&&
zoomFactor
<
1
)
||
(
zoomAtMin
&&
zoomFactor
>
1
))
{
if
((
zoomGreaterMin
&&
zoomLessMax
)
||
(
zoomAtMax
&&
zoomFactor
<
1
)
||
(
zoomAtMin
&&
zoomFactor
>
1
))
return
YES
;
}
else
{
else
return
NO
;
}
}
-
(
void
)
zoomContentByFactor
:
(
float
)
zoomFactor
near
:
(
CGPoint
)
pivot
animated
:
(
BOOL
)
animated
...
...
@@ -635,14 +687,16 @@
// clamp zoom to remain below or equal to maxZoom after zoomAfter will be applied
// Set targetZoom to maxZoom so the map zooms to its maximum
if
(
targetZoom
>
[
self
maxZoom
])
{
if
(
targetZoom
>
[
self
maxZoom
])
{
zoomFactor
=
exp2f
([
self
maxZoom
]
-
[
self
zoom
]);
targetZoom
=
[
self
maxZoom
];
}
// clamp zoom to remain above or equal to minZoom after zoomAfter will be applied
// Set targetZoom to minZoom so the map zooms to its maximum
if
(
targetZoom
<
[
self
minZoom
])
{
if
(
targetZoom
<
[
self
minZoom
])
{
zoomFactor
=
1
/
exp2f
([
self
zoom
]
-
[
self
minZoom
]);
targetZoom
=
[
self
minZoom
];
}
...
...
@@ -672,12 +726,14 @@
-
(
float
)
nextNativeZoomFactor
{
float
newZoom
=
fminf
(
floorf
([
self
zoom
]
+
1
.
0
),
[
self
maxZoom
]);
return
exp2f
(
newZoom
-
[
self
zoom
]);
}
-
(
float
)
previousNativeZoomFactor
{
float
newZoom
=
fmaxf
(
floorf
([
self
zoom
]
-
1
.
0
),
[
self
minZoom
]);
return
exp2f
(
newZoom
-
[
self
zoom
]);
}
...
...
@@ -690,10 +746,14 @@
{
// Calculate rounded zoom
float
newZoom
=
fmin
(
ceilf
([
self
zoom
])
+
0
.
99
,
[
self
maxZoom
]);
if
(
newZoom
==
self
.
zoom
)
return
;
if
(
newZoom
==
self
.
zoom
)
return
;
float
factor
=
exp2f
(
newZoom
-
[
self
zoom
]);
if
(
factor
>
2
.
25
)
{
if
(
factor
>
2
.
25
)
{
newZoom
=
fmin
(
ceilf
([
self
zoom
])
-
0
.
01
,
[
self
maxZoom
]);
factor
=
exp2f
(
newZoom
-
[
self
zoom
]);
}
...
...
@@ -711,10 +771,14 @@
{
// Calculate rounded zoom
float
newZoom
=
fmax
(
floorf
([
self
zoom
])
-
0
.
01
,
[
self
minZoom
]);
if
(
newZoom
==
self
.
zoom
)
return
;
if
(
newZoom
==
self
.
zoom
)
return
;
float
factor
=
exp2f
(
newZoom
-
[
self
zoom
]);
if
(
factor
>
0
.
75
)
{
if
(
factor
>
0
.
75
)
{
newZoom
=
fmax
(
floorf
([
self
zoom
])
-
1
.
01
,
[
self
minZoom
]);
factor
=
exp2f
(
newZoom
-
[
self
zoom
]);
}
...
...
@@ -731,20 +795,22 @@
float
_zoomFactor
=
[
self
adjustedZoomForCurrentBoundingMask
:
zoomFactor
];
float
zoomDelta
=
log2f
(
_zoomFactor
);
float
targetZoom
=
zoomDelta
+
[
self
zoom
];
BOOL
canZoom
=
NO
;
if
(
targetZoom
==
[
self
zoom
])
{
if
(
targetZoom
==
[
self
zoom
])
{
//OK... . I could even do a return here.. but it will hamper with future logic..
canZoom
=
YES
;
}
// clamp zoom to remain below or equal to maxZoom after zoomAfter will be applied
if
(
targetZoom
>
[
self
maxZoom
])
{
if
(
targetZoom
>
[
self
maxZoom
])
zoomFactor
=
exp2f
([
self
maxZoom
]
-
[
self
zoom
]);
}
// clamp zoom to remain above or equal to minZoom after zoomAfter will be applied
if
(
targetZoom
<
[
self
minZoom
])
{
if
(
targetZoom
<
[
self
minZoom
])
zoomFactor
=
1
/
exp2f
([
self
zoom
]
-
[
self
minZoom
]);
}
// bools for syntactical sugar to understand the logic in the if statement below
BOOL
zoomAtMax
=
([
self
zoom
]
==
[
self
maxZoom
]);
...
...
@@ -784,7 +850,8 @@
zRect
.
origin
.
x
<
_southWestConstraint
.
x
||
zRect
.
origin
.
x
+
zRect
.
size
.
width
>
_northEastConstraint
.
x
);
}
if
(
!
canZoom
)
{
if
(
!
canZoom
)
{
RMLog
(
@"Zooming will move map out of bounds: no zoom"
);
return
;
}
...
...
@@ -832,6 +899,7 @@
// 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
;
if
((
myPoint
.
x
/
self
.
bounds
.
size
.
width
)
<
(
myPoint
.
y
/
self
.
bounds
.
size
.
height
))
{
if
((
myPoint
.
y
/
(
self
.
bounds
.
size
.
height
-
pixelBuffer
))
>
1
)
...
...
@@ -848,6 +916,7 @@
zoomRect
.
size
.
height
=
self
.
bounds
.
size
.
height
*
(
myPoint
.
x
/
(
self
.
bounds
.
size
.
width
-
pixelBuffer
));
}
}
myOrigin
.
x
=
myOrigin
.
x
-
(
zoomRect
.
size
.
width
/
2
);
myOrigin
.
y
=
myOrigin
.
y
-
(
zoomRect
.
size
.
height
/
2
);
zoomRect
.
origin
=
myOrigin
;
...
...
@@ -897,11 +966,17 @@
tiledLayerView
=
[[
RMMapTiledLayerView
alloc
]
initWithFrame
:
CGRectMake
(
0
.
0
,
0
.
0
,
contentSize
.
width
,
contentSize
.
height
)
mapView
:
self
];
tiledLayerView
.
delegate
=
self
;
if
(
self
.
adjustTilesForRetinaDisplay
&&
screenScale
>
1
.
0
)
{
if
(
self
.
adjustTilesForRetinaDisplay
&&
screenScale
>
1
.
0
)
{
RMLog
(
@"adjustTiles"
);
((
CATiledLayer
*
)
tiledLayerView
.
layer
).
tileSize
=
CGSizeMake
(
tileSideLength
*
2
.
0
,
tileSideLength
*
2
.
0
);
}
else
}
else
{
((
CATiledLayer
*
)
tiledLayerView
.
layer
).
tileSize
=
CGSizeMake
(
tileSideLength
,
tileSideLength
);
}
[
mapScrollView
addSubview
:
tiledLayerView
];
[
mapScrollView
addObserver
:
self
forKeyPath
:
@"contentOffset"
options
:
NSKeyValueObservingOptionNew
context
:
NULL
];
...
...
@@ -918,6 +993,7 @@
overlayView
=
[[
RMMapOverlayView
alloc
]
initWithFrame
:[
self
bounds
]];
overlayView
.
delegate
=
self
;
[
self
insertSubview
:
overlayView
aboveSubview
:
mapScrollView
];
}
...
...
@@ -968,9 +1044,12 @@
-
(
void
)
mapOverlayView
:
(
RMMapOverlayView
*
)
aMapOverlayView
tapOnAnnotation
:
(
RMAnnotation
*
)
anAnnotation
atPoint
:
(
CGPoint
)
aPoint
{
if
(
_delegateHasTapOnAnnotation
&&
anAnnotation
)
{
if
(
_delegateHasTapOnAnnotation
&&
anAnnotation
)
{
[
delegate
tapOnAnnotation
:
anAnnotation
onMap
:
self
];
}
else
{
}
else
{
if
(
_delegateHasSingleTapOnMap
)
[
delegate
singleTapOnMap
:
self
at
:
aPoint
];
}
...
...
@@ -978,9 +1057,12 @@
-
(
void
)
mapOverlayView
:
(
RMMapOverlayView
*
)
aMapOverlayView
doubleTapOnAnnotation
:
(
RMAnnotation
*
)
anAnnotation
atPoint
:
(
CGPoint
)
aPoint
{
if
(
_delegateHasDoubleTapOnAnnotation
&&
anAnnotation
)
{
if
(
_delegateHasDoubleTapOnAnnotation
&&
anAnnotation
)
{
[
delegate
doubleTapOnAnnotation
:
anAnnotation
onMap
:
self
];
}
else
{
}
else
{
[
self
zoomInToNextNativeZoomAt
:
aPoint
animated
:
YES
];
if
(
_delegateHasDoubleTapOnMap
)
...
...
@@ -990,9 +1072,12 @@
-
(
void
)
mapOverlayView
:
(
RMMapOverlayView
*
)
aMapOverlayView
tapOnLabelForAnnotation
:
(
RMAnnotation
*
)
anAnnotation
atPoint
:
(
CGPoint
)
aPoint
{
if
(
_delegateHasTapOnLabelForAnnotation
&&
anAnnotation
)
{
if
(
_delegateHasTapOnLabelForAnnotation
&&
anAnnotation
)
{
[
delegate
tapOnLabelForAnnotation
:
anAnnotation
onMap
:
self
];
}
else
{
}
else
{
if
(
_delegateHasSingleTapOnMap
)
[
delegate
singleTapOnMap
:
self
at
:
aPoint
];
}
...
...
@@ -1001,8 +1086,11 @@
-
(
void
)
mapOverlayView
:
(
RMMapOverlayView
*
)
aMapOverlayView
doubleTapOnLabelForAnnotation
:
(
RMAnnotation
*
)
anAnnotation
atPoint
:
(
CGPoint
)
aPoint
{
if
(
_delegateHasDoubleTapOnLabelForAnnotation
&&
anAnnotation
)
{
[
delegate
doubleTapOnLabelForAnnotation
:
anAnnotation
onMap
:
self
];
else
{
}
else
{
[
self
zoomInToNextNativeZoomAt
:
aPoint
animated
:
YES
];
if
(
_delegateHasDoubleTapOnMap
)
...
...
@@ -1078,10 +1166,12 @@
[
NSObject
cancelPreviousPerformRequestsWithTarget
:
self
selector
:
@selector
(
correctPositionOfAllAnnotations
)
object
:
nil
];
if
(
_constrainMovement
&&
!
[
self
projectedBounds
:
tileSourceProjectedBounds
containsPoint
:[
self
centerProjectedPoint
]])
{
if
(
_constrainMovement
&&
!
[
self
projectedBounds
:
tileSourceProjectedBounds
containsPoint
:[
self
centerProjectedPoint
]])
{
dispatch_async
(
dispatch_get_main_queue
(),
^
{
[
mapScrollView
setContentOffset
:
_lastContentOffset
animated
:
NO
];
});
return
;
}
...
...
@@ -1092,14 +1182,18 @@
_accumulatedDelta
.
x
+=
delta
.
x
;
_accumulatedDelta
.
y
+=
delta
.
y
;
if
(
fabsf
(
_accumulatedDelta
.
x
)
<
kZoomRectPixelBuffer
&&
fabsf
(
_accumulatedDelta
.
y
)
<
kZoomRectPixelBuffer
)
{
if
(
fabsf
(
_accumulatedDelta
.
x
)
<
kZoomRectPixelBuffer
&&
fabsf
(
_accumulatedDelta
.
y
)
<
kZoomRectPixelBuffer
)
{
[
overlayView
moveLayersBy
:
_accumulatedDelta
];
[
self
performSelector
:
@selector
(
correctPositionOfAllAnnotations
)
withObject
:
nil
afterDelay
:
0
.
1
];
}
else
{
}
else
{
[
self
correctPositionOfAllAnnotations
];
}
}
else
{
}
else
{
[
self
correctPositionOfAllAnnotationsIncludingInvisibles
:
NO
];
_lastZoom
=
zoom
;
}
...
...
@@ -1107,7 +1201,8 @@
_lastContentOffset
=
mapScrollView
.
contentOffset
;
// Don't do anything stupid here or your scrolling experience will suck
if
(
_delegateHasMapViewRegionDidChange
)
[
delegate
mapViewRegionDidChange
:
self
];
if
(
_delegateHasMapViewRegionDidChange
)
[
delegate
mapViewRegionDidChange
:
self
];
}
#pragma mark -
...
...
@@ -1156,7 +1251,8 @@
if
(
backgroundView
==
aView
)
return
;
if
(
backgroundView
!=
nil
)
{
if
(
backgroundView
!=
nil
)
{
[
backgroundView
removeFromSuperview
];
[
backgroundView
release
];
}
...
...
@@ -1183,6 +1279,7 @@
-
(
void
)
setMetersPerPixel
:
(
double
)
newMetersPerPixel
animated
:
(
BOOL
)
animated
{
double
factor
=
self
.
metersPerPixel
/
newMetersPerPixel
;
[
self
zoomContentByFactor
:
factor
near
:
CGPointMake
(
self
.
bounds
.
size
.
width
/
2
.
0
,
self
.
bounds
.
size
.
height
/
2
.
0
)
animated
:
animated
];
}
...
...
@@ -1196,6 +1293,7 @@
double
routemeMetersPerPixel
=
self
.
metersPerPixel
;
double
iphoneMillimetersPerPixel
=
kiPhoneMilimeteresPerPixel
;
double
truescaleDenominator
=
routemeMetersPerPixel
/
(
0
.
001
*
iphoneMillimetersPerPixel
);
return
truescaleDenominator
;
}
...
...
@@ -1236,6 +1334,7 @@
-
(
void
)
setEnableClustering
:
(
BOOL
)
doEnableClustering
{
enableClustering
=
doEnableClustering
;
[
self
correctPositionOfAllAnnotations
];
}
...
...
@@ -1244,8 +1343,12 @@
decelerationMode
=
aDecelerationMode
;
float
decelerationRate
=
0
.
0
;
if
(
aDecelerationMode
==
RMMapDecelerationNormal
)
decelerationRate
=
UIScrollViewDecelerationRateNormal
;
else
if
(
aDecelerationMode
==
RMMapDecelerationFast
)
decelerationRate
=
UIScrollViewDecelerationRateFast
;
if
(
aDecelerationMode
==
RMMapDecelerationNormal
)
decelerationRate
=
UIScrollViewDecelerationRateNormal
;
else
if
(
aDecelerationMode
==
RMMapDecelerationFast
)
decelerationRate
=
UIScrollViewDecelerationRateFast
;
[
mapScrollView
setDecelerationRate
:
decelerationRate
];
}
...
...
@@ -1261,9 +1364,11 @@
-
(
void
)
setAdjustTilesForRetinaDisplay
:
(
BOOL
)
doAdjustTilesForRetinaDisplay
{
if
(
adjustTilesForRetinaDisplay
==
doAdjustTilesForRetinaDisplay
)
return
;
if
(
adjustTilesForRetinaDisplay
==
doAdjustTilesForRetinaDisplay
)
return
;
adjustTilesForRetinaDisplay
=
doAdjustTilesForRetinaDisplay
;
[
self
createMapView
];
}
...
...
@@ -1420,14 +1525,15 @@
if
(
self
.
quadTree
)
{
if
(
!
correctAllAnnotations
)
{
if
(
!
correctAllAnnotations
)
{
for
(
RMAnnotation
*
annotation
in
visibleAnnotations
)
{
[
self
correctScreenPosition
:
annotation
];
}
// RMLog(@"%d annotations corrected", [visibleAnnotations count]);
[
CATransaction
commit
];
return
;
}
...
...
@@ -1451,26 +1557,33 @@
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
];
}
[
previousVisibleAnnotations
removeObject
:
annotation
];
}
for
(
RMAnnotation
*
annotation
in
previousVisibleAnnotations
)
{
if
(
_delegateHasWillHideLayerForAnnotation
)
[
delegate
mapView
:
self
willHideLayerForAnnotation
:
annotation
];
if
(
_delegateHasWillHideLayerForAnnotation
)
[
delegate
mapView
:
self
willHideLayerForAnnotation
:
annotation
];
annotation
.
layer
=
nil
;
if
(
_delegateHasDidHideLayerForAnnotation
)
[
delegate
mapView
:
self
didHideLayerForAnnotation
:
annotation
];
if
(
_delegateHasDidHideLayerForAnnotation
)
[
delegate
mapView
:
self
didHideLayerForAnnotation
:
annotation
];
[
visibleAnnotations
removeObject
:
annotation
];
}
[
previousVisibleAnnotations
release
];
// RMLog(@"%d annotations on screen, %d total", [overlayView sublayersCount], [annotations count]);
}
else
}
else
{
CALayer
*
lastLayer
=
nil
;
...
...
@@ -1481,13 +1594,16 @@
for
(
RMAnnotation
*
annotation
in
annotations
)
{
[
self
correctScreenPosition
:
annotation
];
if
([
annotation
isAnnotationWithinBounds
:[
self
bounds
]])
{
if
([
annotation
isAnnotationWithinBounds
:[
self
bounds
]])
{
if
(
annotation
.
layer
==
nil
&&
_delegateHasLayerForAnnotation
)
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
];
else
...
...
@@ -1495,20 +1611,28 @@
[
visibleAnnotations
addObject
:
annotation
];
}
lastLayer
=
annotation
.
layer
;
}
else
{
if
(
_delegateHasWillHideLayerForAnnotation
)
[
delegate
mapView
:
self
willHideLayerForAnnotation
:
annotation
];
}
else
{
if
(
_delegateHasWillHideLayerForAnnotation
)
[
delegate
mapView
:
self
willHideLayerForAnnotation
:
annotation
];
annotation
.
layer
=
nil
;
[
visibleAnnotations
removeObject
:
annotation
];
if
(
_delegateHasDidHideLayerForAnnotation
)
[
delegate
mapView
:
self
didHideLayerForAnnotation
:
annotation
];
if
(
_delegateHasDidHideLayerForAnnotation
)
[
delegate
mapView
:
self
didHideLayerForAnnotation
:
annotation
];
}
}
// RMLog(@"%d annotations on screen, %d total", [overlayView sublayersCount], [annotations count]);
}
else
{
}
else
{
for
(
RMAnnotation
*
annotation
in
visibleAnnotations
)
{
[
self
correctScreenPosition
:
annotation
];
}
// RMLog(@"%d annotations corrected", [visibleAnnotations count]);
}
}
...
...
@@ -1529,21 +1653,26 @@
-
(
void
)
addAnnotation
:
(
RMAnnotation
*
)
annotation
{
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
[
annotations
addObject
:
annotation
];
[
self
.
quadTree
addAnnotation
:
annotation
];
}
if
(
enableClustering
)
{
if
(
enableClustering
)
{
[
self
correctPositionOfAllAnnotations
];
}
else
{
}
else
{
[
self
correctScreenPosition
:
annotation
];
if
([
annotation
isAnnotationOnScreen
]
&&
[
delegate
respondsToSelector
:
@selector
(
mapView
:
layerForAnnotation
:)])
{
annotation
.
layer
=
[
delegate
mapView
:
self
layerForAnnotation
:
annotation
];
if
(
annotation
.
layer
)
{
if
(
annotation
.
layer
)
{
[
overlayView
addSublayer
:
annotation
.
layer
];
[
visibleAnnotations
addObject
:
annotation
];
}
...
...
@@ -1553,22 +1682,26 @@
-
(
void
)
addAnnotations
:
(
NSArray
*
)
newAnnotations
{
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
for
(
RMAnnotation
*
annotation
in
newAnnotations
)
{
[
annotations
addObject
:
annotation
];
[
self
.
quadTree
addAnnotation
:
annotation
];
}
}
[
self
correctPositionOfAllAnnotationsIncludingInvisibles
:
YES
];
}
-
(
void
)
removeAnnotation
:
(
RMAnnotation
*
)
annotation
{
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
[
annotations
removeObject
:
annotation
];
[
visibleAnnotations
removeObject
:
annotation
];
}
[
self
.
quadTree
removeAnnotation
:
annotation
];
// Remove the layer from the screen
...
...
@@ -1577,7 +1710,8 @@
-
(
void
)
removeAnnotations
:
(
NSArray
*
)
annotationsToRemove
{
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
for
(
RMAnnotation
*
annotation
in
annotationsToRemove
)
{
[
annotations
removeObject
:
annotation
];
...
...
@@ -1592,7 +1726,8 @@
-
(
void
)
removeAllAnnotations
{
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
for
(
RMAnnotation
*
annotation
in
annotations
)
{
// Remove the layer from the screen
...
...
MapView/Map/RMMarker.m
View file @
6f64e50
...
...
@@ -103,12 +103,14 @@
if
(
label
==
aView
)
return
;
if
(
label
!=
nil
)
{
if
(
label
!=
nil
)
{
[[
label
layer
]
removeFromSuperlayer
];
[
label
release
];
label
=
nil
;
}
if
(
aView
!=
nil
)
{
if
(
aView
!=
nil
)
{
label
=
[
aView
retain
];
[
self
addSublayer
:[
label
layer
]];
}
...
...
@@ -166,7 +168,8 @@
-
(
void
)
showLabel
{
if
([
self
.
label
isHidden
])
{
if
([
self
.
label
isHidden
])
{
// Using addSublayer will animate showing the label, whereas setHidden is not animated
[
self
addSublayer
:[
self
.
label
layer
]];
[
self
.
label
setHidden
:
NO
];
...
...
@@ -175,7 +178,8 @@
-
(
void
)
hideLabel
{
if
(
!
[
self
.
label
isHidden
])
{
if
(
!
[
self
.
label
isHidden
])
{
// Using removeFromSuperlayer will animate hiding the label, whereas setHidden is not animated
[[
self
.
label
layer
]
removeFromSuperlayer
];
[
self
.
label
setHidden
:
YES
];
...
...
MapView/Map/RMMemoryCache.h
View file @
6f64e50
...
...
@@ -29,7 +29,8 @@
#import "RMTile.h"
#import "RMTileCache.h"
@interface
RMMemoryCache
:
NSObject
<
RMTileCache
>
{
@interface
RMMemoryCache
:
NSObject
<
RMTileCache
>
{
NSMutableDictionary
*
cache
;
NSUInteger
capacity
;
}
...
...
MapView/Map/RMMemoryCache.m
View file @
6f64e50
...
...
@@ -41,6 +41,7 @@
if
(
aCapacity
<
1
)
aCapacity
=
1
;
capacity
=
aCapacity
;
return
self
;
...
...
@@ -53,24 +54,29 @@
-
(
void
)
dealloc
{
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
[
cache
removeAllObjects
];
[
cache
release
];
cache
=
nil
;
}
[
super
dealloc
];
}
-
(
void
)
didReceiveMemoryWarning
{
LogMethod
();
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
[
cache
removeAllObjects
];
}
}
-
(
void
)
removeTile
:
(
RMTile
)
tile
{
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
[
cache
removeObjectForKey
:[
RMTileCache
tileHash
:
tile
]];
}
}
...
...
@@ -81,13 +87,15 @@
RMCacheObject
*
cachedObject
=
nil
;
NSNumber
*
tileHash
=
[
RMTileCache
tileHash
:
tile
];
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
cachedObject
=
[
cache
objectForKey
:
tileHash
];
if
(
!
cachedObject
)
return
nil
;
if
(
!
[[
cachedObject
cacheKey
]
isEqualToString
:
aCacheKey
])
{
if
(
!
[[
cachedObject
cacheKey
]
isEqualToString
:
aCacheKey
])
{
[
cache
removeObjectForKey
:
tileHash
];
return
nil
;
}
...
...
@@ -103,7 +111,8 @@
/// Remove the least-recently used image from cache, if cache is at or over capacity. Removes only 1 image.
-
(
void
)
makeSpaceInCache
{
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
while
([
cache
count
]
>=
capacity
)
{
// Rather than scanning I would really like to be using a priority queue
...
...
@@ -126,7 +135,8 @@
}
}
if
(
oldestImage
)
{
if
(
oldestImage
)
{
// RMLog(@"Memory cache delete tile %d %d %d (%@)", oldestImage.tile.x, oldestImage.tile.y, oldestImage.tile.zoom, [RMTileCache tileHash:oldestImage.tile]);
[
cache
removeObjectForKey
:[
RMTileCache
tileHash
:
oldestImage
.
tile
]];
}
...
...
@@ -140,7 +150,8 @@
[
self
makeSpaceInCache
];
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
[
cache
setObject
:[
RMCacheObject
cacheObject
:
image
forTile
:
tile
withCacheKey
:
aCacheKey
]
forKey
:[
RMTileCache
tileHash
:
tile
]];
}
}
...
...
@@ -148,7 +159,9 @@
-
(
void
)
removeAllCachedImages
{
LogMethod
();
@synchronized
(
cache
)
{
@synchronized
(
cache
)
{
[
cache
removeAllObjects
];
}
}
...
...
MapView/Map/RMOpenCycleMapSource.h
View file @
6f64e50
...
...
@@ -32,7 +32,6 @@
Provides key-based access to tiles from the Open Cycle Map project.
*/
@interface
RMOpenCycleMapSource
:
RMAbstractWebMapSource
{
}
@interface
RMOpenCycleMapSource
:
RMAbstractWebMapSource
@end
\ No newline at end of file
...
...
MapView/Map/RMOpenCycleMapSource.m
View file @
6f64e50
...
...
@@ -46,6 +46,7 @@
NSAssert4
(((
tile
.
zoom
>=
self
.
minZoom
)
&&
(
tile
.
zoom
<=
self
.
maxZoom
)),
@"%@ tried to retrieve tile with zoomLevel %d, outside source's defined range %f to %f"
,
self
,
tile
.
zoom
,
self
.
minZoom
,
self
.
maxZoom
);
return
[
NSURL
URLWithString
:[
NSString
stringWithFormat
:
@"http://andy.sandbox.cloudmade.com/tiles/cycle/%d/%d/%d.png"
,
tile
.
zoom
,
tile
.
x
,
tile
.
y
]];
}
...
...
MapView/Map/RMOpenStreetMapSource.h
View file @
6f64e50
...
...
@@ -32,7 +32,6 @@
Provides key-based access to tiles from the Open Street Map project.
*/
@interface
RMOpenStreetMapSource
:
RMAbstractWebMapSource
{
}
@interface
RMOpenStreetMapSource
:
RMAbstractWebMapSource
@end
...
...
MapView/Map/RMOpenStreetMapSource.m
View file @
6f64e50
...
...
@@ -46,6 +46,7 @@
NSAssert4
(((
tile
.
zoom
>=
self
.
minZoom
)
&&
(
tile
.
zoom
<=
self
.
maxZoom
)),
@"%@ tried to retrieve tile with zoomLevel %d, outside source's defined range %f to %f"
,
self
,
tile
.
zoom
,
self
.
minZoom
,
self
.
maxZoom
);
return
[
NSURL
URLWithString
:[
NSString
stringWithFormat
:
@"http://tile.openstreetmap.org/%d/%d/%d.png"
,
tile
.
zoom
,
tile
.
x
,
tile
.
y
]];
}
...
...
MapView/Map/RMPath.m
View file @
6f64e50
...
...
@@ -95,7 +95,8 @@
-
(
void
)
recalculateGeometry
{
if
(
ignorePathUpdates
)
return
;
if
(
ignorePathUpdates
)
return
;
CGPoint
myPosition
=
self
.
annotation
.
position
;
...
...
@@ -108,7 +109,9 @@
// The bounds are actually in mercators...
/// \bug if "bounds are actually in mercators", shouldn't be using a CGRect
scaledLineWidth
=
lineWidth
;
if
(
!
scaleLineWidth
)
{
if
(
!
scaleLineWidth
)
{
renderedScale
=
[
mapView
metersPerPixel
];
scaledLineWidth
*=
renderedScale
;
}
...
...
@@ -124,24 +127,31 @@
// Clip top
offset
=
myPosition
.
y
+
pixelBounds
.
origin
.
y
-
screenBounds
.
origin
.
y
+
outset
;
if
(
offset
<
0
.
0
f
)
{
if
(
offset
<
0
.
0
f
)
{
pixelBounds
.
origin
.
y
-=
offset
;
pixelBounds
.
size
.
height
+=
offset
;
}
// Clip left
offset
=
myPosition
.
x
+
pixelBounds
.
origin
.
x
-
screenBounds
.
origin
.
x
+
outset
;
if
(
offset
<
0
.
0
f
)
{
if
(
offset
<
0
.
0
f
)
{
pixelBounds
.
origin
.
x
-=
offset
;
pixelBounds
.
size
.
width
+=
offset
;
}
// Clip bottom
offset
=
myPosition
.
y
+
pixelBounds
.
origin
.
y
+
pixelBounds
.
size
.
height
-
screenBounds
.
origin
.
y
-
screenBounds
.
size
.
height
-
outset
;
if
(
offset
>
0
.
0
f
)
{
if
(
offset
>
0
.
0
f
)
{
pixelBounds
.
size
.
height
-=
offset
;
}
// Clip right
offset
=
myPosition
.
x
+
pixelBounds
.
origin
.
x
+
pixelBounds
.
size
.
width
-
screenBounds
.
origin
.
x
-
screenBounds
.
size
.
width
-
outset
;
if
(
offset
>
0
.
0
f
)
{
if
(
offset
>
0
.
0
f
)
{
pixelBounds
.
size
.
width
-=
offset
;
}
...
...
@@ -154,6 +164,7 @@
pathBoundingBox
=
CGRectMake
(
myPosition
.
x
+
self
.
bounds
.
origin
.
x
,
myPosition
.
y
+
self
.
bounds
.
origin
.
y
,
self
.
bounds
.
size
.
width
,
self
.
bounds
.
size
.
height
);
self
.
anchorPoint
=
CGPointMake
(
-
pixelBounds
.
origin
.
x
/
pixelBounds
.
size
.
width
,
-
pixelBounds
.
origin
.
y
/
pixelBounds
.
size
.
height
);
[
self
setNeedsDisplay
];
}
...
...
@@ -176,11 +187,9 @@
point
.
y
=
point
.
y
-
projectedLocation
.
y
;
if
(
isDrawing
)
{
CGPathAddLineToPoint
(
path
,
NULL
,
point
.
x
,
-
point
.
y
);
}
else
{
else
CGPathMoveToPoint
(
path
,
NULL
,
point
.
x
,
-
point
.
y
);
}
[
self
recalculateGeometry
];
}
...
...
@@ -238,16 +247,17 @@
float
scale
=
1
.
0
f
/
[
mapView
metersPerPixel
];
float
scaledLineWidth
=
lineWidth
;
if
(
!
scaleLineWidth
)
{
if
(
!
scaleLineWidth
)
scaledLineWidth
*=
renderedScale
;
}
// NSLog(@"line width = %f, content scale = %f", scaledLineWidth, renderedScale);
if
(
!
scaleLineDash
&&
_lineDashLengths
)
{
if
(
!
scaleLineDash
&&
_lineDashLengths
)
{
dashLengths
=
_scaledLineDashLengths
;
for
(
size_t
dashIndex
=
0
;
dashIndex
<
_lineDashCount
;
dashIndex
++
)
{
for
(
size_t
dashIndex
=
0
;
dashIndex
<
_lineDashCount
;
dashIndex
++
)
dashLengths
[
dashIndex
]
=
_lineDashLengths
[
dashIndex
]
*
renderedScale
;
}
}
CGContextScaleCTM
(
theContext
,
scale
,
scale
);
...
...
@@ -261,9 +271,8 @@
CGContextSetStrokeColorWithColor
(
theContext
,
[
lineColor
CGColor
]);
CGContextSetFillColorWithColor
(
theContext
,
[
fillColor
CGColor
]);
if
(
_lineDashLengths
)
{
if
(
_lineDashLengths
)
CGContextSetLineDash
(
theContext
,
lineDashPhase
,
dashLengths
,
_lineDashCount
);
}
// according to Apple's documentation, DrawPath closes the path if it's a filled style, so a call to ClosePath isn't necessary
CGContextDrawPath
(
theContext
,
drawingMode
);
...
...
@@ -325,7 +334,8 @@
-
(
void
)
setLineColor
:
(
UIColor
*
)
aLineColor
{
if
(
lineColor
!=
aLineColor
)
{
if
(
lineColor
!=
aLineColor
)
{
[
lineColor
release
];
lineColor
=
[
aLineColor
retain
];
[
self
setNeedsDisplay
];
...
...
@@ -339,7 +349,8 @@
-
(
void
)
setFillColor
:
(
UIColor
*
)
aFillColor
{
if
(
fillColor
!=
aFillColor
)
{
if
(
fillColor
!=
aFillColor
)
{
[
fillColor
release
];
fillColor
=
[
aFillColor
retain
];
[
self
setNeedsDisplay
];
...
...
@@ -349,42 +360,48 @@
-
(
NSArray
*
)
lineDashLengths
{
NSMutableArray
*
lengths
=
[
NSMutableArray
arrayWithCapacity
:
_lineDashCount
];
for
(
size_t
dashIndex
=
0
;
dashIndex
<
_lineDashCount
;
dashIndex
++
)
{
for
(
size_t
dashIndex
=
0
;
dashIndex
<
_lineDashCount
;
dashIndex
++
)
[
lengths
addObject
:(
id
)[
NSNumber
numberWithFloat
:
_lineDashLengths
[
dashIndex
]]];
}
return
lengths
;
}
-
(
void
)
setLineDashLengths
:
(
NSArray
*
)
lengths
{
if
(
_lineDashLengths
)
{
if
(
_lineDashLengths
)
{
free
(
_lineDashLengths
);
_lineDashLengths
=
NULL
;
}
if
(
_scaledLineDashLengths
)
{
if
(
_scaledLineDashLengths
)
{
free
(
_scaledLineDashLengths
);
_scaledLineDashLengths
=
NULL
;
}
_lineDashCount
=
[
lengths
count
];
if
(
!
_lineDashCount
)
{
if
(
!
_lineDashCount
)
return
;
}
_lineDashLengths
=
calloc
(
_lineDashCount
,
sizeof
(
CGFloat
));
if
(
!
scaleLineDash
)
{
if
(
!
scaleLineDash
)
_scaledLineDashLengths
=
calloc
(
_lineDashCount
,
sizeof
(
CGFloat
));
}
NSEnumerator
*
lengthEnumerator
=
[
lengths
objectEnumerator
];
id
lenObj
;
size_t
dashIndex
=
0
;
while
((
lenObj
=
[
lengthEnumerator
nextObject
]))
{
if
([
lenObj
isKindOfClass
:[
NSNumber
class
]])
{
if
([
lenObj
isKindOfClass
:[
NSNumber
class
]])
{
_lineDashLengths
[
dashIndex
]
=
[
lenObj
floatValue
];
}
else
{
}
else
{
_lineDashLengths
[
dashIndex
]
=
0
.
0
;
dashIndex
++
;
}
...
...
MapView/Map/RMPixel.c
View file @
6f64e50
...
...
@@ -31,6 +31,7 @@ CGPoint RMScaleCGPointAboutPoint(CGPoint point, float factor, CGPoint pivot)
{
point
.
x
=
(
point
.
x
-
pivot
.
x
)
*
factor
+
pivot
.
x
;
point
.
y
=
(
point
.
y
-
pivot
.
y
)
*
factor
+
pivot
.
y
;
return
point
;
}
...
...
@@ -39,6 +40,7 @@ CGRect RMScaleCGRectAboutPoint(CGRect rect, float factor, CGPoint pivot)
rect
.
origin
=
RMScaleCGPointAboutPoint
(
rect
.
origin
,
factor
,
pivot
);
rect
.
size
.
width
*=
factor
;
rect
.
size
.
height
*=
factor
;
return
rect
;
}
...
...
@@ -46,11 +48,13 @@ CGPoint RMTranslateCGPointBy(CGPoint point, CGSize delta)
{
point
.
x
+=
delta
.
width
;
point
.
y
+=
delta
.
height
;
return
point
;
}
CGRect
RMTranslateCGRectBy
(
CGRect
rect
,
CGSize
delta
)
{
rect
.
origin
=
RMTranslateCGPointBy
(
rect
.
origin
,
delta
);
return
rect
;
}
...
...
MapView/Map/RMProjection.m
View file @
6f64e50
...
...
@@ -58,6 +58,7 @@
{
RMProjectedRect
theBounds
;
theBounds
=
RMProjectedRectMake
(
0
,
0
,
0
,
0
);
return
[
self
initWithString
:
params
inBounds
:
theBounds
];
}
...
...
@@ -142,10 +143,12 @@ static RMProjection *_latlong = nil;
+
(
RMProjection
*
)
googleProjection
{
if
(
_google
)
{
if
(
_google
)
{
return
_google
;
}
else
{
else
{
RMProjectedRect
theBounds
=
RMProjectedRectMake
(
-
20037508
.
34
,
-
20037508
.
34
,
20037508
.
34
*
2
,
20037508
.
34
*
2
);
_google
=
[[
RMProjection
alloc
]
initWithString
:
@"+title= Google Mercator EPSG:900913 +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"
...
...
@@ -156,10 +159,12 @@ static RMProjection *_latlong = nil;
+
(
RMProjection
*
)
EPSGLatLong
{
if
(
_latlong
)
{
if
(
_latlong
)
{
return
_latlong
;
}
else
{
else
{
RMProjectedRect
theBounds
=
RMProjectedRectMake
(
-
kMaxLong
,
-
kMaxLat
,
360
,
kMaxLong
);
_latlong
=
[[
RMProjection
alloc
]
initWithString
:
@"+proj=latlong +ellps=WGS84"
...
...
MapView/Map/RMQuadTree.m
View file @
6f64e50
...
...
@@ -66,12 +66,14 @@
mapView
=
nil
;
[
cachedClusterAnnotation
release
];
cachedClusterAnnotation
=
nil
;
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
for
(
RMAnnotation
*
annotation
in
annotations
)
{
annotation
.
quadTreeNode
=
nil
;
}
}
[
annotations
release
];
annotations
=
nil
;
[
northWest
release
];
northWest
=
nil
;
...
...
@@ -87,7 +89,8 @@
{
NSArray
*
immutableAnnotations
=
nil
;
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
immutableAnnotations
=
[
NSArray
arrayWithArray
:
annotations
];
}
...
...
@@ -97,26 +100,42 @@
-
(
void
)
addAnnotationToChildNodes
:
(
RMAnnotation
*
)
annotation
{
RMProjectedRect
projectedRect
=
annotation
.
projectedBoundingBox
;
if
(
RMProjectedRectContainsProjectedRect
(
northWestBoundingBox
,
projectedRect
))
{
if
(
!
northWest
)
northWest
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
northWestBoundingBox
];
if
(
RMProjectedRectContainsProjectedRect
(
northWestBoundingBox
,
projectedRect
))
{
if
(
!
northWest
)
northWest
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
northWestBoundingBox
];
[
northWest
addAnnotation
:
annotation
];
}
else
if
(
RMProjectedRectContainsProjectedRect
(
northEastBoundingBox
,
projectedRect
))
{
if
(
!
northEast
)
northEast
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
northEastBoundingBox
];
}
else
if
(
RMProjectedRectContainsProjectedRect
(
northEastBoundingBox
,
projectedRect
))
{
if
(
!
northEast
)
northEast
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
northEastBoundingBox
];
[
northEast
addAnnotation
:
annotation
];
}
else
if
(
RMProjectedRectContainsProjectedRect
(
southWestBoundingBox
,
projectedRect
))
{
if
(
!
southWest
)
southWest
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
southWestBoundingBox
];
}
else
if
(
RMProjectedRectContainsProjectedRect
(
southWestBoundingBox
,
projectedRect
))
{
if
(
!
southWest
)
southWest
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
southWestBoundingBox
];
[
southWest
addAnnotation
:
annotation
];
}
else
if
(
RMProjectedRectContainsProjectedRect
(
southEastBoundingBox
,
projectedRect
))
{
if
(
!
southEast
)
southEast
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
southEastBoundingBox
];
}
else
if
(
RMProjectedRectContainsProjectedRect
(
southEastBoundingBox
,
projectedRect
))
{
if
(
!
southEast
)
southEast
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
self
inBoundingBox
:
southEastBoundingBox
];
[
southEast
addAnnotation
:
annotation
];
}
else
{
@synchronized
(
annotations
)
{
}
else
{
@synchronized
(
annotations
)
{
[
annotations
addObject
:
annotation
];
}
annotation
.
quadTreeNode
=
self
;
[
self
removeUpwardsAllCachedClusterAnnotations
];
}
...
...
@@ -126,12 +145,15 @@
{
if
(
nodeType
==
nodeTypeLeaf
)
{
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
[
annotations
addObject
:
annotation
];
}
annotation
.
quadTreeNode
=
self
;
if
([
annotations
count
]
<=
kMaxAnnotationsPerLeaf
||
boundingBox
.
size
.
width
<
(
kMinimumQuadTreeElementWidth
*
2
.
0
))
{
if
([
annotations
count
]
<=
kMaxAnnotationsPerLeaf
||
boundingBox
.
size
.
width
<
(
kMinimumQuadTreeElementWidth
*
2
.
0
))
{
[
self
removeUpwardsAllCachedClusterAnnotations
];
return
;
}
...
...
@@ -142,7 +164,9 @@
// might be a problem depending on kMaxAnnotationsPerLeaf
NSArray
*
immutableAnnotations
=
nil
;
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
immutableAnnotations
=
[
NSArray
arrayWithArray
:
annotations
];
[
annotations
removeAllObjects
];
}
...
...
@@ -160,10 +184,13 @@
-
(
void
)
removeAnnotation
:
(
RMAnnotation
*
)
annotation
{
if
(
!
annotation
.
quadTreeNode
)
return
;
if
(
!
annotation
.
quadTreeNode
)
return
;
annotation
.
quadTreeNode
=
nil
;
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
[
annotations
removeObject
:
annotation
];
}
...
...
@@ -180,9 +207,11 @@
[
self
removeAnnotation
:
annotation
];
RMQuadTreeNode
*
nextParentNode
=
self
;
while
((
nextParentNode
=
[
nextParentNode
parentNode
]))
{
if
(
RMProjectedRectContainsProjectedRect
(
nextParentNode
.
boundingBox
,
annotation
.
projectedBoundingBox
))
{
if
(
RMProjectedRectContainsProjectedRect
(
nextParentNode
.
boundingBox
,
annotation
.
projectedBoundingBox
))
{
[
nextParentNode
addAnnotationToChildNodes
:
annotation
];
break
;
}
...
...
@@ -217,7 +246,8 @@
{
NSMutableArray
*
unclusteredAnnotations
=
[
NSMutableArray
array
];
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
for
(
RMAnnotation
*
annotation
in
annotations
)
{
if
(
!
annotation
.
clusteringEnabled
)
...
...
@@ -245,33 +275,43 @@
{
NSArray
*
enclosedAnnotations
=
self
.
enclosedAnnotations
;
NSUInteger
enclosedAnnotationsCount
=
[
enclosedAnnotations
count
];
if
(
enclosedAnnotationsCount
<
2
)
{
if
(
enclosedAnnotationsCount
<
2
)
{
[
someArray
addObjectsFromArray
:
enclosedAnnotations
];
return
;
}
RMProjectedPoint
clusterMarkerPosition
;
if
(
findGravityCenter
)
{
double
averageX
=
0
.
0
,
averageY
=
0
.
0
;
for
(
RMAnnotation
*
annotation
in
enclosedAnnotations
)
{
averageX
+=
annotation
.
projectedLocation
.
x
;
averageY
+=
annotation
.
projectedLocation
.
y
;
}
averageX
/=
(
double
)
enclosedAnnotationsCount
;
averageY
/=
(
double
)
enclosedAnnotationsCount
;
double
halfClusterWidth
=
clusterSize
.
width
/
2
.
0
,
halfClusterHeight
=
clusterSize
.
height
/
2
.
0
;
if
(
averageX
-
halfClusterWidth
<
boundingBox
.
origin
.
x
)
averageX
=
boundingBox
.
origin
.
x
+
halfClusterWidth
;
if
(
averageX
+
halfClusterWidth
>
boundingBox
.
origin
.
x
+
boundingBox
.
size
.
width
)
averageX
=
boundingBox
.
origin
.
x
+
boundingBox
.
size
.
width
-
halfClusterWidth
;
if
(
averageY
-
halfClusterHeight
<
boundingBox
.
origin
.
y
)
averageY
=
boundingBox
.
origin
.
y
+
halfClusterHeight
;
if
(
averageY
+
halfClusterHeight
>
boundingBox
.
origin
.
y
+
boundingBox
.
size
.
height
)
averageY
=
boundingBox
.
origin
.
y
+
boundingBox
.
size
.
height
-
halfClusterHeight
;
if
(
averageX
-
halfClusterWidth
<
boundingBox
.
origin
.
x
)
averageX
=
boundingBox
.
origin
.
x
+
halfClusterWidth
;
if
(
averageX
+
halfClusterWidth
>
boundingBox
.
origin
.
x
+
boundingBox
.
size
.
width
)
averageX
=
boundingBox
.
origin
.
x
+
boundingBox
.
size
.
width
-
halfClusterWidth
;
if
(
averageY
-
halfClusterHeight
<
boundingBox
.
origin
.
y
)
averageY
=
boundingBox
.
origin
.
y
+
halfClusterHeight
;
if
(
averageY
+
halfClusterHeight
>
boundingBox
.
origin
.
y
+
boundingBox
.
size
.
height
)
averageY
=
boundingBox
.
origin
.
y
+
boundingBox
.
size
.
height
-
halfClusterHeight
;
// TODO: anchorPoint
clusterMarkerPosition
=
RMProjectedPointMake
(
averageX
,
averageY
);
}
else
}
else
{
clusterMarkerPosition
=
RMProjectedPointMake
(
boundingBox
.
origin
.
x
+
halfWidth
,
boundingBox
.
origin
.
y
+
(
boundingBox
.
size
.
height
/
2
.
0
));
}
...
...
@@ -283,22 +323,30 @@
[
someArray
addObject
:
cachedClusterAnnotation
];
[
someArray
addObjectsFromArray
:[
self
unclusteredAnnotations
]];
return
;
}
// TODO: leaf clustering (necessary?)
if
(
nodeType
==
nodeTypeLeaf
)
{
@synchronized
(
annotations
)
{
if
(
nodeType
==
nodeTypeLeaf
)
{
@synchronized
(
annotations
)
{
[
someArray
addObjectsFromArray
:
annotations
];
}
return
;
}
}
else
{
if
(
nodeType
==
nodeTypeLeaf
)
{
@synchronized
(
annotations
)
{
}
else
{
if
(
nodeType
==
nodeTypeLeaf
)
{
@synchronized
(
annotations
)
{
[
someArray
addObjectsFromArray
:
annotations
];
}
return
;
}
}
...
...
@@ -312,7 +360,8 @@
if
(
RMProjectedRectIntersectsProjectedRect
(
aBoundingBox
,
southEastBoundingBox
))
[
southEast
addAnnotationsInBoundingBox
:
aBoundingBox
toMutableArray
:
someArray
createClusterAnnotations
:
createClusterAnnotations
withClusterSize
:
clusterSize
findGravityCenter
:
findGravityCenter
];
@synchronized
(
annotations
)
{
@synchronized
(
annotations
)
{
for
(
RMAnnotation
*
annotation
in
annotations
)
{
if
(
RMProjectedRectIntersectsProjectedRect
(
aBoundingBox
,
annotation
.
projectedBoundingBox
))
...
...
@@ -323,7 +372,9 @@
-
(
void
)
removeUpwardsAllCachedClusterAnnotations
{
if
(
parentNode
)
[
parentNode
removeUpwardsAllCachedClusterAnnotations
];
if
(
parentNode
)
[
parentNode
removeUpwardsAllCachedClusterAnnotations
];
[
cachedClusterAnnotation
release
];
cachedClusterAnnotation
=
nil
;
}
...
...
@@ -354,21 +405,24 @@
-
(
void
)
addAnnotation
:
(
RMAnnotation
*
)
annotation
{
@synchronized
(
self
)
{
@synchronized
(
self
)
{
[
rootNode
addAnnotation
:
annotation
];
}
}
-
(
void
)
removeAnnotation
:
(
RMAnnotation
*
)
annotation
{
@synchronized
(
self
)
{
@synchronized
(
self
)
{
[
annotation
.
quadTreeNode
removeAnnotation
:
annotation
];
}
}
-
(
void
)
removeAllObjects
{
@synchronized
(
self
)
{
@synchronized
(
self
)
{
[
rootNode
release
];
rootNode
=
[[
RMQuadTreeNode
alloc
]
initWithMapView
:
mapView
forParent
:
nil
inBoundingBox
:[[
RMProjection
googleProjection
]
planetBounds
]];
}
...
...
@@ -385,7 +439,8 @@
{
NSMutableArray
*
annotations
=
[
NSMutableArray
array
];
@synchronized
(
self
)
{
@synchronized
(
self
)
{
[
rootNode
addAnnotationsInBoundingBox
:
boundingBox
toMutableArray
:
annotations
createClusterAnnotations
:
createClusterAnnotations
withClusterSize
:
clusterSize
findGravityCenter
:
findGravityCenter
];
}
...
...
MapView/Map/RMTile.c
View file @
6f64e50
...
...
@@ -39,6 +39,7 @@ uint64_t RMTileHash(RMTile tile)
accumulator
|=
((
uint64_t
)
tile
.
x
&
(
1LL
<<
i
))
<<
i
;
accumulator
|=
((
uint64_t
)
tile
.
y
&
(
1LL
<<
i
))
<<
(
i
+
1
);
}
accumulator
|=
1LL
<<
(
tile
.
zoom
*
2
);
return
accumulator
;
...
...
@@ -61,6 +62,7 @@ RMTile RMTileDummy()
t
.
x
=
-
1
;
t
.
y
=
-
1
;
t
.
zoom
=
-
1
;
return
t
;
}
...
...
@@ -80,6 +82,7 @@ RMTile RMTileMake(uint32_t x, uint32_t y, short zoom)
t
.
x
=
x
;
t
.
y
=
y
;
t
.
zoom
=
zoom
;
return
t
;
}
...
...
@@ -89,6 +92,7 @@ RMTileRect RMTileRectRound(RMTileRect rect)
rect
.
size
.
width
=
ceilf
(
rect
.
size
.
width
+
rect
.
origin
.
offset
.
x
);
rect
.
size
.
height
=
ceilf
(
rect
.
size
.
height
+
rect
.
origin
.
offset
.
y
);
rect
.
origin
.
offset
=
CGPointZero
;
return
rect
;
}
...
...
MapView/Map/RMTileCache.m
View file @
6f64e50
...
...
@@ -50,12 +50,11 @@
memoryCache
=
nil
;
id
cacheCfg
=
[[
RMConfiguration
configuration
]
cacheConfiguration
];
if
(
!
cacheCfg
)
{
if
(
!
cacheCfg
)
cacheCfg
=
[
NSArray
arrayWithObjects
:
[
NSDictionary
dictionaryWithObject
:
@"memory-cache"
forKey
:
@"type"
],
[
NSDictionary
dictionaryWithObject
:
@"db-cache"
forKey
:
@"type"
],
nil
];
}
for
(
id
cfg
in
cacheCfg
)
{
...
...
@@ -65,7 +64,8 @@
NSString
*
type
=
[
cfg
valueForKey
:
@"type"
];
if
([
@"memory-cache"
isEqualToString
:
type
])
{
if
([
@"memory-cache"
isEqualToString
:
type
])
{
memoryCache
=
[[
self
memoryCacheWithConfig
:
cfg
]
retain
];
continue
;
}
...
...
@@ -73,11 +73,10 @@
if
([
@"db-cache"
isEqualToString
:
type
])
newCache
=
[
self
databaseCacheWithConfig
:
cfg
];
if
(
newCache
)
{
if
(
newCache
)
[
caches
addObject
:
newCache
];
}
else
{
else
RMLog
(
@"failed to create cache of type %@"
,
type
);
}
}
@catch
(
NSException
*
e
)
{
...
...
@@ -97,7 +96,8 @@
-
(
void
)
addCache
:
(
id
<
RMTileCache
>
)
cache
{
@synchronized
(
caches
)
{
@synchronized
(
caches
)
{
[
caches
addObject
:
cache
];
}
}
...
...
@@ -111,13 +111,18 @@
-
(
UIImage
*
)
cachedImage
:
(
RMTile
)
tile
withCacheKey
:
(
NSString
*
)
aCacheKey
{
UIImage
*
image
=
[
memoryCache
cachedImage
:
tile
withCacheKey
:
aCacheKey
];
if
(
image
)
return
image
;
@synchronized
(
caches
)
{
if
(
image
)
return
image
;
@synchronized
(
caches
)
{
for
(
id
<
RMTileCache
>
cache
in
caches
)
{
image
=
[
cache
cachedImage
:
tile
withCacheKey
:
aCacheKey
];
if
(
image
!=
nil
)
{
if
(
image
!=
nil
)
{
[
memoryCache
addImage
:
image
forTile
:
tile
withCacheKey
:
aCacheKey
];
return
image
;
}
...
...
@@ -131,12 +136,12 @@
{
[
memoryCache
addImage
:
image
forTile
:
tile
withCacheKey
:
aCacheKey
];
@synchronized
(
caches
)
{
@synchronized
(
caches
)
{
for
(
id
<
RMTileCache
>
cache
in
caches
)
{
if
([
cache
respondsToSelector
:
@selector
(
addImage
:
forTile
:
withCacheKey
:)])
{
if
([
cache
respondsToSelector
:
@selector
(
addImage
:
forTile
:
withCacheKey
:)])
[
cache
addImage
:
image
forTile
:
tile
withCacheKey
:
aCacheKey
];
}
}
}
}
...
...
@@ -146,7 +151,8 @@
LogMethod
();
[
memoryCache
didReceiveMemoryWarning
];
@synchronized
(
caches
)
{
@synchronized
(
caches
)
{
for
(
id
<
RMTileCache
>
cache
in
caches
)
{
[
cache
didReceiveMemoryWarning
];
...
...
@@ -158,7 +164,8 @@
{
[
memoryCache
removeAllCachedImages
];
@synchronized
(
caches
)
{
@synchronized
(
caches
)
{
for
(
id
<
RMTileCache
>
cache
in
caches
)
{
[
cache
removeAllCachedImages
];
...
...
MapView/Map/RouteMe.h
View file @
6f64e50
//
// RouteMe.h
//
// Copyright (c) 2008-201
1
, Route-Me Contributors
// Copyright (c) 2008-201
2
, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
...
...
MapView/MapView.xcodeproj/project.pbxproj
View file @
6f64e50
...
...
@@ -1047,6 +1047,7 @@
GCC_STRICT_ALIASING = YES;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
...
...
@@ -1080,6 +1081,7 @@
GCC_STRICT_ALIASING = YES;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
...
...
Please
register
or
login
to post a comment