-
Notifications
You must be signed in to change notification settings - Fork 0
Adding imodel view cesium-sandcastle command
#75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
5e87d03
Adding share url builder to view iModel in Cesium Sandcastle
wolfo951 cc443f6
Adding ability to auto open the URL in default browser
wolfo951 bad792b
Merge branch 'main' of https://github.com/iTwin/itwin-cli into wolfo9…
wolfo951 6f8831f
Merge branch 'main' of https://github.com/iTwin/itwin-cli into wolfo9…
wolfo951 c5ac658
Handle iTwinPlatform calls before export on the CLI instead of sandca…
wolfo951 a442933
Adding cesium-sandcastle docs
wolfo951 2086634
Fixing cross-spawn dependency
wolfo951 7295540
Adding single character flag
wolfo951 440e645
Updating package.json version to 0.0.4
wolfo951 113cefd
Adding single char flag to command
wolfo951 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # itp imodel view cesium-sandcastle | ||
|
|
||
| Setup iModel and get URL to view it in Cesium Sandcastle. | ||
|
|
||
| ## Options | ||
|
|
||
| - **`--changeset-id`** | ||
| Changeset id to be viewed in Cesium Sandcastle. | ||
| **Type:** `string` **Required:** Yes | ||
|
|
||
| - **`-m, --imodel-id`** | ||
| iModel id to be viewed in Cesium Sandcastle. | ||
| **Type:** `string` **Required:** Yes | ||
|
|
||
| - **`--open`** | ||
| Open the URL in the browser. | ||
| **Type:** `boolean` **Required:** No | ||
|
|
||
| ## Examples | ||
|
|
||
| ```bash | ||
| # Example 1: Get a link to a specific changeset of an iModel in Cesium Sandcastle | ||
| itp imodel view cesium-sandcastle --imodel-id "5e19bee0-3aea-4355-a9f0-c6df9989ee7d" --changeset-id "2f3b4a8c92d747d5c8a8b2f9cde6742e5d74b3b5" | ||
|
|
||
| # Example 2: Get a link to a specific changeset of an iModel in Cesium Sandcastle and open the URL in the browser | ||
| itp imodel view cesium-sandcastle --imodel-id "5e19bee0-3aea-4355-a9f0-c6df9989ee7d" --changeset-id "2f3b4a8c92d747d5c8a8b2f9cde6742e5d74b3b5" --open | ||
| ``` | ||
|
|
||
| ## API Reference | ||
|
|
||
| [Cesium Sandcastle](https://cesium.com/docs/sandcastle/) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # itp imodel view | ||
|
|
||
| Work with views for an iModel. | ||
|
|
||
| ## Available Commands | ||
|
|
||
| - [itp imodel view cesium-sandcastle](imodel/view/cesium-sandcastle.md) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| /*--------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Bentley Systems, Incorporated. All rights reserved. | ||
| * See LICENSE.md in the project root for license terms and full copyright notice. | ||
| *--------------------------------------------------------------------------------------------*/ | ||
|
|
||
| import { Flags } from "@oclif/core"; | ||
| import open from 'open'; | ||
| import { deflate } from "pako"; | ||
|
|
||
| import BaseCommand from "../../../extensions/base-command.js"; | ||
| import { link, links } from "../../../services/general-models/links.js"; | ||
|
|
||
| export default class CesiumSandcastle extends BaseCommand { | ||
| static description = "Setup iModel and get url to view it in Cesium Sandcastle"; | ||
|
|
||
| static flags = { | ||
| "changeset-id": Flags.string({ | ||
| description: "Changeset id to be viewed in Cesium Sandcastle.", | ||
| required: true | ||
| }), | ||
| "imodel-id": Flags.string({ | ||
| char: "m", | ||
| description: "iModel id to be viewed in Cesium Sandcastle.", | ||
| required: true | ||
| }), | ||
| "open": Flags.boolean({ | ||
| description: "Open the URL in the browser.", | ||
| required: false, | ||
| }), | ||
| }; | ||
|
|
||
| async createExport(iModelId: string, changesetId: string): Promise<ExportInfo> { | ||
| const args = [ | ||
| "--method", "POST", | ||
| "--path", "mesh-export", | ||
| "--version-header", "application/vnd.bentley.itwin-platform.v1+json", | ||
| "--body", JSON.stringify({ | ||
| changesetId, | ||
| exportType: "CESIUM", | ||
| iModelId | ||
| }), | ||
| ]; | ||
|
|
||
| const created = await this.runCommand<ExportCreateResponse>("api", args); | ||
| return created.export; | ||
| } | ||
|
|
||
| async getExports(iModelId: string) : Promise<ExportInfo[]> { | ||
| const exportArgs = [ | ||
| "--method", "GET", | ||
| "--path", "mesh-export/", | ||
| "--version-header", "application/vnd.bentley.itwin-platform.v1+json", | ||
| "--query", `iModelId: ${iModelId}`, | ||
| "--header", "Prefer: return=representation" | ||
| ]; | ||
| const response = await this.runCommand<ExportResponse>("api", exportArgs); | ||
| return response.exports; | ||
| } | ||
|
|
||
| async getOrCreateExport(iModelId: string, changesetId: string): Promise<ExportInfo> { | ||
| this.log(`Getting existing exports for iModel: ${iModelId} and changeset: ${changesetId}`); | ||
| let existingExports = await this.getExports(iModelId); | ||
| const existingExport = existingExports.find((exp) => exp.request.exportType === "CESIUM" && exp.request.changesetId === changesetId); | ||
|
|
||
| if (existingExport !== undefined) { | ||
| this.log(`Found existing export with id: ${existingExport.id}`); | ||
| return existingExport; | ||
| } | ||
|
|
||
| this.log(`Creating new export for iModel: ${iModelId} and changeset: ${changesetId}`); | ||
| let newExport = await this.createExport(iModelId, changesetId); | ||
| while (newExport.status !== "Complete") { | ||
| this.log(`Export status is ${newExport.status}. Waiting for export to complete...`); | ||
| // eslint-disable-next-line no-await-in-loop | ||
| existingExports = await this.getExports(iModelId); | ||
| newExport = existingExports.find((exp) => exp.id === newExport.id)!; | ||
| // eslint-disable-next-line no-await-in-loop | ||
| await new Promise((resolve) => {setTimeout(resolve, 5000)}); | ||
| } | ||
|
|
||
| this.log(`Export completed successfully`); | ||
| return newExport; | ||
| } | ||
|
|
||
| async run() { | ||
| const { flags } = await this.parse(CesiumSandcastle); | ||
|
|
||
| const exportInfo : ExportInfo = await this.getOrCreateExport(flags["imodel-id"], flags["changeset-id"]); | ||
|
|
||
| this.log(`Extracting tileset URL from export info`); | ||
| const tilesetUrl : string = extractTileSetUrl(exportInfo); | ||
|
|
||
| const data = [ | ||
| jsData(tilesetUrl), | ||
| htmlData(), | ||
| ]; | ||
|
|
||
| const url = `https://sandcastle.cesium.com/#c=${makeCompressedBase64String(data)}`; | ||
|
|
||
| this.log(`Cesium Sandcastle URL:`); | ||
| this.log(url); | ||
|
|
||
| if (flags.open) { | ||
| this.log(`Opening URL in browser...`); | ||
| open(url); | ||
| } | ||
|
|
||
| return this.logAndReturnResult({ url }); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| type ExportResponse = { | ||
| _links: links | ||
| exports: ExportInfo[], | ||
| } | ||
|
|
||
| type ExportCreateResponse = { | ||
| export: ExportInfo | ||
| } | ||
|
|
||
| type ExportInfo = { | ||
| _links: { | ||
| mesh: link | ||
| }, | ||
| displayName: string, | ||
| error?: string, | ||
| id: string, | ||
| lastModified: Date, | ||
| request: ExportRequest, | ||
| status: "Complete" | "InProgress" | "Invalid" | "NotStarted", | ||
| } | ||
|
|
||
| type ExportRequest = { | ||
| changesetId: string, | ||
| exportType: "3DFT" | "3DTiles" | "CESIUM" | "IMODEL", | ||
| iModelId: string, | ||
| } | ||
|
|
||
| function extractTileSetUrl(exportInfo: ExportInfo): string { | ||
| if(exportInfo._links.mesh.href === undefined) { | ||
| throw new Error(`No tileset url found for export info id: ${exportInfo.id}`); | ||
| } | ||
|
|
||
| const urlParts = exportInfo._links.mesh.href.split("?"); | ||
| return urlParts[0] + "/tileset.json?" + urlParts[1]; | ||
| } | ||
|
|
||
| function makeCompressedBase64String(data: string[]) : string { | ||
| let jsonString = JSON.stringify(data); | ||
| jsonString = jsonString.slice(2, 2 + jsonString.length - 4); | ||
| let base64String = Buffer.from( | ||
| deflate(jsonString, { raw: true }) | ||
| ).toString('base64'); | ||
| base64String = base64String.replace(/=+$/, ''); // remove padding | ||
|
|
||
| return base64String; | ||
| } | ||
|
|
||
| function htmlData() : string { | ||
| return ` | ||
| <style> | ||
| @import url(../templates/bucket.css); | ||
| </style> | ||
|
|
||
| <div id="cesiumContainer" class="fullSize"></div> | ||
| `; | ||
| } | ||
|
|
||
| function jsData(tilesetUrl: string) : string { | ||
| return ` | ||
| const viewer = new Cesium.Viewer("cesiumContainer"); | ||
| viewer.scene.globe.show = true; | ||
| viewer.scene.debugShowFramesPerSecond = true; | ||
| const tilesetUrl = '${tilesetUrl}'; | ||
| const tileset = await Cesium.Cesium3DTileset.fromUrl(tilesetUrl); | ||
| viewer.scene.primitives.add(tileset); | ||
| viewer.zoomTo(tileset); | ||
| `; | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.