GeoServer WMTS切片计算
各级别关系计算规则(1)计算Pixel Size(2)计算Scale(3)切片行列号计算在geoserver中打开GridSets,选择WGS 84的切片进行查看
可以看到如下信息
各级别关系
计算规则
level=0时,切片如图所示
(1)计算Pixel Size
由于像素为256256,切片数量为21,经纬度范围为经度360度(-180到180),纬度180度(-90到90),
所以删除21的切片宽为2562=512像素,高为256像素
所以Pixel Size=360/512=0.703125 ,即每个像素代表0.703125度
当level=i时,由于被分割成了360度被分割成了2*2i张图片,每张图片为256个像素大小,故
pixelSize=360256∗2∗2ipixel Size=\frac{360}{256*2*2^{i}}pixelSize=256∗2∗2i360
(2)计算Scale
∵ 地球半径为6378137米,
∴ 实际距离D=2πR=2π6378137=40,075,016.685578491904米
在OpenGIS的WMTS标准实现中,确定比例尺分母时采用的是标准显示像素尺寸(1个像素大小)0.28mm×0.28mm。虽然实际的像素大小并不可知,但0.28mm对于当前的显示器是较为普遍的实际尺寸。
(参考链接:
(1条消息) Geoserver学习笔记-3、服务标准(WMTS详解)_@柿子树的博客-CSDN博客_geoserver wmts /weixin_38670190/article/details/104953940)
图上距离d=256 * 2 * 0.28/1000=0.14336米
比例尺=d/D=0.14336/40,075,016.685578491904=1:279,541,132.0143589
level=i时,
单个像素长度 = 0.28mm=0.00028m像素个数 = 256 * 2 * 2i图上距离(即地图360对应的像素总长度)为0.00028 * 256 * 2 * 2i地图实际距离(地球周长)=2πR=2 * π * 6378137
-scale=0.00028∗256∗2∗2i2∗π∗6378137scale=\frac{0.00028 * 256 * 2 * 2^{i}}{2*π*6378137} scale=2∗π∗63781370.00028∗256∗2∗2i
(3)切片行列号计算
public void Calculate(){///四至范围可以通过xml文件读取///http://localhost:8080/geoserver/gwc/service/wmts?layer=zny:ShuniuquDOM&REQUEST=GetCapabilities///<ows:Title>ShuniuquDOM</ows:Title>///<ows:WGS84BoundingBox>///< ows:LowerCorner > 99.14775967969356 27.161588984 </ ows:LowerCorner >///< ows:UpperCorner > 99.1598915388142 27.175144923792043 </ ows:UpperCorner >///</ ows:WGS84BoundingBox >var xmin = 99.14775967969356;var ymin = 27.161588984;var xmax = 99.1598915388142;var ymax = 27.175144923792043;var dx = xmax - xmin;var dy = ymax - ymin;var env = Map.Extent;//与视域范围无交集,无需渲染if (env.xMin > xmax || env.yMin > ymax || env.xMax < xmin || env.yMax < ymin)return;//只需加载与视域范围相交的部分if (env.xMin > xmin)xmin = env.xMin;if (env.xMax < xmax)xmax = env.xMax;if (env.yMin > ymin)ymin = env.yMin;if (env.yMax < ymax)ymax = env.yMax;//图层最值点转为像素坐标var p1 = Map.mapToDevicePoint(new SGPoint(xmin,ymin));var p2 = Map.mapToDevicePoint(new SGPoint(xmax,ymax));int level = 0;//图层横长型,用经差进行适配if (dx/dy> env.width/ env.height){//屏幕像素宽度var pw = Math.Ceiling(p2.x - p1.x);var pixelSize = dx / pw;double d = 0;for (int i = 0; i < 22; i++){var std = 360 / (256 * 2 * Math.Pow(2, i));d = std - pixelSize;if (d < 0){level = i;break;}}}//图层竖长型,用纬差进行适配else{var ph = Math.Ceiling(p2.y - p1.y);var pixelSize = dy / ph;double d = 0;for (int i = 0; i < 22; i++){var std = 180 / (256 * Math.Pow(2, i));d = std - pixelSize;if (d < 0){level = i;break;}}}var StandPixelSze = 180 / (256 * Math.Pow(2, level));//展开为360度,最左侧实际为-180,但是由于原点在左上角,,所以需要要x+180,90-y#region 左上角点var col1 = Math.Floor((xmin + 180) / 360.0 * 2 * Math.Pow(2, level));var row1 = Math.Floor((90 - ymax) / 180.0 * Math.Pow(2, level));#endregion#region 右下角点var col2 = Math.Floor((xmax + 180) / 360.0 * 2 * Math.Pow(2, level));var row2 = Math.Floor((90 - ymin) / 180.0 * Math.Pow(2, level));#endregion//需要渲染的所有切片(从上到下,从左到右)for(var col = col1; col <= col2; col++){for(var row = row1; row <= row2; row++){//照片实际四至坐标double x1 = col * StandPixelSze * 256 - 180;double y1 = 90 - (row + 1) * StandPixelSze * 256;double x2 = x1 + 256 * StandPixelSze;double y2 = y1 + 256 * StandPixelSze;var layerName = "ShuniuquDOM";var url = $"http://localhost:8081/geoserver/gwc/service/wmts?layer=zny:{layerName}&style=&tilematrixset=EPSG:4326&" +$"Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/jpeg&" +$"TileMatrix=EPSG:4326:{level}&TileCol={col}&TileRow={row}";Console.WriteLine(url);}}}