@itwin/core-frontend
Version:
iTwin.js frontend components
91 lines • 5.57 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { Cartographic, EcefLocation } from "@itwin/core-common";
import { Range3d } from "@itwin/core-geometry";
import { CRSManager, Downloader, DownloaderXhr, OnlineEngine, OPCReader, OrbitGtBounds, PageCachedFile, UrlFS } from "@itwin/core-orbitgt";
import { FrontendLoggerCategory } from "../../common/FrontendLoggerCategory";
import { BentleyError, expectDefined, Logger, RealityDataStatus } from "@itwin/core-bentley";
import { RealityDataError } from "../../RealityDataSource";
const loggerCategory = FrontendLoggerCategory.RealityData;
/**
* This class provide methods used to interpret Orbit Point Cloud (OPC) format
*/
export class OPCFormatInterpreter {
/** Gets an OPC file reader from a blobFileUrl
* @param blobFileURL the name of the file.
* @returns return a file reader open to read provided blob file
*/
static async getFileReaderFromBlobFileURL(blobFileURL) {
if (Downloader.INSTANCE == null)
Downloader.INSTANCE = new DownloaderXhr();
if (CRSManager.ENGINE == null)
CRSManager.ENGINE = await OnlineEngine.create();
// let blobFileURL: string = rdUrl;
// if (accountName.length > 0) blobFileURL = UrlFS.getAzureBlobSasUrl(opcConfig.accountName, opcConfig.containerName, opcConfig.blobFileName, opcConfig.sasToken);
const urlFS = new UrlFS();
// wrap a caching layer (16 MB) around the blob file
const blobFileSize = await urlFS.getFileLength(blobFileURL);
Logger.logTrace(loggerCategory, `OPC File Size is ${blobFileSize.toString()}`);
const blobFile = new PageCachedFile(urlFS, blobFileURL, blobFileSize, 128 * 1024 /* pageSize */, 128 /* maxPageCount */);
const fileReader = await OPCReader.openFile(blobFile, blobFileURL, true /* lazyLoading */);
return fileReader;
}
/** Gets reality data spatial location and extents
* @param fileReader a file reader instance obtains from call to getFileReaderFromBlobFileURL
* @returns spatial location and volume of interest, in meters, centered around `spatial location`
* @throws [[RealityDataError]] if source is invalid or cannot be read
*/
static async getSpatialLocationAndExtents(fileReader) {
let worldRange = new Range3d();
let location;
let isGeolocated = true;
const bounds = fileReader.getFileBounds();
worldRange = Range3d.createXYZXYZ(bounds.getMinX(), bounds.getMinY(), bounds.getMinZ(), bounds.getMaxX(), bounds.getMaxY(), bounds.getMaxZ());
isGeolocated = false;
const fileCrs = fileReader.getFileCRS();
// the CRS 9300 is not defined in the CRS registry database, so we cannot use CRSManager
// Check to isGeographicCRS and isProjectedCRS are both going to return false in that case and we will fallback to
// use un-georeferenced code path.
await CRSManager.ENGINE.prepareForArea(fileCrs, bounds);
const isGeographicCRS = CRSManager.ENGINE.isGeographicCRS(fileCrs);
const isProjectedCRS = CRSManager.ENGINE.isProjectedCRS(fileCrs);
if (fileCrs && (isProjectedCRS || isGeographicCRS)) {
try {
const wgs84ECEFCrs = "4978";
await CRSManager.ENGINE.prepareForArea(wgs84ECEFCrs, new OrbitGtBounds());
const ecefBounds = CRSManager.transformBounds(bounds, fileCrs, wgs84ECEFCrs);
const ecefRange = Range3d.createXYZXYZ(ecefBounds.getMinX(), ecefBounds.getMinY(), ecefBounds.getMinZ(), ecefBounds.getMaxX(), ecefBounds.getMaxY(), ecefBounds.getMaxZ());
const ecefCenter = expectDefined(ecefRange.localXYZToWorld(.5, .5, .5));
const cartoCenter = expectDefined(Cartographic.fromEcef(ecefCenter));
cartoCenter.height = 0;
const ecefLocation = EcefLocation.createFromCartographicOrigin(cartoCenter);
location = ecefLocation;
// this.iModelDb.setEcefLocation(ecefLocation);
const ecefToWorld = expectDefined(ecefLocation.getTransform().inverse());
worldRange = ecefToWorld.multiplyRange(ecefRange);
isGeolocated = true;
}
catch (e) {
Logger.logWarning(loggerCategory, `Error getSpatialLocationAndExtents - cannot interpret point cloud`);
const errorProps = BentleyError.getErrorProps(e);
const getMetaData = () => {
return { errorProps };
};
const error = new RealityDataError(RealityDataStatus.InvalidData, "Invalid or unknown data", getMetaData);
throw error;
}
}
else {
// NoGCS case
isGeolocated = false;
const centerOfEarth = new EcefLocation({ origin: { x: 0.0, y: 0.0, z: 0.0 }, orientation: { yaw: 0.0, pitch: 0.0, roll: 0.0 } });
location = centerOfEarth;
Logger.logTrace(loggerCategory, "OPC RealityData NOT Geolocated", () => ({ ...location }));
}
const spatialLocation = { location, worldRange, isGeolocated };
return spatialLocation;
}
}
//# sourceMappingURL=OPCFormatInterpreter.js.map