Geolocation 地理空间坐标和距离(公里)

Geolocation 地理空间坐标和距离(公里),geolocation,geospatial,distance,geography,Geolocation,Geospatial,Distance,Geography,这是一个后续行动 我似乎被这件事缠住了。基本上,我需要能够来回转换参考标准度系统中的坐标,或者通过测量沿国际日期线从南极向北的距离,然后从日期线上的该点向东的距离。为了做到这一点(以及一些更通用的距离测量工具),我有一种方法来确定两个lat/lon点之间的距离,另一种方法是获取一个lat/lon点、一个航向和一个距离,并在课程结束时返回lat/lon点 以下是我定义的两个静态方法: /* Takes two lon/lat pairs and returns the distance betwe

这是一个后续行动

我似乎被这件事缠住了。基本上,我需要能够来回转换参考标准度系统中的坐标,或者通过测量沿国际日期线从南极向北的距离,然后从日期线上的该点向东的距离。为了做到这一点(以及一些更通用的距离测量工具),我有一种方法来确定两个lat/lon点之间的距离,另一种方法是获取一个lat/lon点、一个航向和一个距离,并在课程结束时返回lat/lon点

以下是我定义的两个静态方法:

/* Takes two lon/lat pairs and returns the distance between them in kilometers.
*/
public static double distance (double lat1, double lon1, double lat2, double lon2) {
    double theta = toRadians(lon1-lon2);
    lat1 = toRadians(lat1);
    lon1 = toRadians(lon1);
    lat2 = toRadians(lat2);
    lon2 = toRadians(lon2);

    double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta);
    dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;

    return dist;
}

/* endOfCourse takes a lat/lon pair, a heading (in degrees clockwise from north), and a distance (in kilometers), and returns
 * the lat/lon pair that would be reached by traveling that distance in that direction from the given point.
 */
public static double[] endOfCourse (double lat1, double lon1, double tc, double dist) {
    double pi = Math.PI;
    lat1 = toRadians(lat1);
    lon1 = toRadians(lon1);
    tc = toRadians(tc);
    double dist_radians = toRadians(dist / (60 * 1.1515 * 1.609344 * 1000));
    double lat = asin(sin(lat1) * cos(dist_radians) + cos(lat1) * sin(dist_radians) * cos(tc));
    double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
    double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
    double[] endPoint = new double[2];
    endPoint[0] = lat; endPoint[1] = lon;
    return endPoint;
}
下面是我用来测试它的函数:

public static void main(String args[]) throws java.io.IOException, java.io.FileNotFoundException {
    double distNorth = distance(0.0, 0.0, 72.0, 0.0);
    double distEast = distance(72.0, 0.0, 72.0, 31.5);
    double lat1 = endOfCourse(0.0, 0.0, 0.0, distNorth)[0];
    double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
    System.out.println("end at: " + lat1 + " / " + lon1);
    return;
}
“结束于”值应为appx。72.0 / 31.5. 但是我得到的是大约1.25/0.021

我想我一定是错过了什么愚蠢的事情,忘了在什么地方转换单位,或者什么。。。任何帮助都将不胜感激

更新1:

我(正确地)编写了返回米的距离函数,但在注释中错误地写了公里。。。当我今天回到这里时,我当然很困惑。不管怎样,现在这已经解决了,我已经解决了endOfCourse方法中的因式分解错误,我还意识到我也忘记了在该方法中从弧度转换回度。无论如何:虽然看起来我现在得到了正确的纬度值(71.99…),但经度值却相差很远(我得到的是3.54,而不是11.5)

更新2: 我在测试中有一个打字错误,如下所述。它现在已在代码中修复。然而,经度数字仍然是错误的:我现在得到的是-11.34,而不是11.5。我想这些台词一定有问题:

double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
double lon = ((lon1-dlon + pi) % (2*pi)) - pi;

你的密码里有一个很严重的幻数。表达方式:

 (60 * 1.1515 * 1.609344 * 1000)
