Каков наилучший способ интерполировать точки между координатами в пути Google? Правильный ли этот подход? - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь нанести Полилинию на Googlemap, чтобы показать положение водителя / курьера для пользователя, как в Uber.

enter image description here

Я использую Google направления API получить обзор полилинии и нарисовать ее на карте.Теперь я получаю местоположение драйвера с нашего собственного сервера и, чтобы обновить местоположение пользователя на карте, я перебираю координаты в GMSPath, которые я получил, расшифровав полилинию с видом как

            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, поэтому я кеширую всю review_polyline и использую первый в качестве текущей надстрочной линии.

Теперь из чтения и пробной ошибки я выяснил, что может быть ошибка в lat-long перехваченного драйвера, и она может варьироваться от 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)))
            }

, обновляя Polyline как

            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-маршрутов с местоположением водителя

Почему так много оптимизации?

API-интерфейсы Google-маршрутов являются дорогостоящими, а вызов API-интерфейсов Google-маршрутов излишне увеличит финансовую нагрузку, а также испортит весь пользовательский опыт и, следовательно, позволит выполнять большинство расчетов локально.

Но приведенный выше код работает неоптимально :( Он работает, но не очень хорошо: |

Проблемы с этим подходом

Проблема 1: Метод предполагает, что возможная частота ошибок в местоположении водителей не должна превышать 50 м, и когда я оцениваю все расстояния до точек пути,Получите эти 50, но, к сожалению, координаты в путях Google распределены неравномерно, на длинной прямой дороге расстояние между двумя последующими точками в координатах пути может достигать 200 метров.Я протестировал его с

           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))))")
                }
            }

Таким образом, логика сравнения местоположения драйверов со всеми точками на пути с 50 м, так как там нет логики ограничения.

Решение, которое я могу придумать

Если я смогу интерполировать точки между любыми двумя координатами в пути Google с регулярным интервалом 50 м и поднять ограничение до 100 м (расстояние между двумя точками в пути 50 м, ошибка по длине 50 м), что должнодать мне гораздо больше шансов уменьшить количество вызовов API

Что я пробовал?

Я пытался решить эту проблему с помощью линейной интерполяции с использованием

enter image description here

Нет необходимости говорить, что результат катастрофичен, поскольку в уравнении предполагается, что декартова плоскость и земля не плоская: |

Итак, наконец Какого черта вы спрашиваете?

  1. Правильный ли подход для интерполяции точек между двумя координатами пути Google для достижениячто я пытаюсь достичь?

  2. Если да, то какой алгоритм интерполяции лучше использовать?Очевидно, что линейность не имеет большого смысла: (

Пожалуйста, помогите, заранее спасибо

...