将米转换为十进制度数

11

我需要将米转换为C#中的十进制度。 我在维基百科上读到1个十进制度等于111.32公里。 但这是在赤道上,所以如果我位于赤道之上/之下,我的转换将会出错吗? 我认为这是错误的:

long sRad = (long.Parse(sRadTBx.Text)) / (111.32*1000); 

编辑:我需要这个搜索半径来查找附近的用户。

    long myLatitude = 100;
    long myLongitude = 100;
    long sRad = /* right formula to convert meters to decimal degrees*/

long begLat = myLatitude - searchRad;
long endLat = myLatitude + searchRad;
long begLong = myLongitude - searchRad;
long endLong = myLongitude + searchRad;

List<User> FoundUsers = new List<User>();

foreach (User user in db.Users)
{
    // Check if the user in the database is within range
    if (user.usrLat >= begLat && user.usrLat <= endLat && user.usrLong >= begLong && user.usrLong <= endLong)
    {
        // Add the user to the FoundUsers list
        FoundUsers.Add(user);
    }
}

从文本框中获取一个浮点数,@Sayse - Peter
1
但你正在使用双精度数值,所以 double.Parse 更合理。 - Sayse
2个回答

16

同样来自那篇维基百科文章:

 As one moves away from the equator towards a pole, however,
 one degree of longitude is multiplied by
 the cosine of the latitude,
 decreasing the distance, approaching zero at the pole.

因此,这将是一个与纬度有关的函数:

double GetSRad(double latitude)
{
    return 111.32 * Math.Cos(latitude * (Math.PI / 180));
}

或类似的。

编辑:所以,要将米转换为十进制度数,您需要执行以下操作:

double MetersToDecimalDegrees(double meters, double latitude)
{
    return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}

是的,这将告诉您一个十进制度数相当于多少公里,作为纬度的函数。 - Christofer Ohlsson

8

Christopher Olsson已经给出了一个好的答案,但是我想补充一些理论。

我一直觉得this webpage对这些公式很有用。

关于概念的简短说明

想象实际发生的几何形态。

现在,你只是在缩放输入。想象一下气球的经典例子。在气球上画出两条在底部和顶部相交的线段。它们代表经度线,因为它们向上和向下。当然要加引号,因为这些概念并不存在,但我们可以想象。现在,如果你看每条线段,就会发现随着你沿着它们的长度向上和向下移动,它们的距离是不同的。根据原始规格,它们在气球的顶部和底部相交,但在其他任何地方都不相交。经线也是如此。非欧几里得几何告诉我们,如果它们相交,则直线恰好相交两次,这可能很难想象。但由于这个原因,我们的线之间的距离在赤道处被有效地反射。

正如您所看到的,纬度极大地影响经线之间的距离。它们在南北极最近,在赤道最远。
纬线要简单一些。它们不会相交。如果您把我们的理论气球竖直地拿起来,将极点指向上下,也就是说,纬线将与地面平行。更一般地说,它们将垂直于经线极点形成的轴(欧几里得概念)。因此,无论您的经度如何,纬度之间的距离都是恒定的。
现在,您的实现依赖于这些线始终保持恒定距离的想法。如果是这样,您就可以采取简单的缩放方法,就像您所做的那样。如果它们实际上是欧几里得意义上的平行线,那么它与从英里每小时转换为公里每小时的概念并没有太大区别。然而,距离的差异使得这变得更加复杂。
北极的经线距离为零,在赤道上,正如你引用的维基百科页面所述,它是111.32公里。因此,要得到真正准确的结果,您必须考虑您所寻找的纬度。这就是为什么会变得更加复杂的原因。
获取实际结果
现在,根据您最近的编辑,您似乎希望融合纬度和经度进行评估的公式。根据您的代码示例,您似乎想要找到两个坐标之间的距离,并且希望它在短距离内运行良好。因此,我建议使用Haversine公式,就像我在本文开头指向的网站建议的那样。该网站提供了很多有关它的良好信息,但这就是公式本身。我直接从该网站复制它,包括符号,以确保我不犯任何愚蠢的打字错误。当然,这是JavaScript,但您可以基本上只更改一些情况,它将在C#中运行。
在其中,φ是纬度,λ是经度,θ是方位(以弧度表示,顺时针从北方),δ是角距离(以弧度表示)d / R; d是行驶距离,R是地球半径。
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.cos1) * Math.cos2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c;

我认为需要注意的唯一一点是,正如第一行声明的那样,R是地球的半径。正如注释所建议的,我们已经在使用公里,因此您可能需要根据您的实现更改它。幸运的是,在线搜索可以轻松地找到您喜欢的单位下(平均)地球半径。
当然,您还需要注意,toRadians只是将输入乘以Math.PI,然后除以180。非常简单。 替代方案 这段内容可能与您的情况不太相关,但我会包含它。上述公式将给出准确的结果,但速度会受到影响。显然,在任何单个记录上都不是什么大问题,但随着您处理的数据越来越多,这可能会成为一个问题。如果确实存在这样的问题,并且您正在处理一个相当集中的地区,您可以利用我们星球的巨大性质,找到适合纬度和经度之间距离的数字,然后将星球视为“更或多或少欧几里得”(即平面),并使用勾股定理计算值。当然,离原始测试站点越远,这种方法就越不准确(我个人只需通过询问Google Earth或类似产品来查找这些数字)。但如果您正在处理一群密集的用户,那将比运行一堆公式到Math类更快得多。 另一种更抽象的替代方案 你可能还需要考虑逻辑处理的位置。在这里,我有点超出了我的能力范围,但是如果你恰好将数据存储在SQL Server中,则它已经内置了一些非常酷的地理功能,可以为你处理距离计算。只需查看GEOGRAPHY类型即可。 编辑 这是对评论的回应,建议所需结果实际上是表示边界的矩形。现在,我建议不要这样做,因为它并不是你的代码可能暗示的搜索“半径”。
但是,如果你确实想坚持使用该方法,你将需要查看两个单独的距离:一个用于纬度,一个用于经度。这也来自那个网页。 φ1myLatitude,而 λ1myLongitude。该公式接受方位和起始坐标,然后给出结果位置。
var φ2 = Math.asin( Math.sin1)*Math.cos(d/R) + Math.cos1)*Math.sin(d/R)*Math.cos(brng) );
var λ2 = λ1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos1), Math.cos(d/R)-Math.sin1)*Math.sin2));

你可以使用它来确定搜索矩形的边界。

我不想找到两个坐标之间的距离,我想将我的搜索半径从米转换为十进制度数,以便在那个很好用的函数中使用。这可行吗? - Peter
这里的φ1是指我搜索的半径,单位是米?那么d、φ1、φ2和brng分别代表什么意思呢?很抱歉,我对几何学不太擅长,这些变量对我来说一无所知。你写的这两行代码是要替换begLat、endLat、endLong和begLong的值吗? - Peter
@Leek 哎呀!抱歉,我忘记包含那些的定义了。我的错。我编辑了我的答案,你可以在第一个代码块上面找到它们的定义。这两行不会替换任何东西,它们将进入另一个接受方位角(即方向,并且它是以弧度表示的,所以你可能需要修复一下)的函数中。然后,您可以在每个方向上找到距离,以找到 begLat 和其他内容。例如,对于顶部,您希望从距离0度 x 米的点获取纬度。西边将是距离270度 x 米。 - Matthew Haugen

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