【问题标题】:Convert Lat/Long to X,Y position within a Bounding Box将 Lat/Long 转换为边界框中的 X、Y 位置
【发布时间】:2017-01-13 08:14:21
【问题描述】:

我有一个边界框:

Left -122.27671
Bottom 37.80445
Right -122.26673
Top 37.81449

它也可以转换为NE Lat/Long和SW Lat/Long

在该边界框内,我想找到特定纬度/经度的 X、Y 位置。这将使用墨卡托投影。

我已经看到使用墨卡托在世界地图上找到某个位置的 X、Y 的答案,但不在特定的纬度/经度内。

任何帮助表示赞赏!

更新 把我看到的另一个问题放在一起。谁能验证这是否合法?

map_width = 1240
map_height = 1279

map_lon_left = -122.296916
map_lon_right = -122.243380
map_lon_delta = map_lon_right - map_lon_left

map_lat_bottom = 37.782368
map_lat_bottom_degree = map_lat_bottom * Math::PI / 180

def convert_geo_to_pixel(lat, long)
  x = (long - map_lon_left) * (map_width / map_lon_delta)

  lat = lat * Math::PI / 180
  world_map_width = ((map_width / map_lon_delta) * 360) / (2 * Math::PI)
  map_offset_y = (world_map_width / 2 * Math.log((1 + Math.sin(map_lat_bottom_degree)) / (1 - Math.sin(map_lat_bottom_degree))))
  y = map_height - ((world_map_width / 2 * Math.log((1 + Math.sin(lat)) / (1 - Math.sin(lat)))) - map_offset_y)

  return [x, y]
end

【问题讨论】:

    标签: math maps 2d mercator


    【解决方案1】:

    找到了一个我已经测试和验证过的更好的解决方案。将此发布给其他可能觉得有用的人。它是用 Ruby 编写的,但很容易转换为任何其他语言

    @north = to_radians(37.81449)
    @south = to_radians(37.80445)
    @east = to_radians(-122.26673)
    @west = to_radians(-122.27671)
    # Coordinates above are a subsection of Oakland, CA
    
    @map_width = map_width
    @map_height = map_height
    
    def location_to_pixel(lat:, lon:)
      lat = to_radians(lat)
      lon = to_radians(lon)
      ymin = mercator_y(@south)
      ymax = mercator_y(@north)
      x_factor = @map_width/(@east - @west)
      y_factor = @map_height/(ymax - ymin)
    
      y = mercator_y(lat);
      x = (lon - @west) * x_factor
      y = (ymax - y) * y_factor
      [x, y]
    end
    
    def to_radians(deg)
      deg * Math::PI/180
    end
    
    def mercator_y(lat)
        Math.log(
          Math.tan(lat/2 + Math::PI/4)
        )
    end
    

    【讨论】:

      【解决方案2】:

      让我们s 是地图在世界空间中的移动,以弧度 B 表示的底部纬度,以弧度 B 表示的顶部纬度 T。(我假设 y=0 是底部)

      C * Sin(B) = 0 + s
      C * Sin(T) = map_height + s
      =>
      C = map_height / (Sin(T) - Sin(B))
      s = C * Sin(B)
      y = C * Sin(Lat) - s = 
          C * Sin(Lat) - C * Sin(B) = 
          C * (Sin(Lat) - Sin(B)) = 
          map_height * (Sin(Lat) - Sin(B) / (Sin(T) - Sin(B))
      
              // note - resembles linear interpolation is sine space
      

      【讨论】:

      • 我上面使用的代码不正确吗?当在边界框中给定纬度/经度时,无法理解您的示例输出 x, y 的位置?
      • 你的 x 计算是正确的。你似乎错了。我的纬度对应你的纬度,B=map_lat_bottom, T=map_lat_top(在你的代码中看不到)
      • 我从stackoverflow.com/questions/2103924/… 复制了我的解决方案,我相信map_lat left 和right 是左上角和右上角。因为我们知道拐角在哪里,所以我们只需要底部的纬度来完成正方形。我就是这样解释这个解决方案的?
      • 用上面的重构版本发布了一个新答案。我发布的两段代码都有效,但我选择的答案更清楚,因为它指定了 NSEW
      猜你喜欢
      • 1970-01-01
      • 2021-10-16
      • 2020-09-11
      • 2015-05-06
      • 1970-01-01
      • 2022-12-28
      • 1970-01-01
      • 2013-05-28
      • 2011-02-08
      相关资源
      最近更新 更多