【问题标题】:How to calculate the distance between two GPS coordinates without using Google Maps API?如何在不使用 Google Maps API 的情况下计算两个 GPS 坐标之间的距离?
【发布时间】:2020-06-25 05:00:14
【问题描述】:

我想知道是否有一种方法可以在不依赖 Google Maps API 的情况下计算两个 GPS 坐标的距离。

我的应用可能会收到浮点坐标,否则我必须对地址执行反向 GEO。

【问题讨论】:

    标签: ruby google-maps


    【解决方案1】:

    地球上两个坐标之间的距离通常使用Haversine formula 计算。这个公式考虑了地球的形状和半径。这是我用来计算距离(以米为单位)的代码。

    def distance(loc1, loc2)
      rad_per_deg = Math::PI/180  # PI / 180
      rkm = 6371                  # Earth radius in kilometers
      rm = rkm * 1000             # Radius in meters
    
      dlat_rad = (loc2[0]-loc1[0]) * rad_per_deg  # Delta, converted to rad
      dlon_rad = (loc2[1]-loc1[1]) * rad_per_deg
    
      lat1_rad, lon1_rad = loc1.map {|i| i * rad_per_deg }
      lat2_rad, lon2_rad = loc2.map {|i| i * rad_per_deg }
    
      a = Math.sin(dlat_rad/2)**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin(dlon_rad/2)**2
      c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a))
    
      rm * c # Delta in meters
    end
    
    puts distance([46.3625, 15.114444],[46.055556, 14.508333])
    # => 57794.35510874037
    

    【讨论】:

    • Haversine 公式也用于Geocoder,参见文件calculations.rb
    • 这个方法修改了ab的值,这是出乎意料的。我想没有必要使用.map! 代替.map 或再次重用a
    • 已编辑,不再发生。
    【解决方案2】:

    您可以使用geokit ruby gem。它在内部进行这些计算,但如果您需要,还支持通过 google 和其他服务解析地址。

    require 'geokit'
    
    current_location = Geokit::LatLng.new(37.79363,-122.396116)
    destination = "37.786217,-122.41619"
    current_location.distance_to(destination) 
    
    # Returns distance in miles: 1.211200074136264
    

    您还可以找出bearing_to(方向表示为0-360 度之间的浮点数)和midpoint_to(返回一个可以运行.latitude 和.longitude 方法的对象)。

    【讨论】:

      【解决方案3】:

      @Lunivore 答案的一个更短的分隔参数版本

      RAD_PER_DEG = Math::PI / 180
      RM = 6371000 # Earth radius in meters
      
      def distance_between(lat1, lon1, lat2, lon2)
        lat1_rad, lat2_rad = lat1 * RAD_PER_DEG, lat2 * RAD_PER_DEG
        lon1_rad, lon2_rad = lon1 * RAD_PER_DEG, lon2 * RAD_PER_DEG
      
        a = Math.sin((lat2_rad - lat1_rad) / 2) ** 2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin((lon2_rad - lon1_rad) / 2) ** 2
        c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1 - a))
      
        RM * c # Delta in meters
      end
      

      【讨论】:

        【解决方案4】:

        我不确定是否有任何预打包的解决方案,但这似乎是一个相当简单的计算:http://www.movable-type.co.uk/scripts/latlong.html

        【讨论】:

          【解决方案5】:

          您可以像这样使用loc gem

          require 'loc'
          
          loc1 = Loc::Location[49.1, 2]
          loc2 = Loc::Location[50, 3]
          
          loc1.distance_to(loc2)
          => 123364.76538823603 # km
          

          【讨论】:

          【解决方案6】:

          看宝石Geocoder(railscast)

          如果您将坐标存储在 db 中,它会使用数据库计算距离。但在其他情况下也很有效。

          【讨论】:

          【解决方案7】:

          将接受的答案转换为 Swift 3.1(适用于 Xcode 8.3),以防万一有人需要:

          public static func calculateDistanceMeters(departure: CLLocationCoordinate2D, arrival: CLLocationCoordinate2D) -> Double {
          
              let rad_per_deg = Double.pi / 180.0 // PI / 180
              let rkm = 6371.0                    // Earth radius in kilometers
              let rm = rkm * 1000.0               // Radius in meters
          
              let dlat_rad = (arrival.latitude - departure.latitude) * rad_per_deg // Delta, converted to rad
              let dlon_rad = (arrival.longitude - departure.longitude) * rad_per_deg
          
              let lat1_rad = departure.latitude * rad_per_deg
              let lat2_rad = arrival.latitude * rad_per_deg
          
              let sinDlat = sin(dlat_rad/2)
              let sinDlon = sin(dlon_rad/2)
              let a = sinDlat * sinDlat + cos(lat1_rad) * cos(lat2_rad) * sinDlon * sinDlon
              let c = 2.0 * atan2(sqrt(a), sqrt(1-a))
          
              return rm * c
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-07-06
            • 1970-01-01
            • 2018-05-03
            • 2010-09-26
            • 2014-10-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多