How to init a Autodesk viewer with MultiViewerFactory and AggregatedView?

77 Views Asked by At

My goal is to find the nearest Room of a given position, but my models are linked models/ federated or aggregated model, I don't know the correct name, but they're models which have 2 or more linked revit models in it, but const info = new Autodesk.DataVisualization.Core.ModelStructureInfo(model); const levelRoomsMap = await info.getLevelRoomsMap(); only works in each model separately, not in the main federated one, if you know how to solve this, please help.

I'm trying to see if with the aggregated view this Rooms appear in the main model, but I'm using MultiViewerFactory to initialize the viewer, and don't know how to mix them, what I've tried:

function auxinitViewer(factory, aggV, container, config = {}) {
    const viewer = factory.createViewer(
        container,
        config,
        aggV // HERE WAS Autodesk.Viewing.GuiViewer3D
    );
    viewer.start();
    viewer.setTheme("light-theme");
    return viewer;
}

export function initViewer(container) {
    return new Promise(function (resolve, reject) {
        Autodesk.Viewing.Initializer(
            {
                // OPTIONS
            },
            function () {
                let aggV = new Autodesk.Viewing.AggregatedView();
                window.factory = new Autodesk.Viewing.MultiViewerFactory();
                window.viewer1 = auxinitViewer(window.factory, aggV, container, {
                    extensions: [
                        // ...
                    ],
                });
                resolve(window.viewer1);
            }
        );
    });
}

So if you know how to solve this problem at all or how to mix MultiViewerFactory and AggregatedView in viewer initialization please take a note.

1

There are 1 best solutions below

2
Eason Kang On

Unfortunately, loading multiple models in the viewer or AggregatedView won't create a federated model object. Instead, the viewer creates a model object for each loaded model. We see all loaded models using AggregatedView.viewer.getAllModels(). Therefore, you must create ModelStructureInfo for each model loaded in the viewer.

Here is a code snippet of using MultiViewerFactory, but I'm afraid that might not fit your needs.

// https://gist.github.com/yiskang/c404af571ba4d631b5929c777503891e
const multiViewerFactory = new Autodesk.Viewing.MultiViewerFactory();

const options3d = {
      multiViewerFactory,
      viewerConfig: {
        disableBimWalkInfoIcon: true
      },
      extensionOptions: {
        'Autodesk.AEC.Minimap3DExtension': {
            autoFocus: false,
            getMapViewer: container => {
                const mapViewer = multiViewerFactory.createViewer(container);
                mapViewer.start();
                return mapViewer;
            },
            onExpand: async bubbleNode => {
                await this.view.switchView([bubbleNode]);
                await this.view.waitForLoadDone();
            },
        }
      }
};

Autodesk.Viewing.Initializer( options, function() {
      //get the viewer div
      const viewerDiv = document.getElementById( 'viewer' );

      //initialize the viewer object
      const view = new Autodesk.Viewing.AggregatedView();
      view.init( viewerDiv, options3d );

      const viewer = view.viewer;

      const tasks = [];
      models.forEach( md => tasks.push( loadManifest( md.urn, md.viewableId ) ) );


      Promise.all(tasks)
              .then( data =>  Promise.resolve( data.map( dataItem => {
                let bubbles = null;
                if( !dataItem.viewableId ) {
                  bubbles = dataItem.doc.getRoot().search({type:'geometry', role: '3d'});
                } else {
                  bubbles = dataItem.doc.getRoot().search({type:'geometry', role: '3d', viewableID: dataItem.viewableId});
                }

                const bubble = bubbles[0];
                if( !bubble ) return Promise.reject();

                return bubble;
              })))
              .then((bubbles) => {
                view.setNodes(bubbles);
                view.waitForLoadDone();

              });
      });
  }

To load rooms and aggregate it with the main model in one single APS viewer instance, we can do the following:

//https://gist.github.com/yiskang/cedbe270765fdb33925a914c383e2346

    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 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();
    }


    Autodesk.Viewing.Initializer(options, async function () {
      const config3d = {
        modelBrowserStartCollapsed: true,
        modelBrowserExcludeRoot: false,
      };

      let viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('viewer'), 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:dXJuOm...C5ydnQ';
      let mainModel = await loadMainViewAsync(viewer, documentId);
      await loadRoomsAsync(viewer, mainModel);
      //viewer.showAll();
    });