вопрос PHP, связанный с математикой + широта
-
21-08-2019 - |
Вопрос
Я нашел функцию на странице 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.
Существует по меньшей мере три пары различных методов вычисления расстояния на поверхности Земли, которые различаются по точности и требуемым вычислениям.
- Сферический закон косинусов [не очень точный, очень простой в расчете]
- Формула Хаверсина [точный, за исключением меньших расстояний, все еще относительно простой в расчете]
- Формула Винсенти [высокоточный и может использовать несколько различных эллипсоидных моделей земной поверхности, более сложных для расчета]
Приведенный вами пример, по-видимому, основан на вычислении закона косинусов, в то время как 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 в современных вычислениях дает вам такую точность.