【问题标题】:How to convert latitude or longitude to meters?如何将纬度或经度转换为米?
【发布时间】:2010-10-12 23:40:52
【问题描述】:

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

编辑: 好吧,看来我想做的事情是不可能的很容易,但我真正想做的是:

假设我有一个纬度和经度的路点和一个用户的经度和经度是否有一种简单的方法来比较它们以决定何时告诉用户他们在一个合理范围内路点的距离?我意识到合理是主题,但这很容易做到还是仍然过于数学化?

【问题讨论】:

  • 你是指UTM吗? en.wikipedia.org/wiki/…
  • 将纬度/经度转换为米是什么意思?米从哪里?您是否正在寻找一种方法来计算沿地球表面从一个坐标到另一个坐标的距离?
  • 定义“航路点”。定义“合理”。这真的是你想知道的吗:“给定经纬度,你如何计算两点之间的距离?”
  • 我偶然发现了这个问题,想对经纬度进行 SQL 查询,发现this great article 底部有一些 Java 代码。你可能也会感兴趣。

标签: math geolocation geo


【解决方案1】:

这是一个javascript函数:

function measure(lat1, lon1, lat2, lon2){  // generally used geo measurement function
    var R = 6378.137; // Radius of earth in KM
    var dLat = lat2 * Math.PI / 180 - lat1 * Math.PI / 180;
    var dLon = lon2 * Math.PI / 180 - lon1 * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d * 1000; // meters
}

解释:https://en.wikipedia.org/wiki/Haversine_formula

harsine 公式根据它们的经度和纬度确定球体上两点之间的大圆距离。

【讨论】:

  • 对于那些正在寻找在 wgs 和 utm 之间转换的库的人:github.com/urbanetic/utm-converter
  • 如果有人可以在上面的代码中添加一些解释性的 cmets,将不胜感激。提前致谢!
  • 找到了this,这条评论似乎是采用的。该链接还表示其基于this article 的距离计算。因此,任何未回答的问题都应在原始链接中找到。 :)
  • 如何将海拔添加到此计算中?
  • @dangalg,假设地板是平面的距离较短,您还有高度alt1alt2dm 是以米为单位的距离(上面measure 函数的结果)。可以使用JSMath.hypot(x, y)的hypothenuse函数,其中xdmymax(alt1, alt2) - min(alt1, alt2)
【解决方案2】:

假设您正在寻找一个简单的公式,这可能是最简单的方法,假设地球是一个周长为 40075 公里的球体。

纬度 1° 的长度以米为单位 = 始终为 111.32 公里

1°经度的米长度 = 40075 km * cos( latitude ) / 360

【讨论】:

  • 经度方程是如何工作的?纬度为 90 度,您预计它会显示在 111 公里附近;但它显示为 0;同样,接近它的值也接近 0。
  • 纬度在赤道为 0°,在极地为 90°(而不是相反)。对于赤道,公式给出 40075 公里 * cos(0°) / 360 = 111 公里。对于极点,公式给出 40075 * cos(90°) / 360 = 0 公里。
  • 我认为这种方法很简单,特别是因为问题没有询问两点之间的确切距离,而是询问它们是否“足够接近”。通过这些公式,我们可以轻松检查用户是否位于以航路点为中心的正方形内。检查正方形比检查圆形要简单得多。
【解决方案3】:

为了逼近两个坐标之间的短距离,我使用了以下公式 http://en.wikipedia.org/wiki/Lat-lon:

m_per_deg_lat = 111132.954 - 559.822 * cos( 2 * latMid ) + 1.175 * cos( 4 * latMid);
m_per_deg_lon = 111132.954 * cos ( latMid );

.

在下面的代码中,我留下了原始数字以显示它们与维基百科公式的关系。

double latMid, m_per_deg_lat, m_per_deg_lon, deltaLat, deltaLon,dist_m;

latMid = (Lat1+Lat2 )/2.0;  // or just use Lat1 for slightly less accurate estimate


m_per_deg_lat = 111132.954 - 559.822 * cos( 2.0 * latMid ) + 1.175 * cos( 4.0 * latMid);
m_per_deg_lon = (3.14159265359/180 ) * 6367449 * cos ( latMid );

deltaLat = fabs(Lat1 - Lat2);
deltaLon = fabs(Lon1 - Lon2);

dist_m = sqrt (  pow( deltaLat * m_per_deg_lat,2) + pow( deltaLon * m_per_deg_lon , 2) );

维基百科条目指出,距离计算在 0.6 米(纵向 100 公里)和 1 厘米(100 公里纬线)范围内,但我没有验证这一点,因为接近该精度的任何地方都适合我使用。

【讨论】:

  • 请注意,在 2017 年,维基百科页面有另一个(似乎精炼的)公式。
  • 是的,Wikipedia 中的公式略有不同,但似乎other Wikipedia 公式是基于此great SO answer 的类似结果,其中有人实际进行了计算。
  • 请记住,在这个等式中,“latMid”是弧度,而“m_per_deg_lat”是度数。因此,如果您想计算纬度为 30N(例如)的值,请使用等式 latMid = pi*30/180
  • 我认为你有一个错字:m_per_deg_lon 因为输入可能需要是经度而不是纬度。
