2010-10-14 245 views
13

是否有計算兩個緯度/經度點之間夾角的方法?計算兩個緯度/經度點之間的夾角

我想要實現的是知道用戶在哪裏前進。例如,用戶正在走向北美,南美,...東南亞等

但我只有兩分(LNG /有限公司)

THX

+1

我認爲你正在尋找的字是軸承沒有角度。當從點a移動到點b時,方位是指南針上顯示的行進方向。 – Roadie57 2010-10-15 15:26:06

回答

2

我想你想的計算爲Great Circle bearing

+0

嗨HPM,不,我不需要大圓圈軸承。只需要角度:) – praethorian 2010-10-14 11:24:20

+0

@praethorian - 兩個緯度/經度點定義了一個大圓的弧(弧),你必須解釋它們之間的角度是什麼意思。 – 2010-10-14 11:32:27

+0

我編輯了最重要的問題。 thx – praethorian 2010-10-14 11:40:21

1

也許這是你想要什麼:

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

你只可以使用谷歌地圖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

ДарияПечайко..在java中??? – Prabs 2017-09-14 11:28:25

10

兩點之間計算的角度(軸承)的一般公式如下:

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

請注意,在使用此公式之前,應將角度(θ)轉換爲弧度和 Δlong= long2 - long1。

atan2是幾乎所有編程語言(主要是數學包/庫)中的常見函數。通常還有度數和弧度之間轉換的函數(也在數學包/庫中)。請記住,atan2返回-π... +π範圍內的值,將結果轉換爲指南針方位,需要將θ乘以180 /π,然後使用(θ+ 360)%360,其中%是模數除法操作,返回除法的其餘部分。

以下鏈接對於涉及經度和緯度的公式很有用。他們還提供其公式的Javascript實現。

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

+0

cos(lat2)可以重構出來,留下tan(lat2)而不是sin(lat2) – Michael 2017-11-09 22:01:07

32

使用this全球化志願服務青年來計算角度:其實,這個答案是基於此頁面中的信息

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

適用於我,沒有brng = 360 - brng; – Kalisky 2015-05-12 08:19:31

+9

由於經度和緯度通常用度來表示,所以在使用此函數之前不要忘記將它們轉換爲弧度。 – user2700551 2015-12-10 08:48:01

+0

cos(lat2)可以重構出來,留下tan(lat2)而不是sin(lat2) – Michael 2017-11-09 22:00:38

0

確保其恆向線軸承不是一個大圓軸承爲 初始軸承根據距離變化

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

樣品如果點之間的距離是JavaScript代碼少 -

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

對於那些誰使用C/C++,下面是測試的代碼:

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

如果有人需要爲這個PHP代碼功能:

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

你能解釋一下這段代碼來改進你的答案並幫助未來的讀者嗎? – WhatsThePoint 2017-06-19 07:20:41

2

基於Nayanesh Gupte的答案,這裏是一個Python實現,如果有人需要它:

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 

其中的0度角表示向北航向。

0

爲了提供標題,你必須計算軸承。

要了解方位,請閱讀this article

根據該article (section bearing)公式爲:

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

下面是關於如何計算在緯度/經度表示的兩個點之間的角度(度)的樣品。 (在C#中完成)

比方說Point是一個簡單的類,其中兩個double屬性X(經度)和Y(緯度)。

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

使用以下方法:

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

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

使用ComputeBearing你會很容易得到一個角度易於使用的標題

0

考慮Nayanesh Gupte的回答和評論度表示。我已經更改了部分代碼並將其寫入PHP

  • 緯度經度已經轉換爲弧度在函數內部。

下面是函數:

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; 
} 
相關問題