Close

Relief for ODA Team in Ukraine

Learn more
ODA BimRv SDK
Export to IFC Using a Sample Application

This article describes how to export from BimRv to IFC using the BmIfcExportEx sample application.

You can export the BimRv element parameters in the form of IfcPropertySet, and you can obtain, calculate and create IfcCommonProperties and IfcQuantities. You can also export a set of elements instead of the whole model and filter those elements by visibility in a view. The examples below show how to set up the export process in TB_IfcExport by modifying the BmIfcExportEx code.

Export only Visible Elements

Sometimes the document may contain views and plans with elements that you don't want to export. For example, the following file has unwanted elements:

In this case, you can modify the BmIfcExportEx code to filter the unwanted elements and to only export the 3D elements that are visible in the view.

First, add the necessary headers.


#include "Database/Managers/BmViewTable.h"
#include "Database/Entities/BmDBView.h"
#include "ExBimCommandContext.h"
#include "ExStringIO.h"
#include "Ed/EdCommandStack.h"
    

Next, implement a function that finds a BmDBView element or creates it if necessary using the BmDBView3dCreate command.


OdBmObjectId get3DViewId(OdBmDatabase* pDb)
{
  const OdChar* strDefaultViewName = L"{3D}";
   OdBmViewTablePtr pViewTable = pDb->getAppInfo(OdBm::ManagerType::ViewTable);
  OdBmObjectId idView = pViewTable->findViewIdByName("{3D}");
     // in case when DB doesn't contain {3D} view creating own view to collect visible elements
  if (idView.isNull())
  {
    ::odrxDynamicLinker()->loadModule(OdBmCommands);
     OdSmartPtr<ExStringIO> pStringIO = ExStringIO::create(L"{3D} n");
    OdBmCommandContextPtr pDbCmdCtx = ExBimCommandContext::createObject(pStringIO, pDb);
    ::odedRegCmds()->executeCommand(L"BmDBView3dCreate", pDbCmdCtx);
    idView = pViewTable->findViewIdByName("{3D}");
  }
  return idView;
}
    

In the main function, call the function implemented above, turn on the VisibleOnly option, and set the view ID of the FilterViewId option in the export properties. Finally, initiate the export.

// Only export elements visible in the chosen view
    
OdBmObjectId viewId = get3DViewId(pDb);
exporter->properties()->putAt("VisibleOnly", OdRxVariantValue(true));
OdUInt64 filterViewId = (OdUInt64)viewId.getHandle();
exporter->properties()->putAt("FilterViewId", OdRxVariantValue(filterViewId));

// Export BIM file

TB_IFCEXPORT::OdIfcExport::ExportResult expRes = exporter->exportIfc();
if (TB_IFCEXPORT::OdIfcExport::success == expRes)
  odPrintConsoleString(L"\nExport success...\n");

After the modified export, the unwanted elements are filtered out.

Export a Set of Elements

You can export a set of elements instead of the whole model, for example, you might want to export only one element, export a set of elements located on the same level, or export all elements except walls. The following code sample shows how to modify the BmIfcExportEx application to export only the elements located on a chosen level.


#include "Database/Managers/BmLevelPlanViewTracking.h"
#include "HostObj/Entities/BmRoof.h"
#include "Family/Entities/BmFamilyInstance.h"
#include "StairsRamp/Entities/BmStairsElement.h"
#include "Structural/Entities/BmTrussElement.h"
#include "MEP/Entities/BmRbsCurve.h"
    

Next, implement a class with filter rules to filter elements by the associated level ID.


