BimRv SDK: Get Formula Text Representation

Dmytro Kabenok

November 02, 2023

When working with formulas, you can get formula text representations from family and global parameters.

The formulas are represented as a set of expressions in RVT and RFA formats. Each expression is responsible for a part of the formula, a so-called token. The token is a smaller fragment of a string that is separated by a certain character. An expression may contain a string, a number, an operator (binary or unary), a function, or a subexpression with all of the above.

To restore a formula back to a string from a chain of expressions, go through all the dependent expressions from bottom to top and process them correctly, depending on the stored data.

Get a Formula from Family Parameters

One of the ways to obtain a formula is to use the getFormula() method. To use this method, you need an object of the OdBmFamilyManager class, which you can create when working with the RFA format.

Example of getting a formula from a family parameter with a specified ID:

#include "Database/BmDatabase.h"
#include "Database/Managers/BmFamilyManager.h"

OdBmDatabasePtr pDb = pHostAppServices->readFile(L"rac_advanced_sample_family.rfa");
const OdBmObjectId paramId = pDb->getObjectId(OdDbHandle(2534));
OdString formula;
OdResult res = pDb->getFamilyManager()->getFormula(paramId, formula);
if (res == eOk) {
  // do something
}
else {
  // do something else
}

As a result, the following formula is obtained:

L"roundup((Shadow_Length / 1 mm) * tan(Rel_Angle)) * 1 mm"

Another way to obtain the formula is to use the getFormula() method. Example of getting a formula from a family parameter:

#include "Database/BmDatabase.h"
#include "Database/Entities/BmParamElem.h"

OdBmDatabasePtr pDb = pHostAppServices->readFile(L"rac_advanced_sample_family.rfa");
OdBmParamElemPtr pParamElem = pDb->getObjectId(OdDbHandle(2534)).safeOpenObject();
OdString formula;
if (pParamElem->getFormula(formula) == eOk) {
  // do something
}
else {
  // do something else
}

Both methods, getFormula() from the OdBmFamilyManager class and getFormula() from the OdBmParamElem class, perform the same actions internally, so the result of their execution is the same.

The difference in using these two methods depends on the type of parameter. If the parameter is a family parameter, use the method from the OdBmFamilyManager class; if the parameter type is not known (family or global), use the method from the OdBmParamElem class.

Get a Formula from Global Parameters

A formula can be obtained from a global parameter. In this case, OdBmFamilyManager cannot be used, since global parameters may exist in the RVT format, where the family manager is not accessible. Use the method from the OdBmParamElem class, which includes a specialized implementation for the OdBmParamElemGlobal case (the description of the method is described in the previous section).

Example of getting a formula from a global parameter:

#include "Database/BmDatabase.h"
#include "Database/Entities/BmParamElemGlobal.h"

OdBmDatabasePtr pDb = pHostAppServices->readFile(
L"BIM_Projekt_Golden_Nugget-Architektur_und_Ingenieurbau.rvt");

const OdBmObjectId paramId = pDb->getObjectId(OdDbHandle(2685889));
OdBmParamElemGlobalPtr pGlobalParam = paramId.safeOpenObject();
OdString formula;
OdResult res = pGlobalParam->getFormula(formula);
if (res == eOk) {
  // do something
}
else {
  // do something
}

The resulting OdString formula is empty because the selected global parameter has no expression.

Example

See the example in the BmGetFormulaCmd command in TB_Commands:

#include "Database/Entities/BmParamElemGlobal.h"
#include "Database/Managers/BmFamilyManager.h"

void _BmGetFormulaCmd_func(OdEdCommandContext* pCmdCtx) {
  OdBmCommandContextPtr pDbCmdCtx(pCmdCtx);
  OdBmDatabasePtr pDb = pDbCmdCtx->database();
  OdSmartPtr pIO = pDbCmdCtx->userIO();
  const OdInt32 inputId = pIO->getInt(OD_T("Enter parameter ID in decimal system:"), OdEd::kInpDefault, -1);
  if (inputId == -1) {
    return;
  }
  const OdBmObjectId paramId = pDb->getObjectId(OdDbHandle(inputId));
  if (paramId.isNull()) {
    return;
  }
  OdBmParamElemPtr pParamElem = OdBmParamElem::cast(paramId.openObject());
  if (pParamElem.isNull()) {
    pIO->putString(OD_T("Invalid input. ID must belong to a class derived from OdBmParamElem"));
    return;
  }
  OdString formula;
  OdResult result = pParamElem->getFormula(formula);
  if (result == eOk) {
    pIO->putString(OD_T("Formula: ") + formula);
  }
  else {
    pIO->putString(OD_T("Failed to retrieve formula: ") + OdError(result).description());
  }
}

An example of using the getFormula() method from the OdBmFamilyManager class can be found in the FamilyTypesDialog located in the OdaBimApp application example.

You can find more information in our documentation.