将米转换为十进制度

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

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 FoundUsers = new List(); foreach (User user in db.Users) { // Check if the user in the database is within range if (user.usrLat >= begLat && user.usrLat = begLong && user.usrLong <= endLong) { // Add the user to the FoundUsers list FoundUsers.Add(user); } } 

克里斯托弗奥尔森已经有了一个很好的答案,但我想我也会填写一些理论。

我总是发现这个网页对这些公式很有用。

关于这个概念的快速说明

想想实际的几何形状。

就目前而言,您目前只做缩放输入。 想象一下气球的典型例子。 在气球上画两条线,在底部和顶部相遇。 这些代表经度线,因为它们“上下”。 行情,当然,因为没有真正的这样的概念,但我们可以想象。 现在,如果你看一下每一条线,你就会发现它们的距离随着你的长度而变化。 根据原始规格,它们在气球顶部和底部相遇,但它们在其他任何地方都不相符。 经度线也是如此。 非欧几里德几何学告诉我们,如果它们完全相交,则线条相交两次,这很难概念化。 但正因为如此,我们的线之间的距离有效地反映在赤道上。

如您所见,纬度会极大地影响纵向线之间的距离。 它们从北极和南极最近,到赤道最远。

纬度线更容易一些。 他们没有收敛。 如果你把我们的理论气球直接上下移动,两极直指向上并且直线向下,即纬线与地面平行。 在更广义的意义上,它们将垂直于由纵向线的极点构成的轴(欧几里德概念)。 因此,无论经度如何,纬度之间的距离都是恒定的。

你的实施

现在,您的实现依赖于这些线始终处于恒定距离的想法。 如果是这种情况,您可以采用简单的缩放方法,就像您一样。 事实上,如果它们在欧几里德意义上是平行的,那么它与从每小时英里数转换为每小时公里数的概念并没有太大不同。 然而,距离的变化使得这变得更加复杂。

北极经度之间的距离为零,而在赤道,正如您所引用的维基百科页面所述,它是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.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; 

我认为这里唯一需要注意的是,如第一行所说, R是地球的半径。 正如评论所暗示的那样,我们已经在公里工作,因此您可能需要或不必为实施改变它。 幸运的是,通过在线搜索找到您最喜欢的单位中的(平均)半径是很容易的。

当然,您还需要注意, toRadians只是输入乘以Math.PI ,然后除以180.足够简单。

替代

这与您的案例看起来并不相关,但我会将其包括在内。 上述公式将给出准确的结果,但这将以速度为代价。 显然,对于任何一个单独的记录来说这都是一个非常小的交易,但随着你积累的处理越来越多,这可能成为一个问题。 如果确实如此,并且如果你处理的是一个相当集中的地区,那么你可以解决我们这个星球的巨大性质并找到适合一个纬度和经度之间距离的数字,然后将这个星球视为“或多或少”欧几里得“(平,即),并使用毕达哥拉斯定理来计算价值。 当然,您从原始测试站点获得的距离越来越准确(我只是通过询问Google Earth或类似产品来找到这些数字)。 但是如果你正在处理一个密集的用户群,这将比在Math类中运行一系列公式更快,更方便。

另一个更抽象的选择

您可能还想考虑您在做这个逻辑的位置。 在这里,我开始略微超越我的范围,但如果你碰巧将数据存储在SQL Server中,它已经内置了一些非常酷的地理function,可以为你处理距离计算。 只需查看GEOGRAPHY类型。

编辑

这是对评论的回应,表明期望的结果实际上是表示边界的矩形。 现在,我建议不要这样做,因为它不是你的代码所暗示的搜索“半径”。

但是如果你想坚持这种方法,你会看到两个不同的距离:一个用于纬度,一个用于经度。 这也来自该网页。 φ1myLatitudeλ1myLongitude 。 该公式接受轴承和起始坐标,然后给出结果位置。

 var φ2 = Math.asin( Math.sin(φ1)*Math.cos(d/R) + Math.cos(φ1)*Math.sin(d/R)*Math.cos(brng) ); var λ2 = λ1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(φ1), Math.cos(d/R)-Math.sin(φ1)*Math.sin(φ2)); 

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

同样来自维基百科的文章:

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