Last active
April 1, 2024 08:37
-
-
Save yiskang/cedbe270765fdb33925a914c383e2346 to your computer and use it in GitHub Desktop.
Sample: Show Revit rooms from master view with a general Revit 3D view by model aggregation (Loading Multiple Models).
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
<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.88.*/style.min.css" | |
type="text/css"> | |
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.88.*/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/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, { loadAsHidden: false }); | |
await viewer.waitForLoadDone(); | |
resolve(model); | |
} | |
function onDocumentLoadFailure() { | |
reject(new Error('Failed fetching Forge manifest')); | |
} | |
Autodesk.Viewing.Document.load(urn, onDocumentLoadSuccess, onDocumentLoadFailure); | |
}); | |
} | |
async function getRoomDbIdsAsync(model, roomCategoryName = 'Revit Rooms') { | |
return new Promise((resolve, reject) => { | |
model.search( | |
`${roomCategoryName}`, | |
(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', 'externalId'], | |
needsExternalId: true, | |
}, | |
(result) => resolve(result), | |
(error) => reject(error), | |
); | |
}); | |
} | |
async function getRoomViewableInfoAsync(model) { | |
const doc = model.getDocumentNode().getDocument(); | |
let roomDbIds = await getRoomDbIdsAsync(model); | |
if (roomDbIds.length <= 0) | |
roomDbIds = await getRoomDbIdsAsync(model, 'Revit Ambientes'); | |
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, mainModel) { | |
const doc = mainModel.getDocumentNode().getDocument(); | |
let roomInfo = await getRoomViewableInfoAsync(mainModel); | |
if (!roomInfo) return Promise.resolve(); | |
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(),//mainModel.getGlobalOffset(), | |
placementTransform: mainModel.getModelToViewerTransform() | |
} | |
); | |
await viewer.waitForLoadDone(); | |
} | |
return Promise.resolve(); | |
} | |
const options = { | |
env: 'AutodeskProduction', | |
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:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6c2FuZG94L3JhY19iYXNpY19zYW1wbGVfcHJvamVjdC5ydnQ'; | |
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