使用两个经度/纬度点获取方向(罗盘)

21

我正在为移动设备开发一个“指南针”。我的要求如下:

point 1 (current location): Latitude = 47.2246, Longitude = 8.8257
point 2 (target  location): Latitude = 50.9246, Longitude = 10.2257

另外,我有以下信息(来自我的安卓手机):

The compass-direction in degree, which bears to the north. 
For example, when I direct my phone to north, I get 0°

如何创建一个“指南针样式”的箭头,以显示指向点的方向?

这个问题是否有数学问题需要解决?

编辑:好的,我找到了一个解决方案,它看起来像这样:

/**
 * Params: lat1, long1 => Latitude and Longitude of current point
 *         lat2, long2 => Latitude and Longitude of target  point
 *         
 *         headX       => x-Value of built-in phone-compass
 * 
 * Returns the degree of a direction from current point to target point
 *
 */
function getDegrees(lat1, long1, lat2, long2, headX) {
    
    var dLat = toRad(lat2-lat1);
    var dLon = toRad(lon2-lon1);

    lat1 = toRad(lat1);
    lat2 = toRad(lat2);

    var y = Math.sin(dLon) * Math.cos(lat2);
    var x = Math.cos(lat1)*Math.sin(lat2) -
            Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
    var brng = toDeg(Math.atan2(y, x));

    // fix negative degrees
    if(brng<0) {
        brng=360-Math.abs(brng);
    }

    return brng - headX;
}

1
不要发布你自己都不确定的解决方案。 - Tofeeq Ahmad
@Sameer,你对这解决方案有什么问题吗?如果没有其他人发布,我可以给出一个。这只是供参考,如果其他人需要的话。因此被踩了一下,不理解为什么。 - eav
如果您想发布自己问题的解决方案,请将其作为答案发布,而不是编辑问题。回答自己的问题是完全正常的,您可以将其标记为已接受,以引起与其他答案相同的注意(只是不会从中获得任何积分)。如果您以这种方式操作,对于寻找类似问题解决方案的其他用户来说,这样做就更清晰明了。 - Vala
1
函数声明中有 long1 和 long2,但在函数中使用时它们变成了 lon1 和 lon2。 - John Phillips
long2 !== lon2. - digout
显示剩余2条评论
4个回答

19

我忘了说,我最终找到了答案。这个应用程序的作用是确定运输工具和目的地的罗盘方向。基本上,它使用花哨的数学来获取地球曲率,找到角度/罗盘读数,并将该角度与通用罗盘值匹配。当然,你也可以保留罗盘读数并将其应用于图像的旋转量。请注意,这是车辆方向朝着终点站(公交车站)的平均确定,因此它无法知道道路的情况(所以这可能更适用于飞机或轮滑)。

//example obj data containing lat and lng points
//stop location - the radii end point
endpoint.lat = 44.9631;
endpoint.lng = -93.2492;

//bus location from the southeast - the circle center
startpoint.lat = 44.95517;
startpoint.lng = -93.2427;

function vehicleBearing(endpoint, startpoint) {
    endpoint.lat = x1;
    endpoint.lng = y1;
    startpoint.lat = x2;
    startpoint.lng = y2;

    var radians = getAtan2((y1 - y2), (x1 - x2));

    function getAtan2(y, x) {
        return Math.atan2(y, x);
    };

    var compassReading = radians * (180 / Math.PI);

    var coordNames = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"];
    var coordIndex = Math.round(compassReading / 45);
    if (coordIndex < 0) {
        coordIndex = coordIndex + 8
    };

    return coordNames[coordIndex]; // returns the coordinate value
}

例如:车辆定位函数vehicleBearing(mybus, busstation)可能返回“NW”,表示它正在向西北方行驶。


@liquified,抱歉我无法理解为什么要执行(compassReading / 45)。你能告诉我吗?谢谢。 - user2071152
45 是指罗盘的 45 度间隔,对应着罗盘数组中的 9 个坐标名称(人类名称)(如 NSEW 等)。将你的罗盘读数除以 45 可以让你知道在 360 度范围内,你的读数离这些间隔有多近(使用 Math.round)。例如,360 / 45 可以得到 8,这是数组中的第 8 个索引或 "N"。如果你只想要 NSEW,则可以将其除以 90 来进行修改。 - ericjam
@efwjames,“correlating to the 9 coordNames” - 45 * 8 = 360。您的coordNames数组中重复了两次“N”。请将其删除。 - Mandeep Janjua
我投票支持这个答案,并给出我的略微缩短版本(我喜欢数组和更多的风向): const cardinals = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N"]; const carDirect = (x0,y0, x1,y1) => Math.round( Math.atan2((x1-x0),(y1-y0)) * (8 / Math.PI) ); const cardIndex = (dir) => dir<0 ? dir+16 : dir;console.log(cardinals[cardIndex(carDirect( start_lng,start_lat, end_lng,end_lat))]);谢谢。 - allez l'OM

2

我在这里找到了一些有用的数学GPS坐标公式(链接)。 针对这种情况,这是我的解决方案

 private double getDirection(double lat1, double lng1, double lat2, double lng2) {

    double PI = Math.PI;
    double dTeta = Math.log(Math.tan((lat2/2)+(PI/4))/Math.tan((lat1/2)+(PI/4)));
    double dLon = Math.abs(lng1-lng2);
    double teta = Math.atan2(dLon,dTeta);
    double direction = Math.round(Math.toDegrees(teta));
    return direction; //direction in degree

}

0

我无法理解你的解决方案,计算斜率对我有用。 根据efwjames和你的答案进行修改。这应该可以 -

import math
def getDegrees(lat1, lon1, lat2, lon2,head):
    dLat = math.radians(lat2-lat1)
    dLon = math.radians(lon2-lon1)
    bearing = math.degrees(math.atan2(dLon, dLat))
    return head-bearing

-3
你需要计算起点和终点之间的欧几里得向量,然后计算它的角度(相对于正X),这将是你想要旋转箭头的角度。

1
或者你可以变得花哨一些,考虑到地球的曲率。 - StaWho
3
非常好的回答描述,也许可以提供一个真实的例子。 - ericjam
@liquified - 如果您查看帖子,即使在编辑之前,它也没有标记任何语言,并且所提出的问题是:“是否有一个数学问题可以解决这个问题?”除了“math”标签外,也没有提供任何代码,并且在众多解决方法中,OP也没有给出其他指示,比如使用实数三角或复数三角来解决。鉴于问题的模糊参数,我认为答案已经足够了。 - StaWho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接