如何将纬度或经度转换为米?

182

如果我有一个标准NMEA格式的纬度或经度读数,是否有一种简单的方式/公式将该读数转换为米,并且我可以在Java(J9)中实现?

编辑: 好吧,似乎我想做的事情不是很容易,但我真正想做的是:

假设我有一个航点的纬度和经度以及一个用户的纬度和经度,是否有一种简单的方法来比较它们,以决定何时告诉用户他们已经接近航点的合理距离?我知道“合理”是主观的,但这很容易实现还是过于数学化了?


2
你是指 UTM 吗?http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system - Adrian Archer
1
将lat/long转换为米是什么意思?米指的是哪里?您是否正在寻找一种计算从一个坐标到另一个坐标沿着地球表面距离的方法? - Baltimark
2
我偶然发现了这个问题,想要在经纬度上执行SQL查询,并找到了这篇很棒的文章,底部有一些Java代码。它可能也会对你感兴趣。 - Kristof Van Landschoot
1
可能是重复的问题:如何计算两个经纬度点之间的距离? - Teepeemm
1
这里大部分的答案都使用简单的球面三角学,因此与 GPS 系统中使用的 WGS84 椭球距离相比,结果相对粗糙。其中一些答案提到了 Vincenty 的椭球公式,但该算法是为 1960 年代的台式计算器设计的,存在稳定性和精度问题;我们现在有更好的硬件和软件。请参阅 GeographicLib,这是一个高质量的库,具有各种语言的实现。(我不确定 GDAL 在其 WGS84 工作中使用什么,我认为它仍然使用 Vincenty)。 - PM 2Ring
显示剩余4条评论
19个回答

1
要将纬度和经度转换为x和y表示,您需要决定使用哪种地图投影方式。对我来说,椭圆墨卡托投影似乎很好。在这里您可以找到一个实现(也有Java版本)。

1
    'below is from
'http://www.zipcodeworld.com/samples/distance.vbnet.html
Public Function distance(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim theta As Double = lon1 - lon2
    Dim dist As Double = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + _
                            Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * _
                            Math.Cos(deg2rad(theta))
    dist = Math.Acos(dist)
    dist = rad2deg(dist)
    dist = dist * 60 * 1.1515
    If unit = "K" Then
        dist = dist * 1.609344
    ElseIf unit = "N" Then
        dist = dist * 0.8684
    End If
    Return dist
End Function
Public Function Haversine(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim R As Double = 6371 'earth radius in km
    Dim dLat As Double
    Dim dLon As Double
    Dim a As Double
    Dim c As Double
    Dim d As Double
    dLat = deg2rad(lat2 - lat1)
    dLon = deg2rad((lon2 - lon1))
    a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(deg2rad(lat1)) * _
            Math.Cos(deg2rad(lat2)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
    c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a))
    d = R * c
    Select Case unit.ToString.ToUpper
        Case "M"c
            d = d * 0.62137119
        Case "N"c
            d = d * 0.5399568
    End Select
    Return d
End Function
Private Function deg2rad(ByVal deg As Double) As Double
    Return (deg * Math.PI / 180.0)
End Function
Private Function rad2deg(ByVal rad As Double) As Double
    Return rad / Math.PI * 180.0
End Function

我看到链接里面有很多坏掉的。 - tshepang

1

这里是一个 MySQL 函数:

SET @radius_of_earth = 6378.137; -- In kilometers

DROP FUNCTION IF EXISTS Measure;
DELIMITER //
CREATE FUNCTION Measure (lat1 REAL, lon1 REAL, lat2 REAL, lon2 REAL) RETURNS REAL
BEGIN
-- Multiply by 1000 to convert millimeters to meters
RETURN 2 * @radius_of_earth * 1000 * ASIN(SQRT(
    POW(SIN((lat2 - lat1) / 2 * PI() / 180), 2) +
    COS(lat1 * PI() / 180) *
    COS(lat2 * PI() / 180) *
    POW(SIN((lon2 - lon1) / 2 * PI() / 180), 2)
));
END; //
DELIMITER ;

0

这里是用 Swift 的一个版本:

func toDegreeAt(point: CLLocationCoordinate2D) -> CLLocationDegrees {
    let latitude = point.latitude  
    let earthRadiusInMetersAtSeaLevel = 6378137.0
    let earthRadiusInMetersAtPole = 6356752.314
    
    let r1 = earthRadiusInMetersAtSeaLevel
    let r2 = earthRadiusInMetersAtPole
    let beta = latitude

    let earthRadiuseAtGivenLatitude = (
      ( pow(pow(r1, 2) * cos(beta), 2) + pow(pow(r2, 2) * sin(beta), 2) ) /
      ( pow(r1 * cos(beta), 2) + pow(r2 * sin(beta), 2) )
    )
    .squareRoot()
      
    let metersInOneDegree = (2 * Double.pi * earthRadiuseAtGivenLatitude * 1.0) / 360.0
    let value: CLLocationDegrees = self / metersInOneDegree
    return value
  }

0
如果它们足够接近,您可以将它们视为平面坐标。如果不需要完美的准确性,而且您只需要对涉及的距离进行粗略猜测以与任意限制进行比较,那么这在街道或城市级别上是可行的。

3
不行!在不同的纬度下,x距离的单位(m)是不同的。在赤道附近可能可以使用,但越靠近极地,你使用的椭球体就会变得更加极端。 - RickyA
3
虽然您的评论很有道理,但它没有回答用户关于将经纬度差转换为米的问题。 - JivanAmara

0

要直接将两个纬度/经度之间的距离转换为它们之间的x y米,您可以使用维基百科上的地球半径方程。在C语言中,这些方程式如下:

N = a/sqrt(1-e2)*(sin(Lat1)*sin(Lat1))));
latlen = ((1-e2)/(a*a))*N*N*N*(Lat1-Lat2)*PI/180;
lonlen = (N*cos(Lat1))*(Lon1-Lon2)*PI/180;

