/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporated this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// // AI-GENERATED using Claude on 2025-09-05 // Reviewed and adapted by iegorychev@opendesign.com #include "OdaCommon.h" #include "ExIfcTutorial_RelAssocMaterial_EarlyBound.h" #include "IfcFile.h" #include "Ifc4x3/Ifc4x3Entities.h" #include "Ifc4x3/Ifc4x3SelectTypes.h" #include "Ifc4x3/Ifc4x3SchemaSelectTypes.h" using namespace OdIfc; using namespace OdIfc4x3_add2; void Tutorial_RelAssocMaterial_EarlyBound::help() const { odPrintConsoleString(L"Tutorial_RelAssocMaterial_EarlyBound recreates the relassocmaterial.ifc sample file using early-bound approach\n"); odPrintConsoleString(L"It demonstrates creating a steel column with material associations using typed classes\n"); odPrintConsoleString(L"Parameters: \n"); odPrintConsoleString(L"Example: Tutorial_RelAssocMaterial_EarlyBound relassocmaterial_earlybound_output.ifc\n"); } int Tutorial_RelAssocMaterial_EarlyBound::run(const MyServices& svcs, const std::vector& argv, std::ostream& resultStream) { auto parseResult = BaseIfcTutorial::run(svcs, argv, resultStream); if (parseResult != 0) { return parseResult; } try { // Create new IFC file with IFC4X3 schema OdIfcFilePtr pDatabase = svcs.createDatabase(IfcSchema::kScmIfc4x3); OdIfcModelPtr pModel = pDatabase->getModel(sdaiRW); // Step 1: Create basic geometric entities (needed by others) // Create cartesian point (0,0,0) - #2 IfcCartesianPointPtr pOriginPoint = IfcCartesianPoint::createObject(); pOriginPoint->putAttr("coordinates", OdArray({0.0, 0.0, 0.0})); OdDAIObjectId originPoint = pModel->appendEntityInstance(pOriginPoint); // Create cartesian point (0,0,2000) - #215 IfcCartesianPointPtr pTopPoint = IfcCartesianPoint::createObject(); pTopPoint->putAttr("coordinates", OdArray({0.0, 0.0, 2000.0})); OdDAIObjectId topPoint = pModel->appendEntityInstance(pTopPoint); // Create directions // Direction (0,-1,0) - #213 IfcDirectionPtr pRefDir = IfcDirection::createObject(); pRefDir->putAttr("directionratios", OdArray({0.0, -1.0, 0.0})); OdDAIObjectId refDirection = pModel->appendEntityInstance(pRefDir); // Direction (0,0,1) - #214, #221 IfcDirectionPtr pZDir = IfcDirection::createObject(); pZDir->putAttr("directionratios", OdArray({0.0, 0.0, 1.0})); OdDAIObjectId zDirection = pModel->appendEntityInstance(pZDir); // Create axis placement #3 for world coordinates IfcAxis2Placement3DPtr pWorldAxis = IfcAxis2Placement3D::createObject(); pWorldAxis->putAttr("location", originPoint); OdDAIObjectId worldAxisPlacement = pModel->appendEntityInstance(pWorldAxis); // Create axis placement #212 for column IfcAxis2Placement3DPtr pColumnAxis = IfcAxis2Placement3D::createObject(); pColumnAxis->putAttr("location", originPoint); pColumnAxis->putAttr("axis", zDirection); pColumnAxis->putAttr("refdirection", refDirection); OdDAIObjectId columnAxisPlacement = pModel->appendEntityInstance(pColumnAxis); // Step 2: Create geometric representation context #1 IfcGeometricRepresentationContextPtr pGeomContext = IfcGeometricRepresentationContext::createObject(); pGeomContext->setContextType(OdAnsiString("Model")); pGeomContext->putAttr("precision", 0.0001); pGeomContext->putAttr("worldcoordinatesystem", worldAxisPlacement); OdDAIObjectId geomContext = pModel->appendEntityInstance(pGeomContext); // Create sub-contexts #4, #5 IfcGeometricRepresentationSubContextPtr pAxisSubContext = IfcGeometricRepresentationSubContext::createObject(); pAxisSubContext->putAttr("contextidentifier", OdAnsiString("Axis")); pAxisSubContext->setContextType(OdAnsiString("Model")); pAxisSubContext->putAttr("parentcontext", geomContext); pAxisSubContext->setTargetView(kIfcGeometricProjectionEnum_MODEL_VIEW); OdDAIObjectId axisSubContext = pModel->appendEntityInstance(pAxisSubContext); IfcGeometricRepresentationSubContextPtr pBodySubContext = IfcGeometricRepresentationSubContext::createObject(); pBodySubContext->putAttr("contextidentifier", OdAnsiString("Body")); pBodySubContext->setContextType(OdAnsiString("Model")); pBodySubContext->putAttr("parentcontext", geomContext); pBodySubContext->setTargetView(kIfcGeometricProjectionEnum_MODEL_VIEW); OdDAIObjectId bodySubContext = pModel->appendEntityInstance(pBodySubContext); // Step 3: Create person and organization entities // Person #52 IfcPersonPtr pPerson = IfcPerson::createObject(); pPerson->putAttr("identification", OdAnsiString("redacted")); pPerson->putAttr("familyname", OdAnsiString("redacted")); OdDAIObjectId person = pModel->appendEntityInstance(pPerson); // Organization #53 IfcOrganizationPtr pOrganization = IfcOrganization::createObject(); // Use early-bound setter for name where available pOrganization->setName(OdAnsiString("redacted")); OdDAIObjectId organization = pModel->appendEntityInstance(pOrganization); // PersonAndOrganization #51 IfcPersonAndOrganizationPtr pPersonAndOrg = IfcPersonAndOrganization::createObject(); pPersonAndOrg->putAttr("theperson", person); pPersonAndOrg->putAttr("theorganization", organization); OdDAIObjectId personAndOrganization = pModel->appendEntityInstance(pPersonAndOrg); // App Organization #55 IfcOrganizationPtr pAppOrg = IfcOrganization::createObject(); pAppOrg->setName(OdAnsiString("redacted")); OdDAIObjectId appOrganization = pModel->appendEntityInstance(pAppOrg); // Application #54 IfcApplicationPtr pApplication = IfcApplication::createObject(); pApplication->putAttr("applicationdeveloper", appOrganization); pApplication->putAttr("version", OdAnsiString("redacted")); pApplication->putAttr("applicationfullname", OdAnsiString("redacted")); pApplication->putAttr("applicationidentifier", OdAnsiString("redacted")); OdDAIObjectId application = pModel->appendEntityInstance(pApplication); // OwnerHistory #56 IfcOwnerHistoryPtr pOwnerHistory = IfcOwnerHistory::createObject(); pOwnerHistory->putAttr("owninguser", personAndOrganization); pOwnerHistory->putAttr("owningapplication", application); pOwnerHistory->putAttr("changeaction", (const char *)"ADDED"); OdDAIObjectId ownerHistory = pModel->appendEntityInstance(pOwnerHistory); // Step 4: Create units #102, #103, #104 IfcSIUnitPtr pLengthUnit = IfcSIUnit::createObject(); pLengthUnit->setUnitType(kIfcUnitEnum_LENGTHUNIT); pLengthUnit->setPrefix(kIfcSIPrefix_MILLI); pLengthUnit->setName(kIfcSIUnitName_METRE); OdDAIObjectId lengthUnit = pModel->appendEntityInstance(pLengthUnit); IfcSIUnitPtr pAngleUnit = IfcSIUnit::createObject(); pAngleUnit->setUnitType(kIfcUnitEnum_PLANEANGLEUNIT); pAngleUnit->setName(kIfcSIUnitName_RADIAN); OdDAIObjectId angleUnit = pModel->appendEntityInstance(pAngleUnit); IfcSIUnitPtr pTimeUnit = IfcSIUnit::createObject(); pTimeUnit->setUnitType(kIfcUnitEnum_TIMEUNIT); pTimeUnit->setName(kIfcSIUnitName_SECOND); OdDAIObjectId timeUnit = pModel->appendEntityInstance(pTimeUnit); // Unit Assignment #101 IfcUnitAssignmentPtr pUnitAssignment = IfcUnitAssignment::createObject(); pUnitAssignment->putAttr("units", OdDAIObjectIds({lengthUnit, angleUnit, timeUnit})); OdDAIObjectId unitAssignment = pModel->appendEntityInstance(pUnitAssignment); // Step 5: Create project #100 IfcProjectPtr pProject = IfcProject::createObject(); // Use early-bound setters from IfcRoot OdDAI::CompressedGUID guid; guid = OdAnsiString("0$WU4A9R19$vKWO$AdOnKA"); pProject->setGlobalId(guid); pProject->setOwnerHistory(ownerHistory); pProject->setName(OdAnsiString("IfcProject")); pProject->putAttr("representationcontexts", OdDAIObjectIds({geomContext})); pProject->putAttr("unitsassignment", unitAssignment); OdDAIObjectId project = pModel->appendEntityInstance(pProject); // Step 6: Create building #50 IfcBuildingPtr pBuilding = IfcBuilding::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("39t4Pu3nTC4ekXYRIHJB9W"); pBuilding->setGlobalId(guid); pBuilding->setOwnerHistory(ownerHistory); pBuilding->setName(OdAnsiString("IfcBuilding")); OdDAIObjectId building = pModel->appendEntityInstance(pBuilding); // Step 7: Create material entities // Material #200 IfcMaterialPtr pMaterial = IfcMaterial::createObject(); pMaterial->setName(OdAnsiString("S355JR")); pMaterial->setDescription(OdAnsiString("Steel")); OdDAIObjectId material = pModel->appendEntityInstance(pMaterial); // I-Shape Profile #202 IfcIShapeProfileDefPtr pProfile = IfcIShapeProfileDef::createObject(); pProfile->putAttr("profiletype", (const char*)"AREA"); pProfile->putAttr("profilename", OdAnsiString("IPE200")); pProfile->putAttr("overallwidth", 100.0); pProfile->putAttr("overalldepth", 200.0); pProfile->putAttr("webthickness", 5.6); pProfile->putAttr("flangethickness", 8.5); pProfile->putAttr("filletradius", 12.0); OdDAIObjectId iShapeProfile = pModel->appendEntityInstance(pProfile); // Material Profile #203 IfcMaterialProfilePtr pMatProfile = IfcMaterialProfile::createObject(); pMatProfile->setName(OdAnsiString("IPE200")); pMatProfile->putAttr("material", material); pMatProfile->putAttr("profile", iShapeProfile); OdDAIObjectId materialProfile = pModel->appendEntityInstance(pMatProfile); // Material Profile Set #205 IfcMaterialProfileSetPtr pMatProfileSet = IfcMaterialProfileSet::createObject(); pMatProfileSet->setName(OdAnsiString("IPE200")); pMatProfileSet->putAttr("materialprofiles", OdDAIObjectIds({materialProfile})); OdDAIObjectId materialProfileSet = pModel->appendEntityInstance(pMatProfileSet); // Step 8: Create column type #207 IfcColumnTypePtr pColumnType = IfcColumnType::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("3qJDCKcPj1tgEHrIL1MUed"); pColumnType->setGlobalId(guid); pColumnType->setOwnerHistory(ownerHistory); pColumnType->setName(OdAnsiString("IPE200")); pColumnType->putAttr("predefinedtype", (const char*)"COLUMN"); OdDAIObjectId columnType = pModel->appendEntityInstance(pColumnType); // Step 9: Create geometry for column // Local placement #211 IfcLocalPlacementPtr pLocalPlacement = IfcLocalPlacement::createObject(); pLocalPlacement->putAttr("relativeplacement", columnAxisPlacement); OdDAIObjectId localPlacement = pModel->appendEntityInstance(pLocalPlacement); // Polyline for axis representation #217 IfcPolylinePtr pPolyline = IfcPolyline::createObject(); pPolyline->putAttr("points", OdDAIObjectIds({originPoint, topPoint})); OdDAIObjectId polyline = pModel->appendEntityInstance(pPolyline); // Axis shape representation #218 IfcShapeRepresentationPtr pAxisShapeRep = IfcShapeRepresentation::createObject(); pAxisShapeRep->setContextOfItems(axisSubContext); pAxisShapeRep->setRepresentationIdentifier(OdAnsiString("Axis")); pAxisShapeRep->setRepresentationType(OdAnsiString("Curve3D")); pAxisShapeRep->items().createEmpty(); pAxisShapeRep->items().Add(polyline); OdDAIObjectId axisShapeRep = pModel->appendEntityInstance(pAxisShapeRep); // Extruded area solid #222 IfcExtrudedAreaSolidPtr pExtrudedSolid = IfcExtrudedAreaSolid::createObject(); pExtrudedSolid->putAttr("sweptarea", iShapeProfile); pExtrudedSolid->putAttr("extrudeddirection", zDirection); pExtrudedSolid->putAttr("depth", 2000.0); OdDAIObjectId extrudedSolid = pModel->appendEntityInstance(pExtrudedSolid); // Body shape representation #223 IfcShapeRepresentationPtr pBodyShapeRep = IfcShapeRepresentation::createObject(); pBodyShapeRep->setContextOfItems(bodySubContext); pBodyShapeRep->setRepresentationIdentifier(OdAnsiString("Body")); pBodyShapeRep->setRepresentationType(OdAnsiString("SweptSolid")); pBodyShapeRep->items().createEmpty(); pBodyShapeRep->items().Add(extrudedSolid); OdDAIObjectId bodyShapeRep = pModel->appendEntityInstance(pBodyShapeRep); // Product definition shape #224 IfcProductDefinitionShapePtr pProductDefShape = IfcProductDefinitionShape::createObject(); pProductDefShape->representations().createEmpty(); pProductDefShape->representations().addByIndex(0, axisShapeRep); pProductDefShape->representations().addByIndex(1, bodyShapeRep); OdDAIObjectId productDefShape = pModel->appendEntityInstance(pProductDefShape); // Material profile set usage #219 IfcMaterialProfileSetUsagePtr pMatProfileSetUsage = IfcMaterialProfileSetUsage::createObject(); pMatProfileSetUsage->putAttr("forprofileset", materialProfileSet); pMatProfileSetUsage->putAttr("cardinalpoint", 5); // Integer value, not OdDAIObjectId OdDAIObjectId materialProfileSetUsage = pModel->appendEntityInstance(pMatProfileSetUsage); // Step 10: Create column instance #210 IfcColumnPtr pColumn = IfcColumn::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("3S1GK_wA565RDoiWQEJc_l"); pColumn->setGlobalId(guid); pColumn->setOwnerHistory(ownerHistory); pColumn->setName(OdAnsiString("IPE200")); pColumn->putAttr("objectplacement", localPlacement); pColumn->putAttr("representation", productDefShape); OdDAIObjectId column = pModel->appendEntityInstance(pColumn); // Step 11: Create relationships // Material association for column type #206 OdDAIObjectId relAssocMaterialType = createIfcRelAssociateMaterial( pDatabase, ownerHistory, OdString("MatAssoc"), OdString("Material Associates"), OdDAIObjectIds({columnType}), materialProfileSet ); // Material association for column instance #220 OdDAIObjectId relAssocMaterialUsage = createIfcRelAssociateMaterial( pDatabase, ownerHistory, OdString("MatAssoc"), OdString("Material Associates"), OdDAIObjectIds({column}), materialProfileSetUsage ); // Type definition relationship #208 IfcRelDefinesByTypePtr pRelDefinesByType = IfcRelDefinesByType::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("0QSJIMj99DcOpmktgECZT7"); pRelDefinesByType->setGlobalId(guid); pRelDefinesByType->setOwnerHistory(ownerHistory); pRelDefinesByType->putAttr("relatedobjects", OdDAIObjectIds({column})); pRelDefinesByType->putAttr("relatingtype", columnType); OdDAIObjectId relDefinesByType = pModel->appendEntityInstance(pRelDefinesByType); // Declaration relationship #209 IfcRelDeclaresPtr pRelDeclares = IfcRelDeclares::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("2RA6m5trr5aOD9rZCp3GjP"); pRelDeclares->setGlobalId(guid); pRelDeclares->setOwnerHistory(ownerHistory); pRelDeclares->putAttr("relatingcontext", project); pRelDeclares->putAttr("relateddefinitions", OdDAIObjectIds({columnType})); OdDAIObjectId relDeclares = pModel->appendEntityInstance(pRelDeclares); // Project aggregation relationship #105 IfcRelAggregatesPtr pRelAggregates = IfcRelAggregates::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("091a6ewbvCMQ2Vyiqspa7a"); pRelAggregates->setGlobalId(guid); pRelAggregates->setOwnerHistory(ownerHistory); pRelAggregates->setName(OdAnsiString("Project Container")); pRelAggregates->setDescription(OdAnsiString("Project Container for Buildings")); pRelAggregates->putAttr("relatingobject", project); pRelAggregates->putAttr("relatedobjects", OdDAIObjectIds({building})); OdDAIObjectId relAggregates = pModel->appendEntityInstance(pRelAggregates); // Spatial containment relationship #57 IfcRelContainedInSpatialStructurePtr pRelContained = IfcRelContainedInSpatialStructure::createObject(); // Use early-bound setters from IfcRoot guid = OdAnsiString("3Sa3dTJGn0H8TQIGiuGQd5"); pRelContained->setGlobalId(guid); pRelContained->setOwnerHistory(ownerHistory); pRelContained->setName(OdAnsiString("Building")); pRelContained->setDescription(OdAnsiString("Building Container for Elements")); pRelContained->putAttr("relatedelements", OdDAIObjectIds({column})); pRelContained->putAttr("relatingstructure", building); OdDAIObjectId relContained = pModel->appendEntityInstance(pRelContained); // Write the file pDatabase->writeFile(m_outputFileName); OdString successMsg = OdString(L"Successfully created IFC file: ") + m_outputFileName + L"\n"; odPrintConsoleString(successMsg); return 0; } catch (const OdError& e) { OdString errorMsg = OdString(L"Error: ") + e.description() + L"\n"; odPrintConsoleString(errorMsg); return 1; } catch (...) { odPrintConsoleString(L"Unknown error occurred\n"); return 1; } } // Reusable function to create IfcRelAssociatesMaterial relationships using early-bound approach OdDAIObjectId Tutorial_RelAssocMaterial_EarlyBound::createIfcRelAssociateMaterial( const OdIfcFilePtr& pDatabase, const OdDAIObjectId& ownerHistory, const OdString& name, const OdString& description, const OdDAIObjectIds& relatedObjects, const OdDAIObjectId& relatingMaterial) { OdIfcModelPtr pModel = pDatabase->getModel(sdaiRW); // Create the early-bound IfcRelAssociatesMaterial instance IfcRelAssociatesMaterialPtr pRelAssocMaterial = IfcRelAssociatesMaterial::createObject(); // Generate a unique GUID - simplified for tutorial OdDAI::CompressedGUID guid; OdString strGuid = ::odrxSystemServices()->createOdGUID().toString(OdGUID::StringFormat::Base64String); guid = OdAnsiString(strGuid); // Use early-bound setters from IfcRoot where available pRelAssocMaterial->setGlobalId(guid); pRelAssocMaterial->setOwnerHistory(ownerHistory); pRelAssocMaterial->setName(OdAnsiString(name)); pRelAssocMaterial->setDescription(OdAnsiString(description)); // Use early-bound approach for relatedObjects (collection) pRelAssocMaterial->relatedObjects().createEmpty(); for (unsigned int i = 0; i < relatedObjects.size(); i++) { pRelAssocMaterial->relatedObjects().Add(OdRxValue(relatedObjects[i])); } // Set the select using early-bound approach pRelAssocMaterial->relatingMaterial().select().setHandle(relatingMaterial); OdDAIObjectId relAssocMaterial = pModel->appendEntityInstance(pRelAssocMaterial); return relAssocMaterial; }