use*_*958 16 google-maps map latitude-longitude bounds
如何获取已返回的谷歌静态地图的范围,例如,跟随请求
http://maps.googleapis.com/maps/api/staticmap?center=0.0,0.0&zoom=10&size=640x640&sensor=false
Run Code Online (Sandbox Code Playgroud)
据我所知,完整的地球地图是256x256图像.这意味着n个垂直像素包含x度,但n个水平像素包含2x度.对?
正如谷歌所说, 中心定义了地图的中心,与地图的所有边缘等距.据我所知,像素(或度数?)的等距离.并且每个后续缩放级别使水平和垂直尺寸的精度都加倍.所以,我可以找到每个缩放值的地图经度的delta值:
dLongitude = (HorizontalMapSizeInPixels / 256 ) * ( 360 / pow(2, zoom) );
Run Code Online (Sandbox Code Playgroud)
纬度的相同计算:
dLatitude = (VerticalMapSizeInPixels / 256 ) * ( 180 / pow(2, zoom) );
Run Code Online (Sandbox Code Playgroud)
VerticalMapSizeInPixels和HorizontalMapSizeInPixels是URL中地图大小的参数.
计算经度的delta值是好的,但对于Latitude它是错误的.我找不到Latitude的delta值,有一些delta错误.
Mar*_*elo 33
据我所知,完整的地球地图是256x256图像.
是.
这意味着n个垂直像素包含x度,但n个水平像素包含2x度.对?
不可以.一个像素将表示不同的纬度量,具体取决于纬度.赤道处的一个像素表示比极点附近的一个像素更小的纬度.
地图的角落将取决于中心,缩放级别和地图大小,您需要使用墨卡托投影来计算它们.如果您不想加载完整的API,这里是一个MercatorProjection对象:
var MERCATOR_RANGE = 256;
function bound(value, opt_min, opt_max) {
if (opt_min != null) value = Math.max(value, opt_min);
if (opt_max != null) value = Math.min(value, opt_max);
return value;
}
function degreesToRadians(deg) {
return deg * (Math.PI / 180);
}
function radiansToDegrees(rad) {
return rad / (Math.PI / 180);
}
function MercatorProjection() {
this.pixelOrigin_ = new google.maps.Point( MERCATOR_RANGE / 2, MERCATOR_RANGE / 2);
this.pixelsPerLonDegree_ = MERCATOR_RANGE / 360;
this.pixelsPerLonRadian_ = MERCATOR_RANGE / (2 * Math.PI);
};
MercatorProjection.prototype.fromLatLngToPoint = function(latLng, opt_point) {
var me = this;
var point = opt_point || new google.maps.Point(0, 0);
var origin = me.pixelOrigin_;
point.x = origin.x + latLng.lng() * me.pixelsPerLonDegree_;
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
// 89.189. This is about a third of a tile past the edge of the world tile.
var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999, 0.9999);
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) * -me.pixelsPerLonRadian_;
return point;
};
MercatorProjection.prototype.fromPointToLatLng = function(point) {
var me = this;
var origin = me.pixelOrigin_;
var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2);
return new google.maps.LatLng(lat, lng);
};
//pixelCoordinate = worldCoordinate * Math.pow(2,zoomLevel)
Run Code Online (Sandbox Code Playgroud)
您可以将其保存到单独的文件中,例如"MercatorProjection.js",然后将其包含在您的应用程序中.
<script src="MercatorProjection.js"></script>
Run Code Online (Sandbox Code Playgroud)
加载上述文件后,以下函数计算给定大小和给定缩放的地图的SW和NE角.
function getCorners(center,zoom,mapWidth,mapHeight){
var scale = Math.pow(2,zoom);
var centerPx = proj.fromLatLngToPoint(center);
var SWPoint = {x: (centerPx.x -(mapWidth/2)/ scale) , y: (centerPx.y + (mapHeight/2)/ scale)};
var SWLatLon = proj.fromPointToLatLng(SWPoint);
alert('SW: ' + SWLatLon);
var NEPoint = {x: (centerPx.x +(mapWidth/2)/ scale) , y: (centerPx.y - (mapHeight/2)/ scale)};
var NELatLon = proj.fromPointToLatLng(NEPoint);
alert(' NE: '+ NELatLon);
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它:
var proj = new MercatorProjection();
var G = google.maps;
var centerPoint = new G.LatLng(49.141404, -121.960988);
var zoom = 10;
getCorners(centerPoint,zoom,640,640);
Run Code Online (Sandbox Code Playgroud)
jma*_*gue 15
谢谢马塞洛的回答.这非常有帮助.万一有人会感兴趣,这里是代码的Python版本(PHP代码的粗略翻译,可能不像pythonic那样):
from __future__ import division
import math
MERCATOR_RANGE = 256
def bound(value, opt_min, opt_max):
if (opt_min != None):
value = max(value, opt_min)
if (opt_max != None):
value = min(value, opt_max)
return value
def degreesToRadians(deg) :
return deg * (math.pi / 180)
def radiansToDegrees(rad) :
return rad / (math.pi / 180)
class G_Point :
def __init__(self,x=0, y=0):
self.x = x
self.y = y
class G_LatLng :
def __init__(self,lt, ln):
self.lat = lt
self.lng = ln
class MercatorProjection :
def __init__(self) :
self.pixelOrigin_ = G_Point( MERCATOR_RANGE / 2, MERCATOR_RANGE / 2)
self.pixelsPerLonDegree_ = MERCATOR_RANGE / 360
self.pixelsPerLonRadian_ = MERCATOR_RANGE / (2 * math.pi)
def fromLatLngToPoint(self, latLng, opt_point=None) :
point = opt_point if opt_point is not None else G_Point(0,0)
origin = self.pixelOrigin_
point.x = origin.x + latLng.lng * self.pixelsPerLonDegree_
# NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
# 89.189. This is about a third of a tile past the edge of the world tile.
siny = bound(math.sin(degreesToRadians(latLng.lat)), -0.9999, 0.9999)
point.y = origin.y + 0.5 * math.log((1 + siny) / (1 - siny)) * - self.pixelsPerLonRadian_
return point
def fromPointToLatLng(self,point) :
origin = self.pixelOrigin_
lng = (point.x - origin.x) / self.pixelsPerLonDegree_
latRadians = (point.y - origin.y) / -self.pixelsPerLonRadian_
lat = radiansToDegrees(2 * math.atan(math.exp(latRadians)) - math.pi / 2)
return G_LatLng(lat, lng)
#pixelCoordinate = worldCoordinate * pow(2,zoomLevel)
def getCorners(center, zoom, mapWidth, mapHeight):
scale = 2**zoom
proj = MercatorProjection()
centerPx = proj.fromLatLngToPoint(center)
SWPoint = G_Point(centerPx.x-(mapWidth/2)/scale, centerPx.y+(mapHeight/2)/scale)
SWLatLon = proj.fromPointToLatLng(SWPoint)
NEPoint = G_Point(centerPx.x+(mapWidth/2)/scale, centerPx.y-(mapHeight/2)/scale)
NELatLon = proj.fromPointToLatLng(NEPoint)
return {
'N' : NELatLon.lat,
'E' : NELatLon.lng,
'S' : SWLatLon.lat,
'W' : SWLatLon.lng,
}
Run Code Online (Sandbox Code Playgroud)
用法:
>>> import MercatorProjection
>>> centerLat = 49.141404
>>> centerLon = -121.960988
>>> zoom = 10
>>> mapWidth = 640
>>> mapHeight = 640
>>> centerPoint = MercatorProjection.G_LatLng(centerLat, centerLon)
>>> corners = MercatorProjection.getCorners(centerPoint, zoom, mapWidth, mapHeight)
>>> corners
{'E': -65.710988,
'N': 74.11120692972199,
'S': 0.333879313530149,
'W': -178.210988}
>>> mapURL = "http://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=%dx%d&scale=2&maptype=roadmap&sensor=false"%(centerLat,centerLon,zoom,mapWidth,mapHeight)
>>> mapURL
http://maps.googleapis.com/maps/api/staticmap?center=49.141404,-121.960988&zoom=10&size=640x640&scale=2&maptype=roadmap&sensor=false'
Run Code Online (Sandbox Code Playgroud)
小智 5
简单Python版本
在解决类似问题上花费了很长时间并使用此线程寻求帮助后,这里是 Marcelo(和 Jmague)代码的简化 Python 版本:
import math
import requests
def latLngToPoint(mapWidth, mapHeight, lat, lng):
x = (lng + 180) * (mapWidth/360)
y = ((1 - math.log(math.tan(lat * math.pi / 180) + 1 / math.cos(lat * math.pi / 180)) / math.pi) / 2) * mapHeight
return(x, y)
def pointToLatLng(mapWidth, mapHeight, x, y):
lng = x / mapWidth * 360 - 180
n = math.pi - 2 * math.pi * y / mapHeight
lat = (180 / math.pi * math. atan(0.5 * (math.exp(n) - math.exp(-n))))
return(lat, lng)
def getImageBounds(mapWidth, mapHeight, xScale, yScale, lat, lng):
centreX, centreY = latLngToPoint(mapWidth, mapHeight, lat, lng)
southWestX = centreX - (mapWidth/2)/ xScale
southWestY = centreY + (mapHeight/2)/ yScale
SWlat, SWlng = pointToLatLng(mapWidth, mapHeight, southWestX, southWestY)
northEastX = centreX + (mapWidth/2)/ xScale
northEastY = centreY - (mapHeight/2)/ yScale
NElat, NElng = pointToLatLng(mapWidth, mapHeight, northEastX, northEastY)
return[SWlat, SWlng, NElat, NElng]
lat = 37.806716
lng = -122.477702
zoom = 16
picHeight = 640 #Resulting image height in pixels (x2 if scale parameter is set to 2)
picWidth = 640
mapHeight = 256 #Original map size - specific to Google Maps
mapWidth = 256
xScale = math.pow(2, zoom) / (picWidth/mapWidth)
yScale = math.pow(2, zoom) / (picHeight/mapWidth)
corners = getImageBounds(mapWidth, mapHeight, xScale, yScale, lat, lng)
Run Code Online (Sandbox Code Playgroud)
在这里,我使用 x 和 y 表示像素值,并使用 lat lng 表示纬度和经度。lat、lng、zoom、picHeight 和 picWidth 都可以根据您的特定用例进行更改。更改比例/地图类型等不会影响此计算。
我使用此代码平铺静态地图图像,没有间隙/重叠。如果您想了解更多它的使用/它如何在这个意义上工作,我的GitHub上有更多信息。