struct c_evalElem : std::unary_function<OdBmElementPtr, bool> {
  c_evalElem(const OdBmObjectId& assocLevelId) : oAssocLevelId(assocLevelId) {}
  virtual bool operator()(const OdBmElementPtr& pElem) const {
    OdBmObjectId levelId = pElem->getAssocLevelId();
    if (!levelId.isNull())
      return (levelId == oAssocLevelId);
     OdBmElementPtr pElemToCheck = pElem;
    OdArray<OdBm::BuiltInParameter::Enum> priortizedParameterList;
    if (pElem->isA() == OdBmFamilyInstance::desc())
    {
      const OdBmFamilyInstance* pFam = static_cast<const OdBmFamilyInstance*>(pElem.get());
      // If this is a nested family, check the top-level instance for the level parameter information.
      OdBmObjectId elemToCheckId = pFam->getSuperInstanceId();
      if (!elemToCheckId.isNull())
        pElemToCheck = elemToCheckId.safeOpenObject();
       priortizedParameterList.append(OdBm::BuiltInParameter::FAMILY_BASE_LEVEL_PARAM);
      priortizedParameterList.append(OdBm::BuiltInParameter::INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM);
      priortizedParameterList.append(OdBm::BuiltInParameter::INSTANCE_REFERENCE_LEVEL_PARAM);
    }
    else if (pElem->isA() == OdBmRoof::desc())
      priortizedParameterList.append(OdBm::BuiltInParameter::ROOF_CONSTRAINT_LEVEL_PARAM);
    else if (pElem->getHeaderCategoryId() == OdBm::BuiltInCategory::OST_Stairs)
      priortizedParameterList.append(OdBm::BuiltInParameter::STAIRS_BASE_LEVEL_PARAM);
    else if (pElem->isA() == OdBmTrussElement::desc())
      priortizedParameterList.append(OdBm::BuiltInParameter::TRUSS_ELEMENT_REFERENCE_LEVEL_PARAM);
     for (OdBm::BuiltInParameter::Enum levelParameterVal : priortizedParameterList)
    {
      if (eOk == pElemToCheck->getParam(levelParameterVal, levelId))
      {
        if (!levelId.isNull())
          return (levelId == oAssocLevelId);
      }
    }
     if (pElemToCheck->isKindOf(OdBmRbsCurve::desc()))
    {
      const OdBmRbsCurve* pRbsCurve = static_cast<const OdBmRbsCurve*>(pElemToCheck.get());
      OdBmObjectId levelId = pRbsCurve->getStartLevelId();
      if (!levelId.isNull())
        return levelId == oAssocLevelId;
    }
     return false;
  }
protected:
  OdBmObjectId oAssocLevelId;
};
    

Next, implement a function to get all elements with the associated level ID from the database.


OdUInt64Array getLevelElementIds(OdBmDatabase* pDb, unsigned int nLevelIndex)
{
  OdUInt64Array elemIds;
  OdBmMap<OdBmObjectId, OdBmSet mapLevelIds;
  const OdBmLevelPlanViewTrackingPtr pLevelTable = pDb->getAppInfo(OdBm::ManagerType::LevelPlanViewTracking);
  pLevelTable->getLevelIdToPlanViewIds(mapLevelIds);
   unsigned int nIndex = 0;
  if (mapLevelIds.size() < nLevelIndex)
    nLevelIndex = mapLevelIds.size() - 1;
     for (const auto& pair : mapLevelIds)
  {
    if (nIndex != nLevelIndex)
    {
      nIndex++;
      continue;
    }
    auto pElementsIt = pDb->newElemTableIterator()->filter(c_evalElem(pair.first));
    for (auto pElem : pElementsIt)
      elemIds.append((OdUInt64)pElem->objectId().getHandle());
     break;
  }
  return elemIds;
}
    

Finally, in the main function, call the implemented function with the level index, set the received IDs to the ElementsToExport option, and then initiate the export.

// Chosen elements to export

OdUInt64Array ids = getLevelElementIds(pDb, 2);
exporter->properties()->putAt(L"ElementsToExport", OdRxVariantValue(ids));

// Export BIM file

TB_IFCEXPORT::OdIfcExport::ExportResult expRes = exporter->exportIfc();
if (TB_IFCEXPORT::OdIfcExport::success == expRes)
  odPrintConsoleString(L"\nExport success...\n");

After the export, you have only one level of elements in the IFC model.

IfcPropertySets and IfcQuantities

There are three options used for exporting to IFC:

  • BimRvPropSets — Exports BimRv element parameters as IfcProperties.
  • IfcCommonPropSets — Calculates and exports IfcCommonPropertySets.
  • BaseQuantities — Calculates and exports IfcQuantities.

