@itwin/core-frontend
Version:
iTwin.js frontend components
503 lines • 23.8 kB
JavaScript
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Views
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WmtsCapabilities = exports.WmtsCapability = exports.WmtsConstants = void 0;
const core_geometry_1 = require("@itwin/core-geometry");
const internal_1 = require("../../../tile/internal");
var OwsConstants;
(function (OwsConstants) {
OwsConstants["ABSTRACT_XMLTAG"] = "ows:Abstract";
OwsConstants["ACCESSCONSTRAINTS_XMLTAG"] = "ows:AccessConstraints";
OwsConstants["ALLOWEDVALUES_XMLTAG"] = "ows:AllowedValues";
OwsConstants["BOUNDINGBOX_XMLTAG"] = "ows:BoundingBox";
OwsConstants["CONSTRAINT_XMLTAG"] = "ows:Constraint";
OwsConstants["DCP_XMLTAG"] = "ows:DCP";
OwsConstants["FEES_XMLTAG"] = "ows:Fees";
OwsConstants["GET_XMLTAG"] = "ows:Get";
OwsConstants["HTTP_XMLTAG"] = "ows:HTTP";
OwsConstants["IDENTIFIER_XMLTAG"] = "ows:Identifier";
OwsConstants["KEYWORDS_XMLTAG"] = "ows:Keywords";
OwsConstants["KEYWORD_XMLTAG"] = "ows:Keyword";
OwsConstants["LOWERCORNER_XMLTAG"] = "ows:LowerCorner";
OwsConstants["OPERATION_XMLTAG"] = "ows:Operation";
OwsConstants["OPERATIONSMETADATA_XMLTAG"] = "ows:OperationsMetadata";
OwsConstants["POST_XMLTAG"] = "ows:Post";
OwsConstants["SERVICEIDENTIFICATION_XMLTAG"] = "ows:ServiceIdentification";
OwsConstants["SERVICETYPE_XMLTAG"] = "ows:ServiceType";
OwsConstants["SERVICETYPEVERSION_XMLTAG"] = "ows:ServiceTypeVersion";
OwsConstants["SUPPORTEDCRS_XMLTAG"] = "ows:SupportedCRS";
OwsConstants["TITLE_XMLTAG"] = "ows:Title";
OwsConstants["UPPERCORNER_XMLTAG"] = "ows:UpperCorner";
OwsConstants["VALUE_XMLTAG"] = "ows:Value";
OwsConstants["WGS84BOUNDINGBOX_XMLTAG"] = "ows:WGS84BoundingBox";
})(OwsConstants || (OwsConstants = {}));
var XmlConstants;
(function (XmlConstants) {
// Operations names
XmlConstants["GETCAPABILITIES"] = "GetCapabilities";
XmlConstants["GETTILE"] = "GetTile";
XmlConstants["GETFEATUREINFO"] = "GetFeatureInfo";
XmlConstants["MATRIXWIDTH_XMLTAG"] = "MatrixWidth";
XmlConstants["MATRIXHEIGHT_XMLTAG"] = "MatrixHeight";
XmlConstants["SCALEDENOMINATOR_XMLTAG"] = "ScaleDenominator";
XmlConstants["TILEHEIGHT_XMLTAG"] = "TileHeight";
XmlConstants["TILEMATRIX_XMLTAG"] = "TileMatrix";
XmlConstants["TILEMATRIXSETLINK_XMLTAG"] = "TileMatrixSetLink";
XmlConstants["RESOURCEURL_XMLTAG"] = "ResourceURL";
XmlConstants["TILEWIDTH_XMLTAG"] = "TileWidth";
XmlConstants["TOPLEFTCORNER_XMLTAG"] = "TopLeftCorner";
XmlConstants["WELLKNOWNSCALESET_XMLTAG"] = "WellKnownScaleSet";
XmlConstants["CONSTRAINT_NAME_FILTER"] = "Encoding";
XmlConstants["STYLE_ISDEFAULT"] = "IsDefault";
XmlConstants["XLINK_HREF"] = "xlink:href";
})(XmlConstants || (XmlConstants = {}));
var WmtsConstants;
(function (WmtsConstants) {
WmtsConstants[WmtsConstants["GOOGLEMAPS_LEVEL0_SCALE_DENOM"] = 559082264.0287178] = "GOOGLEMAPS_LEVEL0_SCALE_DENOM";
WmtsConstants["GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME"] = "googlemapscompatible";
})(WmtsConstants || (exports.WmtsConstants = WmtsConstants = {}));
/**
* Utility function to extract an element' text content
* @return An element's text content, default to provided defaultTest value if no text is available.
* @param url server URL to address the request
*/
const getElementTextContent = (elem, qualifiedName, defaultText) => {
const tmpElem = elem.getElementsByTagName(qualifiedName);
if (tmpElem.length > 0) {
return tmpElem[0].textContent ?? defaultText;
}
else
return defaultText;
};
/** Encapsulation of the capabilities for an WMTS server
*/
var WmtsCapability;
(function (WmtsCapability) {
class ServiceIdentification {
abstract;
accessConstraints;
fees;
serviceType;
serviceTypeVersion;
title;
keywords;
constructor(elem) {
this.abstract = getElementTextContent(elem, OwsConstants.ABSTRACT_XMLTAG);
this.serviceType = getElementTextContent(elem, OwsConstants.SERVICETYPE_XMLTAG);
this.serviceTypeVersion = getElementTextContent(elem, OwsConstants.SERVICETYPEVERSION_XMLTAG);
this.title = getElementTextContent(elem, OwsConstants.TITLE_XMLTAG);
const keywords = elem.getElementsByTagName(OwsConstants.KEYWORDS_XMLTAG);
if (keywords.length > 0) {
const keyword = keywords[0].getElementsByTagName(OwsConstants.KEYWORD_XMLTAG);
this.keywords = [];
for (const keyworkElem of keyword) {
const keyWordText = keyworkElem.textContent;
if (keyWordText)
this.keywords.push(keyWordText);
}
}
this.accessConstraints = getElementTextContent(elem, OwsConstants.ACCESSCONSTRAINTS_XMLTAG);
this.fees = getElementTextContent(elem, OwsConstants.FEES_XMLTAG);
}
}
WmtsCapability.ServiceIdentification = ServiceIdentification;
class OperationMetadata {
_getCapabilities;
get getCapabilities() { return this._getCapabilities; }
_getFeatureInfo;
get getFeatureInfo() { return this._getFeatureInfo; }
_getTile;
get getTile() { return this._getTile; }
readOperation(op) {
const nameAttr = op.attributes.getNamedItem("name");
if (!nameAttr)
return;
if (nameAttr.textContent === XmlConstants.GETCAPABILITIES) {
this._getCapabilities = new Operation(op);
}
else if (nameAttr.textContent === XmlConstants.GETTILE) {
this._getTile = new Operation(op);
}
else if (nameAttr.textContent === XmlConstants.GETFEATUREINFO) {
this._getFeatureInfo = new Operation(op);
}
}
constructor(elem) {
const operation = elem.getElementsByTagName(OwsConstants.OPERATION_XMLTAG);
if (operation.length > 0) {
for (const op of operation) {
this.readOperation(op);
}
}
}
}
WmtsCapability.OperationMetadata = OperationMetadata;
class HttpDcp {
url;
constraintName;
// For simplicity of use we create a 'static' encoding property instead of having
// a generic constraint data model.
// We make sure the constraint name is 'encoding' related.
encoding;
constructor(elem) {
const url = elem.getAttribute(XmlConstants.XLINK_HREF);
if (url)
this.url = url ?? "";
const constraint = elem.getElementsByTagName(OwsConstants.CONSTRAINT_XMLTAG);
if (constraint.length > 0) {
this.constraintName = constraint[0].getAttribute("name") ?? "";
if (this.constraintName?.endsWith(XmlConstants.CONSTRAINT_NAME_FILTER)) {
const allowedValues = constraint[0].getElementsByTagName(OwsConstants.ALLOWEDVALUES_XMLTAG);
if (allowedValues.length > 0) {
this.encoding = getElementTextContent(allowedValues[0], OwsConstants.VALUE_XMLTAG);
}
}
}
}
}
WmtsCapability.HttpDcp = HttpDcp;
class Operation {
name;
_getDcpHttp;
get getDcpHttp() { return this._getDcpHttp; }
_postDcpHttp;
get postDcpHttp() { return this._postDcpHttp; }
constructor(elem) {
const name = elem.getAttribute("name");
if (name)
this.name = name;
const dcp = elem.getElementsByTagName(OwsConstants.DCP_XMLTAG);
if (!dcp || dcp.length === 0)
return;
const dcpHttp = dcp[0].getElementsByTagName(OwsConstants.HTTP_XMLTAG);
if (!dcpHttp || dcpHttp.length === 0)
return;
const get = dcpHttp[0].getElementsByTagName(OwsConstants.GET_XMLTAG);
if (get.length > 0) {
this._getDcpHttp = [];
for (const getItem of get) {
this._getDcpHttp?.push(new HttpDcp(getItem));
}
}
const post = dcpHttp[0].getElementsByTagName(OwsConstants.POST_XMLTAG);
if (post.length > 0) {
this._postDcpHttp = [];
for (const postItem of post) {
this._postDcpHttp?.push(new HttpDcp(postItem));
}
}
}
}
WmtsCapability.Operation = Operation;
class Contents {
layers = [];
tileMatrixSets = [];
constructor(elem) {
// Layers
const layer = elem.getElementsByTagName("Layer");
if (layer) {
for (const layerElem of layer)
this.layers.push(new Layer(layerElem));
}
// TileMatrixSet
const tms = elem.querySelectorAll("Contents > TileMatrixSet");
if (tms) {
for (const tmsElem of tms)
this.tileMatrixSets.push(new TileMatrixSet(tmsElem));
}
}
getGoogleMapsCompatibleTileMatrixSet() {
const googleMapsTms = [];
this.tileMatrixSets.forEach((tms) => {
if (tms.wellKnownScaleSet?.toLowerCase().includes(WmtsConstants.GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME))
googleMapsTms.push(tms);
// In case wellKnownScaleSet was not been set properly, infer from scaleDenominator
// Note: some servers are quite inaccurate in their scale values, hence I used a delta value of 1.
else if (tms.tileMatrix.length > 0
&& Math.abs(tms.tileMatrix[0].scaleDenominator - WmtsConstants.GOOGLEMAPS_LEVEL0_SCALE_DENOM) < 1
&& (tms.supportedCrs.includes("3857") || tms.supportedCrs.includes("900913")))
googleMapsTms.push(tms);
});
return googleMapsTms;
}
getEpsg4326CompatibleTileMatrixSet() {
return this.tileMatrixSets.filter((tms) => tms.supportedCrs.includes("4326"));
}
}
WmtsCapability.Contents = Contents;
class Style {
isDefault = false;
title;
identifier;
// TODO: LegendURL
constructor(elem) {
if (!elem)
return;
const isDefault = elem.getAttribute("isDefault");
if (isDefault)
this.isDefault = isDefault.toLowerCase() === "true";
this.title = getElementTextContent(elem, OwsConstants.TITLE_XMLTAG);
this.identifier = getElementTextContent(elem, OwsConstants.IDENTIFIER_XMLTAG);
}
}
WmtsCapability.Style = Style;
class BoundingBox {
crs;
range;
constructor(elem) {
this.crs = elem.getAttribute("crs") ?? undefined;
const lowerCorner = getElementTextContent(elem, OwsConstants.LOWERCORNER_XMLTAG);
const upperCorner = getElementTextContent(elem, OwsConstants.UPPERCORNER_XMLTAG);
if (lowerCorner && upperCorner) {
const lowerCornerArray = lowerCorner?.split(" ").map((x) => +x);
const upperCornerArray = upperCorner?.split(" ").map((x) => +x);
if (lowerCornerArray && lowerCornerArray.length === 2 && upperCornerArray && upperCornerArray.length === 2)
this.range = core_geometry_1.Range2d.createXYXY(lowerCornerArray[0], lowerCornerArray[1], upperCornerArray[0], upperCornerArray[1]);
}
}
}
WmtsCapability.BoundingBox = BoundingBox;
class TileMatrixSetLimits {
limits;
tileMatrix;
constructor(elem) {
this.tileMatrix = getElementTextContent(elem, "TileMatrix");
const minTileRow = getElementTextContent(elem, "MinTileRow");
const maxTileRow = getElementTextContent(elem, "MaxTileRow");
const minTileCol = getElementTextContent(elem, "MinTileCol");
const maxTileCol = getElementTextContent(elem, "MaxTileCol");
if (minTileRow !== undefined && maxTileRow !== undefined && minTileCol !== undefined && maxTileCol)
this.limits = core_geometry_1.Range2d.createXYXY(Number(minTileCol), Number(minTileRow), Number(maxTileCol), Number(maxTileRow));
}
}
WmtsCapability.TileMatrixSetLimits = TileMatrixSetLimits;
class TileMatrixSetLink {
tileMatrixSet;
tileMatrixSetLimits = new Array();
constructor(elem) {
this.tileMatrixSet = getElementTextContent(elem, "TileMatrixSet", "");
const tileMatrixLimitsRoot = elem.getElementsByTagName("TileMatrixSetLimits");
if (tileMatrixLimitsRoot.length > 0) {
const tileMatrixLimits = tileMatrixLimitsRoot[0].getElementsByTagName("TileMatrixSetLimits");
for (const tmsl of tileMatrixLimits) {
this.tileMatrixSetLimits.push(new TileMatrixSetLimits(tmsl));
}
}
}
}
WmtsCapability.TileMatrixSetLink = TileMatrixSetLink;
class ResourceURL {
format;
resourceType;
template;
constructor(elem) {
this.format = elem.getAttribute("format") ?? "";
this.resourceType = elem.getAttribute("resourceType") ?? "";
this.template = elem.getAttribute("template") ?? "";
}
}
WmtsCapability.ResourceURL = ResourceURL;
class TileMatrixSet {
identifier;
title;
abstract;
supportedCrs;
wellKnownScaleSet;
tileMatrix = [];
constructor(elem) {
const identifier = getElementTextContent(elem, OwsConstants.IDENTIFIER_XMLTAG);
if (identifier)
this.identifier = identifier;
else
throw new Error("No Identifier found.");
this.title = getElementTextContent(elem, OwsConstants.TITLE_XMLTAG);
this.abstract = getElementTextContent(elem, OwsConstants.ABSTRACT_XMLTAG);
const supportedCrs = getElementTextContent(elem, OwsConstants.SUPPORTEDCRS_XMLTAG);
if (supportedCrs)
this.supportedCrs = supportedCrs;
else
throw new Error("No supported CRS found.");
this.wellKnownScaleSet = getElementTextContent(elem, XmlConstants.WELLKNOWNSCALESET_XMLTAG, "");
// TileMatrix:
// TileMatrix is mandatory on TileMatrixSet, if it doesn't exists, something is OFF with the capability.
const tileMatrix = elem.getElementsByTagName(XmlConstants.TILEMATRIX_XMLTAG);
if (tileMatrix.length === 0)
throw new Error("No matrix set link found for WMTS layer");
for (const tm of tileMatrix) {
this.tileMatrix.push(new TileMatrix(tm));
}
}
}
WmtsCapability.TileMatrixSet = TileMatrixSet;
class TileMatrix {
identifier;
title;
abstract;
scaleDenominator;
topLeftCorner;
tileWidth;
tileHeight;
matrixWidth;
matrixHeight;
constructor(elem) {
const identifier = getElementTextContent(elem, OwsConstants.IDENTIFIER_XMLTAG, "");
if (identifier)
this.identifier = identifier;
else
throw new Error("No Identifier found.");
this.title = getElementTextContent(elem, OwsConstants.TITLE_XMLTAG);
this.abstract = getElementTextContent(elem, OwsConstants.ABSTRACT_XMLTAG);
// Scale denominator
const scaleDenom = getElementTextContent(elem, XmlConstants.SCALEDENOMINATOR_XMLTAG, "");
if (!scaleDenom)
throw new Error("No scale denominator found on TileMatrix.");
this.scaleDenominator = +scaleDenom;
// Top left corner
const topLeftCorner = getElementTextContent(elem, XmlConstants.TOPLEFTCORNER_XMLTAG, "")?.split(" ").map((x) => +x);
if (topLeftCorner?.length !== 2)
throw new Error("No TopLeftCorner found on TileMatrix.");
this.topLeftCorner = core_geometry_1.Point2d.create(topLeftCorner[0], topLeftCorner[1]);
// Tile Width
const tileWidth = getElementTextContent(elem, XmlConstants.TILEWIDTH_XMLTAG);
if (!tileWidth)
throw new Error("No tile width found on TileMatrix.");
this.tileWidth = +tileWidth;
// Tile Height
const tileHeight = getElementTextContent(elem, XmlConstants.TILEHEIGHT_XMLTAG);
if (!tileHeight)
throw new Error("No tile height found on TileMatrix.");
this.tileHeight = +tileHeight;
// Matrix Width
const matrixWidth = getElementTextContent(elem, XmlConstants.MATRIXWIDTH_XMLTAG);
if (!matrixWidth)
throw new Error("No tile width found on TileMatrix.");
this.matrixWidth = +matrixWidth;
// Matrix Height
const matrixHeight = getElementTextContent(elem, XmlConstants.MATRIXHEIGHT_XMLTAG);
if (!matrixHeight)
throw new Error("No tile height found on TileMatrix.");
this.matrixHeight = +matrixHeight;
}
}
WmtsCapability.TileMatrix = TileMatrix;
class Layer {
identifier;
title;
abstract;
format;
wsg84BoundingBox;
boundingBox;
styles = [];
tileMatrixSetLinks = [];
resourceUrls = [];
constructor(elem) {
const identifier = getElementTextContent(elem, OwsConstants.IDENTIFIER_XMLTAG, "");
if (identifier)
this.identifier = identifier;
else
throw new Error("No Identifier found.");
this.title = getElementTextContent(elem, OwsConstants.TITLE_XMLTAG);
this.format = getElementTextContent(elem, "Format");
// BoundingBox
const boundingBox = elem.getElementsByTagName(OwsConstants.BOUNDINGBOX_XMLTAG);
if (boundingBox.length > 0)
this.boundingBox = new BoundingBox(boundingBox[0]);
let lowerCornerArray, upperCornerArray;
const bbox = elem.getElementsByTagName(OwsConstants.WGS84BOUNDINGBOX_XMLTAG);
if (bbox.length > 0) {
lowerCornerArray = getElementTextContent(bbox[0], OwsConstants.LOWERCORNER_XMLTAG)?.split(" ").map((x) => +x);
upperCornerArray = getElementTextContent(bbox[0], OwsConstants.UPPERCORNER_XMLTAG)?.split(" ").map((x) => +x);
}
if (lowerCornerArray?.length === 2 && upperCornerArray?.length === 2)
this.wsg84BoundingBox = internal_1.MapCartoRectangle.fromDegrees(lowerCornerArray[0], lowerCornerArray[1], upperCornerArray[0], upperCornerArray[1]);
// If we could not initialized WSG84 bounding box, attempt to initialized it from Bounding Box
if (!this.wsg84BoundingBox && (this.boundingBox?.crs?.includes("EPSG:4326") || this.boundingBox?.crs?.includes("CRS:84"))) {
const range = this.boundingBox.range;
if (range)
this.wsg84BoundingBox = internal_1.MapCartoRectangle.fromDegrees(range.low.x, range.low.y, range.high.x, range.high.y);
else
this.wsg84BoundingBox = internal_1.MapCartoRectangle.createMaximum();
}
// Style
const style = elem.getElementsByTagName("Style");
if (style.length > 0) {
for (const styleElem of style)
this.styles.push(new Style(styleElem));
}
// TileMatrixSetLink
// TileMatrixSetLink is mandatory on Layer, if it doesn't exists, something is OFF with the capability.
const tileMatrixSetLink = elem.getElementsByTagName(XmlConstants.TILEMATRIXSETLINK_XMLTAG);
if (tileMatrixSetLink.length === 0)
throw new Error("No matrix set link found for WMTS layer");
for (const tmsl of tileMatrixSetLink)
this.tileMatrixSetLinks.push(new TileMatrixSetLink(tmsl));
// ResourceURL are optional. It can be repeated for different resource types.
const resourceUrls = elem.getElementsByTagName(XmlConstants.RESOURCEURL_XMLTAG);
for (const url of resourceUrls)
this.resourceUrls.push(new ResourceURL(url));
}
}
WmtsCapability.Layer = Layer;
})(WmtsCapability || (exports.WmtsCapability = WmtsCapability = {}));
class WmtsCapabilities {
static _capabilitiesCache = new Map();
version;
serviceIdentification;
contents;
operationsMetadata;
constructor(xmlDoc) {
const capabilities = xmlDoc.getElementsByTagName("Capabilities");
if (capabilities.length !== 0) {
const capability = capabilities[0];
this.version = capability.getAttribute("version") ?? undefined;
// Service Identification
const serviceIdentification = capability.getElementsByTagName(OwsConstants.SERVICEIDENTIFICATION_XMLTAG);
if (serviceIdentification.length > 0)
this.serviceIdentification = new WmtsCapability.ServiceIdentification(serviceIdentification[0]);
// Operations metadata
const operationsMetadata = capability.getElementsByTagName(OwsConstants.OPERATIONSMETADATA_XMLTAG);
if (operationsMetadata.length > 0)
this.operationsMetadata = new WmtsCapability.OperationMetadata(operationsMetadata[0]);
// Contents
const content = capability.getElementsByTagName("Contents");
if (content.length > 0)
this.contents = new WmtsCapability.Contents(content[0]);
}
}
static createFromXml(xmlCapabilities) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlCapabilities, "text/xml");
return new WmtsCapabilities(xmlDoc);
}
static async create(url, credentials, ignoreCache, queryParams) {
if (!ignoreCache) {
const cached = WmtsCapabilities._capabilitiesCache.get(url);
if (cached !== undefined)
return cached;
}
const tmpUrl = new URL(internal_1.WmsUtilities.getBaseUrl(url));
tmpUrl.searchParams.append("request", "GetCapabilities");
tmpUrl.searchParams.append("service", "WMTS");
if (queryParams) {
Object.keys(queryParams).forEach((paramKey) => {
if (!tmpUrl.searchParams.has(paramKey))
tmpUrl.searchParams.append(paramKey, queryParams[paramKey]);
});
}
const xmlCapabilities = await internal_1.WmsUtilities.fetchXml(tmpUrl.toString(), credentials);
if (!xmlCapabilities)
return undefined;
const capabilities = WmtsCapabilities.createFromXml(xmlCapabilities);
if (capabilities)
WmtsCapabilities._capabilitiesCache.set(url, capabilities);
return capabilities;
}
}
exports.WmtsCapabilities = WmtsCapabilities;
//# sourceMappingURL=WmtsCapabilities.js.map