我有一个只有中心点经/纬度的静态图像(例如https://api.mapbox.com/styles/v1/mapbox/light-v9/static/-78.4649,42.5128,5,0,0/300x200),我想在画布的帮助下在地图上放置一些标记(经度.long)。但是我需要以某种方式计算这些标记的xy坐标。因此,我知道了地图的中心(纬度/经度)和纬度/经度标记坐标。有什么方法可以将lat / long转换为xy,仅知道缩放级别和中心?
或者如果我知道中心纬度/经度(始终等于150px * 100px)和缩放级别的xy,我可以计算其他标记的xy吗?
我有很多标记(> 200,并且它们都是自定义的svg生成的,依此类推),以将其放置在此地图上。由于标记的限制等原因,我无法使用mapbox mapbox静态地图。
如果要进行线性插值,则需要知道2点的经/纬度和x / y。除非您还有像素转换指标(即),否则仅靠中心点是不可能的。 50个像素为0.1纬度/经度。
如果您有两个点的纬度/经度和x / y,则可以将比率创建为y1- y2 / lat1-lat2或x1-x2 / long1-long2,每个比率应得出相同的比率
然后相对容易,假设比率为5
表示5px/l
,因此您有一个距该中心点(3,-4)的点,您只需乘以倍数即可找到像素偏移量( 15,-20),并将其添加到中心=(165,80)。
由于所有图像都以相同的比例缩放,因此您可以手动计算一次比率并将其存储为常数。
sudo / unested 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