出现两次,但没有太多的解释。借助一些帮助:1.609344是一英里中的公里数;60是度中的分钟数;1000是一公里中的米数;1.1515是一海里的法定英里数(谢谢,丹)。一海里是赤道纬度一分钟的长度

我假设您使用的是球形地球模型,而不是球形地球?代数不够复杂,不可能是球状的

第一个公式——两个纬度和经度对之间的转换——是奇数。您需要delta lat(Δλ)和delta lon(Δφ)来整理答案。此外,对之间的距离:

(60° N, 30° W), (60° N, 60° W)
(60° N, 60° W), (60° N, 90° W)
应该是相同的-但是我很确定你的代码会产生不同的答案

所以,我认为你们需要回到你们的球面三角参考材料,看看你们做错了什么。(我需要一段时间才能找到关于这一主题的书——无论它在哪个盒子里,都需要把它打开。)

[…时间流逝…解包完成…]

给定一个球面三角形,其顶点处有角度a、B、C,与这些顶点相对的边a、B、C(即,边a从B到C等),余弦公式为:

cos a = cos b . cos c + sin b . sin c . cos A
把这个应用到这个问题上,我们可以调用给定的两点B和C,我们创建一个直角球面三角形,在a处有一个直角

最糟糕的ASCII艺术:

                  + C
                 /|
                / |
            a  /  | b
              /   |
             /    |
            /     |
         B +------+ A
              c
c面等于经度差;b边等于纬度差;角度A为90°,因此cos A=0。因此,我认为a的方程式是:

然后,以弧度为单位的角度a乘以地球半径转换为距离。或者,如果以度为单位(以及度的分数),则一度有60海里,因此一度有60*1.1515法定英里,一度有60*1.1515*1.609344公里。除非你想要以米为单位的距离,否则我认为不需要1000的系数

保罗·汤姆布林(Paul Tomblin)指出,这是方程的一个来源——事实上,它就在那里,并且在位置差异很小的情况下,还有一个数值上更稳定的版本

关于基本三角,我们也知道:

cos (A - B) = cos A . cos B + sin A . sin B
在我给出的方程式中应用两次,很可能最终得到航空公式集中的公式

(我的参考:作者:E Roy和D Clarke(2003);我的副本是1977年的第一版,Adam Hilger,ISBN 0-85274-346-7。)


NB查看(谷歌)“定义:“海里”;根据定义,一海里现在似乎是1852米(1.852公里)。乘数1.1515对应于航海英里的旧定义,即约6080英尺。使用比例尺为10的
bc
,我得到:

(1852/(3*0.3048))/1760
1.1507794480
哪个因素对你有效取决于你的基础是什么


从第一原理来看第二个问题,我们有一个稍微不同的设置,我们需要“其他”球面三角方程,正弦公式:

sin A   sin B   sin C
----- = ----- = -----
sin a   sin b   sin c
调整前一个图表:

                  + C
                 /|
                / |
            a  /  | b
           |  /   |
           |X/    |
           |/     |
         B +------+ A
              c
给定起点B,角度X=90º-B,长度(角度)a,角度a=90°。你要找的是b(纬度的增量)和c(经度的增量)

因此,我们有:

sin a   sin b
----- = ----
sin A   sin B

或者,由于A=90°,sina=1,sinb=sin(90°-X)=cos X:

这意味着您将行驶的距离转换为角度a,取其正弦,乘以航向的余弦,然后取结果的反正弦

给定a,b(刚刚计算)和a,b,我们可以应用余弦公式得到c。请注意,我们不能简单地重新应用正弦公式得到c,因为我们没有c的值,而且,因为我们在玩球面三角,所以没有方便的规则c=90°-B(球面三角形中的角度之和可以大于180°;考虑等角球面三角形,所有角度等于90°,这是完全可行的)。


退房

该网站有许多不同的公式和Javascript代码,可以
sin a   sin b
----- = ----
sin A   sin B
        sin a . sin B
sin b = -------------
            sin A
sin b = sin a . cos X
var R = 6371; // km
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c; 
   nm = km /  (1.1515 * 1.609344);
   deg = nm / 60;
   rad = toRadians(deg);
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[0];
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];