/////////////////////////////////////////////////////////////////////////////// // 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_ParametricPole.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); OdDAIObjectId createAxis2Placement3D(OdDAI::ModelPtr& model, const OdGeMatrix3d& position); OdDAIObjectId createLocalPlacement(OdDAI::ModelPtr& model, const OdGeMatrix3d& position); 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); // params [output_file] Tutorial_ParametricPole::Tutorial_ParametricPole(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 createAxis2Placement3dFromZ(OdDAI::ModelPtr& model, double height) { OdArray locationCoordinates; locationCoordinates.append(0.); locationCoordinates.append(0.); locationCoordinates.append(height); OdDAIObjectId idLocation = appendCartesianPoint(model, locationCoordinates); auto position = model->createEntityInstance("ifcaxis2placement3d"); position->putAttr("location", idLocation); auto idPosition = model->appendEntityInstance(position); return idPosition; } OdDAIObjectIds createParametricFundamentRepresentation( OdDAI::ModelPtr& model, const OdDAIObjectId& idDirectionZ, double lowerX, double lowerY, double lowerHeight, double upperX, double upperY, double upperHeight, double& fundamentFullHeight) { // // Geometrical representation // auto lowerRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); lowerRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM lowerRectangleProfileDef->putAttr("profilename", static_cast("Fundament lower part")); lowerRectangleProfileDef->putAttr("xdim", lowerX); lowerRectangleProfileDef->putAttr("ydim", lowerY); auto idLowerRectangleProfileDef = model->appendEntityInstance(lowerRectangleProfileDef); auto lowerExtrudedAreasolid = model->createEntityInstance("ifcextrudedareasolid"); lowerExtrudedAreasolid->putAttr("sweptarea", idLowerRectangleProfileDef); lowerExtrudedAreasolid->putAttr("extrudeddirection", idDirectionZ); lowerExtrudedAreasolid->putAttr("depth", lowerHeight); auto upperRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); upperRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM upperRectangleProfileDef->putAttr("profilename", static_cast("Fundament upper part")); upperRectangleProfileDef->putAttr("xdim", upperX); upperRectangleProfileDef->putAttr("ydim", upperY); auto idUpperRectangleProfileDef = model->appendEntityInstance(upperRectangleProfileDef); auto upperExtrudedAreasolid = model->createEntityInstance("ifcextrudedareasolid"); upperExtrudedAreasolid->putAttr("sweptarea", idUpperRectangleProfileDef); upperExtrudedAreasolid->putAttr("position", createAxis2Placement3dFromZ(model, lowerHeight)); upperExtrudedAreasolid->putAttr("extrudeddirection", idDirectionZ); upperExtrudedAreasolid->putAttr("depth", upperHeight); fundamentFullHeight = lowerHeight + upperHeight; OdDAIObjectIds items; items.append(model->appendEntityInstance(lowerExtrudedAreasolid)); items.append(model->appendEntityInstance(upperExtrudedAreasolid)); return items; } OdDAIObjectIds createParametricMastRepresentation( OdDAI::ModelPtr& model, const OdDAIObjectId& idDirectionZ, double mastBaseHeight, double basePlateX, double basePlateY, double basePlateHeigth, double mastX, double mastY, double mastHeight) { OdDAIObjectId idBasePosition = createAxis2Placement3dFromZ(model, mastBaseHeight); // // Geometrical representation // auto lowerRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); lowerRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM lowerRectangleProfileDef->putAttr("profilename", static_cast("Mast base plate")); lowerRectangleProfileDef->putAttr("xdim", basePlateX); lowerRectangleProfileDef->putAttr("ydim", basePlateY); auto idLowerRectangleProfileDef = model->appendEntityInstance(lowerRectangleProfileDef); auto lowerExtrudedAreasolid = model->createEntityInstance("ifcextrudedareasolid"); lowerExtrudedAreasolid->putAttr("sweptarea", idLowerRectangleProfileDef); lowerExtrudedAreasolid->putAttr("position", idBasePosition); lowerExtrudedAreasolid->putAttr("extrudeddirection", idDirectionZ); lowerExtrudedAreasolid->putAttr("depth", basePlateHeigth); auto upperRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); upperRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM upperRectangleProfileDef->putAttr("profilename", static_cast("Mast")); upperRectangleProfileDef->putAttr("xdim", mastX); upperRectangleProfileDef->putAttr("ydim", mastX); auto idUpperRectangleProfileDef = model->appendEntityInstance(upperRectangleProfileDef); auto upperExtrudedAreasolid = model->createEntityInstance("ifcextrudedareasolid"); upperExtrudedAreasolid->putAttr("sweptarea", idUpperRectangleProfileDef); upperExtrudedAreasolid->putAttr("position", idBasePosition); upperExtrudedAreasolid->putAttr("extrudeddirection", idDirectionZ); upperExtrudedAreasolid->putAttr("depth", mastHeight); OdDAIObjectIds items; items.append(model->appendEntityInstance(lowerExtrudedAreasolid)); items.append(model->appendEntityInstance(upperExtrudedAreasolid)); return items; } OdDAIObjectIds createParametricCantileverRepresentation( OdDAI::ModelPtr& model, const OdDAIObjectId& idDirectionZ, double halfMastX, double cantileverBaseHeight, double cantileverX, double cantileverY, double cantileverZ) { OdDAIObjectId idBasePosition = createAxis2Placement3dFromZ(model, cantileverBaseHeight); double fastenerX = cantileverX / 20.; OdGeMatrix3d transfFastener; transfFastener.setCoordSystem(OdGePoint3d(halfMastX + fastenerX * 0.5, 0., cantileverBaseHeight), OdGeVector3d::kXAxis, OdGeVector3d::kYAxis, OdGeVector3d::kZAxis); OdDAIObjectId idTransfFastener = createAxis2Placement3D(model, transfFastener); // // Fastener representation // auto fastenerRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); fastenerRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM fastenerRectangleProfileDef->putAttr("profilename", static_cast("Cantilever fastener")); fastenerRectangleProfileDef->putAttr("xdim", fastenerX); fastenerRectangleProfileDef->putAttr("ydim", cantileverZ); auto idFastenerRectangleProfileDef = model->appendEntityInstance(fastenerRectangleProfileDef); auto fastenerExtrudedAreaSolid = model->createEntityInstance("ifcextrudedareasolid"); fastenerExtrudedAreaSolid->putAttr("sweptarea", idFastenerRectangleProfileDef); fastenerExtrudedAreaSolid->putAttr("position", idTransfFastener); fastenerExtrudedAreaSolid->putAttr("extrudeddirection", idDirectionZ); fastenerExtrudedAreaSolid->putAttr("depth", cantileverY); // // Beam representation // OdGeMatrix3d transfBeam1; transfBeam1.setCoordSystem(OdGePoint3d(halfMastX + fastenerX * 0.5, 0., cantileverBaseHeight + cantileverY - cantileverZ * 0.5), -OdGeVector3d::kZAxis, OdGeVector3d::kYAxis, OdGeVector3d::kXAxis); OdDAIObjectId idTransfBeam1 = createAxis2Placement3D(model, transfBeam1); auto beamRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); beamRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM beamRectangleProfileDef->putAttr("profilename", static_cast("Beam")); beamRectangleProfileDef->putAttr("xdim", cantileverZ); beamRectangleProfileDef->putAttr("ydim", cantileverZ); auto idBeamRectangleProfileDef = model->appendEntityInstance(beamRectangleProfileDef); auto beamExtrudedAreasolid1 = model->createEntityInstance("ifcextrudedareasolid"); beamExtrudedAreasolid1->putAttr("sweptarea", idBeamRectangleProfileDef); beamExtrudedAreasolid1->putAttr("position", idTransfBeam1); beamExtrudedAreasolid1->putAttr("extrudeddirection", idDirectionZ); beamExtrudedAreasolid1->putAttr("depth", cantileverX - fastenerX * 4); double angle = atan2(-cantileverY * 0.75, cantileverX * 0.5); OdGeMatrix3d transfBeam2; transfBeam2.setCoordSystem(OdGePoint3d(halfMastX + fastenerX * 0.5 + cantileverX * 2./3., 0., cantileverBaseHeight + cantileverY - cantileverZ * 0.5), OdGeVector3d(sin(angle), 0., -cos(angle)), OdGeVector3d::kYAxis, OdGeVector3d(cos(angle), 0, sin(angle))); bool bUSO = transfBeam2.isUniScaledOrtho(); OdDAIObjectId idTransfBeam2 = createAxis2Placement3D(model, transfBeam2); auto beamExtrudedAreasolid2 = model->createEntityInstance("ifcextrudedareasolid"); beamExtrudedAreasolid2->putAttr("sweptarea", idBeamRectangleProfileDef); beamExtrudedAreasolid2->putAttr("position", idTransfBeam2); beamExtrudedAreasolid2->putAttr("extrudeddirection", idDirectionZ); double beamPartLength = cantileverX * 0.3; beamExtrudedAreasolid2->putAttr("depth", beamPartLength); // // Connector representation // OdGeMatrix3d transfConnector; transfConnector.setCoordSystem(OdGePoint3d(halfMastX + cantileverX - fastenerX * 0.5, 0., cantileverBaseHeight), OdGeVector3d::kXAxis, OdGeVector3d::kYAxis, OdGeVector3d::kZAxis); OdDAIObjectId idTransfConnector = createAxis2Placement3D(model, transfConnector); //auto connectorRectangleProfileDef = model->createEntityInstance("ifcrectangleprofiledef"); //connectorRectangleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM //connectorRectangleProfileDef->putAttr("profilename", static_cast("Cantilever connector")); //connectorRectangleProfileDef->putAttr("xdim", fastenerX * 0.5); //connectorRectangleProfileDef->putAttr("ydim", cantileverZ * 0.5); //auto idConnectorProfileDef = model->appendEntityInstance(connectorRectangleProfileDef); auto connectorCircleProfileDef = model->createEntityInstance("ifccircleprofiledef"); connectorCircleProfileDef->putAttr("profiletype", static_cast("AREA")); // ENUM connectorCircleProfileDef->putAttr("profilename", static_cast("Circular connector")); connectorCircleProfileDef->putAttr("radius", cantileverZ * 0.5); auto idConnectorProfileDef = model->appendEntityInstance(connectorCircleProfileDef); auto connectorExtrudedAreaSolid = model->createEntityInstance("ifcextrudedareasolid"); connectorExtrudedAreaSolid->putAttr("sweptarea", idConnectorProfileDef); connectorExtrudedAreaSolid->putAttr("position", idTransfConnector); connectorExtrudedAreaSolid->putAttr("extrudeddirection", idDirectionZ); connectorExtrudedAreaSolid->putAttr("depth", cantileverY * 0.5); OdDAIObjectIds items; items.append(model->appendEntityInstance(fastenerExtrudedAreaSolid)); items.append(model->appendEntityInstance(beamExtrudedAreasolid1)); items.append(model->appendEntityInstance(beamExtrudedAreasolid2)); items.append(model->appendEntityInstance(connectorExtrudedAreaSolid)); return items; } OdDAIObjectId createParametricPole( OdDAI::ModelPtr& model, const OdDAIObjectId& idContext, const OdDAIObjectId& idRailwayPart, const OdDAIObjectId& idOwnerHistory, const OdDAIObjectId& idDirectionZ, const OdDAIObjectId& idSurfaceStyle, double lowerX, double lowerY, double lowerHeight, double upperX, double upperY, double upperHeight, double& fundamentFullHeight, double mastBasePlateX, double mastBasePlateY, double mastBasePlateHeight, double mastX, double mastY, double mastHeight, double cantileverX, double cantileverY, double cantileverZ, const OdGeMatrix3d& objectPlacement) { // // Flow Element itself // OdIfc::OdIfcInstancePtr flowElement = model->createEntityInstance("ifcdistributionflowelement"); flowElement->putAttr("name", static_cast("Flow Element")); flowElement->putAttr("objectplacement", createLocalPlacement(model, objectPlacement)); // This can be any positioning element, e.g. erlative to alignment. auto idFlowElement = appendContained(model, idRailwayPart, flowElement, idOwnerHistory); OdDAIObjectIds items; items.append(createParametricFundamentRepresentation(model, idDirectionZ, lowerX, lowerY, lowerHeight, upperX, upperY, upperHeight, fundamentFullHeight)); items.append(createParametricMastRepresentation(model, idDirectionZ, fundamentFullHeight, mastBasePlateX, mastBasePlateY, mastBasePlateHeight, mastX, mastY, mastHeight)); items.append(createParametricCantileverRepresentation(model, idDirectionZ, mastX * 0.5, fundamentFullHeight + mastHeight - cantileverY - 5., cantileverX, cantileverY, cantileverZ)); // // 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 ("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); flowElement->putAttr("representation", idProductDefinitionShape); return idFlowElement; } int Tutorial_ParametricPole::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_ParametricPole")); 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("Parts")); railwayPart->putAttr("usagetype", static_cast("LONGITUDINAL")); auto idRailwayPart = appendSpatialChild(model, idRailway, railwayPart, idOwnerHistory); // // Railroad parts // OdGeCircArc3d pathCurve(OdGePoint3d(0, 0, 0), OdGeVector3d(0, 0, 1), 1500.); double sleeperHeight = 5.; double fundamentLowerX = 14.; double fundamentLowerY = 12.; double fundamentLowerHeight = 20.; double fundamentUpperX = 8.; double fundamentUpperY = 8.; double fundamentUpperHeight = 8.; double mastBasePlateX = 6.5; double mastBasePlateY = 6.5; double mastBasePlateHeight = 0.5; double mastX = 4.; double mastY = 4.; double mastHeight = 100.; double cantileverX = 60.; double cantileverY = 16.; double cantileverZ = 2.; double sleeperXDim = 170.; double sleeperYDim = 10.; for (int i = 0; i < 360; ++i) { double param = (OdaPI / 180.) * i; double angle = atan2(sin(param), cos(param)); OdGeMatrix3d position = OdGeMatrix3d::kIdentity; 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); double fundamentFullHeight{ 0. }; OdDAIObjectId idFundamentRepr = createParametricPole(model, OdDAIObjectId(ctxModel->id()), idRailwayPart, idOwnerHistory, idDirectionZ, idSurfaceStyle, // Fundament parameters fundamentLowerX, fundamentLowerY, fundamentLowerHeight, fundamentUpperX, fundamentUpperY, fundamentUpperHeight, fundamentFullHeight, // Mast parameters mastBasePlateX, mastBasePlateY, mastBasePlateHeight, mastX, mastY, mastHeight + sin(param * 20) * 25., // Cantilever parameters sleeperXDim * 0.5 /* cantileverX */, cantileverY, cantileverZ, position); } return (int)ifcFile->writeFile(m_ifcOutputFileName); }