Аналитика и тестированиеCRM и платформы данныхМаркетинговые инструменты

Вычисление или запрос расстояния по большому кругу между точками широты и долготы с использованием формулы гаверсинуса (примеры PHP, JavaScript, Java, Python, MySQL, MSSQL)

В этом месяце я программировал на PHP и MySQL для ГИС. Изучая эту тему, я с трудом нашел географические расчеты чтобы найти расстояние между двумя локациями, поэтому я хотел поделиться ими здесь.

Карта полетов в Европу с большим расстоянием по кругу

Простым способом вычисления расстояния между двумя точками является использование формулы Пифагора для вычисления гипотенузы треугольника (A² + B² = C²). Это известно как Евклидово расстояние.

Это интересное начало, но оно неприменимо к географии, поскольку расстояние между линиями широты и долготы равно не равные расстояния друг от друга. По мере приближения к экватору линии широты расходятся дальше. Если вы используете простое уравнение триангуляции, оно может точно измерить расстояние в одном месте и неправильно в другом из-за кривизны Земли.

Расстояние по большому кругу

Маршруты, пройденные на большие расстояния вокруг Земли, известны как расстояние по Большому кругу. То есть… кратчайшее расстояние между двумя точками на сфере отличается от точек на плоской карте. Объедините это с тем фактом, что линии широты и долготы не равноудалены… и вы получите сложный расчет.

Вот фантастическое видео, объясняющее, как работают Великие круги.

Формула Хаверсина

Расстояние с использованием кривизны Земли включено в формулу Хаверсина, которая использует тригонометрию для учета кривизны Земли. Когда вы находите расстояние между двумя точками на Земле (по прямой), прямая линия на самом деле представляет собой дугу.

Это применимо в авиаперелетах — вы когда-нибудь смотрели на настоящую карту полетов и замечали, что они изогнуты? Все потому, что лететь по дуге между двумя точками короче, чем напрямую до локации.

PHP: вычислить расстояние между двумя точками широты и долготы

Вот формула PHP для расчета расстояния между двумя точками (вместе с преобразованием миль в километры), округленная до двух знаков после запятой.

function getDistanceBetweenPointsNew($latitude1, $longitude1, $latitude2, $longitude2, $unit = 'miles') {
  $theta = $longitude1 - $longitude2; 
  $distance = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta))); 
  $distance = acos($distance); 
  $distance = rad2deg($distance); 
  $distance = $distance * 60 * 1.1515; 
  switch($unit) { 
    case 'miles': 
      break; 
    case 'kilometers' : 
      $distance = $distance * 1.609344; 
  } 
  return (round($distance,2)); 
}

Переменные:

  • $широта1 – переменная для широты вашего первого местоположения.
  • $Долгота1 – переменная для долготы вашего первого местоположения
  • $широта2 – переменная для широты вашего второго местоположения.
  • $Долгота2 – переменная для долготы вашего второго местоположения.
  • $единица - значение по умолчанию миль. Это может быть обновлено или передано как километров.

Java: рассчитать расстояние между двумя точками широты и долготы

public static double getDistanceBetweenPointsNew(double latitude1, double longitude1, double latitude2, double longitude2, String unit) {
    double theta = longitude1 - longitude2;
    double distance = 60 * 1.1515 * (180/Math.PI) * Math.acos(
        Math.sin(latitude1 * (Math.PI/180)) * Math.sin(latitude2 * (Math.PI/180)) + 
        Math.cos(latitude1 * (Math.PI/180)) * Math.cos(latitude2 * (Math.PI/180)) * Math.cos(theta * (Math.PI/180))
    );
    if (unit.equals("miles")) {
        return Math.round(distance, 2);
    } else if (unit.equals("kilometers")) {
        return Math.round(distance * 1.609344, 2);
    } else {
        return 0;
    }
}

Переменные:

  • широта1 – переменная для широты вашего первого местоположения.
  • долгота1 – переменная для долготы вашего первого местоположения
  • широта2 – переменная для широты вашего второго местоположения.
  • долгота2 – переменная для долготы вашего второго местоположения.
  • Ед. изм - значение по умолчанию миль. Это может быть обновлено или передано как километров.

JavaScript: рассчитать расстояние между двумя точками широты и долготы

function getDistanceBetweenPoints(latitude1, longitude1, latitude2, longitude2, unit = 'miles') {
    let theta = longitude1 - longitude2;
    let distance = 60 * 1.1515 * (180/Math.PI) * Math.acos(
        Math.sin(latitude1 * (Math.PI/180)) * Math.sin(latitude2 * (Math.PI/180)) + 
        Math.cos(latitude1 * (Math.PI/180)) * Math.cos(latitude2 * (Math.PI/180)) * Math.cos(theta * (Math.PI/180))
    );
    if (unit == 'miles') {
        return Math.round(distance, 2);
    } else if (unit == 'kilometers') {
        return Math.round(distance * 1.609344, 2);
    }
}

Переменные:

  • широта1 – переменная для широты вашего первого местоположения.
  • долгота1 – переменная для долготы вашего первого местоположения
  • широта2 – переменная для широты вашего второго местоположения.
  • долгота2 – переменная для долготы вашего второго местоположения.
  • Ед. изм - значение по умолчанию миль. Это может быть обновлено или передано как километров.

Python: рассчитать расстояние между двумя точками широты и долготы

Вот формула Python для расчета расстояния между двумя точками (вместе с преобразованием миль в километры), округленная до двух десятичных знаков. Благодарность моему сыну Биллу Карру, специалисту по данным из OpenINSIGHTS, для кода.

