2010-10-14 5 views
13

Czy istnieje sposób obliczenia kąta między dwoma punktami szerokości/długości geograficznej?Oblicz kąt między dwoma punktami szerokości/długości geograficznej

To, co próbuję osiągnąć, to wiedzieć, dokąd zmierza użytkownik. Na przykład, użytkownik jest pozycją północ, południe, południowo-wschodniej .... itd

Ale mam tylko dwa punkty (LNG/Ltd)

THX

+1

myślę, że słowo szukasz nie mając kąt. łożysko jest kierunkiem jazdy wyświetlanym na kompasie podczas przemieszczania się z punktu a do punktu b. – Roadie57

Odpowiedz

2

myślę chcesz obliczeń dla Great Circle bearing.

+0

Witam HPM, nie, nie potrzebuję wielkoobrotowego łożyska. Po prostu potrzebujesz kąta :) – praethorian

+0

@praethorian - dwa punkty szerokości/długości geograficznej definiują (łuk) wielkiego koła, musisz wyjaśnić, co masz na myśli przez kąt między nimi. –

+0

Edytowałem pierwsze pytanie. thx – praethorian

1

Może to jest to, co chcesz:

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

Po prostu można użyć google maps 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

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

10

Ogólny wzór na obliczenie kąta (łożyska) między dwoma punktami jest następująco :

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

Pamiętaj, że kąt (θ) powinien zostać przekonwertowany na radiany przed użyciem tej formuły i Δlong = long2 - long1.

atan2 jest wspólną funkcją dostępną w prawie wszystkich językach programowania (głównie w pakiecie/bibliotece Math). Zwykle istnieją również funkcje konwersji pomiędzy stopniami i radianami (również w pakiecie/bibliotece Math).

Pamiętaj, że atan2 zwraca wartości w zakresie -π ... + π, aby przekonwertować wynik na łożysko kompasu, musisz pomnożyć θ przez 180/π, następnie użyć (θ + 360)% 360, gdzie % to operacja dzielenia modułów zwracająca resztę podziału.

Poniższy link jest dobrym źródłem informacji o formułach dotyczących szerokości i długości geograficznej. Zapewniają również implementację formuł w JavaScript.W rzeczywistości, ta odpowiedź jest oparta na informacjach z tej strony:

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

+0

cos (lat2) może być refaktoryzowany, pozostawiając tan (lat2) zamiast grzechu (lat2) – Michael

32

użyciu this Referance obliczyć kąt:

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

Działa dla mnie, bez brng = 360 - brng; – Kalisky

+9

Ponieważ szerokość i długość geograficzna są zwykle wyrażone w stopniach, nie zapomnij przekształcić ich na radiany przed użyciem tej funkcji. – user2700551

+0

cos (lat2) może być refaktoryzowany, pozostawiając tan (lat2) zamiast grzechu (lat2) – Michael

0

Upewnij jego loksodroma łożyska nie wielki krąg łożysko jako początkowe łożysko zmienia się zgodnie z odległością

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

Przykładowy kod javascript, jeśli odległość między punktami jest mniejsza -

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

Dla tych, którzy korzystają z C/C++, poniżej jest testowany Kod:

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

W przypadku gdy ktoś potrzebować kod PHP dla tego funkcjonalność:

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

czy możesz wyjaśnić ten kod nieco, aby poprawić swoją odpowiedź i pomóc przyszłym czytelnikom? – WhatsThePoint

2

podstawie odpowiedzi Nayanesh Gupte, oto jest implementacja Pythona, jeśli ktoś go potrzebuje:

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 

Jeżeli kąt 0 stopni wskazuje północ, nagłówek.

0

Aby podać nagłówek, należy obliczyć położenie.

Aby zrozumieć łożysko, przeczytaj this article.

Według tego article (section bearing) formuła jest:

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

Oto przykład, jak obliczyć kąt (w stopniach) pomiędzy dwoma punktami wyrażone w szerokości/długości. (wykonane w języku C#)

Załóżmy, że Point to prosta klasa z dwoma atrybutami double X (dla długości) i Y (dla szerokości geograficznej).

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

stosując następujące metody:

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

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

Korzystając ComputeBearing będzie łatwo uzyskać kąt wyrażony w stopniach łatwo użytecznych jako nagłówek

0

Zważywszy odpowiedź Nayanesh Gupte „s oraz uwag . Zmieniłem część kodu i napisałem go w PHP.

  • szerokość i Długość zostały przekształcone radianach wewnątrz funkcji.

Oto funkcja:

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