地理空间坐标和以公里为单位的距离 [英] Geospatial coordinates and distance in kilometers

查看:202
本文介绍了地理空间坐标和以公里为单位的距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是此问题的后续行动。



我似乎被卡住了。基本上,我需要能够来回转换为参考标准度数系统中的坐标,或者通过测量沿国际日期线的南极距离北部的距离,然后测量从该日期的该点开始的东部距离线。要做到这一点(以及一些更通用的距离测量的东西),我有一种方法来确定两个经纬度点之间的距离,另一种方法需要一个经纬度点,一个航向和一个距离,并返回

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

  / *取两个长/双对,并以千米为单位返回它们之间的距离。 
* /
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需要一对经纬度,一个航向(从北向顺时针以度数表示)和一个距离(以公里为单位),并返回
* lat / lon对将从给定点通过沿该方向行进的距离达到。
* /
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;
返回endPoint;
}

以下是我用来测试它的函数:

  public static void main(String args [])throws java.io.IOException,java.io.FileNotFoundException {
double distNorth =距离(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;
}

end at值应该是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是海里英里的法定里程数(谢谢DanM)。一海里是赤道纬度一分钟的长度。

我假设你使用的是球形地球模型,而不是球形地球?代数不够复杂,无法形成球体。

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

 (60°N,30°W),(60°N,60°W )
(60°N,60°W),(60°N,90°W)

应该是相同的 - 但我确定你的代码产生了不同的答案。

所以,我认为你需要回到你的球形三角参考材料并看看你做错了什么。 (这需要我花一些时间才能找到关于这个主题的书 - 它需要从任何一个盒子里解开。)



[ .. .time传递...解包完成... ]



给定一个角度为 A 的球形三角形, B C 在顶点和边上 a b c a 是从 B C 等等),余弦公式是:

  cos a = cos b。 cos c + sin b。罪c。 cos A 

应用这个问题,我们可以调用给定的两个点 B C ,然后我们在 A 创建一个直角三角形的正方形三角形。

ASCII艺术在最坏的情况下:

  + C 
/ |
/ |
a / | b
/ |
/ |
/ |
B + ------ + A
c

em> c 等于经度的差异;边 b 等于纬度的差异;角度 A 是90°,所以cos A = 0.因此,我相信 a 的等式是:

  cos a = cosΔλ。 cosΔφ+sinΔλ。 sinΔφ。 cos 90°

a = arccos(cosΔλ。cosΔφ)

然后通过乘以地球半径将弧度中的角度 a 转换为距离。或者,给定以度(度)为单位的 a ,那么有60海里到一度,因此60 * 1.1515法定英里,60 * 1.1515 * 1.609344公里到一度。除非你想要以米为单位的距离,否则我不认为有1000的因素是必要的。

Paul Tomblin指向 Aviation Formulary v1.44 作为等式的来源 - 事实上,它在那里,以及一个更稳定的数字版本

基本的三角函数,我们也知道:

 

cos(A - B)= cos A。 cos B + sin A。罪行B

在我给出的等式中应用两次可能会最终导致航空公式中的公式。



(我的参考资料:Astronomy :Principles and Practice,Fourth Edition由AE Roy和D Clarke(2003)提供;我的副本是1977年的第一版,Adam Hilger,ISBN 0-85274-346-7。)