from numpy import sin, cos, arccos, pi, round

def rad2deg(radians):
    degrees = radians * 180 / pi
    return degrees

def deg2rad(degrees):
    radians = degrees * pi / 180
    return radians

def getDistanceBetweenPointsNew(latitude1, longitude1, latitude2, longitude2, unit = 'miles'):
    
    theta = longitude1 - longitude2
    
    distance = 60 * 1.1515 * rad2deg(
        arccos(
            (sin(deg2rad(latitude1)) * sin(deg2rad(latitude2))) + 
            (cos(deg2rad(latitude1)) * cos(deg2rad(latitude2)) * cos(deg2rad(theta)))
        )
    )
    
    if unit == 'miles':
        return round(distance, 2)
    if unit == 'kilometers':
        return round(distance * 1.609344, 2)

Переменные:

  • широта1 – переменная для вашего первого местоположения широта.
  • долгота1 – переменная для вашего первого местоположения долгота
  • широта2 – переменная для вашего второго местоположения широта.
  • долгота2 – переменная для вашего второго местоположения долгота.
  • Ед. изм - значение по умолчанию миль. Это может быть обновлено или передано как километров.

MySQL: получение всех записей в диапазоне путем вычисления расстояния в милях с использованием широты и долготы

Использование пространственных типов данных в MySQL — более эффективный и удобный способ работы с географическими данными, включая расчет расстояний между точками. MySQL поддерживает такие типы пространственных данных, как POINT, LINESTRINGкачества POLYGON, наряду с пространственными функциями, такими как ST_Distance.

Когда вы используете ST_Distance функция в MySQL с географическими данными, представленными как POINT координаты, он учитывает кривизну поверхности Земли. Сферическая модель, используемая ST_Distance использует формулу Хаверсина. Это приближение подходит для большинства практических целей, но может вносить небольшие неточности на очень больших расстояниях.

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

  1. Создайте таблицу с пространственным типом данных: Сначала создайте таблицу с POINT столбец для хранения географических точек. Например:
CREATE TABLE locations (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    coordinates POINT
);

Вставьте свои географические точки в эту таблицу, используя POINT конструктор:

INSERT INTO locations (name, coordinates)
VALUES
    ('Point A', POINT(40.7128, -74.0060)), -- New York City
    ('Point B', POINT(34.0522, -118.2437)); -- Los Angeles
  1. Вычислить расстояние, используя ST_Distance: Вы можете рассчитать расстояние между двумя точками, используя ST_Distance функция. Вот пример запроса для расчета расстояния между двумя точками:
SELECT
    id1,
    id2,
    (ST_Distance(coordinates1, coordinates2) / 1609.344) AS distance_in_miles
FROM (
    SELECT
        l1.id AS id1,
        l2.id AS id2,
        l1.coordinates AS coordinates1,
        l2.coordinates AS coordinates2
    FROM
        locations l1,
        locations l2
    WHERE
        l1.id = 1 AND l2.id = 2
) AS distances;

Замените 1 и 2 с идентификаторами двух точек, между которыми вы хотите рассчитать расстояние.

  1. Результат: запрос вернет расстояние между двумя точками в милях.

Использование пространственных типов данных и ST_Distance Функция обеспечивает более эффективный и точный способ работы с географическими данными в MySQL. Это также упрощает расчет расстояний между точками, упрощая управление данными и запросы к ним.

MySQL: получение всех записей в диапазоне путем вычисления расстояния в километрах с использованием широты и долготы

По умолчанию ST_Distance возвращает расстояние в метрах, поэтому вам просто нужно обновить запрос на километры:

SELECT
    id1,
    id2,
    (ST_Distance(coordinates1, coordinates2) / 1000) AS distance_in_kilometers
FROM (
    SELECT
        l1.id AS id1,
        l2.id AS id2,
        l1.coordinates AS coordinates1,
        l2.coordinates AS coordinates2
    FROM
        locations l1,
        locations l2
    WHERE
        l1.id = 1 AND l2.id = 2
) AS distances;

Географическое расстояние Microsoft SQL Server: STDistance

Если вы используете Microsoft SQL Server, они предлагают свои собственные функции, STРасстояние для вычисления расстояния между двумя точками с использованием типа данных Geography.

DECLARE @g geography;  
DECLARE @h geography;  
SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326);  
SET @h = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326);  
SELECT @g.STDistance(@h);  

Совет Манашу Саху, основателю и старшему архитектору компании Ион Три.

Douglas Karr

Douglas Karr является директором по маркетингу OpenINSIGHTS и основатель компании Martech Zone. Дуглас помог десяткам успешных стартапов MarTech, помог в комплексной проверке приобретений и инвестиций Martech на сумму более 5 миллиардов долларов, а также продолжает помогать компаниям во внедрении и автоматизации их стратегий продаж и маркетинга. Дуглас — международно признанный эксперт по цифровой трансформации, а также эксперт в области MarTech и спикер. Дуглас также является автором опубликованного руководства для чайников и книги по бизнес-лидерству.

Статьи по теме

Вернуться к началу кнопки
Закрыть

Adblock обнаружен

Martech Zone может предоставить вам этот контент бесплатно, потому что мы монетизируем наш сайт за счет доходов от рекламы, партнерских ссылок и спонсорства. Мы были бы признательны, если бы вы удалили блокировщик рекламы при просмотре нашего сайта.