Created
September 22, 2025 02:13
-
-
Save yiskang/3aa70170d4d20eab54386e653d081b16 to your computer and use it in GitHub Desktop.
RevitRoomsV2.html
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
| <html> | |
| <head> | |
| <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" /> | |
| <meta charset="utf-8"> | |
| <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" | |
| type="text/css"> | |
| <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.min.js"></script> | |
| <style> | |
| body { | |
| margin: 0; | |
| } | |
| #forgeViewer { | |
| width: 100%; | |
| height: 100%; | |
| margin: 0; | |
| background-color: #F0F8FF; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="forgeViewer"></div> | |
| <script> | |
| function fetchForgeToken(callback) { | |
| fetch('http://localhost:8090/api/oauth/token', { | |
| method: 'get', | |
| headers: new Headers({ 'Content-Type': 'application/json' }) | |
| }) | |
| .then((response) => { | |
| if (response.status === 200) { | |
| return response.json(); | |
| } else { | |
| return Promise.reject( | |
| new Error(`Failed to fetch token from server (status: ${response.status}, message: ${response.statusText})`) | |
| ); | |
| } | |
| }) | |
| .then((data) => { | |
| if (!data) return Promise.reject(new Error('Empty token response')); | |
| callback(data.access_token, data.expires_in); | |
| }) | |
| .catch((error) => console.error(error)); | |
| } | |
| async function loadMainViewAsync(viewer, urn, viewableId) { | |
| return new Promise((resolve, reject) => { | |
| async function onDocumentLoadSuccess(doc) { | |
| await doc.downloadAecModelData(); | |
| let viewable = (viewableId ? doc.getRoot().findByGuid(viewableId) : doc.getRoot().getDefaultGeometry()); | |
| let model = await viewer.loadDocumentNode(doc, viewable); | |
| await viewer.waitForLoadDone(); | |
| resolve(model); | |
| } | |
| function onDocumentLoadFailure() { | |
| reject(new Error('Failed fetching Forge manifest')); | |
| } | |
| Autodesk.Viewing.Document.load(urn, onDocumentLoadSuccess, onDocumentLoadFailure); | |
| }); | |
| } | |
| // Start: Method -1 ...... | |
| async function getRoomDbIdsAsync(model) { | |
| return new Promise((resolve, reject) => { | |
| model.search( | |
| 'Revit Rooms', | |
| (dbIds) => resolve(dbIds), | |
| (error) => reject(error), | |
| ['Category'], | |
| { searchHidden: true } | |
| ); | |
| }); | |
| }; | |
| async function getBulkPropertiesAsync(model, dbIds) { | |
| return new Promise((resolve, reject) => { | |
| model.getBulkProperties2( | |
| dbIds, | |
| { | |
| ignoreHidden: false, | |
| propFilter: ['viewable_in'] | |
| }, | |
| (result) => resolve(result), | |
| (error) => reject(error), | |
| ); | |
| }); | |
| } | |
| async function getRoomViewableInfoAsync(model) { | |
| const doc = model.getDocumentNode().getDocument(); | |
| let roomDbIds = await getRoomDbIdsAsync(model); | |
| let result = await getBulkPropertiesAsync(model, roomDbIds); | |
| let roomInfoMap = {}; | |
| result.forEach(r => { | |
| let roomDbId = r.dbId; | |
| let viewableIds = r.properties.map(prop => prop.displayValue); | |
| for (let i = 0; i < viewableIds.length; i++) { | |
| const viewableId = viewableIds[i]; | |
| const bubble = doc.getRoot().findByGuid(viewableId); | |
| if (bubble.is2D()) | |
| continue; | |
| if (roomInfoMap[viewableId]) { | |
| roomInfoMap[viewableId].dbIds.push(roomDbId); | |
| } else { | |
| roomInfoMap[viewableId] = { | |
| bubble, | |
| dbIds: [roomDbId] | |
| }; | |
| } | |
| } | |
| }); | |
| return roomInfoMap; | |
| } | |
| async function loadRoomsAsync(viewer, model) { | |
| const doc = model.getDocumentNode().getDocument(); | |
| let roomInfo = await getRoomViewableInfoAsync(model); | |
| let data = Object.values(roomInfo); | |
| for (let i = 0; i < data.length; i++) { | |
| await viewer.loadDocumentNode( | |
| doc, | |
| data[i].bubble, | |
| { | |
| ids: data[i].dbIds, | |
| modelNameOverride: `Room Phase \`${data[i].bubble.name()}\``, | |
| keepCurrentModels: true, | |
| globalOffset: new THREE.Vector3(),//this.viewer.model.getGlobalOffset(), | |
| placementTransform: viewer.model.getModelToViewerTransform() | |
| } | |
| ); | |
| await viewer.waitForLoadDone(); | |
| } | |
| return Promise.resolve(); | |
| } | |
| // End: Method -1 ...... | |
| // Method -2 | |
| async function loadRoomsBySelectiveLoadingAsync(viewer, model) { | |
| const doc = model.getDocumentNode().getDocument(); | |
| let masterViews = doc.getRoot().getMasterViews(); | |
| for (let i = 0; i < masterViews.length; i++) { | |
| let bubble = masterViews[i]; | |
| await viewer.loadDocumentNode( | |
| doc, | |
| bubble, | |
| { | |
| modelNameOverride: `Room Phase \`${bubble.name()}\``, | |
| keepCurrentModels: true, | |
| filter: { | |
| property_query: [ | |
| { 's.props.p5eddc473': "'Revit Rooms'" } //!<<< This may be changed by the UI language of the last Revit saved the RVT file. Please get correct category name from room properties using `viewer.getProperties( dbId, ... )`. | |
| ] | |
| } | |
| } | |
| ); | |
| await viewer.waitForLoadDone(); | |
| } | |
| return Promise.resolve(); | |
| } | |
| const options = { | |
| env: 'AutodeskProduction2', | |
| api: 'streamingV2', | |
| getAccessToken: fetchForgeToken | |
| }; | |
| Autodesk.Viewing.Initializer(options, async function () { | |
| const config3d = { | |
| modelBrowserStartCollapsed: true, | |
| modelBrowserExcludeRoot: false, | |
| }; | |
| let viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'), config3d); | |
| let startedCode = viewer.start(); | |
| if (startedCode > 0) { | |
| console.error('Failed to create a Viewer: WebGL not supported.'); | |
| return; | |
| } | |
| const profileSettings = Autodesk.Viewing.ProfileSettings.clone(Autodesk.Viewing.ProfileSettings.AEC); | |
| profileSettings.settings.bimWalkToolPopup = false; | |
| const profile = new Autodesk.Viewing.Profile(profileSettings); | |
| viewer.setProfile(profile); | |
| let documentId = 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzdC1zYW5kYm94LWxrd2VqN3hwYmdwNjN4NGhsMzM1eTZtMjZvYWtnZ29mL3JhY2Jhc2ljc2FtcGxlcHJvamVjdC5ydnQ'; | |
| let mainModel = await loadMainViewAsync(viewer, documentId); | |
| await loadRoomsAsync(viewer, mainModel); | |
| viewer.showAll(); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment