GeoServer WMTS切片计算

在geoserver中打开GridSets,选择WGS 84的切片进行查看
在这里插入图片描述
可以看到如下信息
在这里插入图片描述

各级别关系

LevelPixel SizeScaleTiles
ip1 : sm * n
i +1p /21 : (s/2)2m * 2n

计算规则

在这里插入图片描述

在这里插入图片描述
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个像素大小,故
p i x e l S i z e = 360 256 ∗ 2 ∗ 2 i pixel Size=\frac{360}{256*2*2^{i}} pixelSize=25622i360

(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 https://blog.csdn.net/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
    - s c a l e = 0.00028 ∗ 256 ∗ 2 ∗ 2 i 2 ∗ π ∗ 6378137 scale=\frac{0.00028 * 256 * 2 * 2^{i}}{2*π*6378137} scale=2π63781370.0002825622i

(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.1615889820084 </ ows:LowerCorner >
    ///< ows:UpperCorner > 99.1598915388142 27.175144923792043 </ ows:UpperCorner >
    ///</ ows:WGS84BoundingBox >
    var xmin = 99.14775967969356;
    var ymin = 27.1615889820084;
    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);
        }
    }
}
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ShirmyMao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值