Skip to content

Commit 9e547f9

Browse files
authored
Merge pull request #12778 from CesiumGS/imodel-changeset-support
Add support for optional changesets when loading iModels
2 parents cb7fe95 + ab4867f commit 9e547f9

File tree

8 files changed

+308
-139
lines changed

8 files changed

+308
-139
lines changed

Apps/Sandcastle/gallery/Drape Imagery on 3D Tiles.html

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@
4040
});
4141
viewer.scene.skyAtmosphere.show = true;
4242

43-
const iTwinId = "535a24a3-9b29-4e23-bb5d-9cedb524c743";
44-
const realityMeshId = "85897090-3bcc-470b-bec7-20bb639cc1b9";
45-
const tileset = await Cesium.ITwinData.createTilesetForRealityDataId(
46-
iTwinId,
47-
realityMeshId,
48-
);
43+
const tileset = await Cesium.ITwinData.createTilesetForRealityDataId({
44+
iTwinId: "535a24a3-9b29-4e23-bb5d-9cedb524c743",
45+
realityDataId: "85897090-3bcc-470b-bec7-20bb639cc1b9",
46+
});
4947
viewer.scene.primitives.add(tileset);
5048
tileset.maximumScreenSpaceError = 2;
5149

Apps/Sandcastle/gallery/iModel Mesh Export Service.html

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@
110110
}
111111

112112
// Create tilesets using the iModel ids
113-
const surroundingArea = await Cesium.ITwinData.createTilesetFromIModelId(
114-
"f856f57d-3d28-4265-9c4f-5e60c0662c15",
115-
);
116-
const station = await Cesium.ITwinData.createTilesetFromIModelId(
117-
"669dde67-eb69-4e0b-bcf2-f722eee94746",
118-
);
113+
const surroundingArea = await Cesium.ITwinData.createTilesetFromIModelId({
114+
iModelId: "f856f57d-3d28-4265-9c4f-5e60c0662c15",
115+
});
116+
const station = await Cesium.ITwinData.createTilesetFromIModelId({
117+
iModelId: "669dde67-eb69-4e0b-bcf2-f722eee94746",
118+
});
119119
// Change how highlighting with the feature selection changes the color
120120
surroundingArea.colorBlendMode = Cesium.Cesium3DTileColorBlendMode.REPLACE;
121121
station.colorBlendMode = Cesium.Cesium3DTileColorBlendMode.REPLACE;
@@ -124,12 +124,10 @@
124124
scene.primitives.add(station);
125125

126126
// Create tileset of the reality data mesh
127-
const iTwinId = "535a24a3-9b29-4e23-bb5d-9cedb524c743";
128-
const realityMeshId = "85897090-3bcc-470b-bec7-20bb639cc1b9";
129-
const realityMesh = await Cesium.ITwinData.createTilesetForRealityDataId(
130-
iTwinId,
131-
realityMeshId,
132-
);
127+
const realityMesh = await Cesium.ITwinData.createTilesetForRealityDataId({
128+
iTwinId: "535a24a3-9b29-4e23-bb5d-9cedb524c743",
129+
realityDataId: "85897090-3bcc-470b-bec7-20bb639cc1b9",
130+
});
133131
scene.primitives.add(realityMesh);
134132

