经纬度坐标与瓦片坐标转换推导

文章详细阐述了如何将经纬度坐标转换为WebMercator投影坐标,进而计算出对应的瓦片坐标。过程中涉及到了坐标转换公式、分辨率计算以及瓦片服务的准备和前端瓦片的拼接显示。同时提到了使用开源工具如geoserver进行切片服务的发布,以及前端库如leaflet和openlayers在渲染地图时的作用。
[1]经纬度坐标与瓦片坐标的转换
  • 选定转换的经纬度坐标与瓦片坐标(这里选4326地理坐标与谷歌XYZ规范的瓦片坐标:Z表示缩放层级,从0开始;XY的原点在左上角,X从左向右,Y从上向下)

  • 将地理坐标系转为投影坐标系(单位:经纬度=>米)例如将4326=>web墨卡托3857,该坐标系的范围(米为单位)x[-20037508.3427892, 20037508.3427892],范围y同样是[-20037508.3427892, 20037508.3427892]
    WebMercatorX=lng(π180)rWebMercatorY=r2log1+sin(lat∗(π180))1−sin(lat∗(π180)) WebMercatorX=lng(\frac{\pi}{180})r\\ WebMercatorY=\frac{r}{2log_{\frac{1+sin(lat * (\frac{\pi}{180}))}{1-sin(lat * (\frac{\pi}{180}))}}} WebMercatorX=lng(180π)rWebMercatorY=2log1sin(lat(180π))1+sin(lat(180π))r

    // 地球半径
    const r = 6378137
    // 4326转3857
    const lngLatMercator = (lng, lat) => {
        //注意先转为为弧度制,弧度=角度*Math.PI/180,弧长=弧度*半径 
        let x = lng * (Math.PI / 180) * r;
        let rad = lat * (Math.PI / 180)
        let sin = Math.sin(rad)
        let y = r / 2 * Math.log((1 + sin) / (1 - sin))
        return [x, y]
    }
    
  • 计算任意层级zzz下的分辨率(分辨率:一个像素宽所代表的实际长度,这里假设每张瓦片的大小为256∗256256*256256256

    resolutionX=C256∗2zrresolutionY=C256∗2z resolutionX=\frac{C}{256*2^{z}}\\ rresolutionY=\frac{C}{256*2^{z}} resolutionX=2562zCrresolutionY=2562zC

    // 地球周长
    const C = 2 * Math.PI * 6378137
    // 瓦片像素
    const titleSize = 256
    // 获取某一层级下的分辨率(X,Y方向适)
    const getResolution = (n) => {
        const tileNums = Math.pow(2, n)
        const tileTotalPx = tileNums * titleSize
        return C / tileTotalPx
    }
    
  • 计算像素/屏幕坐标(以为web墨卡托默坐标原点在经纬度为0的地方,而屏幕坐标原点位于屏幕左上角,所以这里需要先进行转换)

pixelCoorX=WebMercatorX+C/2resolutionXpixelCoorY=C/2−WebMercatorXresolutionY pixelCoorX=\frac{WebMercatorX+C/2}{resolutionX}\\ pixelCoorY=\frac{C/2-WebMercatorX}{resolutionY} pixelCoorX=resolutionXWebMercatorX+C/2pixelCoorY=resolutionYC/2WebMercatorX

  • 计算瓦片坐标(行列号)
    tileCoorX=pixelCoorX256tileCoorY=pixelCoorY256 tileCoorX=\frac{pixelCoorX}{256}\\ tileCoorY=\frac{pixelCoorY}{256} tileCoorX=256pixelCoorXtileCoorY=256pixelCoorY

    // 根据像素坐标及缩放层级计算瓦片行列号
    const getTileRowAndCol = (x, y, z) => 
       \\因为38574326坐标原点位于经纬度为零的地方,而瓦片坐标原点位于左上角,所以需要将3857坐标原点转到左上角
        x += C / 2     
        y = C / 2 - y
        let resolutionX = getResolution(z)//获取某一层级z下的分辨率
        let row = Math.floor(x / resolutionX / tileSize)
        let col = Math.floor(y / resolutionY / tileSize)
        return [row, col]
    }
    
  • 根据上面的推导可得出经纬度坐标(lng,lat)(lng, lat)lng,lat互转瓦片坐标(row,col)(row, col)rowcol总公式:
    在这里插入图片描述

一些切片工具的工作原理也大致如此,输入你需要切片的数据及要切片的参数(如切片最大、最小层级,瓦片大小等),输出相应目录规范的XYZ切片数据,以供直接调用。

[2]瓦片服务准备

完成经纬度坐标转为瓦片坐标后便可以使用一些切片工具(geoserver等)切一些瓦片然后发布为服务或直接调用在线瓦片服务,在或者直接调用离线瓦片(注意命名规范)

[3]前端瓦片拼接显示

对于生成的栅格瓦片服务或离线瓦片,可以根据瓦片采用的规则以及切片的参数,采用canvas渲染拼接或采用基于canvas的地图库渲染即可。

可采用leaflet和opnelayers来调用瓦片服务并再前端渲染(openlayers不需要写经纬度坐标转瓦片坐标等代码实现,直接调用即可),不过为了学习的话可以使用canvas来实现瓦片地图的加载。但是使用canvas来渲染的话还会遇到许多需要优化东西:比如瓦片的加载顺序(怎么实现先加载屏幕中间的瓦片),缩放时瓦片的更新方式,平滑移动效果,瓦片的缓存机制等

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

seeooco

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值