在Google路径中的坐标之间插入点的最佳方法是什么?这种方法正确吗?

时间:2019-03-05 20:35:56

标签: ios swift google-maps interpolation

我正试图在Googlemap上绘制Polyline,以便像Uber一样向用户显示驾驶员/送货员的位置。

enter image description here

我使用Google directions API获取概览折线并将其绘制在地图上。现在,我从自己的服务器上获取了驾驶员位置,并且为了更新地图上的用户位置,我遍历了GMSPath中的坐标,该坐标是通过将全景Polyline解码为

            if let jsonArray = jsonResult["routes"].array, jsonArray.count > 0 {
                for json in jsonArray {
                    if let polyline = json["overview_polyline"]["points"].string {
                        self.possibleOverViewPolylines.append(polyline)
                    }
                }
            }
            self.currentPolyline =  self.possibleOverViewPolylines[0]
            self.path = GMSMutablePath.init(fromEncodedPath: self.currentPolyline)
            self.polyline = GMSPolyline(path: self.path)

Google在发送alternative=true时通常会返回多条路线,因此我会缓存所有overview_polyline并将第一个用作当前的在线。

现在,通过阅读和尝试错误,我发现捕获的驱动程序的经纬度可能存在错误,范围可能在5至50米之间。因此,一旦获得驱动程序位置,便会遍历路径中的整个坐标,以找到地图中最接近的点并将驱动程序捕捉到该位置

           var overallDistance: CLLocationDistance = 50
           for index in 0 ..< strongSelf.path.count() {
                let coordinate = strongSelf.path.coordinate(at: UInt(index))
                let distance = location.distance(to: coordinate)
                if distance < overallDistance {
                    foundIndex = Int(index)
                    overallDistance = distance
                }
            }
            if overallDistance >= 50 {
                debugPrint("\(location)")
                evaluateAlternativeRoutes()
            }
            else {
                updatepolyline(location: strongSelf.path.coordinate(at: UInt(foundIndex)))
            }

将折线更新为

            self?.polyline.map = nil
            while strongSelf.path.coordinate(at: UInt(0)).latitude != location.latitude &&  strongSelf.path.coordinate(at: UInt(0)).longitude != location.longitude {
                self?.path.removeCoordinate(at: 0)
            }
            if strongSelf.path.coordinate(at: 0).latitude == location.latitude && strongSelf.path.coordinate(at: UInt(0)).longitude == location.longitude {
                self?.path.removeCoordinate(at: 0)
            }
            self?.polyline = GMSPolyline(path: strongSelf.path)

最终替代路线的评价为

        var overallDistance: CLLocationDistance = 50
        var foundIndex = -1

        for (polylineIndex,polyline) in strongSelf.possibleOverViewPolylines.enumerated() {
            if let path = GMSMutablePath.init(fromEncodedPath: polyline) {
                for index in 0 ..< path.count() {
                    let coordinate = path.coordinate(at: UInt(index))
                    let distance = location.distance(to: coordinate)
                    if distance < overallDistance {
                        foundIndex = polylineIndex
                        overallDistance = distance
                    }
                }
            }
        }
        if foundIndex != -1 {
             self?.path = GMSMutablePath.init(fromEncodedPath: strongSelf.possibleOverViewPolylines[foundIndex])
        }
        else {
             //make routes API call again
        }

如果没有可用的替代路由与驱动程序位置相匹配,则驱动程序可能采用了完全不同的路由,因此我再次使用驱动程序位置进行路由API调用

为什么会有那么多优化?

Google的Routes API成本高昂,而不必要地调用google route API会增加财务负担并破坏整个用户体验,因此希望在本地进行大部分计算

但是上面的代码无法达到最佳效果:(它可以工作,但效果不佳:|

是否采用这种方法

问题1: 方法假设驾驶员位置的可能错误率最大为50m,并且当我评估到该路径上所有点的距离时都对照此50进行检查,但不幸的是,在一条漫长的直路上,google路径中的坐标没有平均分布,距离为2路径坐标中的后续点最长可达200​​m。我用

进行了测试
           for i in 0 ..< self.path.count() {
                if i == 0 {
                    debugPrint(self.path.coordinate(at: i))
                }
                else {
                    debugPrint("distance between \(self.path.coordinate(at: (i - 1))) and \(self.path.coordinate(at: (i))) is \(self.path.coordinate(at: (i - 1)).distance(to: self.path.coordinate(at: (i))))")
                }
            }

因此,将车顶位置与距离50m的路径中所有点进行比较的逻辑失败了。

我能想到的解决方案

如果我可以以规则的间隔50m插值google路径中任意两个坐标之间的点,并将上限提高到100m(路径中两个点之间的距离为50m,则经纬度误差为50m),这应该给出我有更多机会减少API调用次数

我尝试了什么?

我尝试使用

进行线性插值求解

enter image description here

不必说结果是灾难性的,因为方程式假定笛卡尔平面且地球不平坦:|

所以最后您在问什么?

  1. 将Google路径的两个坐标之间的点插值以实现要达到的目标是否正确?

  2. 如果是,我应该使用哪种更好的插值算法?显然线性没有多大意义:(

请帮助,在此先感谢

1 个答案:

答案 0 :(得分:1)

Google本身提供了多种在GMSGeometryUtils模块内进行插值的方法。我认为您需要进行插值的可能是: https://developers.google.com/maps/documentation/ios-sdk/reference/group___geometry_utils.html#gad0c5870bd9d182d22310f84a77888124

GMSGeometryInterpolate使用您在给定比例下提供的“从”和“到”坐标之间的最短路径,而GMSPath确实连接了您提供的每个子序列坐标之间的最短路径,因此该路径就足够了。