mirror of https://github.com/CesiumGS/cesium.git
284 lines
9.7 KiB
JavaScript
284 lines
9.7 KiB
JavaScript
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,
|
|
];
|
|
|
|
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;
|