我正试图在Googlemap上绘制Polyline,以便像Uber一样向用户显示驾驶员/送货员的位置。
我使用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路径坐标中的后续点最长可达200m。我用
进行了测试 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调用次数
我尝试了什么?
我尝试使用
进行线性插值求解不必说结果是灾难性的,因为方程式假定笛卡尔平面且地球不平坦:|
所以最后您在问什么?
将Google路径的两个坐标之间的点插值以实现要达到的目标是否正确?
如果是,我应该使用哪种更好的插值算法?显然线性没有多大意义:(
请帮助,在此先感谢
答案 0 :(得分:1)
Google本身提供了多种在GMSGeometryUtils模块内进行插值的方法。我认为您需要进行插值的可能是: https://developers.google.com/maps/documentation/ios-sdk/reference/group___geometry_utils.html#gad0c5870bd9d182d22310f84a77888124
GMSGeometryInterpolate使用您在给定比例下提供的“从”和“到”坐标之间的最短路径,而GMSPath确实连接了您提供的每个子序列坐标之间的最短路径,因此该路径就足够了。