135133
Sandcastle.addToolbarButton(

Apps/Sandcastle/gallery/iTwin Feature Service.html

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,18 @@
6666
viewer.scene.camera.flyTo(birdsEyeView);
6767

6868
// Load feature service geojson files
69-
const points = await Cesium.ITwinData.loadGeospatialFeatures(
70-
iTwinId,
71-
"2380dc1b-1dac-4709-aa5c-f6cb38c4e9f5",
72-
);
73-
const lines = await Cesium.ITwinData.loadGeospatialFeatures(
74-
iTwinId,
75-
"613d2310-4d01-43b7-bc92-873a2ca4a4a0",
76-
);
77-
const areas = await Cesium.ITwinData.loadGeospatialFeatures(
78-
iTwinId,
79-
"93e7ef51-5210-49f2-92a3-c7f6685e102f",
80-
);
69+
const points = await Cesium.ITwinData.loadGeospatialFeatures({
70+
iTwinId: iTwinId,
71+
collectionId: "2380dc1b-1dac-4709-aa5c-f6cb38c4e9f5",
72+
});
73+
const lines = await Cesium.ITwinData.loadGeospatialFeatures({
74+
iTwinId: iTwinId,
75+
collectionId: "613d2310-4d01-43b7-bc92-873a2ca4a4a0",
76+
});
77+
const areas = await Cesium.ITwinData.loadGeospatialFeatures({
78+
iTwinId: iTwinId,
79+
collectionId: "93e7ef51-5210-49f2-92a3-c7f6685e102f",
80+
});
8181

8282
// Add some styling to the lines and points to differentiate types
8383
const pinBuilder = new Cesium.PinBuilder();
@@ -118,17 +118,15 @@
118118
viewer.dataSources.add(areas);
119119

120120
// Create tileset of the reality data mesh and pointcloud
121-
const realityMeshId = "62e4432d-621d-489a-87ff-1fc56a2b5369";
122-
const realityMesh = await Cesium.ITwinData.createTilesetForRealityDataId(
123-
iTwinId,
124-
realityMeshId,
125-
);
121+
const realityMesh = await Cesium.ITwinData.createTilesetForRealityDataId({
122+
iTwinId: iTwinId,
123+
realityDataId: "62e4432d-621d-489a-87ff-1fc56a2b5369",
124+
});
126125
viewer.scene.primitives.add(realityMesh);
127-
const pointcloudId = "ebf2ee74-f0de-4cd6-a311-19a169c55fdc";
128-
const pointcloud = await Cesium.ITwinData.createTilesetForRealityDataId(
129-
iTwinId,
130-
pointcloudId,
131-
);
126+
const pointcloud = await Cesium.ITwinData.createTilesetForRealityDataId({
127+
iTwinId: iTwinId,
128+
realityDataId: "ebf2ee74-f0de-4cd6-a311-19a169c55fdc",
129+
});
132130
// increase the size of the pointcloud points and turn on attenuation to
133131
// make them more visible in the viewer
134132
pointcloud.maximumScreenSpaceError = 1;

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222

2323
- Expand the CustomShader Sample to support real-time modification of CustomShader. [#12702](https://github.com/CesiumGS/cesium/pull/12702)
2424
- Add wrapR property to Sampler and Texture3D, to support the newly added third dimension wrap.[#12701](https://github.com/CesiumGS/cesium/pull/12701)
25+
- Added the ability to load a specific changeset for iTwin Mesh Exports using `ITwinData.createTilesetFromIModelId` [#12778](https://github.com/CesiumGS/cesium/issues/12778)
26+
27+
#### Deprecated :hourglass_flowing_sand:
28+
29+
- Updated all of the `ITwinData.*` functions to accept an `options` parameter instead of individual arguments to avoid confusion with multiple optional arguments. There is a fallback to the old signature that will be removed in 1.133 [#12778](https://github.com/CesiumGS/cesium/issues/12778)
2530

2631
## 1.131 - 2025-07-01
2732

packages/engine/Source/Core/ITwinPlatform.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,17 @@ ITwinPlatform.apiEndpoint = new Resource({
153153
* @private
154154
*
155155
* @param {string} iModelId iModel id
156+
* @param {string} [changesetId] The id of the changeset to filter results by. If not provided, exports from the latest available changesets will be returned.
156157
* @returns {Promise<GetExportsResponse>}
157158
*
158159
* @throws {RuntimeError} If the iTwin API request is not successful
159160
*/
160-
ITwinPlatform.getExports = async function (iModelId) {
161+
ITwinPlatform.getExports = async function (iModelId, changesetId) {
161162
//>>includeStart('debug', pragmas.debug);
162163
Check.typeOf.string("iModelId", iModelId);
164+
if (defined(changesetId)) {
165+
Check.typeOf.string("changesetId", changesetId);
166+
}
163167
if (
164168
!defined(ITwinPlatform.defaultAccessToken) &&
165169
!defined(ITwinPlatform.defaultShareKey)
@@ -191,6 +195,9 @@ ITwinPlatform.getExports = async function (iModelId) {
191195
if (typeof CESIUM_VERSION !== "undefined") {
192196
resource.appendQueryParameters({ clientVersion: CESIUM_VERSION });
193197
}
198+
if (defined(changesetId) && changesetId !== "") {
199+
resource.appendQueryParameters({ changesetId: changesetId });
200+
}
194201

195202
try {
196203
const response = await resource.fetchJson();

packages/engine/Source/Scene/ITwinData.js

Lines changed: 97 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Check from "../Core/Check.js";
77
import KmlDataSource from "../DataSources/KmlDataSource.js";
88
import GeoJsonDataSource from "../DataSources/GeoJsonDataSource.js";
99
import DeveloperError from "../Core/DeveloperError.js";
10+
import deprecationWarning from "../Core/deprecationWarning.js";
1011

1112
/**
1213
* Methods for loading iTwin platform data into CesiumJS
@@ -25,23 +26,40 @@ const ITwinData = {};
2526
* We recommend waiting 10-20 seconds and trying to load the tileset again.
2627
* If all exports are Invalid this will throw an error.
2728
*
29+
* See the {@link https://developer.bentley.com/apis/mesh-export/overview/|iTwin Platform Mesh Export API documentation} for more information on request parameters
30+
*
2831
* @example
29-
* const tileset = await Cesium.ITwinData.createTilesetFromIModelId(iModelId);
32+
* const tileset = await Cesium.ITwinData.createTilesetFromIModelId({ iModelId });
3033
* if (Cesium.defined(tileset)) {
3134
* viewer.scene.primitives.add(tileset);
3235
* }
3336
*
3437
* @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
3538
*
36-
* @param {string} iModelId The id of the iModel to load
37-
* @param {Cesium3DTileset.ConstructorOptions} [options] Object containing options to pass to the internally created {@link Cesium3DTileset}.
39+
* @param {Object} options
40+
* @param {string} options.iModelId The id of the iModel to load
41+
* @param {Cesium3DTileset.ConstructorOptions} [options.tilesetOptions] Object containing options to pass to the internally created {@link Cesium3DTileset}.
42+
* @param {string} [options.changesetId] The id of the changeset to load, if not provided the latest changesets will be used
3843
* @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
3944
*
4045
* @throws {RuntimeError} If all exports for the given iModel are Invalid
4146
* @throws {RuntimeError} If the iTwin API request is not successful
4247
*/
43-
ITwinData.createTilesetFromIModelId = async function (iModelId, options) {
44-
const { exports } = await ITwinPlatform.getExports(iModelId);
48+
ITwinData.createTilesetFromIModelId = async function (options) {
49+
let internalOptions = options;
50+
51+
if (typeof options === "string") {
52+
// the old signature was (iModelId: string, options?: Cesium3DTileset.ConstructorOptions)
53+
// grab the later arguments directly instead of in the params only for this special case
54+
internalOptions = { iModelId: options, tilesetOptions: arguments[1] };
55+
deprecationWarning(
56+
"ITwinData.createTilesetFromIModelId",
57+
"The arguments signature for ITwinData functions has changed in 1.132 in favor of a single options object. Please update your code. This fallback will be removed in 1.133",
58+
);
59+
}
60+
61+
const { iModelId, changesetId, tilesetOptions } = internalOptions;
62+
const { exports } = await ITwinPlatform.getExports(iModelId, changesetId);
4563

4664
if (
4765
exports.length > 0 &&
@@ -72,7 +90,7 @@ ITwinData.createTilesetFromIModelId = async function (iModelId, options) {
7290
url: tilesetUrl,
7391
});
7492

75-
return Cesium3DTileset.fromUrl(resource, options);
93+
return Cesium3DTileset.fromUrl(resource, tilesetOptions);
7694
};
7795

7896
/**
@@ -84,20 +102,35 @@ ITwinData.createTilesetFromIModelId = async function (iModelId, options) {
84102
*
85103
* @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
86104
*
87-
* @param {string} iTwinId The id of the iTwin to load data from
88-
* @param {string} realityDataId The id of the reality data to load
89-
* @param {ITwinPlatform.RealityDataType} [type] The type of this reality data
90-
* @param {string} [rootDocument] The path of the root document for this reality data
105+
* @param {Object} options
106+
* @param {string} options.iTwinId The id of the iTwin to load data from
107+
* @param {string} options.realityDataId The id of the reality data to load
108+
* @param {ITwinPlatform.RealityDataType} [options.type] The type of this reality data
109+
* @param {string} [options.rootDocument] The path of the root document for this reality data
91110
* @returns {Promise<Cesium3DTileset>}
92111
*
93112
* @throws {RuntimeError} if the type of reality data is not supported by this function
94113
*/
95-
ITwinData.createTilesetForRealityDataId = async function (
96-
iTwinId,
97-
realityDataId,
98-
type,
99-
rootDocument,
100-
) {
114+
ITwinData.createTilesetForRealityDataId = async function (options) {
115+
let internalOptions = options;
116+
117+
if (typeof options === "string") {
118+
// the old signature was (iTwinId: string, realityDataId: string, type: RealityDataType, rootDocument: string)
119+
// grab the later arguments directly instead of in the params only for this special case
120+
internalOptions = {
121+
iTwinId: options,
122+
realityDataId: arguments[1],
123+
type: arguments[2],
124+
rootDocument: arguments[3],
125+
};
126+
deprecationWarning(
127+
"ITwinData.createTilesetFromIModelId",
128+
"The arguments signature for ITwinData functions has changed in 1.132 in favor of a single options object. Please update your code. This fallback will be removed in 1.133",
129+
);
130+
}
131+
const { iTwinId, realityDataId } = internalOptions;
132+
let { type, rootDocument } = internalOptions;
133+
101134
//>>includeStart('debug', pragmas.debug);
102135
Check.typeOf.string("iTwinId", iTwinId);
103136
Check.typeOf.string("realityDataId", realityDataId);
@@ -147,20 +180,35 @@ ITwinData.createTilesetForRealityDataId = async function (
147180
* If the <code>type</code> or <code>rootDocument</code> are not provided this function
148181
* will first request the full metadata for the specified reality data to fill these values.
149182
*
150-
* @param {string} iTwinId The id of the iTwin to load data from
151-
* @param {string} realityDataId The id of the reality data to load
152-
* @param {ITwinPlatform.RealityDataType} [type] The type of this reality data
153-
* @param {string} [rootDocument] The path of the root document for this reality data
183+
* @param {Object} options
184+
* @param {string} options.iTwinId The id of the iTwin to load data from
185+
* @param {string} options.realityDataId The id of the reality data to load
186+
* @param {ITwinPlatform.RealityDataType} [options.type] The type of this reality data
187+
* @param {string} [options.rootDocument] The path of the root document for this reality data
154188
* @returns {Promise<GeoJsonDataSource | KmlDataSource>}
155189
*
156190
* @throws {RuntimeError} if the type of reality data is not supported by this function
157191
*/
158-
ITwinData.createDataSourceForRealityDataId = async function (
159-
iTwinId,
160-
realityDataId,
161-
type,
162-
rootDocument,
163-
) {
192+
ITwinData.createDataSourceForRealityDataId = async function (options) {
193+
let internalOptions = options;
194+
195+
if (typeof options === "string") {
196+
// the old signature was (iTwinId: string, realityDataId: string, type: RealityDataType, rootDocument: string)
197+
// grab the later arguments directly instead of in the params only for this special case
198+
internalOptions = {
199+
iTwinId: options,
200+
realityDataId: arguments[1],
201+
type: arguments[2],
202+
rootDocument: arguments[3],
203+
};
204+
deprecationWarning(
205+
"ITwinData.createTilesetFromIModelId",
206+
"The arguments signature for ITwinData functions has changed in 1.132 in favor of a single options object. Please update your code. This fallback will be removed in 1.133",
207+
);
208+
}
209+
const { iTwinId, realityDataId } = internalOptions;
210+
let { type, rootDocument } = internalOptions;
211+
164212
//>>includeStart('debug', pragmas.debug);
165213
Check.typeOf.string("iTwinId", iTwinId);
166214
Check.typeOf.string("realityDataId", realityDataId);
@@ -209,16 +257,31 @@ ITwinData.createDataSourceForRealityDataId = async function (
209257
/**
210258
* Load data from the Geospatial Features API as GeoJSON.
211259
*
212-
* @param {string} iTwinId The id of the iTwin to load data from
213-
* @param {string} collectionId The id of the data collection to load
214-
* @param {number} [limit=10000] number of items per page, must be between 1 and 10,000 inclusive
260+
* @param {Object} options
261+
* @param {string} options.iTwinId The id of the iTwin to load data from
262+
* @param {string} options.collectionId The id of the data collection to load
263+
* @param {number} [options.limit=10000] number of items per page, must be between 1 and 10,000 inclusive
215264
* @returns {Promise<GeoJsonDataSource>}
216265
*/
217-
ITwinData.loadGeospatialFeatures = async function (
218-
iTwinId,
219-
collectionId,
220-
limit,
221-
) {
266+
ITwinData.loadGeospatialFeatures = async function (options) {
267+
let internalOptions = options;
268+
269+
if (typeof options === "string") {
270+
// the old signature was (iTwinId: string, collectionId: string, limit: number)
271+
// grab the later arguments directly instead of in the params only for this special case
272+
internalOptions = {
273+
iTwinId: options,
274+
collectionId: arguments[1],
275+
limit: arguments[2],
276+
};
277+
deprecationWarning(
278+
"ITwinData.createTilesetFromIModelId",
279+
"The arguments signature for ITwinData functions has changed in 1.132 in favor of a single options object. Please update your code. This fallback will be removed in 1.133",
280+
);
281+
}
282+
283+
const { iTwinId, collectionId, limit } = internalOptions;
284+
222285
//>>includeStart('debug', pragmas.debug);
223286
Check.typeOf.string("iTwinId", iTwinId);
224287
Check.typeOf.string("collectionId", collectionId);

packages/engine/Specs/Core/ITwinPlatformSpec.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,17 @@ describe("ITwinPlatform", () => {
156156
expect(resource).toBeDefined();
157157
expect(resource.url).toContain("imodel-id-1");
158158
});
159+
160+
it("uses the changeset in the API request", async () => {
161+
let resource;
162+
requestSpy.and.callFake(function () {
163+
resource = this;
164+
return JSON.stringify({ exports: [] });
165+
});
166+
await ITwinPlatform.getExports("imodel-id-1", "changeset-id-1");
167+
expect(resource).toBeDefined();
168+
expect(resource.url).toContain("changeset-id-1");
169+
});
159170
});
160171

161172
describe("getRealityDataMetadata", () => {

0 commit comments

Comments
 (0)