2010-10-14 22 views
13

C'è un modo per calcolare l'angolo tra due punti di latitudine/longitudine?Calcolare l'angolo tra due punti di latitudine/longitudine

Quello che sto cercando di ottenere è sapere dove si sta dirigendo l'utente. Ad esempio, l'utente si sta dirigendo Nord, Sud, Sud-Est ...., ecc

ma ho solo due punti (Lng/Ltd)

Thx

+1

Credo che la parola che si sta cercando non è dando l'angolo. il rilevamento è la direzione di marcia visualizzata su una bussola quando si sposta dal punto a al punto b. – Roadie57

risposta

2

Penso che si desidera i calcoli per il Great Circle bearing.

+0

Ciao HPM, no non ho bisogno di cuscinetti a sfere grandi. Solo bisogno dell'angolo :) – praethorian

+0

@praethorian - due punti di latitudine/longitudine definiscono (un arco di) un grande cerchio, dovrai spiegare cosa intendi per l'angolo tra di loro. –

+0

Ho modificato la domanda principale. thx – praethorian

1

forse questo è ciò che si vuole:

cos(say) = (cosd(90-lat(1))) * (cos(90-lat(2))) 
     + (sin(90-lat(1))) * (sind(90-lat(2)) * (cosd(abs(Landa(2)-landa(1))))); 
14

È solo possibile utilizzare le mappe di Google computeHeading:

var point1 = new google.maps.LatLng(lat1, lng1); 
var point2 = new google.maps.LatLng(lat2, lng2); 
var heading = google.maps.geometry.spherical.computeHeading(point1,point2); 
+0

Дария Печайко .. In java ??? – Prabs

10

La formula generale per il calcolo dell'angolo (cuscinetto) tra due punti è la seguente :

θ = atan2(sin(Δlong)*cos(lat2), cos(lat1)*sin(lat2) − sin(lat1)*cos(lat2)*cos(Δlong)) 

Si noti che l'angolo (θ) deve essere convertito in radianti prima di utilizzare questa formula e Δlong = long2 - long1.

atan2 è una funzione comune presente in quasi tutti i linguaggi di programmazione (principalmente nel pacchetto/libreria Math). Di solito ci sono anche funzioni per la conversione tra gradi e radianti (anche nel pacchetto/libreria Math).

Ricordare che atan2 restituisce valori nell'intervallo di -π ... + π, per convertire il risultato in un rilevamento di bussola, è necessario moltiplicare θ di 180/π quindi utilizzare (θ + 360)% 360, dove % è un'operazione di divisione modulo che restituisce il resto della divisione.

Il seguente collegamento è una buona risorsa per le formule che implicano latitudini e longitudini. Forniscono anche l'implementazione Javascript delle loro formule.In realtà, questa risposta si basa sulle informazioni da questa pagina:

http://www.yourhomenow.com/house/haversine.html

+0

cos (lat2) può essere refactored out, lasciando tan (lat2) invece di sin (lat2) – Michael

32

utilizzando this referance a calcolare l'angolo:

private double angleFromCoordinate(double lat1, double long1, double lat2, 
     double long2) { 

    double dLon = (long2 - long1); 

    double y = Math.sin(dLon) * Math.cos(lat2); 
    double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) 
      * Math.cos(lat2) * Math.cos(dLon); 

    double brng = Math.atan2(y, x); 

    brng = Math.toDegrees(brng); 
    brng = (brng + 360) % 360; 
    brng = 360 - brng; // count degrees counter-clockwise - remove to make clockwise 

    return brng; 
} 
+5

Works for me, without the brng = 360 - brng; – Kalisky

+9

Poiché latitudine e longitudine sono in genere espresse in gradi, non dimenticare di convertirle in radianti prima di utilizzare questa funzione. – user2700551

+0

cos (lat2) può essere rielaborato, lasciando tan (lat2) invece di sin (lat2) – Michael

0

assicurarsi che la sua una linea lossodromica cuscinetto non un grande cerchio come il cambio iniziale in base alla distanza

double angle= Math.min((pbearingf-tbearingf) < 0 ? pbearingf-tbearingf+360:pbearingf-tbearingf, (tbearingf-pbearingf)<0?tbearingf-pbearingf+360:tbearingf-pbearingf); 
2

