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

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

我使用google directions API获取总览折线并将其绘制在 map 上。现在,我从自己的服务器上获得了驱动程序位置,并且为了更新 map 上的用户位置,我遍历了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米之间。因此,一旦获得驱动程序位置,便会遍历路径中的整个坐标以找到 map 中最接近的点并将驱动程序捕捉到该位置
           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调用次数

我尝试了什么?

我尝试使用线性插值解决

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

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

所以最后您到底在问什么?
  • 将Google路径的两个坐标之间的点插值以实现要实现的目标是否正确?
  • 如果可以,我应该使用哪种更好的插值算法?显然线性没有多大意义:(

  • 请帮助,在此先感谢

    最佳答案

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

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

    关于ios - 在Google路径中的坐标之间插入点的最佳方法是什么?这种方法正确吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55011159/

    10-10 21:01
    查看更多