Analytics og testingCRM og dataplattformermarkedsførings~~POS=TRUNC

Beregn eller spør etter stor sirkelavstand mellom bredde- og lengdepunkter ved å bruke Haversine-formelen (PHP, JavaScript, Java, Python, MySQL, MSSQL-eksempler)

Denne måneden har jeg programmert i PHP og MySQL for GIS. Mens jeg undersøkte emnet, hadde jeg problemer med å finne geografiske beregninger for å finne avstanden mellom to steder, så jeg ville dele dem her.

Flykart Europa med stor sirkelavstand

Den enkle måten å beregne en avstand mellom to punkter på er å bruke den pythagoreiske formelen til å beregne hypotenusen til en trekant (A² + B² = C²). Dette er kjent som Euklidisk avstand.

Det er en interessant start, men det gjelder ikke geografi siden avstanden mellom bredde- og lengdegradslinjer er ikke like avstander fra hverandre. Når du kommer nærmere ekvator, blir breddegradslinjene lenger fra hverandre. Hvis du bruker en enkel trianguleringsligning, kan den måle avstanden nøyaktig på ett sted og feil på det andre på grunn av jordens krumning.

Stor sirkelavstand

Rutene som reises lange avstander rundt jorden er kjent som den store sirkelavstanden. Det vil si... den korteste avstanden mellom to punkter på en kule er forskjellig fra punktene på et flatt kart. Kombiner det med det faktum at bredde- og lengdegradslinjer ikke er like langt ... og du har en vanskelig beregning.

Her er en fantastisk videoforklaring på hvordan Great Circles fungerer.

Haversine-formelen

Avstanden ved bruk av jordens krumning er innlemmet i Haversine-formelen, som bruker trigonometri for å tillate jordens krumning. Når du finner avstanden mellom 2 steder på jorden (i luftlinje), er en rett linje faktisk en bue.

Dette gjelder for flyreiser – har du noen gang sett på det faktiske kartet over flyreiser og lagt merke til at de er buede? Det er fordi å fly i en bue mellom to punkter er kortere enn direkte til stedet.

PHP: Beregn avstand mellom 2 punkter i bredde og lengdegrad

Her er PHP-formelen for å beregne avstanden mellom to punkter (sammen med Mile vs. Kilometer-konvertering) avrundet til to desimaler.

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)); 
}

Variablene er:

  • $Latitude1 – en variabel for breddegraden til det første stedet.
  • $Lengdegrad1 – en variabel for den første plasseringens lengdegrad
  • $Latitude2 – en variabel for den andre plasseringens breddegrad.
  • $Lengdegrad2 – en variabel for den andre plasseringens lengdegrad.
  • $enhet – standard vesen miles. Dette kan oppdateres eller sendes som kilometer.

Java: Beregn avstanden mellom 2 bredde- og lengdepunkter

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;
    }
}

Variablene er:

  • breddegrad 1 – en variabel for breddegraden til det første stedet.
  • lengdegrad 1 – en variabel for den første plasseringens lengdegrad
  • breddegrad 2 – en variabel for den andre plasseringens breddegrad.
  • lengdegrad 2 – en variabel for den andre plasseringens lengdegrad.
  • enhet – standard vesen miles. Dette kan oppdateres eller sendes som kilometer.

JavaScript: Beregn avstanden mellom 2 bredde- og lengdepunkter

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);
    }
}

Variablene er:

  • breddegrad 1 – en variabel for breddegraden til det første stedet.
  • lengdegrad 1 – en variabel for den første plasseringens lengdegrad
  • breddegrad 2 – en variabel for den andre plasseringens breddegrad.
  • lengdegrad 2 – en variabel for den andre plasseringens lengdegrad.
  • enhet – standard vesen miles. Dette kan oppdateres eller sendes som kilometer.

Python: Beregn avstanden mellom 2 bredde- og lengdepunkter