The following example shows how to modify the BmIfcExportEx application to turn on all export properties.

// Property sets and quantities export
    
exporter->properties()->putAt(L"IfcCommonPropSets", OdRxVariantValue(true));
exporter->properties()->putAt(L"BimRvPropSets", OdRxVariantValue(true));
exporter->properties()->putAt(L"BaseQuantities", OdRxVariantValue(true));

// Export BIM file

TB_IFCEXPORT::OdIfcExport::ExportResult expRes = exporter->exportIfc();
if (TB_IFCEXPORT::OdIfcExport::success == expRes)
  odPrintConsoleString(L"\nExport success...\n");

Export Element Classifications

The TB_IfcExport library has six options that determine the result of exporting element classifications:

  • ClName — Name of the classification system.
  • ClSource — Source or publisher of the classification system.
  • ClEdition — Edition number of the classification system.
  • ClEditTime — Edition date.
  • ClDocLocation — Documentation location (usually a URL).
  • ClFieldName &mdash Classification field names.

The following code example demonstrates how to set up export of classifications.

OdIfcExportPtr exporter = createExporter();

/**************************************************************/
/* Set the classification parameters.                         */
/**************************************************************/
OdString strVal = L"Uniclass 2015";
exporter->properties()->putAt(L"ClName", OdRxVariantValue(strVal));

strVal = L"Riba enterprizes";
exporter->properties()->putAt(L"ClSource", OdRxVariantValue(strVal));

strVal = L"2015";
exporter->properties()->putAt(L"ClEdition", OdRxVariantValue(strVal));

strVal = L"www.uniclass.org";
exporter->properties()->putAt(L"ClDocLocation", OdRxVariantValue(strVal));
        
strVal = L"ClassificationCode";
exporter->properties()->putAt(L"ClFieldName", OdRxVariantValue(strVal));
        
OdTimeStamp timeStamp(OdTimeStamp::kInitLocalTime);
timeStamp.getLocalTime();
exporter->properties()->putAt(L"ClEditTime",
  OdRxVariantValue(timeStamp.packedValue()));

The ClFieldName option defines the BimRv element parameter or parameters, the value of which determines the classification code. It can contain one or several parameter names separated by a semicolon. If empty, the ClassificationCode parameter is used by default.

For example, if you export a BimRv wall element with the ClassificationCode parameter's value SS_30_10_30_25 using the options described above, the IFC file will contain the following:

#213=IFCCALENDARDATE(5,6,2022);

#214=IFCCLASSIFICATION('Riba enterprizes','2015',#213,'Uniclass 2015');

#1573=IFCWALLSTANDARDCASE('3CDwZ0n0594QnAOaWKNrTM',#20,'Basic Wall:Generic - 200mm:305313','','Basic Wall:Generic - 200mm',#1556,#1572,'305313');

#1582=IFCWALLTYPE('3kSL0VGKv3gxJCujeqtuWE',#20,'Generic - 200mm','',$,$,$,'1740',$,.STANDARD.);

#1583=IFCCLASSIFICATIONREFERENCE('www.uniclass.org','SS_30_10_30_25','Heavy steel roof framing systems',#214);

#1584=IFCRELASSOCIATESCLASSIFICATION('3MUnE7poj8Uw6HqyosgOZf',#20,'Uniclass 2015 Classification','',(#1573),#1583);

IfcClassification is created from classification options. IfcClassificationReference contains the classification code from the wall parameter, and IfcRelAssociatesClassification associates the exported IfcWallStandartCase and IfcClassificationReference.

The Uniformat classification is created by default and is from the OdBm::BuiltInParameter::UNIFORMAT_CODE and OdBm::BuiltInParameter::UNIFORMAT_DESCRIPTION parameters. For the Uniformat and Omniclass classifications, the classification description field value is taken from the OdBm::BuiltInParameter::UNIFORMAT_DESCRIPTION or OdBm::BuiltInParameter::OMNICLASS_DESCRIPTION element parameters.

After the export, you can check the properties in the right panel of the OpenIfcViewer application.

See Also

Export to IFC

Copyright © 2002 – 2022. Open Design Alliance. All rights reserved.