UNPKG

@itwin/core-frontend

Version:
232 lines • 12.1 kB
/*--------------------------------------------------------------------------------------------- * 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 */ import { BentleyError, BentleyStatus, Logger } from "@itwin/core-bentley"; import { RealityDataFormat, RealityDataProvider } from "@itwin/core-common"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import { CesiumIonAssetProvider, ContextShareProvider, getCesiumAssetUrl } from "./tile/internal"; import { RealityDataSourceTilesetUrlImpl } from "./RealityDataSourceTilesetUrlImpl"; import { RealityDataSourceContextShareImpl } from "./RealityDataSourceContextShareImpl"; import { RealityDataSourceCesiumIonAssetImpl } from "./RealityDataSourceCesiumIonAssetImpl"; import { RealityDataSourceGoogle3dTilesImpl } from "./internal/RealityDataSourceGoogle3dTilesImpl"; import { IModelApp } from "./IModelApp"; import { getCopyrights, GoogleMapsDecorator } from "./internal/GoogleMapsDecorator"; const loggerCategory = FrontendLoggerCategory.RealityData; /** * Reality Data Operation error * @alpha */ export class RealityDataError extends BentleyError { constructor(errorNumber, message, getMetaData) { super(errorNumber, message, getMetaData); } } /** Utility functions for RealityDataSource * @beta */ export var RealityDataSource; (function (RealityDataSource) { /** Create a RealityDataSourceKey from a tilesetUrl. * @param tilesetUrl the reality data attachment url * @param inputProvider identify the RealityDataProvider if known, otherwise function will try to extract it from the tilesetUrl * @param inputFormat identify the RealityDataFormat if known, otherwise function will try to extract it from the tilesetUrl * @returns the RealityDataSourceKey that uniquely identify a reality data for a provider */ function createKeyFromUrl(tilesetUrl, inputProvider, inputFormat) { let format = inputFormat ? inputFormat : RealityDataFormat.fromUrl(tilesetUrl); if (CesiumIonAssetProvider.isProviderUrl(tilesetUrl)) { const provider = RealityDataProvider.CesiumIonAsset; let cesiumIonAssetKey = { provider, format, id: CesiumIonAssetProvider.osmBuildingId }; // default OSM building // Parse URL to extract possible asset id and key if provided const cesiumAsset = CesiumIonAssetProvider.parseCesiumUrl(tilesetUrl); if (cesiumAsset) { cesiumIonAssetKey = RealityDataSource.createCesiumIonAssetKey(cesiumAsset.id, cesiumAsset.key); } return cesiumIonAssetKey; } // Try to extract realityDataId from URL and if not possible, use the url as the key if (ContextShareProvider.isProviderUrl(tilesetUrl)) { const info = ContextShareProvider.getInfoFromUrl(tilesetUrl); const provider = inputProvider ? inputProvider : info.provider; format = inputFormat ? inputFormat : info.format; const contextShareKey = { provider, format, id: info.id, iTwinId: info.iTwinId }; return contextShareKey; } // default to tileSetUrl const provider2 = inputProvider ? inputProvider : RealityDataProvider.TilesetUrl; const urlKey = { provider: provider2, format, id: tilesetUrl }; return urlKey; } RealityDataSource.createKeyFromUrl = createKeyFromUrl; /** @alpha - was used for a very specific case of point cloud (opc) attachment that should not be made public */ function createKeyFromBlobUrl(blobUrl, inputProvider, inputFormat) { const info = ContextShareProvider.getInfoFromBlobUrl(blobUrl); const format = inputFormat ? inputFormat : info.format; const provider = inputProvider ? inputProvider : info.provider; const contextShareKey = { provider, format, id: info.id }; return contextShareKey; } RealityDataSource.createKeyFromBlobUrl = createKeyFromBlobUrl; /** @alpha - OrbitGtBlobProps is alpha */ function createKeyFromOrbitGtBlobProps(orbitGtBlob, inputProvider, inputFormat) { const format = inputFormat ? inputFormat : RealityDataFormat.OPC; if (orbitGtBlob.blobFileName && orbitGtBlob.blobFileName.toLowerCase().startsWith("http")) { return RealityDataSource.createKeyFromBlobUrl(orbitGtBlob.blobFileName, inputProvider, format); } else if (orbitGtBlob.rdsUrl) { return RealityDataSource.createKeyFromUrl(orbitGtBlob.rdsUrl, inputProvider, format); } const provider = inputProvider ? inputProvider : RealityDataProvider.OrbitGtBlob; const id = `${orbitGtBlob.accountName}:${orbitGtBlob.containerName}:${orbitGtBlob.blobFileName}:?${orbitGtBlob.sasToken}`; return { provider, format, id }; } RealityDataSource.createKeyFromOrbitGtBlobProps = createKeyFromOrbitGtBlobProps; /** @alpha - OrbitGtBlobProps is alpha */ function createOrbitGtBlobPropsFromKey(rdSourceKey) { if (rdSourceKey.provider !== RealityDataProvider.OrbitGtBlob) return undefined; const splitIds = rdSourceKey.id.split(":"); const sasTokenIndex = rdSourceKey.id.indexOf(":?"); const sasToken = rdSourceKey.id.substring(sasTokenIndex + 2); const orbitGtBlob = { accountName: splitIds[0], containerName: splitIds[1], blobFileName: splitIds[2], sasToken, }; return orbitGtBlob; } RealityDataSource.createOrbitGtBlobPropsFromKey = createOrbitGtBlobPropsFromKey; /** @internal - Is used by "fdt attach cesium asset" keyin*/ function createCesiumIonAssetKey(osmAssetId, requestKey) { const id = getCesiumAssetUrl(osmAssetId, requestKey); return { provider: RealityDataProvider.CesiumIonAsset, format: RealityDataFormat.ThreeDTile, id }; } RealityDataSource.createCesiumIonAssetKey = createCesiumIonAssetKey; /** Return an instance of a RealityDataSource from a source key. * There will aways be only one reality data RealityDataSource for a corresponding reality data source key. * @alpha */ async function fromKey(key, iTwinId) { const provider = IModelApp.realityDataSourceProviders.find(key.provider); if (!provider) { Logger.logWarning(loggerCategory, `RealityDataSourceProvider "${key.provider}" is not registered`); return undefined; } return provider.createRealityDataSource(key, iTwinId); } RealityDataSource.fromKey = fromKey; })(RealityDataSource || (RealityDataSource = {})); /** A registry of [[RealityDataSourceProvider]]s identified by their unique names. The registry can be accessed via [[IModelApp.realityDataSourceProviders]]. * It includes a handful of built-in providers for sources like Cesium ION, ContextShare, OrbitGT, and arbitrary public-accessible URLs. * Any number of additional providers can be registered. They should typically be registered just after [[IModelApp.startup]]. * @beta */ export class RealityDataSourceProviderRegistry { _providers = new Map(); /** @internal */ constructor() { this.register(RealityDataProvider.CesiumIonAsset, { createRealityDataSource: async (key, iTwinId) => RealityDataSourceCesiumIonAssetImpl.createFromKey(key, iTwinId), }); this.register(RealityDataProvider.TilesetUrl, { createRealityDataSource: async (key, iTwinId) => RealityDataSourceTilesetUrlImpl.createFromKey(key, iTwinId), }); this.register(RealityDataProvider.ContextShare, { createRealityDataSource: async (key, iTwinId) => RealityDataSourceContextShareImpl.createFromKey(key, iTwinId), }); this.register(RealityDataProvider.OrbitGtBlob, { // ###TODO separate TilesetUrlImpl createRealityDataSource: async (key, iTwinId) => RealityDataSourceTilesetUrlImpl.createFromKey(key, iTwinId), }); } /** Register `provider` to produce [[RealityDataSource]]s for the specified provider `name`. */ register(name, provider) { this._providers.set(name, provider); } /** Look up the provider registered by the specified `name`. */ find(name) { return this._providers.get(name); } } /** * Will provide Google Photorealistic 3D Tiles (in 3dTile format). * A valid API key or getAuthToken fuction must be supplied when creating this provider. * To use this provider, you must register it with [[IModelApp.realityDataSourceProviders]]. * Example usage: * ```ts * [[include:GooglePhotorealistic3dTiles_providerApiKey]] * ``` * @see [Google Photorealistic 3D Tiles]($docs/learning/frontend/GooglePhotorealistic3dTiles.md) * @beta */ export class Google3dTilesProvider { /** Google Map Tiles API Key used to access Google 3D Tiles. */ _apiKey; /** Function that returns an OAuth token for authenticating with Google 3D Tiles. This token is expected to not contain the "Bearer" prefix. */ _getAuthToken; /** Decorator for Google Maps logos. */ _decorator; /** Enables cached decorations for this provider. @see [[ViewportDecorator.useCachedDecorations]] */ useCachedDecorations = true; async createRealityDataSource(key, iTwinId) { if (!this._apiKey && !this._getAuthToken) { Logger.logError(loggerCategory, "Either an API key or getAuthToken function are required to create a Google3dTilesProvider."); return undefined; } return RealityDataSourceGoogle3dTilesImpl.createFromKey(key, iTwinId, this._apiKey, this._getAuthToken); } constructor(options) { this._apiKey = options.apiKey; this._getAuthToken = options.getAuthToken; this._decorator = new GoogleMapsDecorator(options.showCreditsOnScreen ?? true); } /** * Initialize the Google 3D Tiles reality data source provider by activating its decorator, which consists of loading the correct Google Maps logo. * @returns `true` if the decorator was successfully activated, otherwise `false`. */ async initialize() { const isActivated = await this._decorator.activate("satellite"); if (!isActivated) { const msg = "Failed to activate decorator"; Logger.logError(loggerCategory, msg); throw new BentleyError(BentleyStatus.ERROR, msg); } return isActivated; } decorate(_context) { this._decorator.decorate(_context); } async addAttributions(cards, vp) { const copyrightMap = getCopyrights(vp); // Only add another logo card if the tiles have copyright if (copyrightMap.size > 0) { // Order by most occurances to least // See https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions const sortedCopyrights = [...copyrightMap.entries()].sort((a, b) => b[1] - a[1]); let copyrightMsg = "Data provided by:<br><ul>"; copyrightMsg += sortedCopyrights.map(([key]) => `<li>${key}</li>`).join(""); copyrightMsg += "</ul>"; const iconSrc = document.createElement("img"); iconSrc.src = `${IModelApp.publicPath}images/GoogleMaps_Logo_Gray.svg`; iconSrc.style.padding = "10px 10px 5px 10px"; cards.appendChild(IModelApp.makeLogoCard({ iconSrc, iconWidth: 98, heading: "Google Photorealistic 3D Tiles", notice: copyrightMsg })); } } } /** Returns the URL used for retrieving Google Photorealistic 3D Tiles. * @beta */ export function getGoogle3dTilesUrl() { return "https://tile.googleapis.com/v1/3dtiles/root.json"; } //# sourceMappingURL=RealityDataSource.js.map