/////////////////////////////////////////////////////////////////////////////// // 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 incorporating 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. /////////////////////////////////////////////////////////////////////////////// #include "OdaCommon.h" #include "ExIfcTutorial_ParametricSleeper.h" #include "daiApplicationInstance.h" #include "IfcEntity.h" #include "IfcModelOps.h" #include "IfcModelOpsFiller.h" #include "IfcModelProcessor.h" #include "Ge/GeCircArc3d.h" // External sub-routines OdDAIObjectId appendIfcSiUnit(OdIfcModel* model, const char* unitType, const char* prefix, const char* name); OdDAIObjectId appendCartesianPoint(OdIfcModel* model, const OdArray& dblArr); OdDAIObjectId appendDirection(OdIfcModel* model, const OdArray& dblArr); OdDAIObjectId appendSpatialChild(OdIfcModel* model, const OdDAIObjectId& idRelating, OdIfc::OdIfcInstance* related, const OdDAIObjectId& idOwnerHistory); OdDAIObjectId appendContained(OdIfcModel* model, const OdDAIObjectId& idRelating, OdIfc::OdIfcInstance* related, const OdDAIObjectId& idOwnerHistory); // params [output_file] Tutorial_ParametricSleeper::Tutorial_ParametricSleeper(const OdString& applicationName) : BaseIfcTutorial(applicationName) { m_tutorialArgsParser .add_param( std::make_shared>(m_ifcOutputFileName, "outputFile", ".ifc file where we should insert IFC entities", false)); m_tutorialArgsParser .add_param( std::make_shared(m_noWait, "-NoWait", "disable \"press any key\" on finish.")); // ExIfcTutorials.exe Number_Of_tutorial outputFile=C:\path\to\dest_file.ifc } OdDAIObjectId createAxis2Placement3D(OdDAI::ModelPtr& model, const OdGeMatrix3d& position) { OdArray coordinates; coordinates.append(position.getCsOrigin().x); coordinates.append(position.getCsOrigin().y); coordinates.append(position.getCsOrigin().z); OdDAIObjectId idLocation = appendCartesianPoint(model, coordinates); OdArray directionZ; directionZ.append(position.getCsZAxis().x); directionZ.append(position.getCsZAxis().y); directionZ.append(position.getCsZAxis().z); OdDAIObjectId idAxis = appendDirection(model, directionZ); OdArray directionX; directionX.append(position.getCsXAxis().x); directionX.append(position.getCsXAxis().y); directionX.append(position.getCsXAxis().z); OdDAIObjectId idRefDirection = appendDirection(model, directionX); OdDAI::ApplicationInstancePtr axis2placement3d = model->createEntityInstance("ifcaxis2placement3d"); axis2placement3d->putAttr("location", idLocation); axis2placement3d->putAttr("axis", idAxis); axis2placement3d->putAttr("refdirection", idRefDirection); auto idAxis2Placement3d = model->appendEntityInstance(axis2placement3d); return idAxis2Placement3d; } OdDAIObjectId createLocalPlacement(OdDAI::ModelPtr &model, const OdGeMatrix3d& position) { OdDAI::ApplicationInstancePtr localPlacement = model->createEntityInstance("ifclocalplacement"); localPlacement->putAttr("relativeplacement", createAxis2Placement3D(model, position)); return model->appendEntityInstance(localPlacement); } OdDAIObjectId createParametricSleeper( OdDAI::ModelPtr& model, const OdDAIObjectId &idContext, const OdDAIObjectId &idRailwayPart, const OdDAIObjectId &idOwnerHistory, const OdDAIObjectId &idDirectionZ, const OdDAIObjectId &idSurfaceStyle, double xDim, double yDim, double height, const OdGeMatrix3d &objectPlacement) { // // Sleeper itself // OdIfc::OdIfcInstancePtr sleeper = model->createEntityInstance("ifctrackelement"); sleeper->putAttr("name", static_cast("Sleeper")); sleeper->putAttr("predefinedtype", static_cast("SLEEPER")); sleeper->putAttr("objectplacement", createLocalPlacement(model, objectPlacement)); // This can be any positioning element, e.g. erlative to alignment. auto idSleeper = appendContained(model, idRailwayPart, sleeper, idOwnerHistory); // // Geometrical representation // auto rectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); rectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM rectangleProfileDef->putAttr("profilename", static_cast("Sleeper Profile")); rectangleProfileDef->putAttr("xdim", xDim); rectangleProfileDef->putAttr("ydim", yDim); auto idRectangleProfileDef = model->appendEntityInstance(rectangleProfileDef); auto extrudedAreasolid = model->createEntityInstance("ifcextrudedareasolid"); extrudedAreasolid->putAttr("sweptarea", idRectangleProfileDef); extrudedAreasolid->putAttr("extrudeddirection", idDirectionZ); extrudedAreasolid->putAttr("depth", height); OdDAIObjectIds items; items.append(model->appendEntityInstance(extrudedAreasolid)); // // Style assignment to Extruded Area Solid // OdArray stylesForIlem; stylesForIlem.append(idSurfaceStyle); auto styledItem = model->createEntityInstance("ifcstyleditem"); styledItem->putAttr("item", items[0]); styledItem->putAttr("styles", stylesForIlem); // Aggregation of Selects auto idStyledItem = model->appendEntityInstance(styledItem); auto shapeRepresentation = model->createEntityInstance("ifcshaperepresentation"); shapeRepresentation->putAttr("contextofitems", idContext); shapeRepresentation->putAttr("representationidentifier", static_cast("Body")); shapeRepresentation->putAttr("representationtype", static_cast < const char*>("SweptSolid")); shapeRepresentation->putAttr("items", items); OdDAIObjectIds idsRepresentation; idsRepresentation.append(model->appendEntityInstance(shapeRepresentation)); auto productDefinitionShape = model->createEntityInstance("ifcproductdefinitionshape"); productDefinitionShape->putAttr("representations", idsRepresentation); auto idProductDefinitionShape = model->appendEntityInstance(productDefinitionShape); sleeper->putAttr("representation", idProductDefinitionShape); return idSleeper; } int Tutorial_ParametricSleeper::run(const MyServices& svcs, const std::vector& argumentList, std::ostream& resultStream) { auto parseResult = BaseIfcTutorial::run(svcs, argumentList, resultStream); if (parseResult != 0) { return parseResult; } OdIfcFilePtr ifcFile = svcs.createDatabase(kScmIfc4x3); OdIfcModelPtr model = ifcFile->getModel(sdaiRW); // // Common header for IFC model // OdDAI::ApplicationInstancePtr person = model->createEntityInstance("ifcperson"); person->putAttr("identification", (const char*)"T-1000"); OdDAIObjectId idPerson = model->appendEntityInstance(person); // person added to model and has id after this line OdDAI::ApplicationInstancePtr organization = model->createEntityInstance("ifcorganization"); organization->putAttr("name", (const char *)"Open Design Alliance"); OdDAIObjectId idOrganization = model->appendEntityInstance(organization); auto personAndOrganization = model->createEntityInstance("ifcpersonandorganization"); personAndOrganization->putAttr("theperson", idPerson); personAndOrganization->putAttr("theorganization", idOrganization); auto idPersonAndOrganization = model->appendEntityInstance(personAndOrganization); auto organizationForApplication = model->createEntityInstance("ifcorganization"); organizationForApplication->putAttr("name", static_cast("Company 1")); organizationForApplication->putAttr("description", static_cast("File produced in ExIfcTutorials, Tutorial_ParametricSleeper")); auto idOrganizationForApplication = model->appendEntityInstance(organizationForApplication); auto application = model->createEntityInstance("ifcapplication"); application->putAttr("applicationdeveloper", idOrganizationForApplication); application->putAttr("version", static_cast("0.1 pre alpha")); application->putAttr("applicationfullname", static_cast("ExIfcTutorials module for ODA IFC SDK")); application->putAttr("applicationidentifier", static_cast("ExIfcTutorials")); auto idApplication = model->appendEntityInstance(application); auto ownerHistory = model->createEntityInstance("ifcownerhistory"); ownerHistory->putAttr("owninguser", idPersonAndOrganization); ownerHistory->putAttr("owningapplication", idApplication); ownerHistory->putAttr("changeaction", static_cast("ADDED")); ownerHistory->putAttr("creationdate", 0); auto idOwnerHistory = model->appendEntityInstance(ownerHistory); OdArray units; units.append(appendIfcSiUnit(model, "LENGTHUNIT", "MILLI", "METRE")); // ENUM units.append(appendIfcSiUnit(model, "PLANEANGLEUNIT", NULL, "RADIAN")); units.append(appendIfcSiUnit(model, "AREAUNIT", NULL, "SQUARE_METRE")); units.append(appendIfcSiUnit(model, "VOLUMEUNIT", NULL, "CUBIC_METRE")); auto unitAssignment = model->createEntityInstance("ifcunitassignment"); unitAssignment->putAttrCaseInsensitive("Units", units); auto idUnitAssignment = model->appendEntityInstance(unitAssignment); auto project = model->createEntityInstance("ifcproject"); project->putAttr("globalid", OdDAI::CompressedGUID::generate()); project->putAttr("ownerhistory", idOwnerHistory); project->putAttr("name", (const char *)"ExIfcTutorials, Tutorial_01, IfcColumn creation"); project->putAttr("unitsincontext", idUnitAssignment); auto idProject = model->appendEntityInstance(project); OdArray dblArr; dblArr.append(0.); dblArr.append(0.); auto idCartesianPoint2d = appendCartesianPoint(model, dblArr); dblArr.append(0.); auto idCartesianPoint3d = appendCartesianPoint(model, dblArr); dblArr[2] = 1.; auto idDirectionZ = appendDirection(model, dblArr); OdDAIObjectIds idsCtx; // Plan context auto axis2placement2d = model->createEntityInstance("ifcaxis2placement2d"); axis2placement2d->putAttr("location", idCartesianPoint2d); auto idAxis2Placement2d = model->appendEntityInstance(axis2placement2d); auto ctxPlan = model->createEntityInstance("ifcgeometricrepresentationcontext"); ctxPlan->putAttr("contextidentifier", static_cast("2D")); ctxPlan->putAttr("contexttype", static_cast("Plan")); ctxPlan->putAttr("coordinatespacedimension", 2); ctxPlan->putAttr("worldcoordinatesystem", idAxis2Placement2d); idsCtx.append(model->appendEntityInstance(ctxPlan)); // Model context auto axis2placement3d = model->createEntityInstance("ifcaxis2placement3d"); axis2placement3d->putAttr("location", idCartesianPoint3d); auto idAxis2Placement3d = model->appendEntityInstance(axis2placement3d); auto ctxModel = model->createEntityInstance("ifcgeometricrepresentationcontext"); ctxModel->putAttr("contextidentifier", static_cast("3D")); ctxModel->putAttr("contexttype", static_cast("Model")); ctxModel->putAttr("coordinatespacedimension", 3); ctxModel->putAttr("worldcoordinatesystem", idAxis2Placement3d); idsCtx.append(model->appendEntityInstance(ctxModel)); project->putAttr("representationcontexts", idsCtx); // Material auto colourRGB = model->createEntityInstance("ifccolourrgb"); colourRGB->putAttr("name", static_cast("Blue")); colourRGB->putAttr("red", 1.); colourRGB->putAttr("green", 1.); colourRGB->putAttr("blue", 0.9); auto idColourRGB = model->appendEntityInstance(colourRGB); auto surfaceStyleRendering = model->createEntityInstance("ifcsurfacestylerendering"); surfaceStyleRendering->putAttr("surfacecolour", idColourRGB); surfaceStyleRendering->putAttr("reflectancemethod", static_cast("NOTDEFINED")); auto idSurfaceStyleRendering = model->appendEntityInstance(surfaceStyleRendering); OdArray styles; // Aggregation of Selects styles.push_back(idSurfaceStyleRendering); auto surfaceStyle = model->createEntityInstance("ifcsurfacestyle"); surfaceStyle->putAttr("name", static_cast("Style for columns")); surfaceStyle->putAttr("side", static_cast("POSITIVE")); surfaceStyle->putAttr("styles", styles); auto idSurfaceStyle = model->appendEntityInstance(surfaceStyle); // // Railroad spatial structure // OdIfc::OdIfcInstancePtr site = model->createEntityInstance("ifcsite"); site->putAttr("name", static_cast("Site")); auto idSite = appendSpatialChild(model, idProject, site, idOwnerHistory); OdIfc::OdIfcInstancePtr railway = model->createEntityInstance("ifcrailway"); railway->putAttr("name", static_cast("Railway")); auto idRailway = appendSpatialChild(model, idSite, railway, idOwnerHistory); OdIfc::OdIfcInstancePtr railwayPart = model->createEntityInstance("ifcrailwaypart"); railwayPart->putAttr("name", static_cast("Sleepers")); railwayPart->putAttr("usagetype", static_cast("LONGITUDINAL")); auto idRailwayPart = appendSpatialChild(model, idRailway, railwayPart, idOwnerHistory); // // Railroad sleepers // OdGeCircArc3d pathCurve(OdGePoint3d(0, 0, 0), OdGeVector3d(0, 0, 1), 1500.); double sleeperHeight = 5.; double sleeperXDim = 170.; double sleeperYDim = 10.; for (int i = 0; i < 360; ++i) { OdGeMatrix3d position = OdGeMatrix3d::kIdentity; double param = (OdaPI / 180.) * i; double angle = atan2(sin(param), cos(param)); OdGeVector3d xAxis(cos(angle), sin(angle), 0.); OdGeVector3d yAxis = xAxis.perpVector(); OdGeVector3d zAxis = xAxis.crossProduct(yAxis); position.setCoordSystem( pathCurve.evalPoint(param), xAxis, yAxis, zAxis ); sleeperXDim = 170. + sin(param * 10) * 40.; createParametricSleeper(model, OdDAIObjectId(ctxModel->id()), idRailwayPart, idOwnerHistory, idDirectionZ, idSurfaceStyle, sleeperXDim, sleeperYDim, sleeperHeight, position); } return (int)ifcFile->writeFile(m_ifcOutputFileName); }