UNPKG

cesium-geoserverterrainprovider

Version:
212 lines (190 loc) 10.2 kB
import { basicAssignResult, CRS, FormatImage, ICRS, IDescription, IFormatImage, IResult } from "./utils"; const C: typeof import('cesium') = (window as any).Cesium const { fetchXML: loadXML } = C.Resource; export async function generate(description: IDescription) { let resultat: IResult; if (description.url) { let urlofServer = description.url; const index = urlofServer.lastIndexOf("?"); if (index > -1) { urlofServer = urlofServer.substring(0, index) } let urlGetCapabilities = urlofServer + '/gwc/service/wmts?REQUEST=GetCapabilities'; if (description.proxy) { urlGetCapabilities = description.proxy.getURL(urlGetCapabilities); } description.xml = await loadXML({ url: urlGetCapabilities }); resultat = getMetaDatafromXML(description); } else if (description.xml) { resultat = getMetaDatafromXML(description); } else { throw new Error('either description.url or description.xml are required.'); } return resultat; }; function getMetaDatafromXML(description: IDescription): IResult { const xml = description.xml; if (!(xml instanceof XMLDocument)) { throw new Error('xml must be a XMLDocument'); } const resultat: Partial<IResult> = {}; const layerName = description.layerName; basicAssignResult(description, resultat); const maxLevel = description.maxLevel; const proxy = description.proxy; let styleName = description.styleName; let template: string = null; let listTileMatrixSetLinkNode: Element[] = []; let urlKVP: string = null, urlRESTful: string = null; let formatImage: IFormatImage = null; //KVP support for now Array.from(xml.querySelectorAll('Operation[name="GetTile"] HTTP Get')) .map((elt) => ({ node: elt, type: elt.querySelector("Value").textContent })) .forEach(item => { if (item.type === "RESTful" && urlRESTful === null) { urlRESTful = item.node.getAttribute("xlink:href"); if (proxy) { urlRESTful = proxy.getURL(urlRESTful); } } if (item.type === "KVP" && urlKVP === null) { urlKVP = item.node.getAttribute("xlink:href"); if (proxy) { urlKVP = proxy.getURL(urlKVP); } } }); const nodeIdentifiers = xml.querySelectorAll("Contents>Layer>Identifier"); let layerNode: ParentNode = null; for (let i = 0; i < nodeIdentifiers.length && layerNode === null; i++) { if (layerName === nodeIdentifiers[i].textContent) { layerNode = nodeIdentifiers[i].parentNode; } } if (layerNode !== null) { //optionality of style in geoserver is not compliant with OGC requirements!! let defaultStyle: string; let selectedStyle: string; Array.from(layerNode.querySelectorAll("Style")).forEach(item => { const style = item.querySelector("Identifier").textContent; if (item.getAttribute("isDefault") != null) { defaultStyle = style; } if (style === styleName) { selectedStyle = style; } }); //Work with attribute isDefault when no style was defined!! if (!styleName || styleName !== selectedStyle) { styleName = defaultStyle || ''; } //format const nodeFormats = Array.from(layerNode.querySelectorAll("Format")); for (let l = 0; l < FormatImage.length && formatImage === null; l++) { const validFormats = nodeFormats.filter(elt => elt.textContent === FormatImage[l].format); if (validFormats.length > 0) { formatImage = FormatImage[l]; } } //TileMatrixSetLink =>TileMatrixSet listTileMatrixSetLinkNode = Array.from(layerNode.querySelectorAll("TileMatrixSetLink")); } const nodeMatrixSetIds = Array.from(xml.querySelectorAll("TileMatrixSet>Identifier")); for (let a = 0; a < listTileMatrixSetLinkNode.length && !resultat.ready; a++) { const matrixSetLinkNode = listTileMatrixSetLinkNode[a]; const tileMatrixSetLinkName = matrixSetLinkNode.querySelector("TileMatrixSet").textContent; let tileMatrixSetNode: ParentNode = null; let CRSSelected: ICRS = null; for (let i = 0; i < nodeMatrixSetIds.length && tileMatrixSetNode === null; i++) { if (nodeMatrixSetIds[i].textContent === tileMatrixSetLinkName) { tileMatrixSetNode = nodeMatrixSetIds[i].parentNode; } } const supportedCRS = tileMatrixSetNode.querySelector("SupportedCRS").textContent; for (let n = 0; n < CRS.length && CRSSelected === null; n++) { if (CRS[n].supportedCRS === supportedCRS) { CRSSelected = CRS[n]; } } if (CRSSelected !== null) { const tileSets: { id: string, maxWidth: number, maxHeight: number, scaleDenominator: number, complete: boolean, tileWidth: number, tileHeight: number, bbox?: { minTileRow: number, maxTileRow: number, minTileCol: number, maxTileCol: number } }[] = Array.from(tileMatrixSetNode.querySelectorAll("TileMatrix")) .map(function (noeud) { let id = noeud.querySelector("Identifier").textContent; let maxWidth = parseInt(noeud.querySelector("MatrixWidth").textContent, 10); let maxHeight = parseInt(noeud.querySelector("MatrixHeight").textContent, 10); let tileWidth = parseInt(noeud.querySelector("TileWidth").textContent, 10); let tileHeight = parseInt(noeud.querySelector("TileHeight").textContent, 10); let scaleDenominator = parseFloat(noeud.querySelector("ScaleDenominator").textContent); return { id, maxWidth, maxHeight, scaleDenominator, complete: false, tileWidth, tileHeight }; }) .sort((a, b) => b.scaleDenominator - a.scaleDenominator); const listTileMatrixLimits = Array.from(matrixSetLinkNode.querySelectorAll("TileMatrixSetLimits>TileMatrixLimits")) .map(nodeLink => ({ id: nodeLink.querySelector("TileMatrix").textContent, bbox: { minTileRow: parseInt(nodeLink.querySelector("MinTileRow").textContent, 10), maxTileRow: parseInt(nodeLink.querySelector("MaxTileRow").textContent, 10), minTileCol: parseInt(nodeLink.querySelector("MinTileCol").textContent, 10), maxTileCol: parseInt(nodeLink.querySelector("MaxTileCol").textContent, 10) } })); tileSets.forEach(tile => { listTileMatrixLimits.forEach(nodeLink => { if (tile.id === nodeLink.id) { tile.bbox = nodeLink.bbox; tile.complete = true; } }); }); if (tileSets.length > 0) { resultat.tilingScheme = new CRSSelected.tilingScheme({ ellipsoid: CRSSelected.ellipsoid, numberOfLevelZeroTilesX: tileSets[0].maxWidth, numberOfLevelZeroTilesY: tileSets[0].maxHeight }); const resourceURL = layerNode.querySelector("ResourceURL[format='" + formatImage.format + "']"); if (resourceURL !== null) { template = resourceURL.getAttribute("template").replace("{TileRow}", "{y}").replace("{TileCol}", "{x}").replace("{style}", styleName).replace("{Style}", styleName). replace("{TileMatrixSet}", tileMatrixSetLinkName).replace("{layer}", layerName).replace("{infoFormatExtension}", formatImage.extension); } else if (urlKVP !== null) { template = urlKVP + "service=WMTS&request=GetTile&version=1.0.0&layer=" + layerName + "&style=" + styleName + "&format=" + formatImage.format + "&TileMatrixSet=" + tileMatrixSetLinkName + "&TileMatrix={TileMatrix}&TileRow={y}&TileCol={x}" } if (template !== null) { resultat.getTileDataAvailable = (x, y, level) => { let retour = false; if (level < maxLevel && level < tileSets.length) { const tile = tileSets[level]; const bbox = tile.bbox; if (tile.complete) { retour = (y <= bbox.maxTileRow && y >= bbox.minTileRow) && (x <= bbox.maxTileCol && x >= bbox.minTileCol); } else { retour = x < tile.maxWidth && y < tile.maxHeight; } } return retour; }; resultat.URLtemplateImage = function (x, y, level) { let retour = ""; if (resultat.getTileDataAvailable(x, y, level)) { let tile = tileSets[level]; retour = template.replace("{TileMatrix}", tile.id); } return retour; }; const imageSize = { width: tileSets[0].tileWidth, height: tileSets[0].tileHeight }; const checkSize = tileSets.filter(elt => elt.tileWidth != imageSize.width || elt.tileHeight != imageSize.height); if (checkSize.length === 0) { resultat.imageSize = imageSize; } resultat.ready = true; } } } } return resultat as IResult; };