From 8665d0f560e23402a0ca1071fc4ec1366a540eda Mon Sep 17 00:00:00 2001
From: jjspace <8007967+jjspace@users.noreply.github.com>
Date: Wed, 27 Nov 2024 14:28:51 -0500
Subject: [PATCH 1/5] add support for iTwin reality geojson and kml files
---
.../gallery/iTwin Feature Service.html | 126 ++++++++++++++++++
packages/engine/Source/Core/ITwinPlatform.js | 41 +-----
packages/engine/Source/Scene/ITwinData.js | 70 ++++++++++
3 files changed, 199 insertions(+), 38 deletions(-)
create mode 100644 Apps/Sandcastle/gallery/iTwin Feature Service.html
diff --git a/Apps/Sandcastle/gallery/iTwin Feature Service.html b/Apps/Sandcastle/gallery/iTwin Feature Service.html
new file mode 100644
index 00000000000..6ec779436fe
--- /dev/null
+++ b/Apps/Sandcastle/gallery/iTwin Feature Service.html
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+ iTwin Feature Service
+
+
+
+
+
+
+ Loading...
+
+
+
+
diff --git a/packages/engine/Source/Core/ITwinPlatform.js b/packages/engine/Source/Core/ITwinPlatform.js
index c6e9e44ba4a..fb05dafc377 100644
--- a/packages/engine/Source/Core/ITwinPlatform.js
+++ b/packages/engine/Source/Core/ITwinPlatform.js
@@ -38,54 +38,19 @@ ITwinPlatform.ExportType = Object.freeze({
});
/**
- * Types of Reality data
+ * Types of Reality data. This is a partial list of types we know we can support
+ *
* @see https://developer.bentley.com/apis/reality-management/rm-rd-details/#types
* @enum {string}
*/
ITwinPlatform.RealityDataType = Object.freeze({
Cesium3DTiles: "Cesium3DTiles",
PNTS: "PNTS",
- OPC: "OPC",
RealityMesh3DTiles: "RealityMesh3DTiles",
Terrain3DTiles: "Terrain3DTiles",
- "3MX": "3MX",
- "3SM": "3SM",
- CCCloudProject: "CCCloudProject",
- CCImageCollection: "CCImageCollection",
- CCOrientations: "CCOrientations",
- ContextCaptureInputs: "ContextCaptureInputs",
- ContextDetector: "ContextDetector",
- ContextScene: "ContextScene",
- DAE: "DAE",
- DGN: "DGN",
- DSM: "DSM",
- FBX: "FBX",
- GLB: "GLB",
- GLTF: "GLTF",
KML: "KML",
- LAS: "LAS",
- LAZ: "LAZ",
- LOD: "LOD",
- LodTree: "LodTree",
- OBJ: "OBJ",
- OMI: "OMI",
- OMR: "OMR",
- Orthophoto: "Orthophoto",
- OrthophotoDSM: "OrthophotoDSM",
- OSGB: "OSGB",
- OVF: "OVF",
- OBT: "OBT",
- PLY: "PLY",
- PointCloud: "PointCloud",
- S3C: "S3C",
- ScanCollection: "ScanCollection",
- SHP: "SHP",
- SLPK: "SLPK",
- SpaceEyes3D: "SpaceEyes3D",
- STL: "STL",
- TSM: "TSM",
+ GeoJSON: "GeoJSON",
Unstructured: "Unstructured",
- Other: "Other",
});
/**
diff --git a/packages/engine/Source/Scene/ITwinData.js b/packages/engine/Source/Scene/ITwinData.js
index 1b53f27e4c9..25fad57eb0a 100644
--- a/packages/engine/Source/Scene/ITwinData.js
+++ b/packages/engine/Source/Scene/ITwinData.js
@@ -4,6 +4,8 @@ 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";
/**
* Methods for loading iTwin platform data into CesiumJS
@@ -86,6 +88,8 @@ ITwinData.createTilesetFromIModelId = async function (iModelId, options) {
* @param {ITwinPlatform.RealityDataType} [type] The type of this reality data
* @param {string} [rootDocument] The path of the root document for this reality data
* @returns {Promise}
+ *
+ * @throws {RuntimeError} if the type of reality data is not supported by this function
*/
ITwinData.createTilesetForRealityDataId = async function (
iTwinId,
@@ -135,4 +139,70 @@ ITwinData.createTilesetForRealityDataId = async function (
});
};
+/**
+ * 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 type
or rootDocument
are not provided this function
+ * will first request the full metadata for the specified reality data to fill these values.
+ *
+ * @param {string} iTwinId The id of the iTwin to load data from
+ * @param {string} realityDataId The id of the reality data to load
+ * @param {ITwinPlatform.RealityDataType} [type] The type of this reality data
+ * @param {string} [rootDocument] The path of the root document for this reality data
+ * @returns {Promise}
+ *
+ * @throws {RuntimeError} if the type of reality data is not supported by this function
+ */
+ITwinData.createDataSourceForRealityDataId = async function loadRealityData(
+ 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);
+};
+
export default ITwinData;
From 19fdd8387de03abbc3a171295b80c02c98ecec63 Mon Sep 17 00:00:00 2001
From: jjspace <8007967+jjspace@users.noreply.github.com>
Date: Wed, 27 Nov 2024 14:57:12 -0500
Subject: [PATCH 2/5] fix and add tests
---
packages/engine/Specs/Scene/ITwinDataSpec.js | 127 ++++++++++++++++++-
1 file changed, 126 insertions(+), 1 deletion(-)
diff --git a/packages/engine/Specs/Scene/ITwinDataSpec.js b/packages/engine/Specs/Scene/ITwinDataSpec.js
index 8eb4322c577..25cb98cd2f3 100644
--- a/packages/engine/Specs/Scene/ITwinDataSpec.js
+++ b/packages/engine/Specs/Scene/ITwinDataSpec.js
@@ -3,6 +3,8 @@ import {
RuntimeError,
Cesium3DTileset,
ITwinData,
+ GeoJsonDataSource,
+ KmlDataSource,
} from "../../index.js";
function createMockExport(
@@ -132,7 +134,7 @@ describe("ITwinData", () => {
ITwinData.createTilesetForRealityDataId(
"imodel-id-1",
"reality-data-id-1",
- ITwinPlatform.RealityDataType.DGN,
+ "DGN",
"root/path.json",
),
).toBeRejectedWithError(RuntimeError, /type is not/);
@@ -221,4 +223,127 @@ describe("ITwinData", () => {
});
});
});
+
+ describe("createDataSourceForRealityDataId", () => {
+ let getMetadataSpy;
+ let getUrlSpy;
+ let geojsonSpy;
+ let kmlSpy;
+ beforeEach(() => {
+ getMetadataSpy = spyOn(ITwinPlatform, "getRealityDataMetadata");
+ getUrlSpy = spyOn(ITwinPlatform, "getRealityDataURL");
+ geojsonSpy = spyOn(GeoJsonDataSource, "load");
+ kmlSpy = spyOn(KmlDataSource, "load");
+ });
+
+ it("rejects if the type is not supported", async () => {
+ await expectAsync(
+ ITwinData.createDataSourceForRealityDataId(
+ "imodel-id-1",
+ "reality-data-id-1",
+ "DGN",
+ "root/path.json",
+ ),
+ ).toBeRejectedWithError(RuntimeError, /type is not/);
+ });
+
+ it("does not fetch metadata if type and rootDocument are defined", async () => {
+ await ITwinData.createDataSourceForRealityDataId(
+ "itwin-id-1",
+ "reality-data-id-1",
+ ITwinPlatform.RealityDataType.GeoJSON,
+ "root/document/path.json",
+ );
+
+ expect(getMetadataSpy).not.toHaveBeenCalled();
+ expect(getUrlSpy).toHaveBeenCalledOnceWith(
+ "itwin-id-1",
+ "reality-data-id-1",
+ "root/document/path.json",
+ );
+ expect(geojsonSpy).toHaveBeenCalled();
+ });
+
+ it("fetches metadata if type is undefined", async () => {
+ getMetadataSpy.and.resolveTo({
+ iModelId: "itwin-id-1",
+ id: "reality-data-id-1",
+ type: ITwinPlatform.RealityDataType.GeoJSON,
+ rootDocument: "root/document/path.json",
+ });
+ await ITwinData.createDataSourceForRealityDataId(
+ "itwin-id-1",
+ "reality-data-id-1",
+ undefined,
+ "root/document/path.json",
+ );
+
+ expect(getMetadataSpy).toHaveBeenCalledOnceWith(
+ "itwin-id-1",
+ "reality-data-id-1",
+ );
+ expect(getUrlSpy).toHaveBeenCalledOnceWith(
+ "itwin-id-1",
+ "reality-data-id-1",
+ "root/document/path.json",
+ );
+ });
+
+ it("fetches metadata if rootDocument is undefined", async () => {
+ getMetadataSpy.and.resolveTo({
+ iModelId: "itwin-id-1",
+ id: "reality-data-id-1",
+ type: ITwinPlatform.RealityDataType.GeoJSON,
+ rootDocument: "root/document/path.json",
+ });
+ await ITwinData.createDataSourceForRealityDataId(
+ "itwin-id-1",
+ "reality-data-id-1",
+ ITwinPlatform.RealityDataType.Cesium3DTiles,
+ undefined,
+ );
+
+ expect(getMetadataSpy).toHaveBeenCalledOnceWith(
+ "itwin-id-1",
+ "reality-data-id-1",
+ );
+ expect(getUrlSpy).toHaveBeenCalledOnceWith(
+ "itwin-id-1",
+ "reality-data-id-1",
+ "root/document/path.json",
+ );
+ });
+
+ it("creates a GeoJsonDataSource from the constructed blob url if the type is GeoJSON", async () => {
+ const tilesetUrl =
+ "https://example.com/root/document/path.json?auth=token";
+ getUrlSpy.and.resolveTo(tilesetUrl);
+
+ await ITwinData.createDataSourceForRealityDataId(
+ "itwin-id-1",
+ "reality-data-id-1",
+ ITwinPlatform.RealityDataType.GeoJSON,
+ "root/document/path.json",
+ );
+
+ expect(geojsonSpy).toHaveBeenCalledOnceWith(tilesetUrl);
+ expect(kmlSpy).not.toHaveBeenCalled();
+ });
+
+ it("creates a KmlDataSource from the constructed blob url if the type is KML", async () => {
+ const tilesetUrl =
+ "https://example.com/root/document/path.json?auth=token";
+ getUrlSpy.and.resolveTo(tilesetUrl);
+
+ await ITwinData.createDataSourceForRealityDataId(
+ "itwin-id-1",
+ "reality-data-id-1",
+ ITwinPlatform.RealityDataType.KML,
+ "root/document/path.json",
+ );
+
+ expect(kmlSpy).toHaveBeenCalledOnceWith(tilesetUrl);
+ expect(geojsonSpy).not.toHaveBeenCalled();
+ });
+ });
});
From b97ce3093fbb0b3e2e8c636b608ab692f71ff220 Mon Sep 17 00:00:00 2001
From: jjspace <8007967+jjspace@users.noreply.github.com>
Date: Mon, 2 Dec 2024 11:56:06 -0500
Subject: [PATCH 3/5] update changes
---
CHANGES.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGES.md b/CHANGES.md
index 6c6aca2d206..61808466ebd 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,6 +7,7 @@
##### Additions :tada:
- Added an integration with the [iTwin Platform](https://developer.bentley.com/) to load iModels as 3D Tiles. Use `ITwinPlatform.defaultAccessToken` to set the access token. Use `ITwinData.createTilesetFromIModelId(iModelId)` to load the iModel as a `Cesium3DTileset`. [#12289](https://github.com/CesiumGS/cesium/pull/12289)
+- Added an integration with the [iTwin Platform](https://developer.bentley.com/) to load Reality Data terrain meshes and GeoJSON. Use `ITwinPlatform.defaultAccessToken` to set the access token. Then use `ITwinData.createTilesetForRealityDataId(iTwinId, dataId)` to load terrain meshes as a `Cesium3DTileset` or `ITwinData.createDataSourceForRealityDataId(iTwinId, dataId)` to load GeoJSON or KML files as data sources. [#12344](https://github.com/CesiumGS/cesium/pull/12344)
- Added `getSample` to `SampledProperty` to get the time of samples. [#12253](https://github.com/CesiumGS/cesium/pull/12253)
- Added `Entity.trackingReferenceFrame` property to allow tracking entities in various reference frames. [#12194](https://github.com/CesiumGS/cesium/pull/12194), [#12314](https://github.com/CesiumGS/cesium/pull/12314)
- `TrackingReferenceFrame.AUTODETECT` (default): uses either VVLH or ENU dependeding on entity's dynamic. Use `TrackingReferenceFrame.ENU` if your camera orientation flips abruptly from time to time.
From 6a36391ac7fca683ba794580f2a48bed3e327fe9 Mon Sep 17 00:00:00 2001
From: jjspace <8007967+jjspace@users.noreply.github.com>
Date: Tue, 3 Dec 2024 16:07:01 -0500
Subject: [PATCH 4/5] update sandcastle with new itwin and add styling
---
.vscode/cspell.json | 1 +
.../gallery/iTwin Feature Service.html | 113 +++++++++++++-----
2 files changed, 82 insertions(+), 32 deletions(-)
diff --git a/.vscode/cspell.json b/.vscode/cspell.json
index 4f3c6c7cb98..e247f0c4a28 100644
--- a/.vscode/cspell.json
+++ b/.vscode/cspell.json
@@ -62,6 +62,7 @@
"iife",
"lerp",
"Lilli",
+ "maki",
"MAXAR",
"minifiers",
"mipmapped",
diff --git a/Apps/Sandcastle/gallery/iTwin Feature Service.html b/Apps/Sandcastle/gallery/iTwin Feature Service.html
index 6ec779436fe..f7c922661ca 100644
--- a/Apps/Sandcastle/gallery/iTwin Feature Service.html
+++ b/Apps/Sandcastle/gallery/iTwin Feature Service.html
@@ -34,37 +34,98 @@
Cesium.ITwinPlatform.defaultAccessToken = token;
- const iTwinId = "535a24a3-9b29-4e23-bb5d-9cedb524c743";
+ const iTwinId = "04ba725f-f3c0-4f30-8014-a4488cbd612d";
const viewer = new Cesium.Viewer("cesiumContainer");
+ const birdsEyeView = {
+ destination: new Cesium.Cartesian3(
+ -1525359.4318772827,
+ 6191643.528984093,
+ 148851.5321709012,
+ ),
+ orientation: new Cesium.HeadingPitchRoll(
+ 0.16657338935967037,
+ -0.7943050121851765,
+ 6.283180723449992,
+ ),
+ duration: 0,
+ easingFunction: Cesium.EasingFunction.LINEAR_NONE,
+ };
+ viewer.scene.camera.flyTo(birdsEyeView);
- const featureServiceBaseUrl = "https://featureservice-eus.bentley.com";
- const proxyUrl = "http://localhost:3000/proxy";
-
+ // Load feature service geojson files
const points = await Cesium.ITwinData.createDataSourceForRealityDataId(
iTwinId,
- "60976bd9-3176-4017-974a-4fcea76346db",
+ "57b975f6-fd92-42ba-8014-79911ed606d1",
);
const lines = await Cesium.ITwinData.createDataSourceForRealityDataId(
iTwinId,
- "5af22b93-cf7e-4879-9305-4c6bdda7987f",
+ "1099c53f-c568-48a3-a57c-0230a6f37229",
);
const areas = await Cesium.ITwinData.createDataSourceForRealityDataId(
iTwinId,
- "ebec69b5-0b5f-49d8-9081-e29bcd517f6b",
+ "21eaf0d0-ab90-400f-97cf-adc455b29a78",
);
+
+ // Add some styling to the lines and points to differentiate types
+ const pinBuilder = new Cesium.PinBuilder();
+ points.entities.values.forEach(async (entity) => {
+ const styleByType = {
+ Tree: { color: Cesium.Color.GREEN, icon: "park2" },
+ Lamp_post: { color: Cesium.Color.WHITE, icon: "lighthouse" },
+ Traffic_light: { color: Cesium.Color.CRIMSON, icon: "circle-stroked" },
+ Arrow_Marking: { color: Cesium.Color.YELLOW, icon: "car" },
+ Road_Sign: { color: Cesium.Color.ORANGE, icon: "triangle" },
+ };
+ const type = entity.properties.Type?.getValue();
+ if (Cesium.defined(type) && Cesium.defined(styleByType[type])) {
+ const { color, icon } = styleByType[type];
+ const canvas = await pinBuilder.fromMakiIconId(icon, color, 48);
+ entity.billboard.image = canvas.toDataURL();
+ entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
+ }
+ });
+ lines.entities.values.forEach((entity) => {
+ const lineColorsByType = {
+ Contours: Cesium.Color.CRIMSON,
+ Lane_Marking: Cesium.Color.WHITE,
+ Kerb: Cesium.Color.BLUEVIOLET,
+ Chevron_marking: Cesium.Color.DARKORANGE,
+ Turning_pocket: Cesium.Color.DEEPPINK,
+ Yellow_Box: Cesium.Color.GOLD,
+ };
+ const type = entity.properties.Type?.getValue();
+ if (Cesium.defined(type) && Cesium.defined(lineColorsByType[type])) {
+ entity.polyline.material = lineColorsByType[type];
+ }
+ });
+
+ // add the geojsons to the viewer
viewer.dataSources.add(points);
viewer.dataSources.add(lines);
viewer.dataSources.add(areas);
- // Create tileset of the reality data mesh
- // TODO: swap this out with a different mesh
- const realityMeshId = "85897090-3bcc-470b-bec7-20bb639cc1b9";
+ // Create tileset of the reality data mesh and pointcloud
+ const realityMeshId = "62e4432d-621d-489a-87ff-1fc56a2b5369";
const realityMesh = await Cesium.ITwinData.createTilesetForRealityDataId(
iTwinId,
realityMeshId,
);
viewer.scene.primitives.add(realityMesh);
+ const pointcloudId = "ebf2ee74-f0de-4cd6-a311-19a169c55fdc";
+ const pointcloud = await Cesium.ITwinData.createTilesetForRealityDataId(
+ iTwinId,
+ pointcloudId,
+ );
+ // increase the size of the pointcloud points and turn on attenuation to
+ // make them more visible in the viewer
+ pointcloud.maximumScreenSpaceError = 1;
+ pointcloud.pointCloudShading.attenuation = true;
+ pointcloud.style = new Cesium.Cesium3DTileStyle({
+ pointSize: 5.0,
+ });
+ pointcloud.show = false;
+ viewer.scene.primitives.add(pointcloud);
Sandcastle.addToolbarButton(
"Toggle Points",
@@ -86,31 +147,19 @@
() => (realityMesh.show = !realityMesh.show),
"layers",
);
+ Sandcastle.addToolbarButton(
+ "Toggle Pointcloud",
+ () => (pointcloud.show = !pointcloud.show),
+ "layers",
+ );
- Sandcastle.addToolbarButton("Zoom to Lines", () => {
- lines.show = true;
- viewer.zoomTo(lines);
+ Sandcastle.addToolbarButton("Birdseye View", () => {
+ viewer.scene.camera.flyTo(birdsEyeView);
});
- Sandcastle.addToolbarButton("Zoom to Reality Mesh", () => {
- realityMesh.show = true;
- viewer.zoomTo(realityMesh);
+ Sandcastle.addToolbarButton("Zoom to Pointcloud", () => {
+ pointcloud.show = true;
+ viewer.zoomTo(pointcloud);
});
-
- const birdsEyeView = {
- destination: new Cesium.Cartesian3(
- -1525452.5685833949,
- 6191771.429542403,
- 148747.35086195532,
- ),
- orientation: new Cesium.HeadingPitchRoll(
- 3.552713678800501e-15,
- -0.7854791130671286,
- 6.283185307179583,
- ),
- duration: 0,
- easingFunction: Cesium.EasingFunction.LINEAR_NONE,
- };
- viewer.scene.camera.flyTo(birdsEyeView);
//Sandcastle_End
Sandcastle.finishedLoading();
};
From b27251bf59e107f540092f855a8af7a82107a716 Mon Sep 17 00:00:00 2001
From: jjspace <8007967+jjspace@users.noreply.github.com>
Date: Wed, 4 Dec 2024 12:34:28 -0500
Subject: [PATCH 5/5] adjust viewer in sandcastle
---
.../gallery/iTwin Feature Service.html | 13 +++++++++++--
.../gallery/iTwin Feature Service.jpg | Bin 0 -> 14590 bytes
2 files changed, 11 insertions(+), 2 deletions(-)
create mode 100644 Apps/Sandcastle/gallery/iTwin Feature Service.jpg
diff --git a/Apps/Sandcastle/gallery/iTwin Feature Service.html b/Apps/Sandcastle/gallery/iTwin Feature Service.html
index f7c922661ca..d12f117ec3d 100644
--- a/Apps/Sandcastle/gallery/iTwin Feature Service.html
+++ b/Apps/Sandcastle/gallery/iTwin Feature Service.html
@@ -36,7 +36,16 @@
const iTwinId = "04ba725f-f3c0-4f30-8014-a4488cbd612d";
- const viewer = new Cesium.Viewer("cesiumContainer");
+ const viewer = new Cesium.Viewer("cesiumContainer", {
+ geocoder: false,
+ sceneModePicker: false,
+ homeButton: false,
+ timeline: false,
+ animation: false,
+ });
+ viewer.baseLayerPicker.viewModel.selectedImagery =
+ viewer.baseLayerPicker.viewModel.imageryProviderViewModels[2];
+
const birdsEyeView = {
destination: new Cesium.Cartesian3(
-1525359.4318772827,
@@ -88,7 +97,7 @@
lines.entities.values.forEach((entity) => {
const lineColorsByType = {
Contours: Cesium.Color.CRIMSON,
- Lane_Marking: Cesium.Color.WHITE,
+ Lane_Marking: Cesium.Color.CYAN,
Kerb: Cesium.Color.BLUEVIOLET,
Chevron_marking: Cesium.Color.DARKORANGE,
Turning_pocket: Cesium.Color.DEEPPINK,
diff --git a/Apps/Sandcastle/gallery/iTwin Feature Service.jpg b/Apps/Sandcastle/gallery/iTwin Feature Service.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..899bd961ab297c6e003835e8aad40b841d14f87e
GIT binary patch
literal 14590
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
literal 0
HcmV?d00001