| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- import Cesium3DTileset from "./Cesium3DTileset.js";
- import defined from "../Core/defined.js";
- import Resource from "../Core/Resource.js";
- import ITwinPlatform from "../Core/ITwinPlatform.js";
- import RuntimeError from "../Core/RuntimeError.js";
- import Check from "../Core/Check.js";
- import KmlDataSource from "../DataSources/KmlDataSource.js";
- import GeoJsonDataSource from "../DataSources/GeoJsonDataSource.js";
- import DeveloperError from "../Core/DeveloperError.js";
-
- /**
- * Methods for loading iTwin platform data into CesiumJS
- *
- * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
- *
- * @see ITwinPlatform
- * @namespace ITwinData
- */
- const ITwinData = {};
-
- /**
- * Create a {@link Cesium3DTileset} for the given iModel id using iTwin's Mesh Export API.
- *
- * If there is not a completed export available for the given iModel id, the returned promise will resolve to <code>undefined</code>.
- * We recommend waiting 10-20 seconds and trying to load the tileset again.
- * If all exports are Invalid this will throw an error.
- *
- * See the {@link https://developer.bentley.com/apis/mesh-export/overview/|iTwin Platform Mesh Export API documentation} for more information on request parameters
- *
- * @example
- * const tileset = await Cesium.ITwinData.createTilesetFromIModelId({ iModelId });
- * if (Cesium.defined(tileset)) {
- * viewer.scene.primitives.add(tileset);
- * }
- *
- * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
- *
- * @param {object} options
- * @param {string} options.iModelId The id of the iModel to load
- * @param {Cesium3DTileset.ConstructorOptions} [options.tilesetOptions] Object containing options to pass to the internally created {@link Cesium3DTileset}.
- * @param {string} [options.changesetId] The id of the changeset to load, if not provided the latest changesets will be used
- * @returns {Promise<Cesium3DTileset | undefined>} A promise that will resolve to the created 3D tileset or <code>undefined</code> if there is no completed export for the given iModel id
- *
- * @throws {RuntimeError} If all exports for the given iModel are Invalid
- * @throws {RuntimeError} If the iTwin API request is not successful
- */
- ITwinData.createTilesetFromIModelId = async function ({
- iModelId,
- changesetId,
- tilesetOptions,
- }) {
- const { exports } = await ITwinPlatform.getExports(iModelId, changesetId);
-
- if (
- exports.length > 0 &&
- exports.every((exportObj) => {
- return exportObj.status === ITwinPlatform.ExportStatus.Invalid;
- })
- ) {
- throw new RuntimeError(
- `All exports for this iModel are Invalid: ${iModelId}`,
- );
- }
-
- const completeExport = exports.find((exportObj) => {
- return exportObj.status === ITwinPlatform.ExportStatus.Complete;
- });
-
- if (!defined(completeExport)) {
- return;
- }
-
- // Convert the link to the tileset url while preserving the search paramaters
- // This link is only valid 1 hour
- const baseUrl = new URL(completeExport._links.mesh.href);
- baseUrl.pathname = `${baseUrl.pathname}/tileset.json`;
- const tilesetUrl = baseUrl.toString();
-
- const resource = new Resource({
- url: tilesetUrl,
- });
-
- return Cesium3DTileset.fromUrl(resource, tilesetOptions);
- };
-
- /**
- * Create a tileset for the specified reality data id. This function only works
- * with 3D Tiles meshes and point clouds.
- *
- * If the <code>type</code> or <code>rootDocument</code> are not provided this function
- * will first request the full metadata for the specified reality data to fill these values.
- *
- * The <code>maximumScreenSpaceError</code> of the resulting tileset will default to 4,
- * unless it is explicitly overridden with the given tileset options.
- *
- * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
- *
- * @param {object} options
- * @param {string} options.iTwinId The id of the iTwin to load data from
- * @param {string} options.realityDataId The id of the reality data to load
- * @param {ITwinPlatform.RealityDataType} [options.type] The type of this reality data
- * @param {string} [options.rootDocument] The path of the root document for this reality data
- * @param {Cesium3DTileset.ConstructorOptions} [options.tilesetOptions] Object containing
- * options to pass to the internally created {@link Cesium3DTileset}.
- * @returns {Promise<Cesium3DTileset>}
- *
- * @throws {RuntimeError} if the type of reality data is not supported by this function
- */
- ITwinData.createTilesetForRealityDataId = async function ({
- iTwinId,
- realityDataId,
- type,
- rootDocument,
- tilesetOptions,
- }) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.string("iTwinId", iTwinId);
- Check.typeOf.string("realityDataId", realityDataId);
- if (defined(type)) {
- Check.typeOf.string("type", type);
- }
- if (defined(rootDocument)) {
- Check.typeOf.string("rootDocument", rootDocument);
- }
- //>>includeEnd('debug');
-
- if (!defined(type) || !defined(rootDocument)) {
- const metadata = await ITwinPlatform.getRealityDataMetadata(
- iTwinId,
- realityDataId,
- );
- rootDocument = metadata.rootDocument;
- type = metadata.type;
- }
-
- const supportedRealityDataTypes = [
- ITwinPlatform.RealityDataType.Cesium3DTiles,
- ITwinPlatform.RealityDataType.PNTS,
- ITwinPlatform.RealityDataType.RealityMesh3DTiles,
- ITwinPlatform.RealityDataType.Terrain3DTiles,
- ITwinPlatform.RealityDataType.GaussianSplat3DTiles,
- ];
-
- if (!supportedRealityDataTypes.includes(type)) {
- throw new RuntimeError(`Reality data type is not a mesh type: ${type}`);
- }
-
- const tilesetAccessUrl = await ITwinPlatform.getRealityDataURL(
- iTwinId,
- realityDataId,
- rootDocument,
- );
-
- // The maximum screen space error was defined to default to 4 for
- // reality data tilesets, because they did not show the expected
- // amount of detail with the default value of 16. Values that are
- // given in the tilesetOptions should still override that default.
- const internalTilesetOptions = {
- maximumScreenSpaceError: 4,
- ...tilesetOptions,
- };
-
- return Cesium3DTileset.fromUrl(tilesetAccessUrl, internalTilesetOptions);
- };
-
- /**
- * Create a data source of the correct type for the specified reality data id.
- * This function only works for KML and GeoJSON type data.
- *
- * If the <code>type</code> or <code>rootDocument</code> are not provided this function
- * will first request the full metadata for the specified reality data to fill these values.
- *
- * @param {object} options
- * @param {string} options.iTwinId The id of the iTwin to load data from
- * @param {string} options.realityDataId The id of the reality data to load
- * @param {ITwinPlatform.RealityDataType} [options.type] The type of this reality data
- * @param {string} [options.rootDocument] The path of the root document for this reality data
- * @returns {Promise<GeoJsonDataSource | KmlDataSource>}
- *
- * @throws {RuntimeError} if the type of reality data is not supported by this function
- */
- ITwinData.createDataSourceForRealityDataId = async function ({
- iTwinId,
- realityDataId,
- type,
- rootDocument,
- }) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.string("iTwinId", iTwinId);
- Check.typeOf.string("realityDataId", realityDataId);
- if (defined(type)) {
- Check.typeOf.string("type", type);
- }
- if (defined(rootDocument)) {
- Check.typeOf.string("rootDocument", rootDocument);
- }
- //>>includeEnd('debug');
-
- if (!defined(type) || !defined(rootDocument)) {
- const metadata = await ITwinPlatform.getRealityDataMetadata(
- iTwinId,
- realityDataId,
- );
- rootDocument = metadata.rootDocument;
- type = metadata.type;
- }
-
- const supportedRealityDataTypes = [
- ITwinPlatform.RealityDataType.KML,
- ITwinPlatform.RealityDataType.GeoJSON,
- ];
-
- if (!supportedRealityDataTypes.includes(type)) {
- throw new RuntimeError(
- `Reality data type is not a data source type: ${type}`,
- );
- }
-
- const tilesetAccessUrl = await ITwinPlatform.getRealityDataURL(
- iTwinId,
- realityDataId,
- rootDocument,
- );
-
- if (type === ITwinPlatform.RealityDataType.GeoJSON) {
- return GeoJsonDataSource.load(tilesetAccessUrl);
- }
-
- // If we get here it's guaranteed to be a KML type
- return KmlDataSource.load(tilesetAccessUrl);
- };
-
- /**
- * Load data from the Geospatial Features API as GeoJSON.
- *
- * @param {object} options
- * @param {string} options.iTwinId The id of the iTwin to load data from
- * @param {string} options.collectionId The id of the data collection to load
- * @param {number} [options.limit=10000] number of items per page, must be between 1 and 10,000 inclusive
- * @returns {Promise<GeoJsonDataSource>}
- */
- ITwinData.loadGeospatialFeatures = async function ({
- iTwinId,
- collectionId,
- limit,
- }) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.string("iTwinId", iTwinId);
- Check.typeOf.string("collectionId", collectionId);
- if (defined(limit)) {
- Check.typeOf.number("limit", limit);
- Check.typeOf.number.lessThanOrEquals("limit", limit, 10000);
- Check.typeOf.number.greaterThanOrEquals("limit", limit, 1);
- }
- if (
- !defined(ITwinPlatform.defaultAccessToken) &&
- !defined(ITwinPlatform.defaultShareKey)
- ) {
- throw new DeveloperError(
- "Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first",
- );
- }
- //>>includeEnd('debug');
-
- const pageLimit = limit ?? 10000;
-
- const tilesetUrl = `${ITwinPlatform.apiEndpoint}geospatial-features/itwins/${iTwinId}/ogc/collections/${collectionId}/items`;
-
- const resource = new Resource({
- url: tilesetUrl,
- headers: {
- Authorization: ITwinPlatform._getAuthorizationHeader(),
- Accept: "application/vnd.bentley.itwin-platform.v1+json",
- },
- queryParameters: {
- limit: pageLimit,
- client: "CesiumJS",
- },
- });
-
- return GeoJsonDataSource.load(resource);
- };
-
- export default ITwinData;
|