这是什么样的解决方案
看起来你不需要JavaScript的解决方案,而是需要使用Python在服务器上进行操作。我已经创建了一个Python示例,但我将依靠数学计算,数学是计算坐标所需的全部内容。让我也用JS做一下,以使片段在浏览器中正常工作。你会发现,Python和JS给出相同的结果。
跳转到答案
如果你只需要每像素度数的公式,那么这里有。它们足够简单,你不需要任何外部库,只需要Python的math
。详细的解释可以在下面找到。
#!/usr/bin/python
import math
w = 400
h = 400
zoom = 16
lat = 53.4055429
lng = -2.9976502
def getPointLatLng(x, y):
parallelMultiplier = math.cos(lat * math.pi / 180)
degreesPerPixelX = 360 / math.pow(2, zoom + 8)
degreesPerPixelY = 360 / math.pow(2, zoom + 8) * parallelMultiplier
pointLat = lat - degreesPerPixelY * ( y - h / 2)
pointLng = lng + degreesPerPixelX * ( x - w / 2)
return (pointLat, pointLng)
print 'NE: ', getPointLatLng(w, 0)
print 'SW: ', getPointLatLng(0, h)
print 'NW: ', getPointLatLng(0, 0)
print 'SE: ', getPointLatLng(w, h)
这个脚本的输出结果是:
$ python getcoords.py
NE: (53.40810128625675, -2.9933586655761717)
SW: (53.40298451374325, -3.001941734423828)
NW: (53.40810128625675, -3.001941734423828)
SE: (53.40298451374325, -2.9933586655761717)
我们需要开始的内容
我们有一些在URL中需要的参数https://maps.googleapis.com/maps/api/staticmap?center=53.4055429,-2.9976502&zoom=16&size=400x400&maptype=satellite&key=YOUR_API_KEY
—— 坐标、缩放比例、像素大小。
让我们引入一些初始变量:
var config = {
lat: 53.4055429,
lng: -2.9976502,
zoom: 16,
size: {
x: 400,
y: 400,
}
};
512像素地球的数学
计算如下。当使用图像大小为512(请参阅文档以获取大小和缩放比例)时,缩放等级1代表完整查看地球赤道的360°。在缩放等级1的示例中可以看到这一点。这是非常重要的一点。比例尺(每像素度数)不取决于图像大小。当更改图像大小时,比例尺保持不变:请比较1和2——第二个图像是一个裁剪版本的大图像。对于googleapis
的最大图像大小为640
。
每次缩小将分辨率增加两倍。因此,根据经度计算出图像的宽度为
lngDegrees = 360 / 2**(zoom - 1)
然后使用线性函数来找到图像中任意点的坐标。需要指出的是,线性仅适用于高缩放比例的图像,对于低于5倍缩放的图像,不能使用线性函数,此时数学稍微复杂一些。
lngDegreesPerPixel = lngDegrees / 512 = 360 / 2**(zoom - 1) / 2**9 = 360 / 2**(zoom + 8);
lngX = config.lng + lngDegreesPerPixel * ( point.x - config.size.x / 2);
纬度度数不同
在赤道上,纬度和经度的度数大小相同,但是如果我们向北或向南前进,由于地球上的纬线圈半径较小,因此经度度数会变得更小 - r = R * cos(lat) < R
,因此图像高度以度为单位变得更小(参见P.S.)。
latDegrees = 360 / 2**(zoom - 1) * cos(lat)
分别为:
latDegreesPerPixel = latDegrees / 512 = 360 / 2**(zoom - 1) * cos(lat) / 2**9 = 360 / 2**(zoom + 8) * cos(lat);
latY = config.lat - latDegreesPerPixel * ( point.y - config.size.y / 2)
config.lat
的符号与lngX
的符号不同,因为地球的经度方向与图像x
方向重合,但是纬度方向与图像y
方向相反。
因此,我们现在可以编写一个简单的函数,使用图片上的x
和y
坐标来查找像素的坐标。
var config = {
lat: 53.4055429,
lng: -2.9976502,
zoom: 16,
size: {
x: 400,
y: 400,
}
};
function getCoordinates(x, y) {
var degreesPerPixelX = 360 / Math.pow(2, config.zoom + 8);
var degreesPerPixelY = 360 / Math.pow(2, config.zoom + 8) * Math.cos(config.lat * Math.PI / 180);
return {
lat: config.lat - degreesPerPixelY * ( y - config.size.y / 2),
lng: config.lng + degreesPerPixelX * ( x - config.size.x / 2),
};
}
console.log('SW', getCoordinates(0, config.size.y));
console.log('NE', getCoordinates(config.size.x, 0));
console.log('SE', getCoordinates(config.size.x, config.size.y));
console.log('NW', getCoordinates(0, 0));
console.log('Something at 300,128', getCoordinates(300, 128));
顺便说一句,你可能会问我为什么在纬度公式中使用 cos(lat)
作为乘数,而不是将其作为除数用于经度公式。我发现谷歌会选择在不同纬度上每个像素保持恒定的经度比例尺,因此,cos
作为乘数被应用于纬度。
center=
参数后面跟随的坐标是地图的中心 (center=53.4055429,-2.9976502
)。你认为它们不是吗? - geocodezip