Updates for better IFC element mapping
Platform 5.1 and IPA IFC plugin now support IFC 4x3.
In IPA Plugin 5.1 release, for IFC elements in the objects.json file's types and objects arrays have new property names so that they can be identified and handled differently from other element types. From IPA Plugin 5.1:
- IFC Type class names are exported as ‘IFCTypeObject’
- IFC Object class names are exported as ‘IFCObject’
Changes to mapRevitTypeCollection script#
Overview#
For IFC models, to make sure the "ElementCategory" and "ElementType" values are mapped, instead of only mapping using type elements, now mapping also extends to elements and their properties in case the type elements have insufficient data.
To avoid getting properties for non-IFC models use a flag and update it if any type element has an "IFCTypeObject" property:
let isIfcModel = false;When looping through the type elements, for types with
"IFCTypeObject"in their properties, enableisIfcModelflag, then store theifcTypeObjectproperty in a variable calledifcClass.for (const typeElement of typeElements) { // variable `ifcClass` let revitFamily, revitType, ifcClass, civil3dClass, autoCADClass; //hidden code // store `ifcTypeObject` in the `ifcClass` variable if ("IFCTypeObject" in typeElement.properties) { ifcClass = typeElement.properties["IFCTypeObject"]; if (!isIfcModel) {isIfcModel = true;} } }When constructing a new row, look up the type map for an entry where the
"IFC Class"matches:let _myRow; if ( // ) { // } else if (ifcClass) { _myRow = revitTypeMap.find( // look up the type map for `"IFC Class"` (x) => x["IFC Class"] === ifcClass.val ); } }When getting the element objects, instead of getting just the items, now we also get their related properties, which are used in the mapping process. This only runs for IFC models.
let elements; if (!isIfcModel) { elements = await PlatformApi.IafScriptEngine.getItems( { _userItemId: model_els_coll._userItemId, options: { page: { getAllItems: true, }, }, }, ctx ); } else { //related props required for ifc mapping const query = { parent: { collectionDesc: { _userItemId: model_els_coll._userItemId, }, options: { page: { getAllItems: true, }, }, }, related: [ { relatedDesc: { _relatedUserType: "rvt_element_props", }, as: "Element Properties", }, ], } elements = await PlatformApi.IafScriptEngine.findWithRelated(query, ctx).then((res) => { elements = res._list; }) }When looping through the elements, add additional mapping code, which does the following:
a. Checks if an element has a related
"IFCObject"property.b. If it does, it is stored in the
ifcClassvariable.c. It looks up the type map to find a row with a matching IFC Class and takes the
"ElementCategory"and"ElementType"values from there.for (let element of elements) { let ifcClass; if ( element["Element Properties"] ._list[0] .properties["IFCObject"] ) { ifcClass = element["Element Properties"] ._list[0] .properties["IFCObject"]; } let isIfcMappingDone = false; if (ifcClass) { let _myRow = revitTypeMap.find( (x) => x["IFC Class"] === ifcClass.val ); if (_myRow){ if (_myRow.hasOwnProperty("ElementCategory")) { element.ElementCategory = _myRow.ElementCategory; } if (_myRow.hasOwnProperty("ElementType")) { element.ElementType = _myRow.ElementType; } isIfcMappingDone = true; } } }
Changes to getModelElementsByTypeProps#
The getModelElementsByTypeProps script in iaf_dt_model_elems.js fetches model elements and their related properties and type information by using a findWithRelated query based on the type data the user selects, then maps that data to a new object called an entity, which contains and formats all the relevant data to display.
Due to the mapping changes made in the mapRevitTypeCollection script, the following updates are required:
When the "Revit Family" property does not exist in the related types, check for the "IFCObject" property in the related properties:
let revitFamily = e["Revit Type Properties"]._list[0].properties[ "Revit Family" ] ? e["Revit Type Properties"]._list[0].properties["Revit Family"].val //Check for revit family in properties : e["Revit Element Properties"]._list[0].properties["IFCObject"] //Check for IFCObject for ifc model in properties ? e["Revit Element Properties"]._list[0].properties["IFCObject"].val : "No Family";When the "Revit Type" property does not exist in the related types, check for it in the related properties:
let revitType = e["Revit Type Properties"]._list[0].properties[ "Revit Type" ] ? e["Revit Type Properties"]._list[0].properties["Revit Type"].val //Check for revit type in properties : e["Revit Element Properties"]._list[0].properties["Name"] //Check for name for ifc model in properties ? e["Revit Element Properties"]._list[0].properties["Name"].val : "No Type";When the SystemelementId property does not exist in the related properties, verify that this is an IFC object, then use the element's source_id:
let sysElemId = e["Revit Element Properties"]._list[0].properties .SystemelementId ? e["Revit Element Properties"]._list[0].properties.SystemelementId.val : e["Revit Element Properties"]._list[0].properties["IFCObject"] ? e.source_id
let modelViewerIds = [e.package_id];