其中,a是赤道上地球半径,e2是地球离心率的平方。这些方程式可以得到两点之间的半径,而PI/180则可以得到这些半径的周长。


-1

基于地球上每度的平均距离。

1° = 111公里;

将其转换为弧度并除以米数,需要一个魔术数字RAD,单位为米:0.000008998719243599958;

然后:

const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;

3
终于,一个直截了当的答案 :) - Ben Hutchison
如果纬度一个是-179,另一个是179,那么x距离应该是2度而不是358度。 - OMGPOP
7
请勿使用此答案(由于某种原因,它已被点赞)。 经度和距离之间不存在单一的比例关系;地球不是平的。 - CPBL
1
我相信它是111.1。 - Abel Callejo
7
注意,在赤道上,一度经度约为111公里,但在其他纬度下则更少。有一个简单的近似公式可以根据纬度计算每经过一度经度所对应的长度(单位为公里):1度经度 = 40000公里 × cos(纬度) ÷ 360(当然,当纬度为90°时结果为111公里)。此外要注意,一度经度几乎总是与一度纬度对应的距离不同。 - Ben

-1
如果你想要一个简单的解决方案,那么使用其他评论中所述的Haversine公式就可以了。如果你的应用需要高精度,请注意Haversine公式不能保证更好的精度,因为它假设地球是一个球体。考虑到地球是一个扁球体,可以考虑使用Vincenty公式。 此外,我不确定在Haversine公式中应该使用什么半径:{赤道: 6,378.137 公里,极地: 6,356.752 公里,容积: 6,371.0088 公里}。

1
它假设地球是一个圆形。现在有些奇怪的人这样做...但你的意思可能更准确地是“它假设地球是一个球体” ;) - derHugo

-2
你需要将坐标转换为弧度来进行球面几何运算。一旦转换完成,你就可以计算两点之间的距离。然后可以将距离转换为任何你想要的单位。

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