计算 256 像素图块的静态 mapbox img 的经纬度
Calculate lat long on static mapbox img for 256px tiles
我有一个只有中心点 lat/long 的静态图像(例如 https://api.mapbox.com/styles/v1/mapbox/light-v9/static/-78.4649,42.5128,5,0,0/300x200),我想借助 canvas。
但我需要以某种方式计算这些标记的 xy 坐标。
所以我知道 map(lat/long) 的中心和 lat/long 标记坐标。有什么方法可以将 lat/long 转换为 xy 只知道缩放级别和中心?
或者如果我知道中心的 xy lat/long(它始终是相同的 150px * 100px)和缩放级别,我可以计算其他标记的 xy 吗?
我有很多标记(>200,它们都是自定义生成的 svg 等等)要放在这张地图上。由于标记限制等原因,我无法使用 mapbox mapbox 静态地图。
UPD: 根据评论我更新了问题。
256px的方块如何计算?
如果您要进行线性插值,则需要知道 lat/long 和 x/y 两点。除非您还有像素的转换指标,否则只有中心点是不可能的 - 即。 50 像素是 .1 增量 lat/long.
如果您有两个点的 lat/long 和 x/y,您可以将比率创建为 y1 - y2 / lat1-lat2 或 x1-x2/long1-long2,每个结果应该相同比率
那么它就相对容易了,假设比率是 5
意思是 5px/l
所以你有一个距离中心点 (3,-4) 的点,你只需multiple 找到像素偏移量 (15,-20) 并将其添加到中心 = (165, 80).
由于您的所有图像都以相同的比例缩放,您可以手动计算一次比例并将其存储为常数。
sudo/untested python:
def getRatio(latlongs=[(1,1),(0,0)], xys=[(5,5),(0,0)]:
return (xys[0][1]-xys[1][1]) / (latlongs[0][0] - latlongs[1][0])
centerLatLong = (5,5)
centerXY = (150, 100)
def getCoord(lat,long,ratio):
y = (lat-centerLatLong[0])*ratio + centerXY[1]
x = (long-centerLatLong[1])*ratio + centerXY[0]
return x, y
根据 OP 评论,为了简单起见,我假设请求的图像是方形的(TILE_SIZE
可以分解为 TILE_SIZE_X
和 TILE_SIZE_Y
组件) .我还假设图像是 256 像素宽 TILE_SIZE=256
我给出了相对于图像中心(distanceInPixels
函数)和左下角(imageCoordinates
函数)的像素坐标。如果有必要,更改到左上角应该是微不足道的(X
将等于 Y = TILE_SIZE -Y
)。
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var latLngMarker = {};
var latLngCenter = {};
// Image dimensions in pixels
var TILE_SIZE = 256;
var zoom = 5;
// Coordinates of the marker to be projected on the image
latLngMarker.lat = 41.850;
latLngMarker.lng = -87.650;
// Coordinates of the image center
latLngCenter.lat = 41.850;
latLngCenter.lng = -87.650;
// Coordinates projected on the cartographic plane (Mercator)
var centerProjected = project(latLngCenter);
var markerProjected = project(latLngMarker);
// The result should be X=Y=0, because I made Marker Lat Lng = Center Lat Lng
var distanceFromCenter = distanceInPixels(centerProjected, markerProjected);
alert("X: " + distanceFromCenter.x + " Y: " + distanceFromCenter.y);
// The result should be X=Y=256/2=128 for the same reason
var coords = imageCoordinates(centerProjected, markerProjected);
alert("X: " + coords.x + " Y: " + coords.y);
// The horizontal distance represented by one pixel for a given latitude and zoom level
function pixelResolution (latLng, zoom) {
var radius = 6378137.0 // semi-axis of WGS84 ellipsoid
var circumference = 2 * Math.PI * radius;
var distancePerImage = circumference * Math.cos(latLng.lat * Math.PI / 180.0) / Math.pow(2,zoom);
var distancePerPixel = distancePerImage / TILE_SIZE;
return distancePerPixel
}
// Web mercator projection.
function project(latLng) {
var siny = Math.sin(latLng.lat * Math.PI / 180);
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
var xy = {};
xy.x = TILE_SIZE * (0.5 + latLng.lng / 360);
xy.y = TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI));
return xy
}
// Marker pixel coordinates relative to the image Center
function distanceInPixels(centerProjected, markerProjected) {
var delta = {};
var spacing = pixelResolution(latLngCenter, zoom);
delta.x = Math.round((centerProjected.x - markerProjected.x)/spacing);
delta.y = Math.round((centerProjected.y - markerProjected.y)/spacing);
return delta
}
// Marker pixel coordinates relative to the Lower Left Corner
function imageCoordinates(centerProjected, markerProjected) {
var pixelCoordinates = {};
var spacing = pixelResolution(latLngCenter, zoom);
var deltaPixels = distanceInPixels(centerProjected, markerProjected);
pixelCoordinates.x = TILE_SIZE / 2 - deltaPixels.x;
pixelCoordinates.y = TILE_SIZE / 2 - deltaPixels.y;
return pixelCoordinates
}
</script>
</body>
</html>
注意:我可以确认 pixelResolution
函数仅适用于尺寸为 2 次幂的正方形图像块。Math.pow(2,zoom);
片段泄露了游戏信息!
Web 墨卡托函数基于:
一个像素表示的水平距离:
https://wiki.openstreetmap.org/wiki/Zoom_levels
另请参阅:
https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Resolution_and_Scale
我有一个只有中心点 lat/long 的静态图像(例如 https://api.mapbox.com/styles/v1/mapbox/light-v9/static/-78.4649,42.5128,5,0,0/300x200),我想借助 canvas。 但我需要以某种方式计算这些标记的 xy 坐标。 所以我知道 map(lat/long) 的中心和 lat/long 标记坐标。有什么方法可以将 lat/long 转换为 xy 只知道缩放级别和中心?
或者如果我知道中心的 xy lat/long(它始终是相同的 150px * 100px)和缩放级别,我可以计算其他标记的 xy 吗?
我有很多标记(>200,它们都是自定义生成的 svg 等等)要放在这张地图上。由于标记限制等原因,我无法使用 mapbox mapbox 静态地图。
UPD: 根据评论我更新了问题。
256px的方块如何计算?
如果您要进行线性插值,则需要知道 lat/long 和 x/y 两点。除非您还有像素的转换指标,否则只有中心点是不可能的 - 即。 50 像素是 .1 增量 lat/long.
如果您有两个点的 lat/long 和 x/y,您可以将比率创建为 y1 - y2 / lat1-lat2 或 x1-x2/long1-long2,每个结果应该相同比率
那么它就相对容易了,假设比率是 5
意思是 5px/l
所以你有一个距离中心点 (3,-4) 的点,你只需multiple 找到像素偏移量 (15,-20) 并将其添加到中心 = (165, 80).
由于您的所有图像都以相同的比例缩放,您可以手动计算一次比例并将其存储为常数。
sudo/untested python:
def getRatio(latlongs=[(1,1),(0,0)], xys=[(5,5),(0,0)]:
return (xys[0][1]-xys[1][1]) / (latlongs[0][0] - latlongs[1][0])
centerLatLong = (5,5)
centerXY = (150, 100)
def getCoord(lat,long,ratio):
y = (lat-centerLatLong[0])*ratio + centerXY[1]
x = (long-centerLatLong[1])*ratio + centerXY[0]
return x, y
根据 OP 评论,为了简单起见,我假设请求的图像是方形的(TILE_SIZE
可以分解为 TILE_SIZE_X
和 TILE_SIZE_Y
组件) .我还假设图像是 256 像素宽 TILE_SIZE=256
我给出了相对于图像中心(distanceInPixels
函数)和左下角(imageCoordinates
函数)的像素坐标。如果有必要,更改到左上角应该是微不足道的(X
将等于 Y = TILE_SIZE -Y
)。
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var latLngMarker = {};
var latLngCenter = {};
// Image dimensions in pixels
var TILE_SIZE = 256;
var zoom = 5;
// Coordinates of the marker to be projected on the image
latLngMarker.lat = 41.850;
latLngMarker.lng = -87.650;
// Coordinates of the image center
latLngCenter.lat = 41.850;
latLngCenter.lng = -87.650;
// Coordinates projected on the cartographic plane (Mercator)
var centerProjected = project(latLngCenter);
var markerProjected = project(latLngMarker);
// The result should be X=Y=0, because I made Marker Lat Lng = Center Lat Lng
var distanceFromCenter = distanceInPixels(centerProjected, markerProjected);
alert("X: " + distanceFromCenter.x + " Y: " + distanceFromCenter.y);
// The result should be X=Y=256/2=128 for the same reason
var coords = imageCoordinates(centerProjected, markerProjected);
alert("X: " + coords.x + " Y: " + coords.y);
// The horizontal distance represented by one pixel for a given latitude and zoom level
function pixelResolution (latLng, zoom) {
var radius = 6378137.0 // semi-axis of WGS84 ellipsoid
var circumference = 2 * Math.PI * radius;
var distancePerImage = circumference * Math.cos(latLng.lat * Math.PI / 180.0) / Math.pow(2,zoom);
var distancePerPixel = distancePerImage / TILE_SIZE;
return distancePerPixel
}
// Web mercator projection.
function project(latLng) {
var siny = Math.sin(latLng.lat * Math.PI / 180);
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
var xy = {};
xy.x = TILE_SIZE * (0.5 + latLng.lng / 360);
xy.y = TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI));
return xy
}
// Marker pixel coordinates relative to the image Center
function distanceInPixels(centerProjected, markerProjected) {
var delta = {};
var spacing = pixelResolution(latLngCenter, zoom);
delta.x = Math.round((centerProjected.x - markerProjected.x)/spacing);
delta.y = Math.round((centerProjected.y - markerProjected.y)/spacing);
return delta
}
// Marker pixel coordinates relative to the Lower Left Corner
function imageCoordinates(centerProjected, markerProjected) {
var pixelCoordinates = {};
var spacing = pixelResolution(latLngCenter, zoom);
var deltaPixels = distanceInPixels(centerProjected, markerProjected);
pixelCoordinates.x = TILE_SIZE / 2 - deltaPixels.x;
pixelCoordinates.y = TILE_SIZE / 2 - deltaPixels.y;
return pixelCoordinates
}
</script>
</body>
</html>
注意:我可以确认 pixelResolution
函数仅适用于尺寸为 2 次幂的正方形图像块。Math.pow(2,zoom);
片段泄露了游戏信息!
Web 墨卡托函数基于:
一个像素表示的水平距离:
https://wiki.openstreetmap.org/wiki/Zoom_levels
另请参阅:
https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Resolution_and_Scale