import Foundation
import MapKit
class GradientPolylineOverlay: NSObject, MKOverlay {
var points: [MKMapPoint] = []
var _pointCount: Int = 0
var pointCount: Int {
return _pointCount
}
var pointSpace: Int = 0
var _boundingMapRect: MKMapRect
var velocity: [CGFloat] = []
var rwLock: pthread_rwlock_t = pthread_rwlock_t()
let initialPointSpace: Int = 1000
let minimumDeltaMeters: Double = 10
init(coord: CLLocationCoordinate2D) {
pointSpace = initialPointSpace
points.append(MKMapPointForCoordinate(coord))
_pointCount = 1
var origin: MKMapPoint = points[0]
origin.x -= MKMapSizeWorld.width / 8.0
origin.y -= MKMapSizeWorld.height / 8.0
var size: MKMapSize = MKMapSizeWorld
size.width /= 4.0
size.height /= 4.0
_boundingMapRect = MKMapRect(origin: origin, size: size)
let worldRect: MKMapRect = MKMapRectMake(0, 0, MKMapSizeWorld.width, MKMapSizeWorld.height)
_boundingMapRect = MKMapRectIntersection(_boundingMapRect, worldRect)
super.init()
pthread_rwlock_init(&rwLock, nil)
}
init(_points: [CLLocationCoordinate2D], _velocity: [CGFloat], _count: Int) {
_pointCount = _count
for point in _points {
self.points.append(MKMapPointForCoordinate(point))
}
for velocity in _velocity {
self.velocity.append(velocity)
}
//bite off up to 1/4 of the world to draw into
var origin: MKMapPoint = points[0]
origin.x -= MKMapSizeWorld.width / 8.0
origin.y -= MKMapSizeWorld.height / 8.0
var size: MKMapSize = MKMapSizeWorld
size.width /= 4.0
size.height /= 4.0
_boundingMapRect = MKMapRect(origin: origin, size: size)
let worldRect = MKMapRectMake(0, 0, MKMapSizeWorld.width, MKMapSizeWorld.height)
_boundingMapRect = MKMapRectIntersection(_boundingMapRect, worldRect)
super.init()
pthread_rwlock_init(&rwLock, nil)
}
deinit {
points.removeAll()
velocity.removeAll()
pthread_rwlock_destroy(&rwLock)
}
func getBoundingMapRect() -> MKMapRect{
return _boundingMapRect
}
func addCoordinate(coord: CLLocationCoordinate2D) -> MKMapRect {
pthread_rwlock_wrlock(&rwLock)
//Convert a CLLocationCoordinate2D to an MKMapPoint
let newPoint: MKMapPoint = MKMapPointForCoordinate(coord)
let prevPoint: MKMapPoint = points[_pointCount-1]
//Get the distance between this new point and previous point
let metersApart: CLLocationDistance = MKMetersBetweenMapPoints(newPoint, prevPoint)
var updateRect: MKMapRect = MKMapRectNull
if (metersApart > minimumDeltaMeters){
//Grow the points array if necessary
if (pointSpace == _pointCount){
pointSpace *= 2
}
//Add the new point to points array
points[_pointCount] = newPoint
_pointCount += 1
//Compute MKMapRect bounding prevPoint and newPoint
let minX: Double = (newPoint.x > prevPoint.x) ? prevPoint.x : newPoint.x
let minY: Double = (newPoint.y > prevPoint.y) ? prevPoint.y : newPoint.y
let maxX: Double = (newPoint.x > prevPoint.x) ? newPoint.x : prevPoint.x
let maxY: Double = (newPoint.y > prevPoint.y) ? newPoint.y : prevPoint.y
updateRect = MKMapRectMake(minX, minY, maxX - minX, maxY - minY)
}
pthread_rwlock_unlock(&rwLock)
return updateRect
}
var boundingMapRect: MKMapRect {
return _boundingMapRect
}
var coordinate: CLLocationCoordinate2D {
return MKCoordinateForMapPoint(points[0])
}
func lockForReading() {
pthread_rwlock_rdlock(&rwLock)
}
func unlockForReading() {
pthread_rwlock_unlock(&rwLock)
}
}