Esempio codice javascript se la distanza tra i punti è minore -

brng = Math.atan2(newLat - oldLat, newLong - oldLong); 
brng = brng * (180/Math.PI); 
brng = (brng + 360) % 360; 
brng = 360 - brng; 
1

Per chi usa C/C++, sotto è il codice testato:

static const auto PI = 3.14159265358979323846, diameterOfEarthMeters = 6371.0 * 2 * 1000; 

double degreeToRadian (double degree) { return (degree * PI/180); }; 
double radianToDegree (double radian) { return (radian * 180/PI); }; 

double CoordinatesToAngle (const double latitude1, 
          const double longitude1, 
          const double latitude2, 
          const double longitude2) 
{ 
    const auto longitudeDifferenceRadians = degreeToRadian(longitude2 - longitude1); 
    auto latitude1Radian = degreeToRadian(latitude1), 
     latitude2Radian = degreeToRadian(latitude2); 

    const auto x = std::cos(latitude1Radian) * std::sin(latitude2Radian) - 
       std::sin(latitude1Radian) * std::cos(latitude2Radian) * 
       std::cos(longitudeDifferenceRadians); 
    const auto y = std::sin(longitudeDifferenceRadians) * std::cos(latitude2Radian); 

    return radianToDegree(std::atan2(y, x)); 
} 

double CoordinatesToMeters (const double latitude1, 
          const double longitude1, 
          const double latitude2, 
          const double longitude2) 
{ 
    auto latitude1Radian = degreeToRadian(latitude1), 
     longitude1Radian = degreeToRadian(longitude1), 
     latitude2Radian = degreeToRadian(latitude2), 
     longitude2Radian = degreeToRadian(longitude2); 
    auto x = std::sin((latitude2Radian - latitude1Radian)/2), 
     y = std::sin((longitude2Radian - longitude1Radian)/2); 

    return diameterOfEarthMeters * 
     std::asin(std::sqrt((x * x) + 
          (std::cos(latitude1Radian) * std::cos(latitude2Radian) * y * y))); 
} 
0

Nel caso qualcuno bisogno PHP codice per questo funzionalità:

/** 
* Calculate angle between 2 given latLng 
* @param float $lat1 
* @param float $lat2 
* @param float $lng1 
* @param float $lng2 
* @return integer 
*/ 
function angle($lat1, $lat2, $lng1, $lng2) { 
    $dLon = $lng2 - $lng1; 
    $y = sin($dLon) * cos($lat2); 
    $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon); 
    return 360 - ((rad2deg(atan2($y, $x)) + 360) % 360); 
} 
0
function calculateAngle(lat, lng) { 
    var checkLengthInterval = 2; 

    // Calculate Angle 
    if (ObjFeed.length == 0) { 
     ObjFeed.push({ 'lat': lat, 'lng': lng }); 
    } else { 
     var tempNode = ObjFeed[ObjFeed.length - 1]; 
     if (!(tempNode.lat == lat && tempNode.lng == lng)) { 
      ObjFeed.push({ 'lat': lat, 'lng': lng }); 
     } else { 
      console.log('exact match for lat lng'); 
     } 
    } 

    if (ObjFeed.length >= checkLengthInterval) { 
     // calculating angle only if previous data point is available 
     ObjFeed = ObjFeed.slice(-1 * checkLengthInterval); // remove all items in array except last two 
     var point1 = ObjFeed[ObjFeed.length - checkLengthInterval]; 
     var point2 = ObjFeed[ObjFeed.length - 1]; 

     console.log('previous point1', point1); 
     console.log('next point2', point2); 

     var dLng = (point2.lng - point1.lng); 
     var dLat = (point2.lat - point1.lat); 

     dLng = dLng * 10000; 
     dLat = dLat * 10000; 

     var dlat_by_dlan = 0; 

     try { 
      dlat_by_dlan = dLng/dLat; 
     } catch (err) { 
      dlat_by_dlan = NaN; 
      console.log('Exception: dLat == 0'); 
     } 

     var angleDegreeBearing = 0, angleBearingRad = 0; 
     angleBearingRad = Math.atan(dlat_by_dlan); 
     angleDegreeBearing = angleBearingRad * 180/Math.PI; 

     if (dLat < 0 && dLng < 0) { 
      angleDegreeBearing = angleDegreeBearing + 180; 
     } else if (dLat < 0 && dLng > 0) { 
      angleDegreeBearing = angleDegreeBearing + 180; 
     } else if (dLat == 0 && dLng == 0) { 
      angleDegreeBearing = prevVechicleAngle; 
     } else if (dlat_by_dlan == NaN) { 
      angleDegreeBearing = prevVechicleAngle; 
     } 

     console.log('angleDegreeBearing', angleDegreeBearing); 

    } else { 
     // setting up default angle to 0 if previous data point is not available to calculate actual anglle 
     console.log('feedArray default angle 0'); 
     angleDegreeBearing = 0; 
    } 
    prevVechicleAngle = angleDegreeBearing; 
    return angleDegreeBearing; 

} 
+0

