Вопрос

Я нашел функцию на странице PHP, которая вычисляет количество миль между 2 точками, но она неисправна.Предполагается, что это работает с Google Maps, но разница в расстояниях в Google Maps составляет от 1,3 до 1,65 раза больше (что является более точным).

Вот эта функция:

$M =  69.09 * rad2deg(acos(sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon1 - $lon2))));

Я нахожу это немного сложным, и я не так много знаю о геометрии, чтобы знать, правильно это или нет.

Может ли кто-нибудь, обладающий немного большим ноу-хау, взглянуть на это и понять, что в этом плохого?

Это было полезно?

Решение

Может быть, вы сравниваете "расстояние полета вороны" (прямая линия между двумя точками) с расстоянием вождения?

Также, смотрите этот пост для вычисления расстояния между двумя точками в PHP.

Другие советы

Вы ищете Формула Хаверсина чтобы вычислить расстояние между двумя точками, для которых у вас есть долгота и широта.

Простая реализация этого в Javascript можно найти здесь, который должно быть легко преобразовать в PHP.

Существует по меньшей мере три пары различных методов вычисления расстояния на поверхности Земли, которые различаются по точности и требуемым вычислениям.

  1. Сферический закон косинусов [не очень точный, очень простой в расчете]
  2. Формула Хаверсина [точный, за исключением меньших расстояний, все еще относительно простой в расчете]
  3. Формула Винсенти [высокоточный и может использовать несколько различных эллипсоидных моделей земной поверхности, более сложных для расчета]

Приведенный вами пример, по-видимому, основан на вычислении закона косинусов, в то время как Google Maps более точен, поскольку использует формулу Винсенти.(Я нахожу, что ссылка на Vincenty объясняет формулу более подробно, чем на странице Википедии)

Редактировать:Я видел комментарий выше о том, что ошибка, вызванная отклонением земной поверхности, тривиальна и не может составлять ошибку, которую вы видите.Боюсь, это верно только на очень больших расстояниях.На расстояниях в пару сотен км или меньше ошибки могут быть явно нетривиальными.

Вот более простая версия, но не точная для очень удаленных мест:

    const ONE_DEGREE = 111120;

public function distance( $point ) {
    $coef = cos( $this->getLatitude() / 180 * M_PI );
    $x = $this->getLatitude() - $point->getLatitude();
    $y = ( $this->getLongitude() - $point->getLongitude() ) * $coef;
    $result = sqrt( $x * $x + $y * $y ) * self::ONE_DEGREE;
    return $result;
}

$point и $this являются экземплярами класса Location с методами getLatitude() и getLongitude().

Я тоже ничего не смыслю в геометрии, но Google подсказал эта страница. Может быть, вы найдете это полезным

Похоже, что формула точна - смотрите, например, Википедия о "дистанции большого круга".Коэффициент 69,09 впереди - это, я полагаю, количество миль в одном градусе, измеренное по большому кругу (например,миль в 1 градусе долготы на экваторе), поэтому ваш ответ будет выражен в милях.

идея джонстджона о том, что вы, возможно, неправильно сравниваете расстояние по прямой с расстоянием вождения, кажется мне наиболее вероятным объяснением.

Редактировать:или это может быть ошибка округления, о которой упоминает Википедия, если вы работаете с небольшими разделениями.Но сначала я бы указал пальцем на разницу в прямой и дальности движения.

Похоже, что в вычислении, на которое вы ссылаетесь, используется сферическая система координат.Формула почти правильная.Часть того, что может сбить с толку ваши вычисления, - это радиус, который вы используете.69,09 - это радиус сферы (в данном случае земли).Как вы, возможно, знаете, земля на самом деле не сфера, скорее эллипсоид.Я бы предложил попробовать приведенную ниже формулировку:

3963 * acos(sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon1 - $lon2)));

Для получения более точных результатов вы захотите использовать вычисления Винсенти или Хаверсина.

Редактировать:Чтобы уточнить, я не пытаюсь подразумевать, что основная часть ошибок, о которых вы сообщаете, связана с использованием вычисления сферических координат.Эта ошибка намного меньше, чем то, что вы видите.Приведенная мной корректировка формулы должна была быть более четкой версией формулы, поскольку 69,09 - это значение радиуса земли, скорректированное в градусной системе, которая менее интуитивно понятна, чем простое использование радианов.Кроме того, стоит отметить, что для вычисления очень малых расстояний использование приведенной выше формулы обеспечивает высокую точность (до расстояний около 1 м), если система, выполняющая вычисления, работает с достаточным количеством знаков после запятой.Использование float в современных вычислениях дает вам такую точность.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top