目錄
- 既有 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 級瓦片:
<TileMatrixLimits>
<TileMatrix>EPSG:4490:0</TileMatrix>
<MinTileRow>190</MinTileRow>
<MaxTileRow>192</MaxTileRow>
<MinTileCol>835</MinTileCol>
<MaxTileCol>838</MaxTileCol>
</TileMatrixLimits>eMatrix>
比對廣東省省界資料的 4326 坐標系第 9 級瓦片陣(TileMatrix)定義:
<TileMatrixLimits>
<TileMatrix>EPSG:4326:9</TileMatrix>
<MinTileRow>183</MinTileRow>
<MaxTileRow>198</MaxTileRow>
<MinTileCol>823</MinTileCol>
<MaxTileCol>845</MaxTileCol>
</TileMatrixLimits>
最大最小行列號略有差別,是因為資料所跨的范圍略有不同,前者范圍較后者(廣東省省界)小,
我只能說比較慶幸,這樣的 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 引數
WebMapTileServiceImageryProvider 的 url 可以是兩種型別的值:string 或 Resource,這個 WMTS 資料需要在所有請求頭中加上訪問令牌(token),所以我選擇創建一個 Resource 物件來傳遞 token,
tileMatrixSetID 和 layer 引數
這里設為 EPSG:4490,指的是能力檔案中該圖層(layer: 'demo')下的 <TileMatrixSetLink></TileMatrixSetLink> 的瓦片陣集ID(TileMatrixSetID):
<TileMatrixSetLink>
<TileMatrixSet>EPSG:4490</TileMatrixSet>
<TileMatrixSetLimits><!-- ... --></TileMatrixSetLimits>
</TileMatrixSetLink>
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 列的瓦片的,但是在能力檔案中,我注意到了一個定義:
<Contents>
<TileMatrixSet>
<ows:Identifier>EPSG:4490</ows:Identifier>
<ows:SupportedCRS>urn:ogc:def:crs:EPSG::4490</ows:SupportedCRS>
<TileMatrix>
<ows:Identifier>EPSG:4490:0</ows:Identifier>
<ScaleDenominator>545978.7734655447</ScaleDenominator>
<TopLeftCorner>90.0 -180.0</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>1024</MatrixWidth>
<MatrixHeight>512</MatrixHeight>
</TileMatrix>
<!-- ... -->
<TileMatrixSet>
</Contents>
這是這個 WMTS 服務下的 EPSG:4490 的瓦片陣集(TileMatrixSet)的第 0 個瓦片陣(TileMatrix)的定義,這里定義了幾個比較重要的引數:
Identifier:瓦片陣的 IDScaleDenominator:比例(分母)TileWidth/TileHeight:該瓦片陣的瓦片的像素寬高MatrixWidth/MatrixHeight:該瓦片陣的瓦片行列數
要用于前端的就是最后一個,行列數:
new GeographicTilingScheme({
numberOfLevelZeroTilesX: 1024,
numberOfLevelZeroTilesY: 512,
})
這樣就能在 CesiumJS 發出第 0 級瓦片請求時,行列號能與 WMTS 的瓦片行列號對應上了,TilingScheme API 的這兩個引數就是這么個用法,前提是切片的形狀滿足 CesiumJS 支持的這兩個:GeographicTilingScheme、WebMercatorTilingScheme
小結
通過這次實踐,我又進一步學習了老舊但是又不得不用的 WMTS 規范,以及這種非標準 4326、3857 切片資料的加載細節,那就是精確地根據能力檔案中各項引數(瓦片陣集的選擇、瓦片陣的范圍等),配合 JsAPI 控制發出準確的請求,
如果真遇上那種不滿足 CesiumJS 這倆切片方案的,估計就難搞了,水平有限,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/545348.html
標籤:其他
