Skip to main content
Version: v4.5

mapRevitTypeCollection

An orchestrator calls the mapRevitTypeCollection script in the iaf_map_elms_type Object Model API script to map elementCategory and elementType properties to model elements.

Calling mapRevitTypeCollection from orchestrator step#

The process of mapping the Revit types to the model elements requires an orchestrator to run the mapRevitTypeCollection script in the iaf_map_elms_type Object Model API script.

User interface one-click orchestrator via ProjectSetup component#

For the user interface one-click project setup, the SetupProject component already runs an orchestrator that includes all steps, including the type map step:

async function runOrchestrator() {  let orchestratorConfig = await IafScriptEngine.addDatasource({    _name: "Setup Project",    _description: "Run all scripts needed for setup",    _namespaces: ctx._namespaces,    _userType: "setup_runner",    _params: {      tasks: [        //tasks before        {          _sequenceno: 6,          _name: "Mapping Revit Collection:",          _orchcomp: "default_script_target",          _actualparams: {            userType: "iaf_map_elms_type",            _scriptName: "mapRevitTypeCollection", // the named script to run in the above OMAPI script          },        },        //tasks after      ]    }  })}

VS code extension orchestrator setup#

For the VS code extension setup, the mapTypeAndElements script creates a single-step orchestrator.

The script calls IafScriptEngine.addDatasource to create a new orchestrator that calls the importModel function from the iaf_import_model Object Model API script:

let typeMapDatasourceResult = await IafScriptEngine.addDatasource(  {    _name: "Map Revit Elements type",    _description:      "Orchestrator to map elements to elementCategory and elementType from type map coll",    _namespaces: ctx._namespaces,    _userType: "map_revit_type",    _params: {      tasks: [        {          _orchcomp: "default_script_target",          _name: "Map type map to elements",          _sequenceno: 1,          _actualparams: {            userType: "iaf_map_elms_type", //script file            _scriptName: "mapRevitTypeCollection", //script function          },        },      ],    },  },  ctx);

The script runs the orchestrator with IafDataSource.runOrchestrator:

    if (typeMapDatasourceResult) {      const params = {        orchestratorId: typeMapDatasourceResult.id      }      const orchResult = await PlatformApi.IafDataSource.runOrchestrator(        typeMapDatasourceResult.id,         params,         ctx      );

The script uses IafDataSource.getOrchRunStatus to get the status of the orchestrator run:


      let orchRunResult = await PlatformApi.IafDataSource.getOrchRunStatus(orchResult.id, ctx);          console.log(`orchRunResult`, orchRunResult[0].orchrunsteps)
          let orchStepRunStatus = orchRunResult[0].orchrunsteps;

It sets an interval of 10000 milliseconds to poll the orchestrator run for a status update until the run finishes:

      //poll based on in run id until finished      let interval = setInterval(async () => {        let errStatus = _.filter(orchStepRunStatus, run_status => {          return run_status._status === "ERROR";        });        let queuedStatus = _.filter(orchStepRunStatus, run_status => {          return run_status._status === "QUEUED";        });        let runningStatus = _.filter(orchStepRunStatus, run_status => {          return run_status._status === "RUNNING";        });
        console.log(`errStatus`, errStatus)        console.log(`queuedStatus`, queuedStatus)        console.log(`runningStatus`, runningStatus)
        if (!_.isEmpty(errStatus) || (_.isEmpty(queuedStatus) && _.isEmpty(runningStatus))) {          if (_.isEmpty(errStatus)) {            orchStepRunStatus.forEach((step) => step.status = 'COMPLETED');          }          //kills the polling when import is complete          clearInterval(interval);        }        orchRunResult = await PlatformApi.IafDataSource.getOrchRunStatus(orchResult.id, ctx);        orchStepRunStatus = orchRunResult[0].orchrunsteps;      }, 10000);
      console.log(`orchRunResult`, orchStepRunStatus)      }  }

mapRevitTypeCollection#

The mapElementsType function cross-references the type elements with the type map elements to add ElementCategory and ElementType properties to the type elements. It then cross-references the model elements with the type elements to add ElementCategory, ElementType, and baType properties to the model elements.

First, the mapRevitTypeCollection script calls the local function getModelVersion..

async function mapRevitTypeCollection(params, PlatformApi, ctx) {  await getModelVersion(params, PlatformApi, ctx);  //rest of script}

The getModelVersion function uses IafScriptEngine.getCompositeCollection to get the latest version of the model, which is a NamedCompositeCollection, and assigns the response to a new script engine environment variable bim_model:

const getModelVersion = async (param, PlatformApi, ctx) => {  //function to get the latest model  let bim_model = await PlatformApi.IafScriptEngine.getCompositeCollection(    {      _userType: "bim_model_version",      "_versions._userAttributes.bimpk.fileId": param._fileId,    },    ctx,    { getLatestVersion: true }  );  //assigns the response to a new script engine environment variable  PlatformApi.IafScriptEngine.setVar("bim_model", bim_model);};

Using this variable, the script gets the collections in the model, which is a NamedCompositeItem, a collection of collections:

const fetched_bim_model = await PlatformApi.IafScriptEngine.getVar(  "bim_model");const modelRelatedCollection =  await PlatformApi.IafScriptEngine.getCollectionsInComposite(    fetched_bim_model._id,    null,    ctx  );

Then, it finds the Revit elements and the Revit types collections:

const model_type_el_coll = modelRelatedCollection.find(  (x) => x._userType === "rvt_type_elements");const model_els_coll = modelRelatedCollection.find(  (x) => x._userType === "rvt_elements");

With the _userItemId, you can get their RelatedItems:

//gets the Revit typeslet typeElements = await PlatformApi.IafScriptEngine.getItems(  {    _userItemId: model_type_el_coll._userItemId,    options: {      page: {        getAllItems: true,      },    },  },  ctx);//gets the Revit model elementslet elements = await PlatformApi.IafScriptEngine.getItems(  {    _userItemId: model_els_coll._userItemId,    options: {      page: {        getAllItems: true,      },    },  },  ctx);//gets the Revit type mapslet revitTypeMap = await PlatformApi.IafScriptEngine.getItems(  {    collectionDesc: {      _userType: "iaf_ref_type_map_defs_coll",      _namespaces: ctx._namespaces,    },    options: {      page: {        getAllItems: true,      },    },  },  ctx);

Next, the script re-maps the type elements by doing the following:

  1. It goes through each type element and stores its types data to variables
for (const typeElement of typeElements) {  let revitFamily, revitType, ifcTypeObject, civil3dClass, autoCADClass;  if ("Revit Family" in typeElement.properties) {    revitFamily = typeElement.properties["Revit Family"];  }
  if ("Revit Type" in typeElement.properties) {    revitType = typeElement.properties["Revit Type"];  }
  if ("IFCTypeObject" in typeElement.properties) {    ifcTypeObject = typeElement.properties["IFCTypeObject"];  }
  if ("Civil3D Class" in typeElement.properties) {    civil3dClass = typeElement.properties["Civil3D Class"];  }
  if ("AutoCAD Class" in typeElement.properties) {    autoCADClass = typeElement.properties["AutoCAD Class"];  }
  1. It cross-references it with the type map to find an object with the same type and stores the properties in the _myRow variable:
let _myRow;
if (  (revitFamily && revitType) ||  ifcTypeObject ||  civil3dClass ||  autoCADClass) {  if (revitFamily && revitType) {    _myRow = revitTypeMap.find(      (x) =>        x["Revit Family"] === revitFamily.val &&        x["Revit Type"] === revitType.val    );  } else if (ifcTypeObject) {    _myRow = revitTypeMap.find(      (x) => x["IFCTypeObject"] === ifcTypeObject.val    );  } else if (civil3dClass) {    _myRow = revitTypeMap.find(      (x) => x["Revit Family"] === civil3dClass.val    );  } else if (autoCADClass) {    _myRow = revitTypeMap.find(      (x) => x["AutoCAD Class"] === autoCADClass.val    );  }
  1. If it does find a type map definition, it attributes the type values to the type element.
function updateTypeElement(_myRow) {  if (_myRow) {    if (_myRow.hasOwnProperty("ElementCategory")) {      typeElement.ElementCategory = _myRow.ElementCategory;    }    if (_myRow.hasOwnProperty("ElementType")) {      typeElement.ElementType = _myRow.ElementType;    }  }}
  1. It then updates the type elements in the Item Service with IafScriptEngine.updateItemsBulk:
await PlatformApi.IafScriptEngine.updateItemsBulk(  {    _userItemId: model_type_el_coll._userItemId,    items: typeElements,  },  ctx);

Next, the script re-maps the model elements by doing the following:

  1. It goes through each model element and cross-references it with the type elements to find an object where the type element's id equals the model element's type_id value.
  2. If it does find a type definition, it attributes its ElementCategory, and ElementType values to the model element.
console.log(JSON.stringify({ message: "Re-mapping Model Elements" }));for (let element of elements) {  let _myVal = typeElements.find((x) => x.id == element.type_id);  if (_myVal) {    if (_myVal.hasOwnProperty("ElementCategory")) {      element.ElementCategory = _myVal.ElementCategory;    }    if (_myVal.hasOwnProperty("ElementType")) {      element.ElementType = _myVal.ElementType;    }  }}
  1. It then updates the model elements in the Item Service with IafScriptEngine.updateItemsBulk:
await PlatformApi.IafScriptEngine.updateItemsBulk(  {    _userItemId: model_els_coll._userItemId,    items: elements,  },  ctx);