-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
734 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,297 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta | ||
name="viewport" | ||
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" | ||
/> | ||
<meta | ||
name="description" | ||
content="Use Viewer to start building new applications or easily embed Cesium into existing applications." | ||
/> | ||
<meta name="cesium-sandcastle-labels" content="Beginner, Showcases" /> | ||
<title>Cesium Demo</title> | ||
<script type="text/javascript" src="../Sandcastle-header.js"></script> | ||
<script type="module" src="../load-cesium-es6.js"></script> | ||
</head> | ||
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html"> | ||
<style> | ||
@import url(../templates/bucket.css); | ||
</style> | ||
<div id="cesiumContainer" class="fullSize"></div> | ||
<div id="loadingOverlay"><h1>Loading...</h1></div> | ||
<div id="toolbar"> | ||
<div id="checkbox"></div> | ||
<output id="status">Initializing</output> | ||
</div> | ||
<script id="cesium_sandcastle_script"> | ||
window.startup = async function (Cesium) { | ||
"use strict"; | ||
//Sandcastle_Begin | ||
// Gabby's token or one created using the Share API? | ||
// const accessToken = | ||
// "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkJlbnRsZXlJTVNfMjAyNCIsInBpLmF0bSI6ImE4bWUifQ.eyJzY29wZSI6WyJtZXNoLWV4cG9ydDpyZWFkIiwibWVzaC1leHBvcnQ6bW9kaWZ5Il0sImNsaWVudF9pZCI6Iml0d2luLWRldmVsb3Blci1jb25zb2xlIiwiYXVkIjpbImh0dHBzOi8vaW1zLmJlbnRsZXkuY29tL2FzL3Rva2VuLm9hdXRoMiIsImh0dHBzOi8vaW1zb2lkYy5iZW50bGV5LmNvbS9hcy90b2tlbi5vYXV0aDIiLCJodHRwczovL2ltc29pZGMuYmVudGxleS5jb20vcmVzb3VyY2VzIiwiYmVudGxleS1hcGktbWFuYWdlbWVudCJdLCJzdWIiOiJiNmFmMjk1ZC00NGNiLTRjYjMtYThlMy0yMTM3ODM3MDU2ZGUiLCJyb2xlIjoiQkVOVExFWV9FTVBMT1lFRSIsIm9yZyI6ImZhYjk3NzRiLWIzMzgtNGNjMi1hNmM5LTQ1OGJkZjdmOTY2YSIsInN1YmplY3QiOiJiNmFmMjk1ZC00NGNiLTRjYjMtYThlMy0yMTM3ODM3MDU2ZGUiLCJpc3MiOiJodHRwczovL2ltcy5iZW50bGV5LmNvbSIsImVudGl0bGVtZW50IjpbIkJFTlRMRVlfTEVBUk4iLCJJTlRFUk5BTCIsIlNFTEVDVF8yMDA2IiwiQkVOIiwiQkROIl0sInByZWZlcnJlZF91c2VybmFtZSI6IkdhYmJ5LkdldHpAYmVudGxleS5jb20iLCJnaXZlbl9uYW1lIjoiR2FiYnkiLCJzaWQiOiIzZWNtdVUzNWJXV3hyQ1lfVWVnR0IxVkFxcmMuU1UxVExVSmxiblJzWlhrdFZWTS5FbzV4LnVYMEFyS1Ixcm5udHpQNDJsNG9uOGJpWTQiLCJuYmYiOjE3MjkyNzAwNTMsInVsdGltYXRlX3NpdGUiOiIxMDAxMzg5MTE3IiwidXNhZ2VfY291bnRyeV9pc28iOiJVUyIsImF1dGhfdGltZSI6MTcyOTI3MDM1MywibmFtZSI6IkdhYmJ5LkdldHpAYmVudGxleS5jb20iLCJvcmdfbmFtZSI6IkJlbnRsZXkgU3lzdGVtcyBJbmMiLCJmYW1pbHlfbmFtZSI6IkdldHoiLCJlbWFpbCI6IkdhYmJ5LkdldHpAYmVudGxleS5jb20iLCJleHAiOjE3MjkyNzM5NTN9.DTm5w_ARIHL0AuNaGFtgQ7-yhcaVcL8mawKu1wy-9RKVGn-gA-yZx9wU79XDwTI1yGef6ZrJpuwkiGSSkp45dKdwonWEZA0Mb9HYtlFqk519jY3sDxeFb_E2eIMIblA0P6lSyrkP3CNnlLhFctr8jR6LOSSgvYMWvBQhBpA2LgMFDRShxl0-V95qCAL7iP7E-m9WwXghllOMHfmviOU7nmG73fSPcboI9QCPpAINO9bzvPHkJnumvQsukHAbdn4CPEl0cRukZpJTxvTJllQ_YimDeWPtgQOwfidRLoYZviu3PYDYbRVs5X1WEsLd1SeJzfj8WVUMFkfsrlEdpvmbNQ"; | ||
// My access token, must be created for the Start export route, probably an oauth scope thing? | ||
const accessToken = | ||
"Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkJlbnRsZXlJTVNfMjAyNCIsInBpLmF0bSI6ImE4bWUifQ.eyJzY29wZSI6WyJtZXNoLWV4cG9ydDpyZWFkIiwibWVzaC1leHBvcnQ6bW9kaWZ5Il0sImNsaWVudF9pZCI6Iml0d2luLWRldmVsb3Blci1jb25zb2xlIiwiYXVkIjpbImh0dHBzOi8vaW1zLmJlbnRsZXkuY29tL2FzL3Rva2VuLm9hdXRoMiIsImh0dHBzOi8vaW1zb2lkYy5iZW50bGV5LmNvbS9hcy90b2tlbi5vYXV0aDIiLCJodHRwczovL2ltc29pZGMuYmVudGxleS5jb20vcmVzb3VyY2VzIiwiYmVudGxleS1hcGktbWFuYWdlbWVudCJdLCJzdWIiOiJjMWM1MzRhNy0zZDk2LTQ2MzMtYjY5ZC1jMGEzNzE5OWQwZGUiLCJyb2xlIjoiQkVOVExFWV9FTVBMT1lFRSIsIm9yZyI6ImZhYjk3NzRiLWIzMzgtNGNjMi1hNmM5LTQ1OGJkZjdmOTY2YSIsInN1YmplY3QiOiJjMWM1MzRhNy0zZDk2LTQ2MzMtYjY5ZC1jMGEzNzE5OWQwZGUiLCJpc3MiOiJodHRwczovL2ltcy5iZW50bGV5LmNvbSIsImVudGl0bGVtZW50IjpbIkJFTlRMRVlfTEVBUk4iLCJJTlRFUk5BTCIsIlNFTEVDVF8yMDA2IiwiQkVOIiwiQkROIl0sInByZWZlcnJlZF91c2VybmFtZSI6Ikpvc2guUm91emVyQGJlbnRsZXkuY29tIiwiZ2l2ZW5fbmFtZSI6Ikpvc2giLCJzaWQiOiJHMGZTamlOXzBMRjE1Vy1IYnRTaWtoeDNuSXMuU1UxVExVSmxiblJzWlhrdFZWTS5LUDVRLjZCakNoYXptMldBMjBIdXVWMUxwNFB6RVAiLCJuYmYiOjE3MzA3NDc3NjUsInVsdGltYXRlX3NpdGUiOiIxMDAxMzg5MTE3IiwidXNhZ2VfY291bnRyeV9pc28iOiJVUyIsImF1dGhfdGltZSI6MTczMDc0ODA2NSwibmFtZSI6Ikpvc2guUm91emVyQGJlbnRsZXkuY29tIiwib3JnX25hbWUiOiJCZW50bGV5IFN5c3RlbXMgSW5jIiwiZmFtaWx5X25hbWUiOiJSb3V6ZXIiLCJlbWFpbCI6Ikpvc2guUm91emVyQGJlbnRsZXkuY29tIiwiZXhwIjoxNzMwNzUxNjY2fQ.0yEQZAyKKAdwNDiwHSD6f_Qzq0M8cbHJcMfT6JidBldw9qiyU4jx6ZdqILddrL-seWCkf9sRtWuoHm7Fw-j_wtaLASaOpHMMwC7IVdh25pbRB-D3mN8_rmQiDbXUadJ1MwH8-pNCubrER1lZLYEPrQ4zJcRtAblbJGNjFdoOi3FXB-y3JLleH4qYykLceDkbW3l2lZRfdIW2pytCIuZs7XZ9Hr6F_cLsYIrs9iRfBFVxxHxxfwgRLQoRuPmDuzKl9-ylLZUFN6CQZUfv7vzL9feoXJXGdZeGgqlyFuMOCiVbYU_elx7P7fFm8G13HvTti5hz98mV1r2bXYvfNpuklg"; | ||
Cesium.ITwin.defaultAccessToken = accessToken; | ||
// this is the iModel in the "Hello iTwinCesium" iTwin that we should all have access to | ||
// https://developer.bentley.com/my-itwins/b4a30036-0456-49ea-a439-3fcd9365e24e/home/ | ||
const imodelId = "2852c3d7-00c3-4b5d-a0ce-82bbde4f061e"; | ||
|
||
// const knownExportId = undefined; | ||
const knownExportId = "ab9953b2-bc8e-48ac-a5b0-5d43d68593e8"; | ||
|
||
// async function startExport(iModelId, changesetId, accessToken) { | ||
// console.log("Start Export"); | ||
|
||
// const requestOptions = { | ||
// method: "POST", | ||
// headers: { | ||
// Authorization: accessToken, | ||
// Accept: "application/vnd.bentley.itwin-platform.v1+json", | ||
// "Content-Type": "application/json", | ||
// }, | ||
// body: JSON.stringify({ | ||
// iModelId, | ||
// changesetId, | ||
// exportType: "CESIUM", | ||
// }), | ||
// }; | ||
|
||
// // initiate mesh export | ||
// const response = await fetch( | ||
// `https://api.bentley.com/mesh-export/`, | ||
// requestOptions, | ||
// ); | ||
// if (!response.ok) { | ||
// if (response.status === 401) { | ||
// console.error("Unauthorized, bad token, wrong scopes or headers bad"); | ||
// } else if (response.status === 403) { | ||
// console.error("Not allowed, forbidden"); | ||
// } else if (response.status === 422) { | ||
// console.error("Unprocessable: Cannot create export job"); | ||
// } else if (response.status === 429) { | ||
// console.log("Too many requests"); | ||
// } else { | ||
// console.error("Bad request, unknown error", response); | ||
// } | ||
// return undefined; | ||
// } | ||
// const result = JSON.parse(JSON.stringify(await response.json())); | ||
// return result?.export?.id; | ||
// } | ||
|
||
// async function getExport(exportId, accessToken) { | ||
// const headers = { | ||
// Authorization: accessToken, | ||
// Accept: "application/vnd.bentley.itwin-platform.v1+json", | ||
// }; | ||
|
||
// // obtain export for specified export id | ||
// const url = `https://api.bentley.com/mesh-export/${exportId}`; | ||
// try { | ||
// // TODO: this request is _really_ slow, like 7 whole second alone for me | ||
// const response = await fetch(url, { headers }); | ||
// if (!response.ok) { | ||
// if (response.status === 401) { | ||
// console.error("Unauthorized, bad token, wrong scopes or headers bad"); | ||
// } else if (response.status === 404) { | ||
// console.error("Requested export is not available", exportId); | ||
// } else if (response.status === 429) { | ||
// console.error("Too many requests"); | ||
// } else { | ||
// console.log("Unknown request failure", response); | ||
// } | ||
// return undefined; | ||
// } | ||
// const result = JSON.parse(JSON.stringify(await response.json())); | ||
// return result; | ||
// } catch (err) { | ||
// return undefined; | ||
// } | ||
// } | ||
|
||
const delay = (ms) => new Promise((res) => setTimeout(res, ms)); | ||
|
||
// Grabbed mapping from the iTwin Viewer | ||
const classes = { | ||
2199023255632: "Building Roof", | ||
2199023255694: "Building Wall", | ||
2199023255696: "Building Window", | ||
}; | ||
|
||
let selectedFeature; | ||
let picking = false; | ||
|
||
Sandcastle.addToggleButton( | ||
"Per-feature selection", | ||
false, | ||
function (checked) { | ||
picking = checked; | ||
if (!picking) { | ||
unselectFeature(selectedFeature); | ||
} | ||
}, | ||
"checkbox", | ||
); | ||
|
||
// Set up viewer | ||
const viewer = new Cesium.Viewer("cesiumContainer", { | ||
terrain: Cesium.Terrain.fromWorldTerrain(), | ||
}); | ||
const scene = viewer.scene; | ||
scene.globe.show = true; | ||
scene.debugShowFramesPerSecond = true; | ||
|
||
// HTML overlay for showing feature name on mouseover | ||
const nameOverlay = document.createElement("div"); | ||
viewer.container.appendChild(nameOverlay); | ||
nameOverlay.className = "backdrop"; | ||
nameOverlay.style.display = "none"; | ||
nameOverlay.style.position = "absolute"; | ||
nameOverlay.style.bottom = "0"; | ||
nameOverlay.style.left = "0"; | ||
nameOverlay.style["pointer-events"] = "none"; | ||
nameOverlay.style.padding = "4px"; | ||
nameOverlay.style.backgroundColor = "black"; | ||
nameOverlay.style.whiteSpace = "pre-line"; | ||
nameOverlay.style.fontSize = "12px"; | ||
|
||
function selectFeature(feature, movement) { | ||
feature.color = Cesium.Color.clone( | ||
Cesium.Color.fromCssColorString("#eeff41"), | ||
feature.color, | ||
); | ||
selectedFeature = feature; | ||
|
||
nameOverlay.style.display = "block"; | ||
nameOverlay.style.bottom = `${ | ||
viewer.canvas.clientHeight - movement.endPosition.y | ||
}px`; | ||
nameOverlay.style.left = `${movement.endPosition.x}px`; | ||
const element = feature.getProperty("element"); | ||
const subcategory = feature.getProperty("subcategory"); | ||
const message = ` | ||
Element ID: ${element} | ||
Subcategory: ${classes[subcategory] ?? subcategory} | ||
Feature ID: ${feature.featureId}`; | ||
nameOverlay.textContent = message; | ||
} | ||
|
||
function unselectFeature(feature) { | ||
if (!Cesium.defined(feature)) { | ||
return; | ||
} | ||
|
||
feature.color = Cesium.Color.clone(Cesium.Color.WHITE, feature.color); | ||
selectedFeature = undefined; | ||
nameOverlay.style.display = "none"; | ||
} | ||
|
||
const statusOutput = document.querySelector("#status"); | ||
async function init() { | ||
// TODO: just testing | ||
// await Cesium.createIModel3DTileset.deleteExport( | ||
// "3a627319-cf6e-4535-9499-da5320a69791", | ||
// ); | ||
// console.log(await Cesium.createIModel3DTileset.checkForCesiumExport(imodelId)); | ||
// console.log(await Cesium.createIModel3DTileset.getExports(imodelId)); | ||
|
||
const changesetId = ""; | ||
const cesiumExport = await Cesium.createIModel3DTileset.checkForCesiumExport( | ||
imodelId, | ||
changesetId, | ||
); | ||
let exportId = cesiumExport?.id; | ||
if (!Cesium.defined(cesiumExport)) { | ||
exportId = await Cesium.createIModel3DTileset.createExportForModelId( | ||
imodelId, | ||
changesetId, | ||
accessToken, | ||
); | ||
} | ||
|
||
statusOutput.innerText = "Starting export"; | ||
// const exportId = | ||
// knownExportId ?? | ||
// (await Cesium.createIModel3DTileset.createExportForModelId( | ||
// imodelId, | ||
// "", | ||
// accessToken, | ||
// )); | ||
|
||
if (!exportId) { | ||
console.error("No export id returned"); | ||
return; | ||
} | ||
console.log("Using export id", exportId); | ||
|
||
const start = Date.now(); | ||
// let result = await getExport(exportId, accessToken); | ||
// let status = result.export.status; | ||
// while (status !== "Complete") { | ||
// await delay(5000); | ||
// result = await getExport(exportId, accessToken); | ||
// status = result.export.status; | ||
// console.log(`Export is ${status}`); | ||
|
||
// if (Date.now() - start > 300_000) { | ||
// throw new Error("Export did not complete in time."); | ||
// } | ||
// } | ||
|
||
// if (result.export.request.exportType !== "CESIUM") { | ||
// console.error("Wrong export type", result.export.request.exportType); | ||
// throw new Error(`Wrong export type ${result.export.request.exportType}`); | ||
// } | ||
|
||
// // This link is only valid 1 hour | ||
// let tilesetUrl = result.export._links.mesh.href; | ||
// const splitStr = tilesetUrl.split("?"); | ||
// // is there a cleaner way to do this? | ||
// tilesetUrl = `${splitStr[0]}/tileset.json?${splitStr[1]}`; | ||
|
||
// const tileset = await Cesium.Cesium3DTileset.fromUrl(tilesetUrl); | ||
statusOutput.innerText = "Creating Tileset"; | ||
const tileset = await Cesium.createIModel3DTileset(exportId); | ||
scene.primitives.add(tileset); | ||
tileset.colorBlendMode = Cesium.Cesium3DTileColorBlendMode.REPLACE; | ||
|
||
statusOutput.innerText = "Loaded"; | ||
|
||
viewer.zoomTo(tileset); | ||
console.log(`Finished in ${((Date.now() - start) / 1000).toString()} seconds`); | ||
|
||
const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas); | ||
handler.setInputAction(function (movement) { | ||
if (!picking) { | ||
return; | ||
} | ||
unselectFeature(selectedFeature); | ||
|
||
const feature = scene.pick(movement.endPosition); | ||
|
||
if (feature instanceof Cesium.Cesium3DTileFeature) { | ||
selectFeature(feature, movement); | ||
} | ||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE); | ||
} | ||
|
||
init(); | ||
|
||
//Sandcastle_End | ||
Sandcastle.finishedLoading(); | ||
}; | ||
if (typeof Cesium !== "undefined") { | ||
window.startupCalled = true; | ||
window.startup(Cesium).catch((error) => { | ||
"use strict"; | ||
console.error(error); | ||
}); | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains 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,66 @@ | ||
import Resource from "./Resource.js"; | ||
|
||
/** | ||
* Default settings for accessing the iTwin platform. | ||
* | ||
* Keys can be created using the iModels share routes {@link https://developer.bentley.com/apis/imodels-v2/operations/create-imodel-share/} | ||
* | ||
* An ion access token is only required if you are using any ion related APIs. | ||
* A default access token is provided for evaluation purposes only. | ||
* Sign up for a free ion account and get your own access token at {@link https://cesium.com} | ||
* | ||
* @see IonResource | ||
* @see IonImageryProvider | ||
* @see IonGeocoderService | ||
* @see createWorldImagery | ||
* @see createWorldTerrain | ||
* @namespace ITwin | ||
*/ | ||
const ITwin = {}; | ||
|
||
/** | ||
* Gets or sets the default iTwin access token. | ||
* | ||
* TODO: I'm not sure we can even do this kind of access token. Each route seems to need it's own scopes | ||
* and we may not be able to guarantee this "top level token" has them all | ||
* So far we use | ||
* `mesh-export:read` for loading meshes GET /mesh-export(s) | ||
* `mesh-export:modify` if we want to include a function to create an export | ||
* `itwin-platform` if we want to use the iModel shares ourselves GET /imodels/{id}/shares | ||
* | ||
* | ||
* @type {string|undefined} | ||
*/ | ||
ITwin.defaultAccessToken = undefined; | ||
|
||
/** | ||
* Gets or sets the default Google Map Tiles API endpoint. | ||
* | ||
* @type {string|Resource} | ||
* @default https://api.bentley.com | ||
*/ | ||
ITwin.apiEndpoint = new Resource({ | ||
url: "https://api.bentley.com", | ||
}); | ||
|
||
// TODO: this should only be needed if we have a way to generate really long term access tokens | ||
// to sample data that is accessible to everyone | ||
// ITwin.getDefaultTokenCredit = function (providedKey) { | ||
// if (providedKey !== defaultAccessToken) { | ||
// return undefined; | ||
// } | ||
|
||
// if (!defined(defaultTokenCredit)) { | ||
// const defaultTokenMessage = | ||
// '<b> \ | ||
// This application is using Cesium\'s default ion access token. Please assign <i>Cesium.Ion.defaultAccessToken</i> \ | ||
// with an access token from your ion account before making any Cesium API calls. \ | ||
// You can sign up for a free ion account at <a href="https://cesium.com">https://cesium.com</a>.</b>'; | ||
|
||
// defaultTokenCredit = new Credit(defaultTokenMessage, true); | ||
// } | ||
|
||
// return defaultTokenCredit; | ||
// }; | ||
|
||
export default ITwin; |
Oops, something went wrong.