Created
April 6, 2018 08:33
-
-
Save abin0992/343f90833434bf8ece6e3c16bfd46bc2 to your computer and use it in GitHub Desktop.
Map playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: A MapKit based Playground | |
import MapKit | |
import PlaygroundSupport | |
var points: [Any] = [] | |
class MapDelegate: NSObject, MKMapViewDelegate { | |
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { | |
guard let myAnnotation = annotation as? MKPointAnnotation else { | |
fatalError("Not a MyAnnotation") | |
} | |
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myannotation") ?? MKPinAnnotationView(annotation: myAnnotation, reuseIdentifier: "myannotation") | |
annotationView.canShowCallout = true | |
return annotationView | |
} | |
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { | |
let calloutView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) | |
calloutView.backgroundColor = .red | |
calloutView.addConstraint(NSLayoutConstraint(item: calloutView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: calloutView.frame.width)) | |
calloutView.addConstraint(NSLayoutConstraint(item: calloutView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: calloutView.frame.height)) | |
view.detailCalloutAccessoryView = calloutView | |
} | |
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { | |
guard let polyline = overlay as? MKPolyline else { | |
fatalError("Not a MKPolyline") | |
} | |
let renderer = MKPolylineRenderer(polyline: polyline) | |
renderer.strokeColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1) | |
renderer.lineWidth = 8 | |
// renderer.lineDashPattern = [0, 10] | |
return renderer | |
} | |
func mapView(_ mapView: MKMapView, didAdd renderers: [MKOverlayRenderer]) { | |
// Animate a 'fade' | |
for overlayRenderer: MKOverlayRenderer? in renderers { | |
// MKPolylineRenderer | |
// Animate a 'fade' | |
if (overlayRenderer is MKPolylineRenderer) { | |
// Get MKPolylineRenderer | |
let polylineRenderer = overlayRenderer as? MKPolylineRenderer | |
// Let's manually set alpha to 0 | |
polylineRenderer?.alpha = 0.0 | |
// Animate it back to 1 | |
DispatchQueue.main.async(execute: {() -> Void in | |
UIView.animate(withDuration: 0.4, animations: {() -> Void in | |
polylineRenderer?.alpha = 1.0 | |
}) | |
}) | |
} | |
} | |
} | |
} | |
class MyRenderer: MKOverlayRenderer { | |
} | |
class MyAnnotation: NSObject, MKAnnotation { | |
var title: String? | |
var subtitle: String? | |
var coordinate: CLLocationCoordinate2D | |
init(title: String, coordinate: CLLocationCoordinate2D) { | |
self.title = title | |
self.coordinate = coordinate | |
} | |
} | |
func getPointsOnRoute(from: CLLocation?, to: CLLocation?, on mapView: MKMapView?) -> [Any]? { | |
let NUMBER_OF_PIXELS_TO_SKIP: Int = 20 | |
//lower number will give a more smooth animation, but will result in more layers | |
var ret = [Any]() | |
var fromPoint: CGPoint? = nil | |
if let aCoordinate = from?.coordinate { | |
fromPoint = mapView?.convert(aCoordinate, toPointTo: mapView) | |
} | |
var toPoint: CGPoint? = nil | |
if let aCoordinate = to?.coordinate { | |
toPoint = mapView?.convert(aCoordinate, toPointTo: mapView) | |
} | |
let allPixels = getAllPoints(from: fromPoint!, to: toPoint!) | |
var i = 0 | |
while i < (allPixels?.count)! { | |
let pointVal = allPixels![i] as? NSValue | |
ret.append(point(toLocation: mapView, from: (pointVal?.cgPointValue)!)!) | |
i += NUMBER_OF_PIXELS_TO_SKIP | |
} | |
ret.append(point(toLocation: mapView, from: toPoint!)!) | |
return ret | |
} | |
/**convert a CGPoint to a CLLocation according to a mapView*/ | |
func point(toLocation mapView: MKMapView?, from fromPoint: CGPoint) -> CLLocation? { | |
let coord: CLLocationCoordinate2D? = mapView?.convert(fromPoint, toCoordinateFrom: mapView) | |
return CLLocation(latitude: coord?.latitude ?? 0, longitude: coord?.longitude ?? 0) | |
} | |
func getAllPoints(from fPoint: CGPoint, to tPoint: CGPoint) -> [Any]? { | |
/*Simplyfied implementation of Bresenham's line algoritme */ | |
var ret = [AnyHashable]() | |
let deltaX: Float = fabsf(Float(tPoint.x - fPoint.x)) | |
let deltaY: Float = fabsf(Float(tPoint.y - fPoint.y)) | |
var x: Float = Float(fPoint.x) | |
var y: Float = Float(fPoint.y) | |
var err: Float = deltaX - deltaY | |
var sx: Float = -0.5 | |
var sy: Float = -0.5 | |
if fPoint.x < tPoint.x { | |
sx = 0.5 | |
} | |
if fPoint.y < tPoint.y { | |
sy = 0.5 | |
} | |
repeat { | |
ret.append(NSValue(cgPoint: CGPoint(x: CGFloat(x), y: CGFloat(y)))) | |
let e: Float = 2 * err | |
if e > -deltaY { | |
err -= deltaY | |
x += sx | |
} | |
if e < deltaX { | |
err += deltaX | |
y += sy | |
} | |
} while round(Float(x)) != round(Float(tPoint.x)) && round(Float(y)) != round(Float(tPoint.y)) | |
ret.append(NSValue(cgPoint: tPoint)) | |
//add final point | |
return ret | |
} | |
func addOverlaysFromPointsWithStart(from end: NSNumber?) { | |
// let intEnd = Int(truncating: end ?? 0) | |
// //construct polyline view from start | |
// let locations: CLLocationCoordinate2D? = malloc(MemoryLayout<CLLocationCoordinate2D>.size * 2) | |
// let loc1 = points[0] as? CLLocation | |
// let loc2 = points[intEnd] as? CLLocation | |
// if let aCoordinate = loc1?.coordinate { | |
// locations![0] = aCoordinate | |
// } | |
// if let aCoordinate = loc2?.coordinate { | |
// locations![1] = aCoordinate | |
// } | |
// let line = MKPolyline(coordinates: locations, count: 2) | |
// mapView?.add(line) | |
// if (intEnd + 1) < points.count { | |
// perform(Selector("addOverlaysFromPointsWithStartFrom:"), with: intEnd + 1, afterDelay: 0.01) | |
// } | |
} | |
let mapDelegate = MapDelegate() | |
let frame = CGRect(x: 0, y: 0, width: 400, height: 600) | |
let mapView = MKMapView(frame: frame) | |
mapView.centerCoordinate = CLLocationCoordinate2DMake(51.107, 17.0385) | |
let span = MKCoordinateSpanMake(18.075, 18.075) | |
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.107, longitude: 17.0385), span: span) | |
mapView.setRegion(region, animated: true) | |
mapView.delegate = mapDelegate | |
//let myAnnotation = MyAnnotation(title: "Foo", coordinate: CLLocationCoordinate2DMake(35, -100)) | |
//mapView.addAnnotation(myAnnotation) | |
let pointAnnotation = MKPointAnnotation() | |
pointAnnotation.coordinate = CLLocationCoordinate2DMake(51.107, 17.0385) | |
pointAnnotation.title = "Point Annotation" | |
mapView.addAnnotation(pointAnnotation) | |
var coordinates = [ | |
CLLocationCoordinate2DMake(50.41880, 20.49000), | |
CLLocationCoordinate2DMake(55.76105, 10.14051) | |
] | |
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count) | |
print(polyline.pointCount) | |
mapView.addOverlays([polyline]) | |
var from = coordinates.first | |
var fLat: CLLocationDegrees = from!.latitude | |
var fLon: CLLocationDegrees = from!.longitude | |
var froml: CLLocation = CLLocation(latitude: fLat, longitude: fLon) | |
var to = coordinates.last | |
var tLat: CLLocationDegrees = to!.latitude | |
var tLon: CLLocationDegrees = to!.longitude | |
var tol: CLLocation = CLLocation(latitude: tLat, longitude: tLon) | |
points = getPointsOnRoute(from: froml, to: tol, on: mapView)! | |
print("Coordinates on route are \(points)") | |
PlaygroundPage.current.liveView = mapView |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment