/////////////////////////////////////////////////////////////////////////////// // 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 "OdString.h" #include "RxVariantValue.h" #include "ExSystemServices.h" #include "ExHostAppServices.h" #include "IfcExamplesCommon.h" #include "IfcCore.h" #include "StaticRxObject.h" #include "RxDynamicModule.h" #include "OdPerfTimer.h" #include "ExPrintConsole.h" #include "Common/ModuleNames.h" #include "../Exchange/Exports/Ifc2Dwg/Include/IfcExport.h" using namespace TD_IFC_EXPORT; class DbServices : public ExSystemServices, public ExHostAppServices { protected: ODRX_USING_HEAP_OPERATORS(ExSystemServices); virtual void warning(const char*, const OdString& msg) ODRX_OVERRIDE { odPrintConsoleString(L"Exception: "); odPrintConsoleString(msg.c_str()); odPrintConsoleString(L"\n"); } }; // // Define module map for statically linked modules: // #if !defined(_TOOLKIT_IN_DLL_) ODRX_DECLARE_IFC2DWG_STATIC_MODULES_ENTRY_POINTS() // Or ODRX_DECLARE_IFC2DWG_STATIC_MODULES_SOLIDMODELER_ENTRY_POINTS() // for ODA SolidModeler ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT(OdRecomputeDimBlockModule); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT(OdRxThreadPoolService); ODRX_BEGIN_STATIC_MODULE_MAP() ODRX_DEFINE_IFC2DWG_STATIC_APPMODULES() // Or ODRX_DEFINE_IFC2DWG_STATIC_SOLIDMODELER_APPMODULES() // for ODA SolidModeler ODRX_DEFINE_STATIC_APPMODULE(OdRecomputeDimBlockModuleName, OdRecomputeDimBlockModule) ODRX_DEFINE_STATIC_APPMODULE(OdThreadPoolModuleName, OdRxThreadPoolService) ODRX_END_STATIC_MODULE_MAP() #endif #include #include /************************************************************************/ /* Main */ /************************************************************************/ #if defined(OD_USE_WMAIN) int wmain(int argc, wchar_t* argv[]) #else int main(int argc, char* argv[]) #endif { ::odSetAssertFunc(MyAssert); int nRes = 0; // Return value for main #if defined(TARGET_OS_MAC) && !defined(__MACH__) argc = ccommand(&argv); #endif setlocale(LC_TIME, ""); // set current user locale (not OD_T("C")), for strftime /**********************************************************************/ /* Create a Services object */ /**********************************************************************/ OdStaticRxObject dbSvcs; OdStaticRxObject ifcSvcs; /**********************************************************************/ /* Display the Product and Version that created the executable */ /**********************************************************************/ odPrintConsoleString(L"\nExIfc2Dwg example developed using %ls ver %ls", ifcSvcs.product().c_str(), ifcSvcs.versionString().c_str()); /**********************************************************************/ /* Parse Command Line inputs */ /**********************************************************************/ const OdString noWaitKeyword = OD_T("-noWait"); bool bInvalidArgs = (argc < 2 || argc > 5); if (bInvalidArgs) { bInvalidArgs = true; nRes = 1; } if (bInvalidArgs) { odPrintConsoleString(L"\n\nusage: ExIfc2Dwg [out filename] [export to model space]"); odPrintConsoleString(L"\n - input .ifc or .ifczip file\n"); odPrintConsoleString(L"\n[out filename] - output .dwg file, optional\n"); odPrintConsoleString(L"\n[export to model space: yes|no ] - allow to extract representations directly in model space, optional, default no\n"); odPrintConsoleString(L"\n[%s] - optional disable \"Press ENTER to continue\" on finish\n", noWaitKeyword.c_str()); return nRes; } #if !defined(_TOOLKIT_IN_DLL_) ODRX_INIT_STATIC_MODULE_MAP(); #endif /**********************************************************************/ /* Initialize ODA SDK */ /**********************************************************************/ odrxInitialize(&dbSvcs); /**********************************************************************/ /* Initialize Drawings SDK */ /**********************************************************************/ odInitialize(&dbSvcs); /**********************************************************************/ /* Initialize IFC SDK */ /**********************************************************************/ // 1. Conversion can be done using just abstract OdIfcExportPtr interface, // so IFC SDK initialization can be skipped here. In this case it is // performed inside Ifc2Dwg module. // 2. ifcSvcs is also optional, if it isn't provided, internal implementation // will be used. // 3. ODA Facet Modeler or ODA Solid Modeler can be used for IFC geometry // processing. The first one is used as default, so for Solid Modeler in static // configuration project should be linked with ${TCOMPONENTS_BREPMODELER_LIB} and // ${IFCBREPMODELER_LIB} (see CMakeLists.txt for ExIfc2Dwg), and appropriate modules // should be registered within ODA linker (see upper lines of this .cpp, // !defined(_TOOLKIT_IN_DLL_) section). odIfcInitialize( false /* No CDA */, true /* Geometry calculation needed */ /* , ModelerType::kBrepModeler */ ); try { OdString ifcInFileName(argv[1]); OdString dwgOutFileName; OdInt16 exportMode = kBuildingElementProxy | kAsSubDMesh; OdBool noWait = false; for (int argIndex = 2; argIndex < argc; ++argIndex) { OdString buf(argv[argIndex]); if (0 == buf.right(4).iCompare(".dwg")) { dwgOutFileName = buf; continue; } if (0 == buf.right(3).iCompare("yes")) { exportMode |= kExportDirectlyToModelSpace; continue; } if (0 == buf.iCompare(noWaitKeyword)) { noWait = true; continue; } } OdIfc2DwgModulePtr pIfc2DwgModule = ::odrxDynamicLinker()->loadApp(OdIfc2DwgModuleName, false); if (!pIfc2DwgModule.isNull()) { OdIfcExportPtr Exporter = pIfc2DwgModule->create(); #ifdef _EXTERNALLY_CONFIGURED_IFC_FILE // This way allows to configure options for IFC file processing OdIfcFilePtr ifcFile = ifcSvcs.readFile(ifcInFileName); ifcFile->getContext().setDrawSpaces(true); #endif Exporter->properties()->putAt(L"OdDbServices", static_cast(&dbSvcs)); Exporter->properties()->putAt(L"IfcServices", static_cast(&ifcSvcs)); // Optional #ifndef _EXTERNALLY_CONFIGURED_IFC_FILE Exporter->properties()->putAt(L"IfcFilePath", OdRxVariantValue(ifcInFileName)); #else Exporter->properties()->putAt(L"IfcFile", ifcFile.get()); #endif //Exporter->properties()->putAt(L"ExportBuildingElementProxy", OdRxVariantValue(true)); Exporter->properties()->putAt(L"ZoomExtents", OdRxVariantValue(true)); Exporter->properties()->putAt(L"ExportMode", OdRxVariantValue(exportMode)); //Exporter->properties()->putAt(L"ExportDirectlyToModelSpace", OdRxVariantValue(exportToModelSpace)); OdPerfTimerWrapper timerWrapper; timerWrapper.getTimer()->start(); // Start conversion OdIfcExport::ExportResult res = Exporter->run(); timerWrapper.getTimer()->stop(); odPrintConsoleString(L"\nIfc2Dwg: ifc conversion time is %d msec", timerWrapper.getTimer()->countedMSec()); OdDbDatabasePtr pDb; if (res == OdIfcExport::success) { odPrintConsoleString(L"\nIfc2Dwg: successful conversion"); pDb = Exporter->properties()->getAt(L"Database"); // Created inside of Ifc2Dwg module if wasn't provided before. OdRxObjectPtr pFile = Exporter->properties()->getAt(L"IfcFile"); OdIfcConnectionMapPtr pMap = Exporter->properties()->getAt(L"IfcConnectionMap"); OdRxObjectPtr pMapAssignedFile = pMap->getIfcFile(); ODA_ASSERT(pFile.get() == pMapAssignedFile.get()); if (!dwgOutFileName.isEmpty()) { odPrintConsoleString(L"\nIfc2Dwg: writing .dwg file %s", dwgOutFileName.c_str()); pDb->writeFile(dwgOutFileName, OdDb::kDwg, OdDb::vAC32); } } else { switch (res) { case OdIfcExport::bad_database: odPrintConsoleString(L"\nIfc2Dwg: bad database\n"); break; case OdIfcExport::bad_file: odPrintConsoleString(L"\nIfc2Dwg: bad ifc file\n"); break; case OdIfcExport::fail: odPrintConsoleString(L"\nIfc2Dwg: unknown conversion error\n"); break; case OdIfcExport::bad_password: odPrintConsoleString(L"\nIfc2Dwg: bad password\n"); break; case OdIfcExport::schema_not_supported: odPrintConsoleString(L"\nIfc2Dwg: schema not supported\n"); break; case OdIfcExport::success: break; case OdIfcExport::file_internal_error: odPrintConsoleString(L"\nIfc2Dwg: file internal error\n"); break; } } } // Unload Ifc2Dwg module pIfc2DwgModule = nullptr; odrxDynamicLinker()->unloadModule(OdIfc2DwgModuleName); if (!noWait) { odPrintConsoleString(L"\nPress ENTER to continue\n"); getchar(); } } catch(OdError& e) { odPrintConsoleString(L"\n\nError: %ls", e.description().c_str()); nRes = -1; } catch(...) { odPrintConsoleString(L"\n\nUnexpected error."); nRes = -1; throw; } /**********************************************************************/ /* Uninitialize IFC SDK */ /**********************************************************************/ odIfcUninitialize(); /**********************************************************************/ /* Uninitialize Drawings SDK */ /**********************************************************************/ odUninitialize(); /**********************************************************************/ /* Uninitialize ODA SDK */ /**********************************************************************/ odrxUninitialize(); return nRes; }