UNPKG

cesium-geoserverterrainprovider

Version:
149 lines (136 loc) 6.7 kB
import { arrayToBuffer, defaultDescription, type IDescription, type IFormatArray, imageToBuffer, type IResult } from './utils'; import { generate as tmsParser } from './tmsParser'; import { generate as wmsParser } from './wmsParser'; import { generate as wmtsParser } from './wmtsParser'; import { GeoserverTerrainProvider as provider } from './terrainProvider'; const C: typeof import('cesium') = (window as any).Cesium; const { fetchArrayBuffer: loadArrayBuffer, fetchImage: loadImage } = C.Resource; /** * parse wms,TMS or WMTS url from an url and a layer. request metadata information on server. * * * @param {String} * description.layerName the name of the layer. * @param {String} * [description.url] The URL of the server providing wms. * @param {String} * [description.xml] the xml after requesting "getCapabilities" * from web map server. * @param {String} * [description.service] the type of service requested (WMS,TMS,WMTS). WMS is default * from web map server. * @param {Object} * [description.proxy] A proxy to use for requests. custom object * is expected to have a getURL function which returns the * proxied URL, if needed. * @param {Number} * [description.heightMapWidth] width of a tile in pixels * @param {Number} * [description.heightMapHeight] height of a tile in pixels * @param {Number} * [description.offset] offset of the tiles (in meters) * @param {Number} * [description.highest] highest altitude in the tiles (in meters) * @param {Number} * [description.lowest] lowest altitude in the tiles (in meters) * @param {String} * [description.styleName] name of the Style used for images. * @param {boolean} * [description.hasStyledImage] indicates if the requested images are styled with SLD * @param {Number} * [description.maxLevel] maximum level to request * @param {Object} * [description.formatImage] see OGCHelper.FormatImage * @param {Object} * [description.formatArray] see OGCHelper.FormatArray * return a promise of GeoserverTerrainProvider: */ export async function GeoserverTerrainProvider(description: IDescription) { description = Object.assign(defaultDescription, description); let resultat: Promise<IResult>; switch (description.service) { case "TMS": resultat = tmsParser(description); break; case "WMTS": resultat = wmtsParser(description); break; default: resultat = wmsParser(description); } const end = await resultat; TerrainParser(end); if (description.service === 'WMTS') { return new provider(end); } else { return new C.CustomHeightmapTerrainProvider({ height: end.heightMapHeight, width: end.heightMapWidth, tilingScheme: end.tilingScheme, callback: end.GeometryCallback }); } } (window as any).Cesium.GeoserverTerrainProvider = GeoserverTerrainProvider; export function TerrainParser(resultat: IResult) { resultat.levelZeroMaximumGeometricError = C.TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap( resultat.tilingScheme.ellipsoid, resultat.heightMapWidth, resultat.tilingScheme.getNumberOfXTilesAtLevel(0)); if (resultat.URLtemplateImage) { resultat.getBufferImage = async (x, y, level) => { let retour: Int16Array = null; if (!isNaN(x + y + level)) { const urlArray = templateToURL(resultat.URLtemplateImage(x, y, level), x, y, level, resultat); const limitations = { highest: resultat.highest, lowest: resultat.lowest, offset: resultat.offset }; let promise = loadImage({ url: urlArray }); retour = await promise.then((image) => imageToBuffer(image as HTMLImageElement, limitations, { width: resultat.heightMapWidth, height: resultat.heightMapHeight }, resultat.hasStyledImage)) .catch(() => new Int16Array(resultat.heightMapWidth * resultat.heightMapHeight)); } return retour; }; } if (resultat.URLtemplateArray) { resultat.getBufferArray = async (x, y, level) => { let retour: Int16Array | Float32Array = null; if (!isNaN(x + y + level)) { const urlArray = templateToURL(resultat.URLtemplateArray(x, y, level), x, y, level, resultat); const limitations = { highest: resultat.highest, lowest: resultat.lowest, offset: resultat.offset }; let promise = loadArrayBuffer({ url: urlArray }); retour = await promise.then((arrayBuffer) => arrayToBuffer(arrayBuffer, limitations, { width: resultat.heightMapWidth, height: resultat.heightMapHeight }, resultat.formatArray as IFormatArray)) .catch(() => new Int16Array(resultat.heightMapWidth * resultat.heightMapHeight)); } return retour; }; } resultat.GeometryCallback = async (x: number, y: number, level: number) => { let retour: Int16Array | Float32Array; if (resultat.getBufferArray) { retour = await resultat.getBufferArray(x, y, level) as Int16Array | Float32Array; } else if (resultat.getBufferImage) { retour = await resultat.getBufferImage(x, y, level) as Int16Array | Float32Array; } return retour; } } function templateToURL(urlParam: string, x: number, y: number, level: number, resultat: IResult) { const rect = resultat.tilingScheme.tileXYToNativeRectangle(x, y, level); const xSpacing = (rect.east - rect.west) / (resultat.heightMapWidth - 1); const ySpacing = (rect.north - rect.south) / (resultat.heightMapHeight - 1); rect.west -= xSpacing * 0.5; rect.east += xSpacing * 0.5; rect.south -= ySpacing * 0.5; rect.north += ySpacing * 0.5; const yTiles = resultat.tilingScheme.getNumberOfYTilesAtLevel(level); const tmsY = (yTiles - y - 1); return urlParam.replace("{south}", rect.south.toString()).replace("{north}", rect.north.toString()).replace("{west}", rect.west.toString()) .replace("{east}", rect.east.toString()).replace("{x}", x.toString()).replace("{y}", y.toString()).replace("{tmsY}", tmsY.toString()); }