Laske tai kysy suurympyrän etäisyys leveys- ja pituusastepisteiden välillä Haversine-kaavan avulla (esimerkkejä PHP, JavaScript, Java, Python, MySQL, MSSQL)
Tässä kuussa olen ohjelmoinut PHP:llä ja MySQL:llä GIS:lle. Aihetta tutkiessani minulla oli vaikeuksia löytää maantieteelliset laskelmat kahden sijainnin välisen etäisyyden selvittämiseksi, joten halusin jakaa ne täällä.
Yksinkertainen tapa laskea kahden pisteen välinen etäisyys on Pythagorean kaavan avulla laskettaessa kolmion hypotenuus (A² + B² = C²). Tätä kutsutaan Euklidinen etäisyys.
Tämä on mielenkiintoinen alku, mutta se ei koske maantiedettä, koska leveys- ja pituuspiirien välinen etäisyys on eivät ole yhtä kaukana toisistaan. Kun tulet lähemmäksi päiväntasaajaa, leveyspiirit etääntyvät toisistaan. Jos käytät yksinkertaista kolmioyhtälöä, se voi mitata etäisyyden tarkasti yhdessä paikassa ja väärin toisessa Maan kaarevuuden vuoksi.
Suuri ympyräetäisyys
Reittejä, jotka kulkivat pitkiä matkoja Maan ympäri, tunnetaan nimellä Great Circle Distance. Eli… lyhin etäisyys kahden pallon pisteen välillä eroaa tasaisen kartan pisteistä. Yhdistä se siihen, että leveys- ja pituuspiirit eivät ole yhtä kaukana toisistaan… ja sinulla on vaikea laskelma.
Tässä on upea videoesitys siitä, kuinka suuret piirit toimivat.
Haversinen kaava
Maan kaarevuutta käyttävä etäisyys sisältyy Haversinen kaavaan, joka käyttää trigonometriaa maan kaarevuuden sallimiseksi. Kun etsit etäisyyttä maan kahden paikan välillä (lintulento), suora on itse asiassa kaari.
Tämä pätee lentolennolle – oletko koskaan katsonut lentojen todellista karttaa ja huomannut, että ne ovat kaarevia? Tämä johtuu siitä, että kaaressa lentäminen kahden pisteen välillä on lyhyempää kuin suoraan kohteeseen.
PHP: Laske etäisyys kahden leveys- ja pituusasteen välillä
Tässä on PHP-kaava kahden pisteen välisen etäisyyden laskemiseen (sekä Mailia vs. Kilometrit -muunnos) pyöristettynä kahteen desimaaliin.
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));
}
Muuttujat ovat:
- $Latitude1 – ensimmäisen sijaintisi leveysasteen muuttuja.
- $Pituusaste1 – ensimmäisen sijaintisi pituusasteen muuttuja
- $Latitude2 – toisen sijaintisi leveysasteen muuttuja.
- $Pituusaste2 – toisen sijaintisi pituusasteen muuttuja.
- $yksikkö – oletusarvo mailia. Tämä voidaan päivittää tai antaa eteenpäin kilometriä.
Java: Laske etäisyys 2 leveys- ja pituusasteen välillä
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;
}
}
Muuttujat ovat:
- leveysaste1 – ensimmäisen sijaintisi leveysasteen muuttuja.
- pituusaste1 – ensimmäisen sijaintisi pituusasteen muuttuja
- leveysaste2 – toisen sijaintisi leveysasteen muuttuja.
- pituusaste2 – toisen sijaintisi pituusasteen muuttuja.
- yksikkö – oletusarvo mailia. Tämä voidaan päivittää tai antaa eteenpäin kilometriä.
JavaScript: Laske etäisyys 2 leveys- ja pituusasteen välillä
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);
}
}
Muuttujat ovat:
- leveysaste1 – ensimmäisen sijaintisi leveysasteen muuttuja.
- pituusaste1 – ensimmäisen sijaintisi pituusasteen muuttuja
- leveysaste2 – toisen sijaintisi leveysasteen muuttuja.
- pituusaste2 – toisen sijaintisi pituusasteen muuttuja.
- yksikkö – oletusarvo mailia. Tämä voidaan päivittää tai antaa eteenpäin kilometriä.
Python: Laske etäisyys 2 leveys- ja pituusasteen välillä
Tässä on Python-kaava kahden pisteen välisen etäisyyden laskemiseksi (yhdessä maili vs. kilometri -muunnoksen kanssa) pyöristettynä kahteen desimaaliin. Kiitos pojalleni Bill Karrille, joka on tietotutkija OpenINSIGHTS, koodia varten.
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)
Muuttujat ovat:
- leveysaste1 – ensimmäisen sijaintisi muuttuja leveysaste.
- pituusaste1 – ensimmäisen sijaintisi muuttuja pituusaste
- leveysaste2 – toisen sijaintisi muuttuja leveysaste.
- pituusaste2 – toisen sijaintisi muuttuja pituusaste.
- yksikkö – oletusarvo mailia. Tämä voidaan päivittää tai antaa eteenpäin kilometriä.
MySQL: Hae kaikki tietueet tietyn alueen sisällä laskemalla etäisyys maileina käyttämällä leveys- ja pituusasteita
Paikkatietotyyppien käyttäminen MySQL:ssä on tehokkaampi ja kätevämpi tapa käsitellä maantieteellisiä tietoja, mukaan lukien pisteiden välisten etäisyyksien laskeminen. MySQL tukee paikkatietotyyppejä, kuten POINT
, LINESTRING
ja POLYGON
, sekä tilafunktiot, kuten ST_Distance
.
Kun käytät ST_Distance
toiminto MySQL:ssä ja maantieteelliset tiedot esitetään muodossa POINT
koordinaatit, se ottaa huomioon maan pinnan kaarevuuden. Pallomainen malli, jota käytti ST_Distance
käyttää Haversine-kaavaa. Tämä likiarvo sopii useimpiin käytännön tarkoituksiin, mutta se voi aiheuttaa pieniä epätarkkuuksia erittäin pitkillä etäisyyksillä.
Näin voit laskea kahden pisteen väliset etäisyydet paikkatietotyyppien avulla:
- Luo taulukko paikkatietotyypillä: Luo ensin taulukko a
POINT
sarake tallentaa maantieteellisiä pisteitä. Esimerkiksi:
CREATE TABLE locations (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
coordinates POINT
);
Lisää maantieteelliset pisteet tähän taulukkoon käyttämällä POINT
rakentaja:
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
- Laske etäisyys käyttämällä ST_Distance: Voit laskea kahden pisteen välisen etäisyyden käyttämällä
ST_Distance
toiminto. Tässä on esimerkkikysely kahden pisteen välisen etäisyyden laskemiseksi:
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;
korvata 1
ja 2
niiden kahden pisteen tunnuksilla, joiden välillä haluat laskea etäisyyden.
- Tulos: Kysely palauttaa kahden pisteen välisen etäisyyden maileina.
Paikkatietotyyppien ja ST_Distance
-toiminto tarjoaa tehokkaamman ja tarkemman tavan käsitellä maantieteellisiä tietoja MySQL:ssä. Se myös yksinkertaistaa pisteiden välisten etäisyyksien laskemista, mikä helpottaa tietojen hallintaa ja kyselyitä.
MySQL: Hae kaikki tietueet tietyllä alueella laskemalla etäisyys kilometreinä käyttämällä leveys- ja pituusasteita
Oletuksena ST_Distance
palauttaa etäisyyden metreinä, joten sinun tarvitsee vain päivittää kilometrikysely:
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 Maantieteellinen etäisyys: STDistance
Jos käytät Microsoft SQL Serveriä, ne tarjoavat oman toimintonsa, STDistance kahden pisteen välisen etäisyyden laskemiseen maantiede-tietotyypin avulla.
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);
Hattuvinkki Manash Sahoolle, yrityksen perustajalle ja vanhemmalle arkkitehdille Ioni kolme.