potresti spiegare questo codice un po 'per migliorare la tua risposta e aiutare i futuri lettori? – WhatsThePoint

2

in base alla risposta del Nayanesh Gupte, ecco un implementazione di Python, se qualcuno ha bisogno:

def angleFromCoordinate(lat1, long1, lat2, long2): 
    dLon = (long2 - long1) 

    y = math.sin(dLon) * math.cos(lat2) 
    x = math.cos(lat1) * math.sin(lat2) - math.sin(lat1) * math.cos(lat2) * math.cos(dLon) 

    brng = math.atan2(y, x) 

    brng = math.degrees(brng) 
    brng = (brng + 360) % 360 
    brng = 360 - brng # count degrees clockwise - remove to make counter-clockwise 

    return brng 

Dove un angolo di 0 gradi indica una rubrica verso nord.

0

Per fornire la direzione è necessario calcolare il rilevamento.

Per comprendere il rilevamento leggere this article.

Secondo questa article (section bearing) la formula è:

θ = atan2(sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ) 
where φ1, λ1 is the start point, 
     φ2, λ2 the end point, 
     Δλ is the difference in longitude` 

Ecco un esempio su come calcolare l'angolo (in gradi) tra due punti espressi in Lat/Lon. (fatto in C#)

Diciamo che Point è una classe semplice con due attributi double X (per longitudine) e Y (per latitudine).

public double ComputeBearing(Point start,Point end) 
{ 
    var φ1 = start.Y; //latitude 1 
    var λ1 = start.X; //longitude 1 
    var φ2 = end.Y; //latitude 2 
    var λ2 = end.X; //longitude 2 

    var y = Math.Sin(this.degreeToRadian(λ2 - λ1)) * Math.Cos(this.degreeToRadian(φ2)); 
    var x = Math.Cos(this.degreeToRadian(φ1)) * Math.Sin(this.degreeToRadian(φ2)) - Math.Sin(this.degreeToRadian(φ1)) * Math.Cos(this.degreeToRadian(φ2)) * Math.Cos(this.degreeToRadian(λ2 - λ1)); 

    var θ = Math.Atan2(y, x); 
    θ = this.radianToDegree(θ); 

    return θ; 
} 

utilizzando i seguenti metodi:

public double degreeToRadian(double angle) 
{ 
    return Math.PI * angle/180.0; 
} 

public double radianToDegree(double angle) 
{ 
    return angle * (180.0/Math.PI); 
} 

Usando ComputeBearing vi sarà facile ottenere un angolo espresso in gradi facilmente utilizzabili come voce

0

Considerando risposta e le sue osservazioni Nayanesh Gupte s' . Ho modificato parte del codice e l'ho scritto in PHP.

  • latitudine e longitudine sono stati convertiti in radianti all'interno della funzione.

Qui è la funzione:

function angleFromCoordinate($lat1, $long1, $lat2, $long2) { 

    $lat1 = deg2rad($lat1); 
    $lat2 = deg2rad($lat2); 
    $long1 = deg2rad($long1); 
    $long2 = deg2rad($long2); 

    $dLon = $long2 - $long1; 

    $y = sin($dLon) * cos($lat2); 
    $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon); 

    $brng = atan2($y, $x); 

    $brng = $brng * 180/pi(); 
    $brng = fmod($brng + 360, 360); 

    return $brng; 
} 
Problemi correlati