Add existing to tracked
This commit is contained in:
+284
@@ -0,0 +1,284 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user