2

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 locations. I've got that working on mkmapview using the built in directions and geocoding api calls for Apple. However after using it for a while a realized that a lot of countries are not supported by Apple Apple - Supported Countries For Directions

So is there a way to get routes from the google maps SDK and translate them to a MKPolyline or MKOverlay? I haven't worked with google maps so keep that in mind. I saw this question iPhone: Using Google to get directions it has an answer, but the newest solution is 4 years old and its in objective-C. Although I do understand how to convert objective-C code to swift, I'd rather not have to go through a whole project. Keep in mind that this a part of a bigger project, so I can't switch the whole thing over to google maps.

Community
  • 1
  • 1
DatForis
  • 1,331
  • 12
  • 19
  • Google provide the api for get routes between certain location by the used of that api you can draw a path on MKMapView – Chirag Shah Jul 10 '15 at 05:24
  • Can the google SDK be used to directly draw Routes on a MKMapView? – DatForis Jul 10 '15 at 05:48
  • No in google api responce you find the polyline object which is combination of latitude and longitude. You have to decrypt it in latitude and longitude and from that you can draw a path on any map – Chirag Shah Jul 10 '15 at 06:00
  • Is there a ready made solution for that? And are google going to be ok with that? – DatForis Jul 10 '15 at 06:32
  • 1
    I think google to be ok with this – Chirag Shah Jul 10 '15 at 07:01
  • http://stackoverflow.com/questions/9217274/how-to-decode-the-google-directions-api-polylines-field-into-lat-long-points-in this is used to decode google polylines to MKPolyline, check out the accepted answer – DatForis Jul 10 '15 at 07:38
  • yes this is also right method for you but if you used google map then other method is also usefull – Chirag Shah Jul 10 '15 at 07:58
  • Use this http://stackoverflow.com/questions/28784034/swift-ios-google-map-path-to-coordinate/34435391#34435391 – LC 웃 Dec 23 '15 at 12:09

3 Answers3

3

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.

enter image description here

Community
  • 1
  • 1
ztan
  • 6,861
  • 2
  • 24
  • 44
  • Yes I'm using it and I can confirm that its working. – DatForis Jul 11 '15 at 09:34
  • Use this http://stackoverflow.com/questions/28784034/swift-ios-google-map-path-to-coordinate/34435391#34435391 – LC 웃 Dec 23 '15 at 12:09
  • This algorithm has some issues. For some routes, I get some irrelevant lines on the map. I created a category for the ObjC method and bridged it to the swift project, works perfectly! – iOS Apr 11 '16 at 08:26
2

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
}
djdance
  • 3,110
  • 27
  • 33
0

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:

  • mode (defaults to driving) driving give you more options, or set
    walking, bicycling, transit.
  • alternatives : false give u just one route, option true give all directions between origin and destinations, then you can choose which route u want deponent on duration, or distance inside legs.

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)

hadeel
  • 1