/////////////////////////////////////////////////////////////////////////////// // 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_ModelOpsFloor.h" #include "daiApplicationInstance.h" #include "IfcModelOps.h" #include "IfcModelOpsFiller.h" #include "IfcModelProcessor.h" // try to append ifcbuildingstorey from source building N times with offset in model length units to new output file based on existing one // params [input_file] [id_floor] [id_upper_floor] [z_offset] [num_clones] [output_file] Tutorial_ModelOpsFloor::Tutorial_ModelOpsFloor(const OdString& applicationName) : BaseIfcTutorial(applicationName) { m_tutorialArgsParser .add_param( std::make_shared>(m_ifcSourceFile, "inputFile", ".ifc file where clonable entity is contained", false)); m_tutorialArgsParser .add_param( std::make_shared>(m_sourceFloorId, "sourceFloorId", "instance id of source floor within model", false)); m_tutorialArgsParser .add_param( std::make_shared>(m_upperFloorId, "upperFloorId", "instance id of upper floor within model", false)); m_tutorialArgsParser .add_param( std::make_shared>(m_zOffset, "offset", "floor instance offset", false)); m_tutorialArgsParser .add_param( std::make_shared>(m_clonesCount, "count", "count of floor to increase", false)); m_tutorialArgsParser .add_param( std::make_shared>(m_ifcDestFile, "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 TutorialNumber inputFile=C:\path\to\input_file.ifc sourceFloorId=43 upperFloorId=51 offset=2.7 count=3 outputFile=C:\path\to\output_file.ifc } int Tutorial_ModelOpsFloor::run(const MyServices& svcs, const std::vector& argumentList, std::ostream& resultStream) { auto parseResult = BaseIfcTutorial::run(svcs, argumentList, resultStream); if (parseResult != 0) { return parseResult; } OdIfcFilePtr pSourceFile = svcs.createDatabase(); OdResult res = pSourceFile->readFile(m_ifcSourceFile); if (res == eOk) { odPrintConsoleString(OD_T("\nSource file opened successfully.\n")); } else { odPrintConsoleString(OD_T("\nSource file open error. Press any key to finish...")); if (m_noWait == false) { getchar(); } return res; } OdIfcModelPtr pSourceModel = pSourceFile->getModel(sdaiRW); if (pSourceModel.isNull()) { odPrintConsoleString(OD_T("\nSource model is not valid. Press any key to finish...\n")); if (m_noWait == false) { getchar(); } return -1; } std::unique_ptr modelFiller = nullptr; OdIfcFilePtr pDestinationFile = svcs.createDatabase(); res = pDestinationFile->readFile(m_ifcDestFile); if (res == eOk) { odPrintConsoleString(OD_T("\nDestination file exists and will be rewritten.\n")); pDestinationFile = pSourceFile; } else if (res == eFileNotFound) { odPrintConsoleString(OD_T("\nDestination file will be created.\n")); pDestinationFile = pSourceFile; } else { odPrintConsoleString(OD_T("\nDestination file open error. Press any key to finish...")); if (m_noWait == false) { getchar(); } return res; } odPrintConsoleString(OD_T("\nRetrieving model information\n")); OdIfcModelPtr pTargetModel = pSourceModel; odPrintConsoleString(OD_T("\nProcessing entities...")); { OdDbHandle sourceInstance = OdDbHandle(m_sourceFloorId); OdDbHandle upperInstance = OdDbHandle(m_upperFloorId); auto clonableEntity = pSourceModel->getEntityInstance(sourceInstance); OdIfc::OdIfcInstancePtr pClonableEntInstance = clonableEntity.openObject(); if (pClonableEntInstance.isNull()) { odPrintConsoleString(OD_T("\nSource model doesn't contain entity with specified Id = #%d. Press any key to finish...\n"), sourceInstance); return -1; } OdAnsiString typeName = pClonableEntInstance->typeName(); if (!pClonableEntInstance->isKindOf("ifcbuildingstorey")) { odPrintConsoleString(OD_T("\nUnsupported source entity type = %ls. Press any key to finish...\n"), OdString(typeName).c_str()); return -1; } auto upperEntity = pSourceModel->getEntityInstance(upperInstance); OdIfc::OdIfcInstancePtr pUpperEntInstance = upperEntity.openObject(); if (pUpperEntInstance.isNull()) { odPrintConsoleString(OD_T("\nSource model doesn't contain entity with specified Id = #%d. Press any key to finish...\n"), m_upperFloorId); return -1; } typeName = pUpperEntInstance->typeName(); if (!pUpperEntInstance->isKindOf("ifcbuildingstorey")) { odPrintConsoleString(OD_T("\nUnsupported source entity type = %ls. Press any key to finish...\n"), OdString(typeName).c_str()); return -1; } OdDAIObjectId targetEntity = OdDAIObjectId(); if (modelFiller == nullptr) modelFiller = std::unique_ptr(new IfcModelOpsFiller(pTargetModel)); if (!pTargetModel->getEntityExtent("ifcbuilding")->getMemberCount()) { odPrintConsoleString(OD_T("\nBuilding entity not found. Press any key to finish...\n")); return -1; } targetEntity = pTargetModel->getEntityExtent("ifcbuilding")->getArray()[0]; OdIfc::OdIfcInstancePtr pTargetEntInstance = targetEntity.openObject(); OdIfc::ModelOps::IfcModelProcessor processor(pTargetModel); for (int floorCounter = 1; floorCounter <= m_clonesCount; floorCounter++) { if (!clonableEntity.isNull()) { if (!pTargetEntInstance.isNull()) { processor.setTargetOffset(OdGePoint3d(0.0, 0.0, m_zOffset*floorCounter)); OdDAIObjectId clonedItem = processor.ifcCloneTo(clonableEntity, targetEntity); if (!clonedItem.isNull()) { OdIfc::OdIfcInstancePtr pRelAggr = modelFiller->addRelAggregates(pTargetEntInstance, clonedItem.openObject()); } } else { odPrintConsoleString(OD_T("\nFailed to access target entity. Press any key to finish...\n")); return -1; } } } if (!upperEntity.isNull() && m_clonesCount > 0) { processor.setTargetOffset(OdGePoint3d(0.0, 0.0, m_zOffset*(m_clonesCount))); OdDAIObjectId clonedUpperItem = processor.ifcCloneTo(upperEntity, targetEntity); // the upperEntity still in decompose relationships OdIfc::ModelOps::removeRepresentationFrom(upperEntity); // to remove upperEntity from relationships and entity itself we should use removeFromRelAggregates // OdIfc::ModelOps::removeFromRelAggregates(upperEntity); } } try { pDestinationFile->writeFile(m_ifcDestFile); } catch (...) { return -1; } odPrintConsoleString(OD_T("\n\nProcess finished\n")); return 0; }