有没有办法使用谷歌为 mkmapview 获取路线(只是路线)?

Posted

技术标签:

【中文标题】有没有办法使用谷歌为 mkmapview 获取路线(只是路线)?【英文标题】:Is there a way to get directions(just routes) using google for mkmapview? 【发布时间】:2015-09-28 16:50:21 【问题描述】:

我在 ios 上使用 swift 并使用 MKMapView。 我一直在努力为用户提供从 - 到文本字段,并让用户在起点和终点之间有一种路线形式。我已经使用 Apple 的内置方向和地理编码 api 调用在 mkmapview 上工作。但是用了一段时间后发现很多国家都不支持苹果Apple - Supported Countries For Directions

那么有没有办法从谷歌地图 SDK 获取路线并将它们转换为 MKPolyline 或 MKOverlay?我没有使用谷歌地图,所以请记住这一点。我看到了这个问题iPhone: Using Google to get directions 它有一个答案,但最新的解决方案已经有 4 年历史了,而且它在 Objective-C 中。尽管我确实了解如何将 Objective-C 代码转换为 swift,但我宁愿不必经历整个项目。请记住,这是一个更大项目的一部分,所以我无法将整个项目切换到谷歌地图。

【问题讨论】:

Google 提供了获取特定位置之间路线的 API,您可以使用该 API 在 MKMapView 上绘制路径 可以用google SDK直接在MKMapView上绘制Routes吗? 在谷歌 api 响应中没有,您会找到由纬度和经度组合而成的折线对象。您必须在纬度和经度中解密它,然后您可以在任何地图上绘制路径 有现成的解决方案吗?谷歌会接受吗? 我认为 google 可以接受这个 【参考方案1】:

我认为this *** answer 可以将编码的折线转换为MKPolyline。

答案是Objective-C版本,所以我尝试将其转换为Swift,示例代码:

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
    

您可以尝试来自this GitHub link 的示例项目。

下图是使用 Google Direction API Web 服务在 MKMapView 上渲染从旧金山到圣何塞的路线。

【讨论】:

是的,我正在使用它,我可以确认它可以正常工作。 使用这个***.com/questions/28784034/… 这个算法有一些问题。对于某些路线,我在地图上得到了一些不相关的线。我为 ObjC 方法创建了一个类别并将其桥接到 swift 项目,完美运行!【参考方案2】:

Swift 3 版本,略微精简,感谢ztan

如果您想在没有 Google SDK 的情况下在 iOS 中使用 Google 地理折线。

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

【讨论】:

【参考方案3】:

使用google api 查找起点和终点之间的路线。

必填参数:

origin : lat + long 当前位置或地点 ID .

destination : lat + long 目标位置或地点 ID .

密钥:创建新的 google api 密钥。

可选参数:

模式(默认为驾驶)驾驶为您提供更多选择,或设置 步行、骑自行车、公交。 alternatives : false 只给你一条路线,选项 true 给出起点和目的地之间的所有方向,然后你可以选择哪个 路线您希望在持续时间或腿内距离上有所帮助。

然后使用 Polyline 库将点(在 overview_polyline 内)转换为 CLLocationCoordinate2D 列表 https://github.com/raphaelmor/Polyline

像这样:

func convertPointToCoordinates() -> [CLLocationCoordinate2D]?

让 polyline = Polyline(encodedPolyline: overviewPolyline.points ?? "")

返回折线.坐标

让坐标 = convertPointToCoordinates()

让 polyLine = MKPolyline(coordinates: 坐标?? [], count: (coordinates?.count ?? 0))

在地图视图上添加折线:

self.mapView.add(polyLine)

专注于折线区域:

self.mapView.setVisibleMapRect(polyLine.boundingMapRect, edgePadding: UIEdgeInsets.init(top: 60, left: 60, bottom: 60, right: 60), 动画: true)

【讨论】:

以上是关于有没有办法使用谷歌为 mkmapview 获取路线(只是路线)?的主要内容,如果未能解决你的问题,请参考以下文章

谷歌为Chromebook推出双系统启动软件:可装Windows

如何获取地图上两点之间的路线方向以绘制行车路线?

使用 UIView 作为 MKMapView 子视图来绘制路线

如何在 SwiftUI 中获取 MKMapView 方向

确定行进路径 mkmapview swift 上的距离

iOS6中的iOS行车路线