【问题标题】:Distance between 2 geocodes2个地理编码之间的距离
【发布时间】:2010-11-09 18:44:49
【问题描述】:

计算两个地理编码之间距离的公式是什么?我在这个网站上看到了一些答案,但他们基本上说要依赖 SQL Server 08 功能,我还没有使用 08。任何帮助将不胜感激。

【问题讨论】:

    标签: map geocoding


    【解决方案1】:

    如果您使用的是 sql server,这里有一个方法。

    CREATE function dist (@Lat1 varchar(50), @Lng1 varchar(50),@Lat2 varchar(50), @Lng2 varchar(50)) 
    returns float 
    as
    begin
    
    declare @p1 geography
    declare @p2 geography
    
    set @p1 = geography::STGeomFromText('POINT('+ @Lng1+' '+ @Lat1 +')', 4326)
    set @p2 = geography::STGeomFromText('POINT('+ @Lng2+' '+ @Lat2 +')', 4326)
    
    return @p1.STDistance(@p2)
    end
    

    【讨论】:

      【解决方案2】:

      如果

      • 你知道这 2 个点 “相距不远”
      • 并且您可以容忍“相当小的”错误。

      然后,假设地球在两点之间是平的:

      • 纬度方向的距离差为EarthRadius * latitude difference
      • 经度方向的距离差为EarthRadius * longitude difference * cos(latitude)。 我们乘以cos(lat),因为如果纬度发生变化,经度度数不会产生相同的公里距离。由于 P1 和 P2 接近,因此 cos(latP1) 与 cos(latP2) 接近
      • 然后是毕达哥拉斯

      在 JavaScript 中:

      function ClosePointsDistance(latP1, lngP1, latP2, lngP2) {
          var d2r = Math.PI / 180,
          R=6371; // Earth Radius in km
          latP1 *= d2r; lngP1 *= d2r; latP2 *= d2r; lngP2 *= d2r; // convert to radians
          dlat = latP2 - latP1,
          dlng = (lngP2 - lngP1) * Math.cos(latP1);
          return R * Math.sqrt( dlat*dlat + dlng*dlng );
      }
      

      我在巴黎和奥尔良(法国)之间进行了测试:公式找到了 110.9 公里,而(精确的)Haversine 公式找到了 111.0 公里。

      !!!注意 0 子午线附近的情况(你可以移动它):如果 P1 在 Lng 359,P2 在 Lng 0,函数会认为它们异常远!!!

      【讨论】:

        【解决方案3】:

        这将在 c# 中为您完成。

        在命名空间中放置这些:

         public enum DistanceType { Miles, Kilometers };
        
        public struct Position
        {
            public double Latitude;
            public double Longitude;
        }
        
        class Haversine
        {
        
            public double Distance(Position pos1, Position pos2, DistanceType type)
            {
                double preDlat = pos2.Latitude - pos1.Latitude;
                double preDlon = pos2.Longitude - pos1.Longitude;
                double R = (type == DistanceType.Miles) ? 3960 : 6371;
                double dLat = this.toRadian(preDlat);
                double dLon = this.toRadian(preDlon);
                double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                Math.Cos(this.toRadian(pos1.Latitude)) * Math.Cos(this.toRadian(pos2.Latitude)) *
                Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
                double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)));
                double d = R * c;
                return d;
            }
        
            private double toRadian(double val)
            {
                return (Math.PI / 180) * val;
            }
        

        然后在主代码中使用这些:

        Position pos1 = new Position();
                            pos1.Latitude = Convert.ToDouble(hotelx.latitude);
                            pos1.Longitude = Convert.ToDouble(hotelx.longitude);
                            Position pos2 = new Position();
                            pos2.Latitude = Convert.ToDouble(lat);
                            pos2.Longitude = Convert.ToDouble(lng);
                            Haversine calc = new Haversine();
        
                            double result = calc.Distance(pos1, pos2, DistanceType.Miles);
        

        【讨论】:

          【解决方案4】:

          这里其他人提供的勾股定理不太适用。

          最好、最简单的答案是将地球近似为一个球体(它实际上是一个稍微扁平的球体,但这非常接近)。例如,在 Haskell 中,您可能会使用以下代码,但数学几乎可以转换为任何内容:

          distRadians (lat1,lon1) (lat2,lon2) = 
              radius_of_earth * 
              acos (cos lat1 * cos lon1 * cos lat2 * cos lon2 + 
                    cos lat1 * sin lon1 * cos lat2 * sin lon2 + 
                    sin lat1 * sin lat2) where
              radius_of_earth = 6378 -- kilometers
          
          
          distDegrees a b = distRadians (coord2rad a) (coord2rad b) where
              deg2rad d = d * pi / 180
              coord2rad (lat,lon) = (deg2rad lat, deg2rad lon)
          

          distRadians 要求您的角度以弧度表示。

          distDegrees 是一个辅助函数,可以获取纬度和经度的度数。

          有关此公式推导的更多信息,请参阅this series of posts

          如果您真的需要通过假设地球是椭球体而获得的额外精度,请参阅此常见问题解答:http://www.movable-type.co.uk/scripts/gis-faq-5.1.html

          【讨论】:

            【解决方案5】:

            对不起,我什至不知道你在哪个国家。我们是在谈论 Easting and Northings(英国,Ordance Survey 系统)还是 Lat/Long 或其他一些系统? 如果我们在谈论东向和北向,那么您可以使用
            sqr((x1-x2)^2 + (y1-y2)^2)
            这不允许地球是一个球体这一事实,但对于短距离你不会注意到。我们在工作中使用它来测量县内各点之间的距离。
            请注意您使用多长时间的网格参考。我认为 8 位数的参考会给你以米为单位的距离。如果没有其他人提供,我将能够在下周的工作中得到明确的答案。

            【讨论】:

              【解决方案6】:

              使用地球的近似值和Haversine 公式。您可以通过以下网址获取 javascript 版本,您可以将其翻译成您选择的语言:

              http://www.movable-type.co.uk/scripts/latlong.html

              这是另一种方式:http://escience.anu.edu.au/project/04S2/SE/3DVOT/3DVOT/pHatTrack_Application/Source_code/pHatTrack/Converter.java

              【讨论】:

                【解决方案7】:

                您正在寻找球体上两点之间的大圆路径的长度。尝试在 Google 上查找“大圆路径”或“大圆距离”。

                【讨论】:

                  【解决方案8】:

                  【讨论】:

                    【解决方案9】:

                    勾股定理?

                    【讨论】:

                    • 这取决于您使用的投影。有一个在相对较短的距离内非常准确的状态平面投影。对于状态平面投影,勾股定理很好。如果您使用的是已经以角度(而不是距离)表示的纬度/经度坐标,则不能使用 pythogorean theorem。
                    猜你喜欢
                    • 2013-04-23
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多