【解决方案4】:

这里是b-h-'s function的R版本,以防万一:

measure <- function(lon1,lat1,lon2,lat2) {
    R <- 6378.137                                # radius of earth in Km
    dLat <- (lat2-lat1)*pi/180
    dLon <- (lon2-lon1)*pi/180
    a <- sin((dLat/2))^2 + cos(lat1*pi/180)*cos(lat2*pi/180)*(sin(dLon/2))^2
    c <- 2 * atan2(sqrt(a), sqrt(1-a))
    d <- R * c
    return (d * 1000)                            # distance in meters
}

【讨论】:

    【解决方案5】:

    有许多工具可以让这一切变得简单。有关所涉及内容的更多详细信息,请参阅monjardin's answer

    但是,这样做并不一定很困难。听起来您正在使用 Java,所以我建议您查看 GDAL 之类的内容。它为其例程提供了 java 包装器,并且它们具有从 Lat/Lon(地理坐标)转换为 UTM(投影坐标系)或其他一些合理的地图投影所需的所有工具。

    UTM 很好,因为它是米,很容易使用。但是,您需要获得适当的 UTM zone 才能让它做好。有一些简单的代码可通过谷歌搜索找到适合经度/经度对的区域。

    【讨论】:

      【解决方案6】:

      地球是一个令人讨厌的不规则表面,因此没有简单的公式可以准确地做到这一点。您必须使用地球的近似模型,并将您的坐标投影到它上面。我通常看到的用于此的模型是WGS 84。这就是 GPS 设备通常用来解决完全相同的问题的方法。

      NOAA 有一些您可以下载的软件来帮助解决这个问题on their website

      【讨论】:

        【解决方案7】:

        一海里(1852 米)定义为赤道经度arcminute。但是,您需要定义一个 map projection(另请参阅 UTM),以便让转换真正有意义。

        【讨论】:

        • 不,国际标准 (v en.wikipedia.org/wiki/Nautical_mile) 将海里定义为 1852m。它与地球等椭球体表面上的弧线测量的关系现在既是历史的又是近似的。
        【解决方案8】:

        有很多方法可以计算这个。它们都使用球面三角的近似值,其中半径是地球之一。

        尝试http://www.movable-type.co.uk/scripts/latlong.html 了解一些不同语言的方法和代码。

        【讨论】:

          【解决方案9】:
              '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
          

          【讨论】:

          • 我看到链接全断了。
          【解决方案10】:

          要在 x 和 y 表示中转换纬度和经度,您需要决定使用哪种类型的地图投影。至于我,椭圆墨卡托似乎很好。 Here 你可以找到一个实现(Java 也是)。

          【讨论】:

            【解决方案11】:

            这是一个 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 ;
            

            【讨论】:

              【解决方案12】:

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

              【讨论】:

              • 不,这行不通!对于不同的纬度值,以 m 为单位的 x 距离是不同的。在赤道,你可能会侥幸逃脱,但你越靠近两极,你的椭球就会变得越极端。
              • 虽然您的评论是合理的,但它并没有回答用户关于将纬度/经度差异转换为米的问题。
              【解决方案13】:

              这是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
                }
              

              【讨论】:

                【解决方案14】:

                基于地球的平均退步距离。

                1° = 111 公里;

                将其转换为弧度并除以米,这是 RAD 的一个幻数,以米为单位:0.000008998719243599958;

                然后:

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

                【讨论】:

                • 最后,一个直截了当的答案:)
                • 如果纬度是-179,另一个是179,x距离应该是2度而不是358
                • 不要使用这个答案(出于某种原因,它被赞成)。经度和距离之间没有单一的比例;地球不是平的。
                • 我相信是111.1
                • 请注意,赤道的经度为 111 公里,而其他纬度则更少。有一个简单的近似公式可以在纬度的函数中找到以公里为单位的 1° 经度的长度:经度 1° = 40000 公里 * cos(纬度)/ 360(当然,纬度 = 90° 为 111 公里)。另请注意,经度 1° 与纬度 1° 的距离几乎总是不同的。
                【解决方案15】:

                如果您想要一个简单的解决方案,请使用其他 cmets 概述的 Haversine formula。如果您有一个对精度敏感的应用程序,请记住,Haversine 公式不能保证精度优于 0.5%,因为它假设地球是一个球体。要考虑地球是一个扁球体,请考虑使用Vincenty's formulae。 此外,我不确定我们应该使用Haversine公式使用什么半径:{Equator: 6,378.137 km, Polar: 6,356.752 km, Volumetric: 6,371.0088 km}。

                【讨论】:

                • it is assuming the earth is a circle ^^ 现在有些奇怪的人会这样做......但你的意思可能是it is assuming the earth is a sphere ;)
                【解决方案16】:

                您需要将坐标转换为弧度来进行球面几何。转换后,您可以计算两点之间的距离。然后可以将距离转换为您想要的任何度量。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-02-21
                  • 2012-01-14
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多