Her er Python-formelen for å beregne avstanden mellom to punkter (sammen med Mile vs. Kilometer-konvertering) avrundet til to desimaler. Takk til sønnen min, Bill Karr, en dataforsker for Åpne INSIGHTS, for koden.

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)

Variablene er:

  • breddegrad 1 – en variabel for din første plassering breddegrad.
  • lengdegrad 1 – en variabel for din første plassering lengdegrad
  • breddegrad 2 – en variabel for din andre plassering breddegrad.
  • lengdegrad 2 – en variabel for din andre plassering lengdegrad.
  • enhet – standard vesen miles. Dette kan oppdateres eller sendes som kilometer.

MySQL: Henter alle poster innenfor et område ved å beregne avstand i miles ved bruk av breddegrad og lengdegrad

Bruk av romlige datatyper i MySQL er en mer effektiv og praktisk måte å jobbe med geografiske data på, inkludert beregning av avstander mellom punkter. MySQL støtter romlige datatyper som f.eks POINT, LINESTRINGog POLYGON, sammen med romlige funksjoner som ST_Distance.

Når du bruker ST_Distance funksjon i MySQL med geografiske data representert som POINT koordinater, tar den hensyn til krumningen til jordens overflate. Den sfæriske modellen brukt av ST_Distance bruker Haversine-formelen. Denne tilnærmingen er egnet for de fleste praktiske formål, men kan introdusere små unøyaktigheter for svært lange avstander.

Slik kan du beregne avstander mellom to punkter ved hjelp av romlige datatyper:

  1. Opprett en tabell med romdatatype: Først lager du en tabell med en POINT kolonne for å lagre geografiske punkter. For eksempel:
CREATE TABLE locations (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    coordinates POINT
);

Sett inn dine geografiske punkter i denne tabellen ved å bruke 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
  1. Beregn avstand ved å bruke ST_Distance: Du kan beregne avstanden mellom to punkter ved å bruke ST_Distance funksjon. Her er et eksempelspørsmål for å beregne avstanden mellom to punkter:
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;

Erstatt 1 og 2 med ID-ene til de to punktene du vil beregne avstanden mellom.

  1. Resultat: Spørringen vil returnere avstanden mellom de to punktene i miles.

Bruk av romlige datatyper og ST_Distance funksjon gir en mer effektiv og nøyaktig måte å jobbe med geografiske data i MySQL. Det forenkler også beregning av avstander mellom punkter, noe som gjør det enklere å administrere og søke etter dataene dine.

MySQL: Henter alle poster innenfor et område ved å beregne avstand i kilometer ved å bruke breddegrad og lengdegrad

Som standard ST_Distance returnerer avstanden i meter, så du trenger bare å oppdatere spørringen for kilometer:

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 Geografisk Avstand: STDistance

Hvis du bruker Microsoft SQL Server, tilbyr de sin egen funksjon, STDistance for å beregne avstanden mellom to punkter ved hjelp av datatypen Geografi.

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);  

Hattip til Manash Sahoo, grunnlegger og seniorarkitekt hos Ion tre.

Douglas Karr

Douglas Karr er CMO for Åpne INSIGHTS og grunnleggeren av Martech Zone. Douglas har hjulpet dusinvis av vellykkede MarTech-startups, har bistått med due diligence på over 5 milliarder dollar i Martech-oppkjøp og -investeringer, og fortsetter å hjelpe selskaper med å implementere og automatisere salgs- og markedsføringsstrategier. Douglas er en internasjonalt anerkjent digital transformasjons- og MarTech-ekspert og foredragsholder. Douglas er også en publisert forfatter av en Dummies guide og en bok om lederskap for bedrifter.

Relaterte artikler

Tilbake til toppen-knappen
Lukke

Annonseblokkering oppdaget

Martech Zone er i stand til å gi deg dette innholdet uten kostnad fordi vi tjener penger på nettstedet vårt gjennom annonseinntekter, tilknyttede lenker og sponsing. Vi vil sette pris på om du vil fjerne annonseblokkeringen når du ser på nettstedet vårt.