6 Oct 2020

Mapping between sheets and 3D views of AEC models

AEC sheet to model mapping

EDIT: Ever since this blog post has been published, the AEC utilities in Forge Viewer (including the 2D to 3D mapping) have been refactored. If you're using one the latest versions of the viewer, you'll want to update the code explained in this tutorial as shown in this git commit: https://github.com/petrbroz/forge-viewer-samples/commit/34732b2b11369bb30c7d63e924cf4a6ebf2c59a8.

When working with AEC models in Forge Viewer, developers sometimes need to be able to map 2D sheet coordinates to 3D view coordinates and vice versa. Let's take a look at how that could be done.

Last year, my colleague Xiaodong blogged about the Model Derivative service extracting additional, AEC-specific metadata in his article Consume AEC Data which are from Model Derivative API. Basically, the translation of AEC designs now outputs an additional JSON with information about construction phases, building levels, etc.

AEC model JSON

You may have seen various viewer extensions that make use of the AEC metadata already, for example:

  • Autodesk.AEC.LevelsExtension - allowing you to easily show and hide individual building levels
  • Autodesk.AEC.Minimap3DExtension - showing & controlling your position on a small 2D map when walking around in a 3D view

AEC Viewer Extensions

Many of these extensions use a global object called Autodesk.AEC.AecModelData which is basically a collection of utility functions based on the content of the AEC metadata JSON, for example:

  • Autodesk.AEC.AecModelData.findViewportsOnSheet(sheet) - finding all viewports on a 2D sheet (the sheet parameter is a specific viewable from the manifest retrieved by the Autodesk.Viewing.Document.load method)
  • Autodesk.AEC.AecModelData.get2DTo3DMatrix(viewport, sheetUnitScale) - computing THREE.Matrix4 to convert 2D sheet coords within the given viewport to 3D model coordinates
  • Autodesk.AEC.AecModelData.get3DTo2DMatrix(viewport, sheetUnitScale) - computing THREE.Matrix4 to convert 3D model coords to 2D sheet coords within a given viewport
  • Autodesk.AEC.AecModelData.findViewportAtPoint(sheet, point, filter) - finding a viewport at specific 2D coordinates of a sheet

Now let's see how we can leverage these functions in our own code to map coordinates from a 2D sheet to their corresponding coords in a 3D view:

Step 1: Get the utility function code

The helper functions under Autodesk.AEC.AecModelData are not bundled with Forge Viewer itself. You'll have to load one of the AEC-specific extensions mentioned earlier to make sure this object is available, for example:

const config = {
    extensions: ['Autodesk.AEC.LevelsExtension']
};
let viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('preview'), config);

Step 2: Load the AEC metadata

The AEC metadata has to be loaded explicitly. You can do so with a single call to the Autodesk.Viewing.Document.getAecModelData function, like so:

function loadModel(viewer, urn, guid) {
    function onDocumentLoadSuccess(doc) {
        // Asynchronously requests the AEC metadata and makes it available under a new property `aec_model_data` of the `doc` object
        Autodesk.Viewing.Document.getAecModelData(doc.getRoot())
            .then(aec => console.log('AEC metadata', aec)); 
        // Starts loading the actual model
        viewer.loadDocumentNode(doc, doc.getRoot().findByGuid(guid))
    }
    function onDocumentLoadFailure(code, message) {
        console.error('Could not load document.', message);
    }
    Autodesk.Viewing.Document.load('urn:' + urn, onDocumentLoadSuccess, onDocumentLoadFailure);
}

If you don't see any AEC metadata, it's possible that it hasn't been extracted by the Model Derivative service. You can check its existence by requesting your model's manifest and looking for an asset with "role": "Autodesk.AEC.ModelData". If the metadata isn't available in the manifest, you may need to translate your file again, or save it with a newer version of the authoring application.

Step 3: Find a sheet viewport for given 2D coordinates

Given 2D coordinates in a sheet (for example, obtained by calling Viewer3D#hitTest), use the Autodesk.AEC.AecModelData.findViewportAtPoint function to find the corresponding sheet viewport:

const viewport = Autodesk.AEC.AecModelData.findViewportAtPoint(model2d, new THREE.Vector2(sheetPos.x, sheetPos.y));

Step 4: Get the transformation from viewport to model coordinate system

Use the Autodesk.AEC.AecModelData.get2DTo3DMatrix function to get the THREE.Matrix4 transformation from the viewport coordinate system to the model coordinate system:

const sheetUnitScale = sheetModel.getUnitScale();
const matrix = Autodesk.AEC.AecModelData.get2DTo3DMatrix(viewport, sheetUnitScale);

That's it! With the matrix you can now transform 2D sheet coordinates into 3D model coordinates. Note that the 3D model can be placed with a custom offset, so you'll want to take the offset into account as well:

const globalOffset = model.getData().globalOffset;
const worldCoords = sheetCoords.clone().applyMatrix4(matrix).sub(globalOffset);

Here's a complete code sample: https://github.com/petrbroz/forge-viewer-samples/blob/master/public/aec-mapping-2d-to-3d.html.

You can also test it live on Heroku: https://forge-viewer-samples.herokuapp.com/aec-mapping-2d-to-3d.html.

Related Article