最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

【全球新要闻】记一次 CesiumJS 中非 4326/3857 WMTS 数据的加载

来源:博客园
目录
  • 既有 WMTS 的现状
  • 兵来将挡水来土掩 - 问题解决
    • url 参数
    • tileMatrixSetID 和 layer 参数
    • tileMatrixLabels 参数
    • rectangle 参数
    • tilingScheme 参数
  • 小结

记一次 CesiumJS 中 WMTS 数据的加载

CesiumJS 能用的 WMTS 目前只支持两种切片方案(TilingScheme):


(相关资料图)

  • 0 级瓦片有 2 个的 GeographicTilingScheme
  • 0 级瓦片只有 1 个的 WebMercatorTilingScheme

光说很抽象,上图:

0 级瓦片有 2 个的投影,是直接以经纬度数值展平成平面,众所周知:

\[纬度跨度:经度跨度 = 180:360 = 1:2\]

所以 GeographicTilingScheme的样子就是一个一比二的 矩形,刚好就在 0 级瓦片时有两个,后续就按常规的四叉树切分即可。而 WebMercator投影后的坐标系 xy 值域是 \([-20037508.34,20037508.34]^2\),是一个 正方形,所以可以按单个 0 级瓦片进行四叉树切分。

以上,是技术前提,CesiumJS 只能支持这两种切分方案,也就是说,我国常用的其他投影方法,例如高斯投影、兰伯特投影等是不支持的,主要是形状不太满足构造四叉树瓦片。

既有 WMTS 的现状

需求是这样的,这一份 WMTS 的起切等级并不是 0 级,通过观察能力文档,我可以得出如下几个结论:

  • 它是自定义切片方案,但满足 GeographicTilingScheme方案的形状,是 1:2的矩形
  • 它的 0 级瓦片与 EPSG:4326的 0 级瓦片不同
  • 它的 0 级瓦片分辨率与 EPSG:4326的 9 级瓦片相同
  • 它的 0 级瓦片共有 1024 列 × 512 行,而 EPSG:4326是 2 列 × 1 行,是 4326 的 \(512^2\) 倍

如果读者足够敏锐,可以得知这个 WMTS 的起切瓦片实际上几乎就是 4326 的第 9 级瓦片:

    EPSG:4490:0    190    192    835    838eMatrix>

比对广东省省界数据的 4326 坐标系第 9 级瓦片阵(TileMatrix)定义:

    EPSG:4326:9    183    198    823    845

最大最小行列号略有差别,是因为数据所跨的范围略有不同,前者范围较后者(广东省省界)小。

我只能说比较庆幸,这样的 WMTS 基本还是可以满足加载要求的,现有 API 可以满足加载调整。

兵来将挡水来土掩 - 问题解决

先给代码,然后解释:

const provider = new WebMapTileServiceImageryProvider({  url: new Resource({    url: "http://127.0.0.1/server/wmts", // 简写 url,会意即可    headers: {      "tk": "aaaaaaaaa", // 数据保密,需要传递 token    }  }),  tileMatrixSetID: "EPSG:4490",  format: "image/png",  tileMatrixLabels: Object.keys(new Array(11).fill(0)).map(v => `EPSG:4490:${v}`),  layer: "demo",  rectangle: Rectangle.fromDegrees(113.75549, 22.383494, 114.662777, 22.888641),  style: "",  tilingScheme: new GeographicTilingScheme({    numberOfLevelZeroTilesX: 1024,    numberOfLevelZeroTilesY: 512,  })})viewer.imageryLayers.addImageryProvider(provider)

url 参数

WebMapTileServiceImageryProviderurl可以是两种类型的值:stringResource,这个 WMTS 数据需要在所有请求头中加上访问令牌(token),所以我选择创建一个 Resource对象来传递 token。

tileMatrixSetID 和 layer 参数

这里设为 EPSG:4490,指的是能力文档中该图层(layer: "demo")下的 的瓦片阵集ID(TileMatrixSetID):

    EPSG:4490    

tileMatrixLabels 参数

这个没什么好说的,就是每一层瓦片阵的访问标签,我这里使用 JavaScript 的数组语法糖快速生成了 11 级(0到10,共11层)瓦片阵的 ID,即:

Object.keys(new Array(11).fill(0)).map(v => `EPSG:4490:${v}`)// ["EPSG:4490:0", "EPSG:4490:1", ..., "EPSG:4490:10"]

这样,网络请求瓦片的链接:

http://127.0.0.1/server/wmts?tilematrix=EPSG%3A4490%3A1&layer=ZT%3ATDYT&style=&tilerow=382&tilecol=1671&tilematrixset=EPSG%3A4490&format=image%2Fpng&service=WMTS&version=1.0.0&request=GetTile

中的 tilematrix参数的值:EPSG:4490:1就是正确的了。tileMatrixLabels 数组默认是数字 0 ~ 最大等级,如果图层在能力文档中定义的 tilematrix的 ID 不是 0 ~ 最大等级的数字的话,就需要这样构造一个数组来告诉 CesiumJS,要以什么样的 tilematrix 发出请求。

rectangle 参数

加上这个参数,就可以最大优化 WMTS 的请求性能,如果不加这个参数限制请求范围,就会取相机视角下的所有筛选到的瓦片,这对这个例子十分有效,主要还是要加上最后一个参数:

tilingScheme 参数

上文已经提及,这个 WMTS 的切片方案与 4326 的是几乎一致的,只不过其 0 级相当于 4326 的 9 级。

那么,当 CesiumJS 发出第 0 级瓦片请求时,默认的 TilingScheme是只有 1 行 2 列的瓦片的,但是在能力文档中,我注意到了一个定义:

            EPSG:4490        urn:ogc:def:crs:EPSG::4490                    EPSG:4490:0            545978.7734655447            90.0 -180.0            256            256            1024            512                    

这是这个 WMTS 服务下的 EPSG:4490的瓦片阵集(TileMatrixSet)的第 0 个瓦片阵(TileMatrix)的定义,这里定义了几个比较重要的参数:

  • Identifier:瓦片阵的 ID
  • ScaleDenominator:比例(分母)
  • TileWidth/ TileHeight:该瓦片阵的瓦片的像素宽高
  • MatrixWidth/ MatrixHeight:该瓦片阵的瓦片行列数

要用于前端的就是最后一个,行列数:

new GeographicTilingScheme({  numberOfLevelZeroTilesX: 1024,  numberOfLevelZeroTilesY: 512,})

这样就能在 CesiumJS 发出第 0 级瓦片请求时,行列号能与 WMTS 的瓦片行列号对应上了,TilingSchemeAPI 的这两个参数就是这么个用法,前提是切片的形状满足 CesiumJS 支持的这两个:GeographicTilingSchemeWebMercatorTilingScheme

小结

通过这次实践,我又进一步学习了老旧但是又不得不用的 WMTS 规范,以及这种非标准 4326、3857 切片数据的加载细节,那就是精确地根据能力文档中各项参数(瓦片阵集的选择、瓦片阵的范围等),配合 JsAPI 控制发出准确的请求。

如果真遇上那种不满足 CesiumJS 这俩切片方案的,估计就难搞了,水平有限。

关键词: 兵来将挡水来土掩 问题解决