TB_IfcExportモジュールを使用して.ifcファイルにエクスポートする際に、単位変換について質問がある場合があります。この記事には、単位の操作と.ifcファイルへのエクスポートの例が含まれています。
プロジェクト単位割り当ての作成
OdIfcExportImpl::createDefaultUnits() 関数は IfcUnitAssignment を作成します。これは、内部のBimRv単位を既知の単位に変換する長い単位リストです。
変換ベースの単位
たとえば、長さ単位を使用して変換ベースの単位を作成するアルゴリズムを考えてみましょう。
1. UnitsTracking Manager と FormatOptions を使用して内部単位を取得します。
OdBmUnitsTrackingPtr pUnitsTracking = m_database->getAppInfo(OdBm::ManagerType::UnitsTracking);
OdBmUnitsElemPtr pUnitsElem = pUnitsTracking->getUnitsElemId().safeOpenObject();
OdBmAUnitsPtr pAUnits = pUnitsElem->getUnits();
OdBmFormatOptionsPtrArray aFormatOptions;
pAUnits->getFormatOptionsArr(aFormatOptions);
OdDAIObjectId lenSIBaseUnit;
{
bool lenConversionBased = false;
bool lenUseDefault = false;
OdAnsiString lenConvName;
OdAnsiString lenUnitType = "LENGTHUNIT";
OdAnsiString lenPrefix;
OdAnsiString lenUnitName = "METRE";
OdBmFormatOptionsPtr pFormatOptions = aFormatOptions[OdBm::UnitType::UT_Length];
switch (pFormatOptions->getDisplayUnits())
{
case OdBm::DisplayUnitType::DUT_METERS:
case OdBm::DisplayUnitType::DUT_METERS_CENTIMETERS:
break;
case OdBm::DisplayUnitType::DUT_CENTIMETERS:
lenPrefix = "CENTI";
break;
case OdBm::DisplayUnitType::DUT_MILLIMETERS:
lenPrefix = "MILLI";
break;
case OdBm::DisplayUnitType::DUT_DECIMAL_FEET:
case OdBm::DisplayUnitType::DUT_FEET_FRACTIONAL_INCHES:
{
if (exportToCOBIE)
lenConvName = "foot";
else
lenConvName = "FOOT";
lenConversionBased = true;
}
break;
case OdBm::DisplayUnitType::DUT_FRACTIONAL_INCHES:
case OdBm::DisplayUnitType::DUT_DECIMAL_INCHES:
{
if (exportToCOBIE)
lenConvName = "inch";
else
lenConvName = "INCH";
}
lenConversionBased = true;
break;
default:
{
//Couldn't find display unit type conversion -- assuming foot
if (exportToCOBIE)
lenConvName = "foot";
else
lenConvName = "FOOT";
lenConversionBased = true;
lenUseDefault = true;
}
break;
}
2. 必要に応じて、基本SI単位インスタンスと接頭辞付きSI単位インスタンスを作成します。
OdDAIObjectId lenSIUnit = OdInstanceExporter::createSIUnit(m_model, lenUnitType, lenPrefix,
lenUnitName);
if (lenPrefix.isEmpty())
lenSIBaseUnit = lenSIUnit;
else
lenSIBaseUnit = OdInstanceExporter::createSIUnit(m_model, lenUnitType, NULL, lenUnitName);
3. BmUnitUtils を使用して長さスケール係数を取得します。
double lengthScaleFactor = OdBmUnitUtils::convertFromInternalUnits(1.0, lenUseDefault ?
OdBm::DisplayUnitType::DUT_DECIMAL_FEET : pFormatOptions->getDisplayUnits());
// If BIM Units differ from SI Units, for example Inches or Foots using for length measure, creating // Base Conversion Unit. First getting Conversion Scale Factor using OdBmUnitUtils:
if (lenConversionBased)
{
double lengthSIScaleFactor = OdBmUnitUtils::convertFromInternalUnits(1.0,
OdBm::DisplayUnitType::DUT_METERS) / lengthScaleFactor;
4. 次元指数インスタンス (長さの次元が 1 つ) を作成します。
OdDAIObjectId lenDims = OdInstanceExporter::createDimensionalExponents(m_model, 1, 0, 0,
0, 0, 0, 0);
5. 変換する単位 (SI 長さ単位) と変換方法 (lengthSIScaleFactor 比率) を決定するオブジェクトである、単位付き測定値を作成します。
ODIFC_CREATE_AS_RATIO_MEASURE(supVal, lengthSIScaleFactor)
OdDAIObjectId lenConvFactor = OdInstanceExporter::createMeasureWithUnit(m_model, supVal, lenSIUnit);
6. 以前に作成した次元指数オブジェクトと単位付き測定値オブジェクトを属性とする、変換に基づいた測定単位を作成します。
lenSIUnit = OdInstanceExporter::createConversionBasedUnit(m_model, lenDims, lenUnitType,
lenConvName, lenConvFactor);
7. SI 単位オブジェクトを UnitSet 配列に追加します。
unitSet.push_back(lenSIUnit);
8. SI 単位とスケール係数を単位キャッシュに追加します。
OdExporterCacheManager::getUnitsCache()->addUnit(OdBm::UnitType::UT_Length,
lenSIUnit,lengthScaleFactor, 0.0);
式単位
たとえば、質量密度単位を使用して式単位を作成するアルゴリズムを考えてみましょう。
1. 質量 SI 単位を作成します。
OdDAIObjectId massSIUnit;
{
massSIUnit = createSIUnit(OdBm::UnitType::UT_Mass, "MASSUNIT", "GRAM", "KILO",
OdBm::DisplayUnitType::DUT_UNDEFINED);
unitSet.push_back(massSIUnit);
}
2. キログラムの 1 乗とメートルの -3 乗を使用して派生単位要素を作成します。派生単位要素の属性は、上記で作成した SI 単位オブジェクト (質量 SI 単位と長さ SI 単位) です。
OdDAIObjectIds elements;
elements.push_back(OdInstanceExporter::createDerivedUnitElement(m_model, massSIUnit, 1));
elements.push_back(OdInstanceExporter::createDerivedUnitElement(m_model, lenSIBaseUnit, -3));
3. 派生単位要素を使用して kg/(m^3) 派生単位を作成します。
OdDAIObjectId massDensityUnit = OdInstanceExporter::createDerivedUnit(m_model, elements, "MASSDENSITYUNIT", NULL);
4. 作成した派生単位とスケール係数を追加して、UnitSet 配列を単位キャッシュに投影します。
unitSet.push_back(massDensityUnit);
double massDensityFactor = OdBmUnitUtils::convertFromInternalUnits(1.0, OdBm::DisplayUnitType::DUT_KILOGRAMS_PER_CUBIC_METER);
OdExporterCacheManager::getUnitsCache()->addUnit(OdBm::UnitType::UT_MassDensity, massDensityUnit,
massDensityFactor, 0.0);
5. 面積、体積、平面角、時間、周波数、温度などの他の単位を埋めるために、同様の方法を繰り返します。
6. 最後に、UnitSet 配列を埋めた後、プロジェクト UnitAssignment インスタンスを作成します。
OdInstanceExporter::createUnitAssignment(m_model, unitSet);
エクスポートプロセスでの単位変換に UnitsCache と UnitUtils を使用する
オブジェクトのエクスポートプロセスでは、BimRv API から取得した測定単位を IFC プロジェクト単位に変換します。これらの目的のために、キャッシュとこのキャッシュを使用するためのユーティリティが作成されます。次のレベルエクスポートの例で、それらの適用を検討してください。
// …
// some code to fill levels array from database
// …
OdBmLevelPtr level = levels[ii];
double elev = level->getElevation(); // elevation in internal units
1. ScaleLength() ユーティリティを使用して、標高を BimRv 単位から IFC 単位に変換します。
double elevation = OdUnitUtil::ScaleLength(elev);
2. 変換された標高を使用して、建築階と建築階のローカル配置を作成します。
OdGeVector3d orig(0.0, 0.0, elevation);
OdDAIObjectId placement = OdExporterUtil::createLocalPlacement(m_model, buildingPlacement, &orig,
NULL, NULL);
OdDAIObjectId buildingStorey = OdInstanceExporter::createBuildingStorey(m_model, level,
OdExporterCacheManager::getOwnerHistoryHandle(),
bsObjectType, placement, "ELEMENT", elevation);
エクスポート結果
エクスポートの結果、ファイルには以下の行が含まれます。
1. 長さの単位 (SI単位系ではメートル、BimRvデータベースではフィート):
#21=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#22=IFCDIMENSIONALEXPONENTS(1,0,0,0,0,0,0);
#23=IFCMEASUREWITHUNIT(IFCRATIOMEASURE(0.30480000000000035),#21);
#24=IFCCONVERSIONBASEDUNIT(#22,.LENGTHUNIT.,'FOOT',#23);
2. 質量および質量密度の単位:
#37=IFCSIUNIT(*,.MASSUNIT.,.KILO.,.GRAM.);
#38=IFCDERIVEDUNITELEMENT(#37,1);
#39=IFCDERIVEDUNITELEMENT(#21,-3);
#40=IFCDERIVEDUNIT((#38,#39),.MASSDENSITYUNIT.,'');
3. プロジェクト単位の割り当て:
#73=IFCUNITASSIGNMENT((#24,#28,#32,#36,#37,#40,#41,#42,#44,#48,#52,#53,#54,#55,#56,#57,#58,#59,#64,#67,#68,#72));
4. 建築階:
#76=IFCCARTESIANPOINT((0.00000000000000000,0.00000000000000000,-800.00000000000000));
#77=IFCAXIS2PLACEMENT3D(#76,$,$);
#78=IFCLOCALPLACEMENT(#16,#77);
#79=IFCBUILDINGSTOREY('1i_YYDONP3AgUe36R0EAL1',#20,'Foundation','','8mm Head',#78,$,'Foundation',.ELEMENT.,-800.00000000000068);