2010-10-14 15 views
13

¿Hay alguna forma de calcular el ángulo entre dos puntos de latitud/longitud?Calcular el ángulo entre dos puntos de latitud/longitud

Lo que estoy tratando de lograr es saber hacia dónde se dirige el usuario. Por ejemplo, el usuario se dirige Norte, Sur, Sudeste ...., etc.

Pero tiene sólo dos puntos (GNL/Ltd)

Thx

+1

Creo que la palabra que busca no está dando sus ángulos. el rumbo es la dirección del recorrido que se muestra en una brújula cuando se mueve del punto a al punto b. – Roadie57

Respuesta

2

Creo desea que los cálculos para el Great Circle bearing.

+0

Hola HPM, no, no necesito Rodamiento de gran círculo. Solo necesito el ángulo :) – praethorian

+0

@praethorian - dos puntos de Latitud/Longitud definen (un arco de) un Gran Círculo, tendrás que explicar lo que quieres decir con el ángulo que los separa. –

+0

He editado la pregunta principal. thx – praethorian

1

Tal vez esto es lo que quiere:

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

Usted sólo puede usar los mapas de 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

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

10

La fórmula general para calcular el ángulo (rumbo) entre dos puntos es la siguiente :

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

Tenga en cuenta que el ángulo (θ) debe convertirse a radianes antes de usar esta fórmula y Δlong = long2 - long1.

atan2 es una función común que se encuentra en casi todos los lenguajes de programación (principalmente en el paquete matemático/biblioteca). Por lo general, también hay funciones para la conversión entre grados y radianes (también en el paquete matemático/biblioteca).

Recuerde que atan2 devuelve valores en el rango de -π ... + π, para convertir el resultado a una orientación de la brújula, debe multiplicar θ por 180/π y luego use (θ + 360)% 360, donde % es la operación de división del módulo que devuelve el resto de la división.

El siguiente enlace es un buen recurso para fórmulas que involucran latitudes y longitudes. También proporcionan la implementación de Javascript de sus fórmulas.De hecho, esta respuesta se basa en la información de esta página:

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

+0

cos (lat2) se puede refactorizar, dejando tan (lat2) en lugar de sin (lat2) – Michael

32

usando this referance para calcular Ángulo:

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

Funciona para mí, sin el brng = 360 - brng; – Kalisky

+9

Como la latitud y la longitud suelen expresarse en grados, no olvide convertirlas en radianes antes de utilizar esta función. – user2700551

+0

cos (lat2) se puede refactorizar, dejando tan (lat2) en lugar de sin (lat2) – Michael

0

Asegúrese de que su una línea de rumbo que lleva no es un gran círculo teniendo como el cambios iniciales del cojinete según la distancia

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

Muestra de código javascript si la distancia entre los puntos es menor -

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

Para aquellos que utilizan C/C++, a continuación es el código de prueba:

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

En caso de que alguien necesita PHP código para esta funcionalidad:

/** 
* 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

¿Podría explicar este código un poco para mejorar su respuesta y ayudar a los lectores en el futuro? – WhatsThePoint

2

Sobre la base de la respuesta de Nayanesh Gupte, aquí es una implementación de Python si alguien lo necesita:

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 

Cuando un ángulo de 0 grados indica un rumbo hacia el norte.

0

Para proporcionar el rumbo, debe calcular el rumbo.

Para entender el rodamiento, lea this article.

Según esta article (section bearing) La fórmula es:

θ = 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` 

He aquí una muestra sobre la manera de calcular el ángulo (en grados) entre dos puntos expresadas en Lat/Lon. (Hecho en C#)

Digamos Point es una clase simple con dos double atributos X (por longitud) e Y (para la latitud).

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

utilizando los siguientes métodos:

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

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

Al usar ComputeBearing obtendrá fácilmente un ángulo expresado en grados fácilmente utilizables como rúbrica

0

Considerando respuesta Nayanesh Gupte 's y sus comentarios . Cambié parte del código y lo escribí en PHP.

  • latitud y longitud han sido convertidos a radianes dentro de la función.

Aquí es la función:

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