NB 结账(Google)'定义:海里根据定义,现在看来海里现在是1852米(1.852公里)。乘数1.1515对应于海里的旧定义,大约为6080英尺。使用 bc ,比例为10,我得到:

 (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,长度(角度) 和角度 = 90 °。你所追求的是 b (纬度的增量)和 c (经度的增量)。所以,我们有:

  sin a sin b 
----- = ----
sin a sin b



  sin a。罪B 
罪b = -------------
罪A


因为A = 90°,sin A = 1,sin B = sin(90° - X)= cos X:

  sin b = sin a。 cos X 

这意味着您将行进的距离转换为角度 a ,取其正弦值,乘以路线方向的余弦值,并取结果的反正弦值。

给定 a > b (只是计算)和 A B ,我们可以应用余弦公式来获取 c 。请注意,我们不能简单地重新应用正弦公式来获取 c ,因为我们没有 C 的值,并且因为我们在玩球面三角函数,所以不是一个方便的规则,C = 90° - B(球面三角形的角度之和可以大于180°;考虑一个等角球面三角形,所有角度都等于90°,​​这是完全可行的)。 >



This is a followup to this question.

I seem to be stuck on this. Basically, I need to be able to convert back and forth to referring to coordinates either in the standard degree system OR by measuring a distance north from the south pole along the international date line, and then a distance east starting from that point on the date line. To do this (as well as some more general distance-measuring stuff), I have one method for determining the distance between two lat/lon points, and another method that takes a lat/lon point, a heading and a distance, and returns the lat/lon point at the end of that course.

Here are the two static methods I've defined:

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

And here's the function I'm using to test it:

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

The "end at" values should be appx. 72.0 / 31.5. But instead I'm getting approximately 1.25 / 0.021.

I assume I must be missing something stupid, forgetting to convert units somewhere, or something... Any help would be greatly appreciated!

UPDATE 1:

I had (correctly) written the distance function to return meters, but wrote kilometers in the comments by mistake ... which of course confused me when I came back to it today. Anyway, now that's fixed, and I've fixed the factoring error in the endOfCourse method, and I also realized I'd forgotten to convert back to degrees from radians in that method too. Anyway: while it appears I'm now getting the correct latitude number (71.99...), the longitude number is way off (I get 3.54 instead of 11.5).

UPDATE 2: I had a typo in the test, as mentioned below. It's now fixed in the code. The longitude number is still, however, wrong: I'm now getting -11.34 instead of 11.5. I think there must be something wrong with these lines:

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;

解决方案

You've got a serious case of the magic numbers in the code. The expression:

 (60 * 1.1515 * 1.609344 * 1000)

appears twice, but there's not much explanation of it. With some help: 1.609344 is the number of kilometres in a mile; 60 is the number of minutes in a degree; 1000 is the number of metres in a kilometre; and 1.1515 is the number of statute miles in a nautical mile (thanks, DanM). One nautical mile is the length of one minute of latitude at the equator.

I assume you are using a spherical earth model, rather than a spheroidal earth? The algebra isn't complex enough to be spheroidal.

The first formula - conversion between two latitude and longitude pairs - is odd. You need both delta-lat (Δλ) and delta-lon (Δφ) to sort out the answer. Further, the distance between the pairs:

(60° N, 30° W), (60° N, 60° W)
(60° N, 60° W), (60° N, 90° W)

should be the same - but I'm pretty sure your code produces different answers.

So, I think you need to go back to your spherical trigonometry reference materials and see what you're doing wrong. (It would take me a while to find my book on the subject - it would need to be unpacked from whichever box it is in.)

[...time passes...unpacking done...]

Given a spherical triangle with angles A, B, C at the vertices and sides a, b, c opposite those vertices (that is, side a is from B to C, etc.), the Cosine Formula is:

cos a = cos b . cos c + sin b . sin c . cos A

Applying this to the problem, we can call the two points given B and C, and we create a right spherical triangle with a right angle at A.

ASCII art at its worst:

                  + C
                 /|
                / |
            a  /  | b
              /   |
             /    |
            /     |
         B +------+ A
              c

The side c is equal to the difference in longitude; the side b is equal to the difference in latitude; the angle A is 90°, so cos A = 0. Therefore, I believe an equation for a is:

cos a = cos Δλ . cos Δφ + sin Δλ . sin Δφ . cos 90°

a = arccos (cos Δλ . cos Δφ)

The angle a in radians is then converted to a distance by multiplying by the radius of the Earth. Alternatively, given a in degrees (and fractions of a degree), then there are 60 nautical miles to one degree, hence 60 * 1.1515 statute miles, and 60 * 1.1515 * 1.609344 kilometres to one degree. Unless you want the distance in metres, I don't see a need for the factor of 1000.

Paul Tomblin points to Aviation Formulary v1.44 as a source of the equation - and indeed, it is there, together with a more numerically stable version for when the difference in position is small.

Going to basic trigonometry, we also know that:

cos (A - B) = cos A . cos B + sin A . sin B

Applying that twice in the equation I gave might well end up at the formula in the Aviation Formulary.

(My reference: "Astronomy: Principles and Practice, Fourth Edition" by A E Roy and D Clarke (2003); my copy is the first edition from 1977, Adam Hilger, ISBN 0-85274-346-7.)


NB Check out (Google) 'define:"nautical mile"'; it appears that a nautical mile is now 1852 m (1.852 km) by definition. The multiplier 1.1515 corresponds to the old definition of the nautical mile as approximately 6080 ft. Using bc with a scale of 10, I get:

(1852/(3*0.3048))/1760
1.1507794480

Which factor works for you depends on what your basis is.


Looking at the second problem from first principles, we have a slightly different setup, and we need the 'other' spherical trigonometry equation, the Sine Formula:

sin A   sin B   sin C
----- = ----- = -----
sin a   sin b   sin c

Adapting the previous diagram:

                  + C
                 /|
                / |
            a  /  | b
           |  /   |
           |X/    |
           |/     |
         B +------+ A
              c

You are given starting point B, angle X = 90º - B, length (angle) a, and angle A = 90°. What you are after is b (the delta in latitude) and c (the delta in longitude).

So, we have:

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

Or

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

Or, since A = 90°, sin A = 1, and sin B = sin (90° - X) = cos X:

sin b = sin a . cos X

That means you convert the distance travelled into an angle a, take the sine of that, multiply by the cosine of the course direction, and take the arcsine of the result.

Given a, b (just calculated) and A and B, we can apply the cosine formula to get c. Note that we cannot simply re-apply the sine formula to get c since we don't have the value of C and, because we're playing with spherical trigonometry, there is no convenient rule that C = 90° - B (the sum of the angles in a spherical triangle can be greater than 180°; consider an equilateral spherical triangle with all angles equal to 90°, which is perfectly feasible).


这篇关于地理空间坐标和以公里为单位的距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