@itwin/core-frontend
Version:
iTwin.js frontend components
200 lines • 10.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WmtsMapLayerImageryProvider = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Tiles
*/
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const internal_1 = require("../../../../tile/internal");
const tileMatrixSetToken = "{TileMatrixSet}";
const tileMatrixToken = "{TileMatrix}";
const tileColToken = "{TileCol}";
const tileRowToken = "{TileRow}";
class WmtsMapLayerImageryProvider extends internal_1.MapLayerImageryProvider {
_baseUrl;
_capabilities;
_preferredLayerTileMatrixSet = new Map();
_preferredLayerStyle = new Map();
displayedLayerName = "";
_resourceUrlTemplate;
_maximumZoomLevel;
get mutualExclusiveSubLayer() { return true; }
constructor(settings) {
super(settings, true);
this._maximumZoomLevel = this.defaultMaximumZoomLevel;
this._baseUrl = internal_1.WmsUtilities.getBaseUrl(this._settings.url);
}
async initialize() {
try {
this._capabilities = await internal_1.WmtsCapabilities.create(this._baseUrl);
this.initPreferredTileMatrixSet();
this.initPreferredStyle();
this.initDisplayedLayer();
this.initCartoRange();
this.initResourceUrl();
if (this._preferredLayerTileMatrixSet.size === 0 || this._preferredLayerStyle.size === 0)
throw new core_common_1.ServerError(core_bentley_1.IModelStatus.ValidationFailed, "");
}
catch (error) {
// Don't throw error if unauthorized status:
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
// When credentials will be provided, a new provider will be created, and initialization should be fine.
if (error?.status === 401) {
this.setStatus(internal_1.MapLayerImageryProviderStatus.RequireAuth);
}
else {
throw new core_common_1.ServerError(core_bentley_1.IModelStatus.ValidationFailed, "");
}
}
}
get maximumZoomLevel() { return this._maximumZoomLevel; }
initDisplayedLayer() {
const layers = this._capabilities?.contents?.layers;
if (0 === this._settings.subLayers.length && layers && layers.length > 0) {
// No sub-layers defined in settings, pick first layer from capabilities.
this.displayedLayerName = layers[0].identifier;
return;
}
// If sub-layers are defined in settings, pick the first one that is visible.
const firstDisplayedLayer = this._settings.subLayers.find((subLayer) => subLayer.visible);
this.displayedLayerName = firstDisplayedLayer ? firstDisplayedLayer.name : this._settings.subLayers[0].name;
}
initResourceUrl() {
const layersCapabilities = this._capabilities?.contents?.layers;
if (undefined === layersCapabilities) {
return;
}
const layerCapability = layersCapabilities.find((layer) => layer.identifier === this.displayedLayerName);
if (undefined === layerCapability) {
return;
}
let resourceUrl = layerCapability.resourceUrls.find((url) => url.format.includes("png"));
if (undefined === resourceUrl) {
// If no PNG resource URL is found, try to find a JPEG one.
resourceUrl = layerCapability.resourceUrls.find((url) => url.format.includes("jpeg") || url.format.includes("jpg"));
}
if (undefined !== resourceUrl
&& (resourceUrl.template.indexOf(tileMatrixToken) > 0
&& resourceUrl.template.indexOf(tileColToken) > 0
&& resourceUrl.template.indexOf(tileRowToken) > 0)) {
this._resourceUrlTemplate = resourceUrl.template;
}
}
// Each layer can be served in multiple tile matrix set (i.e. TileTree).
// We have to pick one for each layer: for now we look for a Google Maps compatible tile tree.
initPreferredTileMatrixSet() {
const googleMapsTms = this._capabilities?.contents?.getGoogleMapsCompatibleTileMatrixSet();
const wellGoogleKnownTms = googleMapsTms?.find((tms) => tms.wellKnownScaleSet?.toLowerCase().includes(internal_1.WmtsConstants.GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME));
this._capabilities?.contents?.layers.forEach((layer) => {
let preferredTms;
if (wellGoogleKnownTms && layer.tileMatrixSetLinks.some((tmsl) => tmsl.tileMatrixSet === wellGoogleKnownTms.identifier)) {
// Favor tile matrix set that was explicitly marked as GoogleMaps compatible
preferredTms = wellGoogleKnownTms;
}
else {
// Search all compatible tile set matrix if previous attempt didn't work.
// If more than one candidate is found, pick the tile set with the most LODs.
let tileMatrixSets = googleMapsTms?.filter((tms) => {
return layer.tileMatrixSetLinks.some((tmsl) => tmsl.tileMatrixSet === tms.identifier);
});
if (!tileMatrixSets || tileMatrixSets.length === 0) {
const eps4326CompatibleTms = this._capabilities?.contents?.getEpsg4326CompatibleTileMatrixSet();
tileMatrixSets = eps4326CompatibleTms?.filter((tms) => {
return layer.tileMatrixSetLinks.some((tmsl) => tmsl.tileMatrixSet === tms.identifier);
});
}
if (tileMatrixSets && tileMatrixSets.length === 1)
preferredTms = tileMatrixSets[0];
else if (tileMatrixSets && tileMatrixSets?.length > 1)
preferredTms = tileMatrixSets.reduce((prev, current) => (prev.tileMatrix.length > current.tileMatrix.length) ? prev : current);
}
if (preferredTms !== undefined) {
const tmsLink = layer.tileMatrixSetLinks.find((tmsl) => tmsl.tileMatrixSet === preferredTms.identifier);
this._preferredLayerTileMatrixSet.set(layer.identifier, { tileMatrixSet: preferredTms, limits: tmsLink?.tileMatrixSetLimits });
this._maximumZoomLevel = Math.max(this._maximumZoomLevel, preferredTms.tileMatrix.length - 1);
}
});
}
// Each layer can be published different style. We look for a style flagged as 'Default'.
initPreferredStyle() {
this._capabilities?.contents?.layers.forEach((layer) => {
let preferredStyle;
if (layer.styles.length === 1)
preferredStyle = layer.styles[0];
else if (layer.styles.length > 1) {
// If more than style is available, takes the default one, otherwise the first one.
const defaultStyle = layer.styles.find((style) => style.isDefault);
if (defaultStyle)
preferredStyle = defaultStyle;
else
preferredStyle = layer.styles[0];
}
if (preferredStyle)
this._preferredLayerStyle.set(layer.identifier, preferredStyle);
});
}
initCartoRange() {
const activeLayer = this._capabilities?.contents?.layers.find((layer) => layer.identifier === this.displayedLayerName);
if (activeLayer?.wsg84BoundingBox) {
if (this.cartoRange)
this.cartoRange.extendRange(activeLayer.wsg84BoundingBox);
else
this.cartoRange = activeLayer.wsg84BoundingBox.clone();
}
}
getDisplayedTileMatrixSetAndLimits() {
return this._preferredLayerTileMatrixSet.get(this.displayedLayerName);
}
_generateChildIds(quadId, resolveChildren) {
const childIds = this.getPotentialChildIds(quadId);
const matrixSetAndLimits = this.getDisplayedTileMatrixSetAndLimits();
if (!matrixSetAndLimits) {
(0, core_bentley_1.assert)(false); // Must always hava a matrix set.
return;
}
const limits = matrixSetAndLimits.limits?.[quadId.level + 1]?.limits;
if (!limits) {
resolveChildren(childIds);
return;
}
const availableChildIds = [];
for (const childId of childIds)
if (limits.containsXY(childId.column, childId.row))
availableChildIds.push(childId);
resolveChildren(availableChildIds);
}
get useGeographicTilingScheme() {
const matrixSetAndLimits = this.getDisplayedTileMatrixSetAndLimits();
return matrixSetAndLimits ? (matrixSetAndLimits?.tileMatrixSet.identifier?.includes("4326") || matrixSetAndLimits?.tileMatrixSet.supportedCrs?.includes("4326")) : false;
}
async constructUrl(row, column, zoomLevel) {
const matrixSetAndLimits = this.getDisplayedTileMatrixSetAndLimits();
const style = this._preferredLayerStyle.get(this.displayedLayerName);
// Matrix identifier might be something other than standard 0..n zoom level,
// so lookup the matrix identifier just in case.
let tileMatrix;
if (matrixSetAndLimits && matrixSetAndLimits.tileMatrixSet.tileMatrix.length > zoomLevel)
tileMatrix = matrixSetAndLimits.tileMatrixSet.tileMatrix[zoomLevel].identifier;
if (this._resourceUrlTemplate) {
const tmpUrl = this._resourceUrlTemplate
.replace(tileMatrixSetToken, matrixSetAndLimits?.tileMatrixSet.identifier ?? "")
.replace(tileMatrixToken, tileMatrix ?? zoomLevel.toString())
.replace(tileColToken, column.toString())
.replace(tileRowToken, row.toString());
return this.appendCustomParams(tmpUrl);
}
const styleParam = (style?.identifier === undefined ? "" : `&style=${style.identifier}`);
if (tileMatrix !== undefined && matrixSetAndLimits !== undefined) {
const tmpUrl = `${this._baseUrl}?Service=WMTS&Version=1.0.0&Request=GetTile&Format=image%2Fpng&layer=${this.displayedLayerName}${styleParam}&TileMatrixSet=${matrixSetAndLimits.tileMatrixSet.identifier}&TileMatrix=${tileMatrix}&TileCol=${column}&TileRow=${row}`;
return this.appendCustomParams(tmpUrl);
}
return "";
}
}
exports.WmtsMapLayerImageryProvider = WmtsMapLayerImageryProvider;
//# sourceMappingURL=WmtsMapLayerImageryProvider.js.map