I\'m using swift on iOS and using MKMapView. I\'ve been working on giving a user a from - to textfield and letting the user have a form of route between the from and to loca
Swift 3 version, slightly condensed, thanks to ztan.
If you want to use Googles geo polylines in iOS without Google SDK.
func polyLineWithEncodedString(encodedString: String) -> [CLLocationCoordinate2D] {
var myRoutePoints=[CLLocationCoordinate2D]()
let bytes = (encodedString as NSString).utf8String
var idx: Int = 0
var latitude: Double = 0
var longitude: Double = 0
while (idx < encodedString.lengthOfBytes(using: String.Encoding.utf8)) {
var byte = 0
var res = 0
var shift = 0
repeat {
byte = bytes![idx] - 63
idx += 1
res |= (byte & 0x1F) << shift
shift += 5
} while (byte >= 0x20)
let deltaLat = ((res & 1) != 0x0 ? ~(res >> 1) : (res >> 1))
latitude += Double(deltaLat)
shift = 0
res = 0
repeat {
byte = bytes![idx] - 63
idx += 1
res |= (byte & 0x1F) << shift
shift += 5
} while (byte >= 0x20)
let deltaLon = ((res & 1) != 0x0 ? ~(res >> 1) : (res >> 1))
longitude += Double(deltaLon)
myRoutePoints.append(CLLocation(latitude: Double(latitude * 1E-5), longitude: Double(longitude * 1E-5)).coordinate)
}
return myRoutePoints
}
I think this Stackoverflow answer can convert the encoded polyline to MKPolyline.
The answer is an Objective-C version, so I tried to convert it to Swift, sample code:
func polyLineWithEncodedString(encodedString: String) -> MKPolyline {
let bytes = (encodedString as NSString).UTF8String
let length = encodedString.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
var idx: Int = 0
var count = length / 4
var coords = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(count)
var coordIdx: Int = 0
var latitude: Double = 0
var longitude: Double = 0
while (idx < length) {
var byte = 0
var res = 0
var shift = 0
do {
byte = bytes[idx++] - 0x3F
res |= (byte & 0x1F) << shift
shift += 5
} while (byte >= 0x20)
let deltaLat = ((res & 1) != 0x0 ? ~(res >> 1) : (res >> 1))
latitude += Double(deltaLat)
shift = 0
res = 0
do {
byte = bytes[idx++] - 0x3F
res |= (byte & 0x1F) << shift
shift += 5
} while (byte >= 0x20)
let deltaLon = ((res & 1) != 0x0 ? ~(res >> 1) : (res >> 1))
longitude += Double(deltaLon)
let finalLat: Double = latitude * 1E-5
let finalLon: Double = longitude * 1E-5
let coord = CLLocationCoordinate2DMake(finalLat, finalLon)
coords[coordIdx++] = coord
if coordIdx == count {
let newCount = count + 10
let temp = coords
coords.dealloc(count)
coords = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(newCount)
for index in 0..<count {
coords[index] = temp[index]
}
temp.destroy()
count = newCount
}
}
let polyLine = MKPolyline(coordinates: coords, count: coordIdx)
coords.destroy()
return polyLine
}
You can try the sample project from this GitHub link.
Below is the image of using Google Direction API web service to render a route on MKMapView from San Francisco to San Jose.
Using google api to find directions between origin and destination.
Required parameters:
origin : lat + long current location or place ID .
destination : lat + long destination location or place ID .
Key: to create new google api key .
Optional parameters:
then convert points (inside overview_polyline) to list of CLLocationCoordinate2D using Polyline library https://github.com/raphaelmor/Polyline
Like this:
func convertPointToCoordinates() -> [CLLocationCoordinate2D]? {
let polyline = Polyline(encodedPolyline: overviewPolyline.points ?? "")
return polyline.coordinates
}
let coordinates = convertPointToCoordinates()
let polyLine = MKPolyline(coordinates: coordinates ?? [], count: (coordinates?.count ?? 0))
to add polyline on map view:
self.mapView.add(polyLine)
to focus on polyline region:
self.mapView.setVisibleMapRect(polyLine.boundingMapRect, edgePadding: UIEdgeInsets.init(top: 60, left: 60, bottom: 60, right: 60), animated: true)