假设我有一张地图,例如来自 openstreetmaps.org。我知道地图左上角和右下角的 WGS-84 纬度/经度。如何从给定的 WGS-84 纬度/经度坐标中找到地图上的其他位置?
1 回答
如果地图大致是街道/城市级别,使用墨卡托投影(如openstreetmap.org似乎那样),并且不太靠近两极,则线性插值可能足够准确。假设如下:
- TL = 左上角的纬度/经度
- BR = 右下角的纬度/经度
- P = 您要在地图上定位的点的纬度/经度
- (w,h) = 您拥有的地图的宽度和高度(像素?)
- 地图图像的原点 (0,0) 位于其左上角
,我们可以将对应于 P 的 (x,y) 位置内插为:
x = w * (P.lon - TL.lon) / (BR.lon - TL.lon)
y = h * (P.lat - TL.lat) / (BR.lat - TL.lat)
常见的陷阱:
纬度/经度符号约定首先列出纬度,然后列出经度,即“垂直”在“水平”之前。这与图像坐标的常见 x,y 表示法相反。
向北方向(“向上”)时,纬度值会增加,而向下时,地图图像中的 y 坐标可能会增加。
如果地图覆盖更大的区域,则线性插值对于纬度将不那么准确。对于跨越一个纬度并位于地球可居住区域(例如海湾地区)的地图,中心纬度将偏移 0.2% 左右,这可能会小于一个像素(取决于大小)
如果这对您的需求足够精确,您可以在这里停下来!
从 P 的纬度到像素 y 位置的更精确的数学将从墨卡托数学开始。我们知道,对于纬度 P.lat,从赤道开始的投影上的 Y 位置如下(我将使用大写 Y 与我们正在寻找的 y 值不同,Y 从赤道开始并增加向北):
Y = k * ln((1 + sin(P.lat)) / (1 - sin(P.lat)))
常数k取决于地图的垂直缩放,我们可能不知道。幸运的是,可以通过观察 y(TL) - y(BR) = h 来推断。这让我们:
k = h / (ln((1 + sin(TL.lat)) / (1 - sin(TL.lat))) - ln((1 + sin(BR.lat)) / (1 - sin(BR.lat))))
(哎呀!这是四级括号!)已知k,我们现在有公式来找出任何纬度的Y位置。我们只需要纠正:(1)我们的 y 值从 TL.lat 开始,而不是赤道,(2)y 向南而不是向北增长。这让我们:
Y(TL.lat) = k * ln((1 + sin(TL.lat)) / (1 - sin(TL.lat)))
Y(P.lat) = k * ln((1 + sin(P.lat )) / (1 - sin(P.lat )))
y(P.lat) = -(Y(P.lat) - Y(TL.lat))
所以这让你:
x = w * (P.lon - TL.lon) / (BR.lon - TL.lon) // like before
y = -(Y(P.lat) - Y(TL.lat)) // where Y(anything) depends just on h, TL.lat and BR.lat