Vypočítejte nebo dotazujte vzdálenost velkého kruhu mezi body zeměpisné šířky a délky pomocí vzorce Haversine (příklady PHP, JavaScript, Java, Python, MySQL, MSSQL)
Tento měsíc jsem programoval v PHP a MySQL pro GIS. Při zkoumání tématu jsem měl problém najít geografické výpočty najít vzdálenost mezi dvěma místy, tak jsem je chtěl sdílet zde.
Jednoduchý způsob výpočtu vzdálenosti mezi dvěma body je pomocí Pythagorovy vzorce pro výpočet přepony trojúhelníku (A² + B² = C²). Toto je známé jako Euklidovská vzdálenost.
To je zajímavý začátek, ale neplatí to pro geografii, protože vzdálenost mezi čarami zeměpisné šířky a délky je nejsou od sebe ve stejné vzdálenosti. Jak se přibližujete k rovníku, čáry zeměpisné šířky se vzdalují. Pokud použijete jednoduchou triangulační rovnici, může změřit vzdálenost přesně v jednom místě a špatně ve druhém kvůli zakřivení Země.
Velká vzdálenost kruhu
Trasy ujeté na dlouhé vzdálenosti kolem Země jsou známé jako Velká kruhová vzdálenost. To znamená... nejkratší vzdálenost mezi dvěma body na kouli se liší od bodů na ploché mapě. Zkombinujte to se skutečností, že čáry zeměpisné šířky a délky nejsou stejně vzdálené... a máte obtížný výpočet.
Zde je fantastické video vysvětlení toho, jak Great Circles fungují.
Vzorec Haversine
Vzdálenost využívající zakřivení Země je začleněna do Haversinova vzorce, který využívá trigonometrii k zohlednění zakřivení Země. Když zjišťujete vzdálenost mezi 2 místy na Zemi (vzdušnou čarou), přímka je ve skutečnosti oblouk.
To platí v leteckém letu – už jste se někdy podívali na skutečnou mapu letů a všimli jste si, že jsou klenuté? Je to proto, že let v oblouku mezi dvěma body je kratší než přímo na místo.
PHP: Vypočítejte vzdálenost mezi 2 body zeměpisné šířky a délky
Zde je vzorec PHP pro výpočet vzdálenosti mezi dvěma body (spolu s převodem Míle vs. Kilometr) zaokrouhlený na dvě desetinná místa.
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));
}
Proměnné jsou:
- $Latitude1 – proměnná pro zeměpisnou šířku vašeho prvního místa.
- $Longitude1 – proměnná pro zeměpisnou délku vašeho prvního místa
- $Latitude2 – proměnná pro zeměpisnou šířku vašeho druhého místa.
- $Longitude2 – proměnná pro zeměpisnou délku vašeho druhého místa.
- $jednotka – výchozí bytost míle. To lze aktualizovat nebo předat jako kilometrů.
Java: Vypočítejte vzdálenost mezi 2 body zeměpisné šířky a délky
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;
}
}
Proměnné jsou:
- zeměpisná šířka 1 – proměnná pro zeměpisnou šířku vašeho prvního místa.
- zeměpisná délka 1 – proměnná pro zeměpisnou délku vašeho prvního místa
- zeměpisná šířka 2 – proměnná pro zeměpisnou šířku vašeho druhého místa.
- zeměpisná délka 2 – proměnná pro zeměpisnou délku vašeho druhého místa.
- jednotka – výchozí bytost míle. To lze aktualizovat nebo předat jako kilometrů.
JavaScript: Vypočítejte vzdálenost mezi 2 body zeměpisné šířky a délky
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);
}
}
Proměnné jsou:
- zeměpisná šířka 1 – proměnná pro zeměpisnou šířku vašeho prvního místa.
- zeměpisná délka 1 – proměnná pro zeměpisnou délku vašeho prvního místa
- zeměpisná šířka 2 – proměnná pro zeměpisnou šířku vašeho druhého místa.
- zeměpisná délka 2 – proměnná pro zeměpisnou délku vašeho druhého místa.
- jednotka – výchozí bytost míle. To lze aktualizovat nebo předat jako kilometrů.
Python: Vypočítejte vzdálenost mezi 2 body zeměpisné šířky a délky
Zde je pythonovský vzorec pro výpočet vzdálenosti mezi dvěma body (spolu s převodem Míle vs. Kilometr) zaokrouhlený na dvě desetinná místa. Poděkování patří mému synovi, Billu Karrovi, datovému vědci za OpenINSIGHTS, pro kód.
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)
Proměnné jsou:
- zeměpisná šířka 1 – proměnná pro vaše první umístění zeměpisná šířka.
- zeměpisná délka 1 – proměnná pro vaše první umístění zeměpisná délka
- zeměpisná šířka 2 – proměnná pro vaše druhé umístění zeměpisná šířka.
- zeměpisná délka 2 – proměnná pro vaše druhé umístění zeměpisná délka.
- jednotka – výchozí bytost míle. To lze aktualizovat nebo předat jako kilometrů.
MySQL: Získávání všech záznamů v rámci rozsahu výpočtem vzdálenosti v mílích pomocí zeměpisné šířky a délky
Použití typů prostorových dat v MySQL je efektivnější a pohodlnější způsob práce s geografickými daty, včetně výpočtu vzdáleností mezi body. MySQL podporuje typy prostorových dat jako např POINT
, LINESTRING
, a POLYGON
, spolu s prostorovými funkcemi jako ST_Distance
.
Když používáte ST_Distance
funkce v MySQL s geografickými daty reprezentovanými jako POINT
souřadnice, zohledňuje zakřivení zemského povrchu. Sférický model, který používá ST_Distance
využívá Haversinův vzorec. Tato aproximace je vhodná pro většinu praktických účelů, ale může způsobit mírné nepřesnosti na velmi dlouhé vzdálenosti.
Zde je návod, jak vypočítat vzdálenosti mezi dvěma body pomocí typů prostorových dat:
- Vytvořte tabulku s typem prostorových dat: Nejprve vytvořte tabulku s a
POINT
sloupec pro uložení geografických bodů. Například:
CREATE TABLE locations (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
coordinates POINT
);
Vložte své geografické body do této tabulky pomocí POINT
konstruktér:
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
- Vypočítejte vzdálenost pomocí ST_Distance: Vzdálenost mezi dvěma body můžete vypočítat pomocí
ST_Distance
funkce. Zde je příklad dotazu pro výpočet vzdálenosti mezi dvěma body:
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;
Nahradit 1
a 2
s ID dvou bodů, mezi kterými chcete vypočítat vzdálenost.
- Výsledek: Dotaz vrátí vzdálenost mezi dvěma body v mílích.
Použití typů prostorových dat a ST_Distance
poskytuje efektivnější a přesnější způsob práce s geografickými daty v MySQL. Zjednodušuje také výpočet vzdáleností mezi body, což usnadňuje správu a dotazování vašich dat.
MySQL: Získávání všech záznamů v rámci rozsahu výpočtem vzdálenosti v kilometrech pomocí zeměpisné šířky a délky
Ve výchozím nastavení ST_Distance
vrací vzdálenost v metrech, takže stačí aktualizovat dotaz na kilometry:
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;
Geografická vzdálenost Microsoft SQL Server: STDistance
Pokud používáte Microsoft SQL Server, nabízejí své vlastní funkce, STDvzdálenost pro výpočet vzdálenosti mezi dvěma body pomocí datového typu Geografie.
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);
Klobouk pro Manash Sahoo, zakladatele a hlavního architekta ve společnosti Ion tři.