Leaflet在缩放级别下计算每像素米数

15

我正在尝试确定 Leaflet 中给定缩放级别和地理中心点时,1个像素所代表的米数的计算方法。是否有人可以指导我相关的数学知识或者是否有一种可以直接在 Leaflet 中实现的方法?目前我并没有找到太多相关信息。

4个回答

23

您可以使用L.MapcontainerPointToLatLng转换函数获取给定像素坐标的经纬度坐标。如果您选择第一个像素和下一个像素中的一个,您可以使用L.LatLngdistanceTo实用方法来计算它们之间的距离(以米为单位)。请参见以下代码(假设地图是L.Map的实例):

var centerLatLng = map.getCenter(); // get map center
var pointC = map.latLngToContainerPoint(centerLatLng); // convert to containerpoint (pixels)
var pointX = [pointC.x + 1, pointC.y]; // add one pixel to x
var pointY = [pointC.x, pointC.y + 1]; // add one pixel to y

// convert containerpoints to latlng's
var latLngC = map.containerPointToLatLng(pointC);
var latLngX = map.containerPointToLatLng(pointX);
var latLngY = map.containerPointToLatLng(pointY);

var distanceX = latLngC.distanceTo(latLngX); // calculate distance between c and x (latitude)
var distanceY = latLngC.distanceTo(latLngY); // calculate distance between c and y (longitude)

应该可以工作了,感谢Jarek Piórkowski在编辑之前指出我的错误。


3
“我不确定你为什么提到中心点,因为无论从哪里获取结果,它们都会是相同的。” 不,这并不正确。纬度和经度的每一度长度因所处纬度而异,在较大的尺度上可能会产生影响。你可以在 http://www.csgnetwork.com/degreelenllavcalc.html 上进行测试。 - Jarek Piórkowski
1
当然啦 :) 我知道这点,但不知怎么忘了。我会编辑我的回答,非常感谢。 - iH8
2
当缩小时,这对我有效,但放大时失败了 - distanceX 为零。选择一个距离100像素的像素,然后将结果除以100似乎更好。我不知道这是否是一种有效的方法。 - Tom Chadwin

12
您可以使用此方法来计算每像素的米数:
metresPerPixel = 40075016.686 * Math.abs(Math.cos(map.getCenter().lat * Math.PI/180)) / Math.pow(2, map.getZoom()+8);

1
非常有趣,您能再详细解释一下吗?我很好奇2^(放大级别+8)的来源以及“缩放级别”数字是否独立于所使用的投影。我猜想这个神奇的数字是地球赤道的长度。 - Davide
2
只是确认一下:上面的答案似乎是正确的,我已经将iH8提供的解决方案和synkyo提供的解决方案并排实现,它们返回相同的结果,精确到小数点后6位。来源:http://wiki.openstreetmap.org/wiki/Zoom_levels - Hendrik
1
这里还有一些补充说明:https://dev59.com/bV0a5IYBdhLWcg3wHlek - herve
6
我认为上面的意思应该是...Math.cos(map.getCenter().lat Math.PI/180))...而不是... Math.cos(map.getCenter().lat * 180/Math.PI))...因为我们正在从角度转换为弧度。 - mwakerman
2
Leaflet开发人员(Per Liedman)告诉我,这种方法只适用于EPSG:3857。 - Tom Chadwin
@mwakerman 确实,我没有注意到你的评论,得到了错误的结果,所以我编辑了答案来修复它(我猜 synkyo 不在了)。 - anol

2

如果我错了,请纠正我,以我个人看来,每像素米数 = 地图高度(米)/ 地图高度(像素)

function metresPerPixel() {
    const southEastPoint = map.getBounds().getSouthEast();
    const northEastPoint = map.getBounds().getNorthEast();
    const mapHeightInMetres = southEastPoint.distanceTo(northEastPoint);
    const mapHeightInPixels = map.getSize().y;

    return mapHeightInMetres / mapHeightInPixels;
}

2
请查看openstreetmap.org关于缩放级别的页面。其中给出了计算每像素米数的公式:

一个像素所代表的距离(S)由以下公式给出:

S=C*cos(y)/2^(z+8) 其中...

C是地球的赤道周长

z是缩放级别

y是您感兴趣的比例尺所在位置的纬度。


1
Leaflet开发人员(Per Liedman)告诉我,这种方法只适用于EPSG:3857。 - Tom Chadwin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接