经纬度转换为256x256瓦片中的OSM像素

4

OpenStreetMap(OSM)有一个瓦片服务器。瓦片是特定缩放下的世界地图的256x256像素的图片。

I have longitude and latitude and I can find the correct tile by using this function.

function long2tile(lon,zoom) {return (Math.floor((lon+180)/360*Math.pow(2,zoom))); }
function lat2tile(lat,zoom)  { return (Math.floor((1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,zoom))); }
var zoom = 4;
var x= long2tile(13.393562,zoom);
var y = lat2tile(52.519582,zoom);
document.getElementById('a').src='https://tile.openstreetmap.org/'+zoom+'/'+ x+'/'+y+'.png';
<img src="" id="a" style="border:1px solid black"/>

我的问题是,我想知道我设置的位置在256x256像素中的哪个坐标。

如何获取这个瓦片内的x-y坐标?


一个简单的方法是直接使用reverse函数。您已经拥有了瓦片编号,瓦片编号到纬度/经度的功能将为您提供左上角像素的坐标。还要查看计算比例尺的功能。 - scai
2个回答

1

四舍五入会产生差异!

function lo2t(lon,zoom){
    return (lon+180)/360*Math.pow(2,zoom);
}
function la2t(lat,zoom){
    return (1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,zoom);
}
function long2tile(lon,zoom) {return Math.floor(lo2t(lon,zoom)); }
function lat2tile(lat,zoom)  {return Math.floor(la2t(lat,zoom)); }
function long2tfac(lon,zoom) {
    return long2tile(lon,zoom)-lo2t(lon,zoom);
}
function lat2tfac(lat,zoom) {
    return lat2tile(lat,zoom)-la2t(lat,zoom);
}
var zoom = 4;
var x= long2tile(13.393562,zoom);
var y = lat2tile(52.519582,zoom);
document.getElementById('a').src='https://tile.openstreetmap.org/'+zoom+'/'+ x+'/'+y+'.png';
var point = document.getElementById('point');
var pos=";"; pos+="left:"+long2tfac(13.393562,zoom)*-256;
 pos+="px;top:"+lat2tfac(52.519582,zoom)*-256;
 point.setAttribute('style',point.getAttribute('style')+pos+'px;');
<img src="" id="a" style="border:1px solid black"/>
<div id="point" style="display:block; position:absolute; width:30px; height:30px; border:1px solid black; border-radius:15px;">&nbsp;</div>


这在Java中对我来说似乎失败了,当经度为负数时:例如 (53.09391806811101, -8.223464321282336, 5) => (68,105),(53.10290141391111, -8.208504672019474, 5) => (69,104),但是如果经度“更大”,我总是期望得到更大的像素值。在这里,对于经度值“更大”,y 值为 105 和 104 似乎失败了! - undefined
在瓦片中,(0,0)坐标位于哪里?是在左上角还是左下角? - undefined
我认为它是左上角。 - undefined
请记住,经度和纬度是在球体上的坐标。在正北极点上,0°经度和90°经度之间的距离仅约为一米。这就是为什么矩形总是有弯曲的边缘,而且边缘的长度也不同。让人难以置信吧? - undefined
谢谢,是的,我希望现在已经得到了足够的具体信息。正确地获取增加值的方向使它起作用。不幸的是,在处理LatLon/UTM与OSM瓦片编号和瓦片中的像素时,方向是不同的。 - undefined

0

您可以使用OpenLayers库来实现这个目的,它可以为您管理各种计算和转换:

const source = new ol.source.OSM();
const grid = source.getTileGrid();

const projectedCoordinate=ol.proj.fromLonLat([13.393562,52.519582], "EPSG:3857");
const tileCoord = grid.getTileCoordForCoordAndZ(projectedCoordinate, 4/*zoom-level*/);
const projectedExtent=grid.getTileCoordExtent(tileCoord);
const extent = ol.proj.transformExtent(projectedExtent, ol.proj.get('EPSG:3857'), ol.proj.get('EPSG:4326'));
const yWidth=extent[2]-extent[0];
const xWidth=extent[3]-extent[1];
const tileUrlFunction = source.getTileUrlFunction();
const url=tileUrlFunction(tileCoord, 1, ol.proj.get('EPSG:3857'))

function convertPixelToLonLat(xPixel,yPixel){
  if(!(xPixel>=0 && xPixel<=256)){
    throw new Error('invalid xPixel');
  }
   if(!(yPixel>=0 && yPixel<=256)){
    throw new Error('invalid yPixel');
  }
  
  return {lon:extent[1]+xWidth/256*xPixel,lat:extent[2]-yWidth/256*yPixel}
}
document.querySelector('img').src=url;
console.log("top-left of tile:",convertPixelToLonLat(0,0))
console.log("bottom-right of tile:",convertPixelToLonLat(256,256))
console.log("middle of tile:",convertPixelToLonLat(128,128))
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
  <title>Test</title>
</head>
<body>
 <img />
 </body>
</html>


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