2010-10-14 240 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; 
} 
相关问题