UNPKG

@itwin/core-frontend

Version:
225 lines • 10.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 { request } from "./request/Request"; import { assert, Logger } from "@itwin/core-bentley"; import { RealityDataFormat, RealityDataProvider } from "@itwin/core-common"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import { IModelApp } from "./IModelApp"; import { OPCFormatInterpreter, ThreeDTileFormatInterpreter } from "./tile/internal"; /** This class provides access to the reality data provider services. * It encapsulates access to a reality data weiter it be from local access, http or ProjectWise Context Share. * The key provided at the creation determines if this is ProjectWise Context Share reference. * If not then it is considered local (ex: C:\temp\TileRoot.json) or plain http access (http://someserver.com/data/TileRoot.json) * There is a one to one relationship between a reality data and the instances of present class. * @internal */ export class RealityDataSourceContextShareImpl { key; /** The URL that supplies the 3d tiles for displaying the reality model. */ _tilesetUrl; _isUrlResolved = false; _rd; /** For use by all Reality Data. For RD stored on PW Context Share, represents the portion from the root of the Azure Blob Container*/ _baseUrl = ""; /** Construct a new reality data source. * @param props JSON representation of the reality data source */ constructor(props) { // this implementaiton is specific to ContextShare provider assert(props.sourceKey.provider === RealityDataProvider.ContextShare); this.key = props.sourceKey; this._isUrlResolved = false; } /** * Create an instance of this class from a source key and iTwin context/ */ static async createFromKey(sourceKey, iTwinId) { if (sourceKey.provider !== RealityDataProvider.ContextShare) return undefined; const rdSource = new RealityDataSourceContextShareImpl({ sourceKey }); let tilesetUrl; try { await rdSource.queryRealityData(iTwinId); tilesetUrl = await rdSource.getServiceUrl(iTwinId); } catch { } return (tilesetUrl !== undefined) ? rdSource : undefined; } get isContextShare() { return (this.key.provider === RealityDataProvider.ContextShare); } /** * Returns Reality Data if available */ get realityData() { return this._rd; } get realityDataId() { const realityDataId = this.key.id; return realityDataId; } /** * Returns Reality Data type if available */ get realityDataType() { return this._rd?.type; } /** * Query Reality Data from provider */ async queryRealityData(iTwinId) { if (!this._rd) { const token = await IModelApp.getAccessToken(); if (token && this.realityDataId) { if (undefined === IModelApp.realityDataAccess) throw new Error("Missing an implementation of RealityDataAccess on IModelApp, it is required to access reality data. Please provide an implementation to the IModelApp.startup using IModelAppOptions.realityDataAccess."); this._rd = await IModelApp.realityDataAccess.getRealityData(token, iTwinId, this.realityDataId); // A reality data that has not root document set should not be considered. const rootDocument = this._rd.rootDocument ?? ""; this.setBaseUrl(rootDocument); } } } // This is to set the root url from the provided root document path. // If the root document is stored on PW Context Share then the root document property of the Reality Data is provided, // otherwise the full path to root document is given. // The base URL contains the base URL from which tile relative path are constructed. // The tile's path root will need to be reinserted for child tiles to return a 200 setBaseUrl(url) { const urlParts = url.split("/"); urlParts.pop(); if (urlParts.length === 0) this._baseUrl = ""; else this._baseUrl = `${urlParts.join("/")}/`; } /** * Gets a tileset's app data json * @param name name or path of tile * @returns app data json object * @internal */ async getRealityDataTileJson(accessToken, name, realityData) { const url = await realityData.getBlobUrl(accessToken, name); return request(url.toString(), "json"); } /** * This method returns the URL to access the actual 3d tiles from the service provider. * @returns string containing the URL to reality data. */ async getServiceUrl(iTwinId) { // If url was not resolved - resolve it if (!this._isUrlResolved) { const rdSourceKey = this.key; // we need to resolve tilesetURl from realityDataId and iTwinId if (undefined === IModelApp.realityDataAccess) throw new Error("Missing an implementation of RealityDataAccess on IModelApp, it is required to access reality data. Please provide an implementation to the IModelApp.startup using IModelAppOptions.realityDataAccess."); try { const resolvedITwinId = iTwinId ? iTwinId : rdSourceKey.iTwinId; this._tilesetUrl = await IModelApp.realityDataAccess.getRealityDataUrl(resolvedITwinId, rdSourceKey.id); this._isUrlResolved = true; } catch { const errMsg = `Error getting URL from ContextShare using realityDataId=${rdSourceKey.id} and iTwinId=${iTwinId}`; Logger.logError(FrontendLoggerCategory.RealityData, errMsg); } } return this._tilesetUrl; } async getRootDocument(_iTwinId) { const token = await IModelApp.getAccessToken(); if (token) { const realityData = this.realityData; if (!realityData) throw new Error(`Reality Data not defined`); if (!realityData.rootDocument) throw new Error(`Root document not defined for reality data: ${realityData.id}`); return this.getRealityDataTileJson(token, realityData.rootDocument, realityData); } } /** * Gets tile content * @param name name or path of tile * @returns array buffer of tile content */ async getRealityDataTileContent(accessToken, name, realityData) { const url = await realityData.getBlobUrl(accessToken, name); return request(url.toString(), "arraybuffer"); } /** * Returns the tile content. The path to the tile is relative to the base url of present reality data whatever the type. */ async getTileContent(name) { const token = await IModelApp.getAccessToken(); const tileUrl = this._baseUrl + name; if (this.realityData) { return this.getRealityDataTileContent(token, tileUrl, this.realityData); } return undefined; } /** * Returns the tile content in json format. The path to the tile is relative to the base url of present reality data whatever the type. */ async getTileJson(name) { const token = await IModelApp.getAccessToken(); const tileUrl = this._baseUrl + name; if (this.realityData) { return this.getRealityDataTileJson(token, tileUrl, this.realityData); } return undefined; } getTileContentType(url) { return url.endsWith("json") ? "tileset" : "tile"; } /** * Gets spatial location and extents of this reality data source * @returns spatial location and extents * @internal */ async getSpatialLocationAndExtents() { let spatialLocation; const fileType = this.realityDataType; // Mapping Resource are not currenlty supported if (fileType === "OMR") return undefined; if (this.key.format === RealityDataFormat.ThreeDTile) { const rootDocument = await this.getRootDocument(undefined); spatialLocation = ThreeDTileFormatInterpreter.getSpatialLocationAndExtents(rootDocument); } else if (this.key.format === RealityDataFormat.OPC) { if (this.realityData === undefined) return undefined; const token = await IModelApp.getAccessToken(); const docRootName = this.realityData.rootDocument; if (!docRootName) return undefined; const blobUrl = await this.realityData.getBlobUrl(token, docRootName); if (!blobUrl) return undefined; const blobStringUrl = blobUrl.toString(); const filereader = await OPCFormatInterpreter.getFileReaderFromBlobFileURL(blobStringUrl); spatialLocation = await OPCFormatInterpreter.getSpatialLocationAndExtents(filereader); } return spatialLocation; } /** * Gets information to identify the product and engine that create this reality data * Will return undefined if cannot be resolved * @returns information to identify the product and engine that create this reality data * @alpha */ async getPublisherProductInfo() { let publisherInfo; if (this.key.format === RealityDataFormat.ThreeDTile) { const rootDocument = await this.getRootDocument(undefined); publisherInfo = ThreeDTileFormatInterpreter.getPublisherProductInfo(rootDocument); } return publisherInfo; } } //# sourceMappingURL=RealityDataSourceContextShareImpl.js.map