/////////////////////////////////////////////////////////////////////////////// // 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 "RxDynamicModule.h" #include "RxVariantValue.h" #include "RxInit.h" #include "Bim2Visualize.h" #include "TvFilerTimer.h" #include "TvModuleNames.h" #include "TvDatabaseCleaner.h" #include "TvDatabaseUtils.h" #include "BimCommon.h" #include "RxObjectImpl.h" #include "ExBimHostAppServices.h" #include "Database/BmDatabase.h" #include "Database/BmAbstractViewportData.h" #include "Database/Managers/BmDBDrawingInfo.h" #include "Database/Entities/BmDBDrawing.h" #include "BmGsManager.h" #include "Entities/BmDBDrawing.h" #include "Database/Managers/BmViewTable.h" #include "Entities/BmViewport.h" #include "Database/BmGsViewNode.h" #include "ColorMapping.h" #include "../Extensions/ExVisualizeDevice/GsVisualizeVectorizer.h" #include "Bim2VisualizeThreadContext.h" #include "Essential/Entities/BmDBView3d.h" #include "BmTransaction.h" #include "Base/BmParameterSet.h" #include "DynamicLinker.h" /************************************************************************/ /* Replaced forbidden symbols in the name */ /************************************************************************/ OdString correctName(const OdString& str) { OdString res = str; res.replace('<', '_'); res.replace('>', '_'); res.replace('\\', '_'); res.replace('/', '_'); res.replace(':', '_'); res.replace(';', '_'); res.replace('?', '_'); res.replace('*', '_'); res.replace('|', '_'); res.replace('=', '_'); res.replace(L"'", L"_"); return res; } /************************************************************************/ /* Convert BimRv view format name from enum to string */ /************************************************************************/ OdString getNodeNameByViewType(OdBm::ViewType::Enum viewType) { OdString sName; switch (viewType) { case OdBm::ViewType::FloorPlan: { sName = L"Floor Plans"; break; } case OdBm::ViewType::CeilingPlan: { sName = L"Ceiling Plans"; break; } case OdBm::ViewType::Elevation: { sName = L"Elevations"; break; } case OdBm::ViewType::ThreeD: { sName = L"3D views"; break; } case OdBm::ViewType::Schedule: { sName = L"Schedule views"; break; } case OdBm::ViewType::DrawingSheet: { sName = L"Sheets"; break; } case OdBm::ViewType::ProjectBrowser: { sName = L"Project views"; break; } case OdBm::ViewType::Report: { sName = L"Report views"; break; } case OdBm::ViewType::DraftingView: { sName = L"Drafting views"; break; } case OdBm::ViewType::Legend: { sName = L"Legend views"; break; } case OdBm::ViewType::SystemBrowser: { sName = L"MEP browser views"; break; } case OdBm::ViewType::EngineeringPlan: { sName = L"Engineering or Structural views"; break; } case OdBm::ViewType::AreaPlan: { sName = L"Area Plans views"; break; } case OdBm::ViewType::Section: { sName = L"Cross section views"; break; } case OdBm::ViewType::Detail: { sName = L"Detail section views"; break; } case OdBm::ViewType::CostReport: { sName = L"Cost report views"; break; } case OdBm::ViewType::LoadsReport: { sName = L"Loads report views"; break; } case OdBm::ViewType::PressureLossReport: { sName = L"Pressure loss report views"; break; } case OdBm::ViewType::ColumnSchedule: { sName = L"Column schedule views"; break; } case OdBm::ViewType::PanelSchedule: { sName = L"Panel schedule views"; break; } case OdBm::ViewType::Walkthrough: { sName = L"Walk-Through 3D views"; break; } case OdBm::ViewType::Rendering: { sName = L"Rendering views"; break; } case OdBm::ViewType::SystemsAnalysisReport: { sName = L"Systems analysis report views"; break; } case OdBm::ViewType::Internal: { sName = L"Internal views"; break; } default: { sName = L"Unknown Views"; break; } } return sName; } void performZoomExtents(OdBmDBDrawingPtr pDBDrawing) { bool bNeedZoom(true); { OdBmObjectIdArray viewportIds; pDBDrawing->getViewports(viewportIds); if (viewportIds.size() == 0) bNeedZoom = false; else { OdBmViewportPtr pFirstViewport = viewportIds.first().safeOpenObject(); OdBmDBViewPtr pDbView = pFirstViewport->getDbViewId().safeOpenObject(); if (pDbView->isPerspective()) bNeedZoom = false; } } if (bNeedZoom) { OdBmAbstractViewportDataPtr(pDBDrawing)->zoomExtents(pDBDrawing); } return; } void removeTextureAndShadowSupportFromPrefferedVS(OdTvDatabaseId dbId) { //remove texture support from preferable VS for (OdUInt32 i = OdUInt32(OdTvDatabase::kShaded); i <= OdUInt32(OdTvDatabase::kShadedWithIsolines); i++) { OdTvDatabase::PreferableVisualStylesType type = OdTvDatabase::PreferableVisualStylesType(i); OdTvVisualStyleId visStyleId = dbId.openObject()->getPreferableVisualStyle(type); if (!visStyleId.isNull()) { OdTvVisualStylePtr pVisualStyle = visStyleId.openObject(OdTv::kForWrite); if (!pVisualStyle.isNull()) { //not show texture OdInt32 iVal = 0; pVisualStyle->getOption(OdTvVisualStyleOptions::kDisplayStyles, iVal); SETBIT(iVal, OdTvVisualStyleOptions::kTextures, false); pVisualStyle->setOption(OdTvVisualStyleOptions::kDisplayStyles, iVal); //not show shadows pVisualStyle->setOption(OdTvVisualStyleOptions::kDisplayShadow, false); } } } } #if defined(ODA_WINDOWS) #define MAX_PATH_LENGTH 1024 #define SMALL_STRING_SIZE 32 #define LARGE_STRING_SIZE 1024 bool GetRegistryString( HKEY key, const wchar_t *subkey, const wchar_t *name, wchar_t *value, int size) { bool rv = false; HKEY hKey; if( RegOpenKeyExW( key, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { DWORD dwSize( MAX_PATH_LENGTH); unsigned char data[MAX_PATH_LENGTH]; memset (&data, 0x00, MAX_PATH_LENGTH); if( RegQueryValueExW( hKey, name, 0, 0, &data[0], &dwSize) == ERROR_SUCCESS) { rv = true; } else { if ( ERROR_SUCCESS == RegEnumKeyExW(hKey, 0, (LPWSTR)(unsigned short*)&data[0], &dwSize , NULL, NULL, NULL, NULL)) { rv = true; } } if( size < MAX_PATH_LENGTH) { swprintf( value, size, L"%ls\0", (const wchar_t*)data); } else { wcsncpy( value, (wchar_t*)data, size - 1); value[ size-1] = '\0'; } RegCloseKey(hKey); } return rv; } OdString GetRegistryADSKTextureLibraryLocation() { OdString subkey = L"SOFTWARE\\WOW6432Node\\Autodesk\\ADSKTextureLibrary\\1"; TCHAR searchPath[LARGE_STRING_SIZE]; // get the version and concatenate onto subkey if (GetRegistryString(HKEY_LOCAL_MACHINE, (LPCTSTR)subkey, L"LibraryPaths", searchPath, LARGE_STRING_SIZE) != 0) return OdString(searchPath); else { subkey = L"SOFTWARE\\WOW6432Node\\Autodesk\\ADSKTextureLibraryNew\\1"; if (GetRegistryString(HKEY_LOCAL_MACHINE, (LPCTSTR)subkey, L"LibraryPaths", searchPath, LARGE_STRING_SIZE) != 0) { subkey += L"\\"; subkey += searchPath;//it should be year if (GetRegistryString(HKEY_LOCAL_MACHINE, (LPCTSTR)subkey, L"LibraryPaths", searchPath, LARGE_STRING_SIZE) != 0) return OdString(searchPath); } } return L""; } #ifndef ODA_UNIXOS #define pathChar '\\' #define oldPathChar '/' #else #define pathChar '/' #define oldPathChar '\\' #endif OdString OdTvService::findFile( const OdString& file, OdDbBaseDatabase* pBaseDb, FindFileHint hint ) { OdString ffile = OdBmLoaderHostAppServices::findFile(file, pBaseDb, hint); if (!ffile.isEmpty()) return ffile; OdString sPath; if (hint == kTextureMapFile) sPath = GetRegistryADSKTextureLibraryLocation(); if (!sPath.isEmpty()) { ffile = sPath + OdChar(pathChar) + file; ffile = OdBmLoaderHostAppServices::findFile(ffile, pBaseDb, hint); if (!ffile.isEmpty()) return ffile; // some times there is no 1/Mats in path, check it. ffile = sPath + OD_T("1") + OdChar(pathChar) + OD_T("Mats") + OdChar(pathChar) + file; ffile = OdBmLoaderHostAppServices::findFile(ffile, pBaseDb, hint); if (!ffile.isEmpty()) return ffile; } OdInt32 nSlashPos = file.reverseFind(pathChar) + 1; sPath = file.right(file.getLength() - nSlashPos); sPath = OdBmLoaderHostAppServices::findFile(sPath, pBaseDb, hint); return sPath; } #endif //*************************************************************************************// // Implementation of the methods of the inheritants of 'OdTvVisualizeBimFilerDbSource' //*************************************************************************************// class OdTvVisualizeBimFilerSourceFromDb : public OdTvVisualizeBimFilerDbSource { OdDbBaseDatabase *mDatabase; public: OdTvVisualizeBimFilerSourceFromDb(OdDbBaseDatabase* pDatabase) : mDatabase(pDatabase) { initialize(); }; virtual OdBmDatabasePtr getDb() { return mDatabase; }; virtual bool odWasInitialized() const { return false; } virtual OdString getFilename() { OdBmDatabasePtr pDb = mDatabase; if (!pDb.isNull()) { OdString fileName = pDb->getFilename(); if (!fileName.isEmpty()) return fileName; } return OD_T("NoNameBimDatabase"); } protected: void initialize() { OdBmDatabasePtr pDb = mDatabase; if (!pDb.isNull()) { m_filePath = pDb->getFilename(); } }; }; class OdTvVisualizeBimFilerSourceFromStream : public OdTvVisualizeBimFilerDbSource { OdStreamBufPtr mStreamBuf; protected: double m_initTime; public: OdTvVisualizeBimFilerSourceFromStream(OdStreamBufPtr pBuffer, OdTvFilerTimeProfiling* pProfileRes) { initialize(pBuffer, pProfileRes); }; virtual OdBmDatabasePtr getDb() { return m_svcs.readFile(mStreamBuf); }; virtual double getInitTime() const { return m_initTime; } virtual OdString getFilename() { OdString strFileName = mStreamBuf->fileName(); if (strFileName.isEmpty()) return OD_T("NoNameBimDatabase"); //generate name for the stream file return OdTvDatabaseUtils::getFileNameFromPath(strFileName); }; protected: OdTvVisualizeBimFilerSourceFromStream() {}; void initialize(OdStreamBufPtr pBuffer, OdTvFilerTimeProfiling* pProfileRes) { mStreamBuf = pBuffer; OdTvFilerTimer timing(needTimer(pProfileRes)); timing.startTotal(); //load module ::odrxDynamicLinker()->loadApp(OdBmLoaderModuleName, false); timing.endTotal(); m_initTime = timing.getTotalTime(); m_filePath = mStreamBuf->fileName(); }; }; class OdTvVisualizeBimFilerSourceFromFile : public OdTvVisualizeBimFilerDbSource { protected: double m_initTime; public: OdTvVisualizeBimFilerSourceFromFile(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes) { initialize(filePath, pProfileRes); }; virtual OdBmDatabasePtr getDb() { return m_svcs.readFile(m_filePath); }; virtual double getInitTime() const { return m_initTime; } virtual OdString getFilename() { //generate name for the stream file return OdTvDatabaseUtils::getFileNameFromPath(m_filePath); }; protected: OdTvVisualizeBimFilerSourceFromFile() {}; void initialize(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes) { m_filePath = filePath; OdTvFilerTimer timing(needTimer(pProfileRes)); timing.startTotal(); //load module ::odrxDynamicLinker()->loadApp(OdBmLoaderModuleName, false); timing.endTotal(); m_initTime = timing.getTotalTime(); }; }; //***************************************************************************// // 'OdTvVisualizeBimFilerProperties' methods implementation //***************************************************************************// using namespace BIM2Visualize; OdTvVisualizeBimFilerProperties::OdTvVisualizeBimFilerProperties() : m_background(ODRGB(255, 255, 255)), m_flags(kThinLines | kUseCustomDeviation), m_pCallback(NULL), m_pWarningCallback(NULL), m_nViewsImportThreads(4), m_default3DViewDisplayStyle(6), m_default3DViewDetailLevel(2), m_dCustomDeviation(0.005) { m_importRect.xmax = 1; m_importRect.xmin = 0; m_importRect.ymax = 0; m_importRect.ymin = 1; } OdRxDictionaryPtr OdTvVisualizeBimFilerProperties::createObject() { return OdRxObjectImpl::createObject(); } OdTvVisualizeBimFilerProperties::~OdTvVisualizeBimFilerProperties() { } namespace BIM2Visualize { ODRX_DECLARE_PROPERTY(BackgroundColor) ODRX_DECLARE_PROPERTY(DCRect) ODRX_DECLARE_PROPERTY(ObjectNaming) ODRX_DECLARE_PROPERTY(StoreSourceObjects) ODRX_DECLARE_PROPERTY(ThinLines) ODRX_DECLARE_PROPERTY(FeedbackForChooseCallback) ODRX_DECLARE_PROPERTY(FeedbackForWarningCallback) ODRX_DECLARE_PROPERTY(ClearEmptyObjects) ODRX_DECLARE_PROPERTY(AppendTransform) ODRX_DECLARE_PROPERTY(NeedCDATree) ODRX_DECLARE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_DECLARE_PROPERTY(IgnoreEdgesColors) ODRX_DECLARE_PROPERTY(UseSilhouettes) ODRX_DECLARE_PROPERTY(UseMTforViewsImport) ODRX_DECLARE_PROPERTY(ViewsImportThreads) ODRX_DECLARE_PROPERTY(Create3DView) ODRX_DECLARE_PROPERTY(UseAlternativeCDATree) ODRX_DECLARE_PROPERTY(DisableFaceFillPatterns) ODRX_DECLARE_PROPERTY(ClipViewportContent) ODRX_DECLARE_PROPERTY(Default3DViewDisplayStyle) ODRX_DECLARE_PROPERTY(Default3DViewDetailLevel) ODRX_DECLARE_PROPERTY(CalculateIsolines) ODRX_DECLARE_PROPERTY(UseCustomDeviation) ODRX_DECLARE_PROPERTY(CustomDeviation) ODRX_DECLARE_PROPERTY(ForceImportLevelLinesAndBasePoints) ODRX_DECLARE_PROPERTY(CustomCDAModule) ODRX_DECLARE_PROPERTY(StoreCategoryId) ODRX_BEGIN_DYNAMIC_PROPERTY_MAP(OdTvVisualizeBimFilerProperties); ODRX_GENERATE_PROPERTY(BackgroundColor) ODRX_GENERATE_PROPERTY(DCRect) ODRX_GENERATE_PROPERTY(ObjectNaming) ODRX_GENERATE_PROPERTY(StoreSourceObjects) ODRX_GENERATE_PROPERTY(ThinLines) ODRX_GENERATE_PROPERTY(FeedbackForChooseCallback) ODRX_GENERATE_PROPERTY(FeedbackForWarningCallback) ODRX_GENERATE_PROPERTY(ClearEmptyObjects) ODRX_GENERATE_PROPERTY(AppendTransform) ODRX_GENERATE_PROPERTY(NeedCDATree) ODRX_GENERATE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_GENERATE_PROPERTY(IgnoreEdgesColors) ODRX_GENERATE_PROPERTY(UseSilhouettes) ODRX_GENERATE_PROPERTY(UseMTforViewsImport) ODRX_GENERATE_PROPERTY(ViewsImportThreads) ODRX_GENERATE_PROPERTY(Create3DView) ODRX_GENERATE_PROPERTY(UseAlternativeCDATree) ODRX_GENERATE_PROPERTY(DisableFaceFillPatterns) ODRX_GENERATE_PROPERTY( ClipViewportContent ) ODRX_GENERATE_PROPERTY(Default3DViewDisplayStyle) ODRX_GENERATE_PROPERTY(Default3DViewDetailLevel) ODRX_GENERATE_PROPERTY(CalculateIsolines) ODRX_GENERATE_PROPERTY(UseCustomDeviation) ODRX_GENERATE_PROPERTY(CustomDeviation) ODRX_GENERATE_PROPERTY(ForceImportLevelLinesAndBasePoints) ODRX_GENERATE_PROPERTY(CustomCDAModule) ODRX_GENERATE_PROPERTY(StoreCategoryId) ODRX_END_DYNAMIC_PROPERTY_MAP(OdTvVisualizeBimFilerProperties); ODRX_DEFINE_PROPERTY_METHODS(BackgroundColor, OdTvVisualizeBimFilerProperties, getBackgroundColor, setBackgroundColor, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(DCRect, OdTvVisualizeBimFilerProperties, getDCRect, setDCRect, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ObjectNaming, OdTvVisualizeBimFilerProperties, getObjectNaming, setObjectNaming, getBool); ODRX_DEFINE_PROPERTY_METHODS(StoreSourceObjects, OdTvVisualizeBimFilerProperties, getStoreSourceObjects, setStoreSourceObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(ThinLines, OdTvVisualizeBimFilerProperties, getThinLines, setThinLines, getBool); ODRX_DEFINE_PROPERTY_METHODS(FeedbackForChooseCallback, OdTvVisualizeBimFilerProperties, getFeedbackForChooseCallback, setFeedbackForChooseCallback, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(FeedbackForWarningCallback, OdTvVisualizeBimFilerProperties, getFeedbackForWarningCallback, setFeedbackForWarningCallback, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ClearEmptyObjects, OdTvVisualizeBimFilerProperties, getClearEmptyObjects, setClearEmptyObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(AppendTransform, OdTvVisualizeBimFilerProperties, getAppendTransform, setAppendTransform, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(NeedCDATree, OdTvVisualizeBimFilerProperties, getNeedCDATree, setNeedCDATree, getBool); ODRX_DEFINE_PROPERTY_METHODS(NeedCollectPropertiesInCDA, OdTvVisualizeBimFilerProperties, getNeedCollectPropertiesInCDA, setNeedCollectPropertiesInCDA, getBool); ODRX_DEFINE_PROPERTY_METHODS(IgnoreEdgesColors, OdTvVisualizeBimFilerProperties, getIgnoreEdgesColors, setIgnoreEdgesColors, getBool); ODRX_DEFINE_PROPERTY_METHODS(UseSilhouettes, OdTvVisualizeBimFilerProperties, getUseSilhouettes, setUseSilhouettes, getBool); ODRX_DEFINE_PROPERTY_METHODS(UseMTforViewsImport, OdTvVisualizeBimFilerProperties, getUseMTforViewsImport, setUseMTforViewsImport, getBool); ODRX_DEFINE_PROPERTY_METHODS(ViewsImportThreads, OdTvVisualizeBimFilerProperties, getViewsImportThreads, setViewsImportThreads, getUInt64); ODRX_DEFINE_PROPERTY_METHODS(Create3DView, OdTvVisualizeBimFilerProperties, getCreate3DView, setCreate3DView, getBool); ODRX_DEFINE_PROPERTY_METHODS(UseAlternativeCDATree, OdTvVisualizeBimFilerProperties, getUseAlternativeCDATree, setUseAlternativeCDATree, getBool); ODRX_DEFINE_PROPERTY_METHODS(DisableFaceFillPatterns, OdTvVisualizeBimFilerProperties, getDisableFaceFillPatterns, setDisableFaceFillPatterns, getBool); ODRX_DEFINE_PROPERTY_METHODS( ClipViewportContent, OdTvVisualizeBimFilerProperties, getClipViewportContent, setClipViewportContent, getBool ); ODRX_DEFINE_PROPERTY_METHODS(Default3DViewDisplayStyle, OdTvVisualizeBimFilerProperties, getDefault3DViewDisplayStyle, setDefault3DViewDisplayStyle, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(Default3DViewDetailLevel, OdTvVisualizeBimFilerProperties, getDefault3DViewDetailLevel, setDefault3DViewDetailLevel, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(CalculateIsolines, OdTvVisualizeBimFilerProperties, getCalculateIsolines, setCalculateIsolines, getBool); ODRX_DEFINE_PROPERTY_METHODS(UseCustomDeviation, OdTvVisualizeBimFilerProperties, getUseCustomDeviation, setUseCustomDeviation, getBool); ODRX_DEFINE_PROPERTY_METHODS(CustomDeviation, OdTvVisualizeBimFilerProperties, getCustomDeviation, setCustomDeviation, getDouble); ODRX_DEFINE_PROPERTY_METHODS(ForceImportLevelLinesAndBasePoints, OdTvVisualizeBimFilerProperties, getForceImportLevelLinesAndBasePoints, setForceImportLevelLinesAndBasePoints, getBool); ODRX_DEFINE_PROPERTY_METHODS(CustomCDAModule, OdTvVisualizeBimFilerProperties, getCustomCDAModule, setCustomCDAModule, getString); ODRX_DEFINE_PROPERTY_METHODS(StoreCategoryId, OdTvVisualizeBimFilerProperties, getStoreCategoryId, setStoreCategoryId, getBool); } void OdTvVisualizeBimFilerProperties::setBackgroundColor(OdIntPtr ptr) { ODCOLORREF* pColor = (ODCOLORREF*)(ptr); if (!pColor) { ODA_ASSERT(false); } m_background = *pColor; } OdIntPtr OdTvVisualizeBimFilerProperties::getBackgroundColor() const { return (OdIntPtr)(&m_background); } void OdTvVisualizeBimFilerProperties::setFeedbackForChooseCallback(OdIntPtr pCallback) { m_pCallback = (OdTvFeedbackForChooseCallback)pCallback; } OdIntPtr OdTvVisualizeBimFilerProperties::getFeedbackForChooseCallback() const { return (OdIntPtr)m_pCallback; } void OdTvVisualizeBimFilerProperties::setFeedbackForWarningCallback(OdIntPtr pCallback) { m_pWarningCallback = (OdTvFeedbackForWarningCallback)pCallback; } OdIntPtr OdTvVisualizeBimFilerProperties::getFeedbackForWarningCallback() const { return (OdIntPtr)m_pWarningCallback; } void OdTvVisualizeBimFilerProperties::setDCRect(OdIntPtr rect) { OdTvDCRect* pRect = (OdTvDCRect*)(rect); if (!pRect) { ODA_ASSERT(false); } m_importRect = *pRect; } OdIntPtr OdTvVisualizeBimFilerProperties::getDCRect() const { return (OdIntPtr)(&m_importRect); } void OdTvVisualizeBimFilerProperties::setAppendTransform(OdIntPtr pTransform) { const OdTvMatrix* pAppendTransform = (const OdTvMatrix*)(pTransform); if (pAppendTransform) { m_appendTransform = *pAppendTransform; } else { m_appendTransform = OdTvMatrix::kIdentity; } } OdIntPtr OdTvVisualizeBimFilerProperties::getAppendTransform() const { return (OdIntPtr)(&m_appendTransform); } //***************************************************************************// // 'OdTvVisualizeBimFiler' methods implementation //***************************************************************************// OdTvVisualizeBimFiler::OdTvVisualizeBimFiler() : m_properties(OdTvVisualizeBimFilerProperties::createObject()), m_moduleNameForCDA(L"TB_CDAProperties") { m_bForeignDatabase = false; } OdTvDatabaseId OdTvVisualizeBimFiler::loadFrom(OdDbBaseDatabase *pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeBimFilerSourceFromDb dl(pDatabase); if (!checkFileVersion(&dl, rc)) return OdTvDatabaseId(); m_bForeignDatabase = true; if (m_properties->getUseMTforViewsImport()) return loadFromMT(&dl, pProfileRes, rc); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeBimFiler::loadFrom(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeBimFilerSourceFromStream dl(pBuffer, pProfileRes); if (!checkFileVersion(&dl, rc)) return OdTvDatabaseId(); if (m_properties->getUseMTforViewsImport()) return loadFromMT(&dl, pProfileRes, rc); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeBimFiler::loadFrom(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeBimFilerSourceFromFile dl(filePath, pProfileRes); if (!checkFileVersion(&dl, rc)) return OdTvDatabaseId(); if (m_properties->getUseMTforViewsImport()) return loadFromMT(&dl, pProfileRes, rc); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeBimFiler::loadFromMT(OdTvVisualizeBimFilerDbSource *pBimDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { ODCOLORREF background = *((ODCOLORREF*)m_properties->getBackgroundColor()); OdTvDatabaseId tvDbId; if (rc) *rc = tvOk; //check that time profiling is need bool bUseTimeProfiling = needTimer(pProfileRes); double dbReadingTime = 0; double tvDbExternalTiming = 0; double tvDbInternalTiming = 0.; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); try { timing.startMisc(); OdBmDatabasePtr pDb = pBimDatabaseSource->getDb(); // Create 3D view, if it's absent if (!pDb.isNull()) { if (m_properties->getCreate3DView()) create3DView(pDb.get()); } timing.endMisc(); dbReadingTime = timing.getMiscTime() + pBimDatabaseSource->getInitTime(); if (!pDb.isNull()) { // Get chosen views OdTvFilerFeedbackForChooseObject filerFeedbackForChooseObject(OD_T("Choose views for import")); bool bCanceled = false; getChosenViews(pDb, filerFeedbackForChooseObject, bCanceled); if (bCanceled) { if (rc) *rc = tvFilerEmptyInternalDatabase; //unload Bim modules (try to emulate the OdUninitialized for BIM) //here we will unload all including Visualize device pDb = NULL; odrxDynamicLinker()->unloadUnreferenced(); return tvDbId; } timing.startVectorizing(); OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdTvVisualizeDeviceModuleName, false); if (pGs.isNull()) { if (rc) *rc = tvMissingVisualizeDeviceModule; return tvDbId; } //create empty tv database. OdTvFactoryId tvFactoryId = odTvGetFactory(); tvDbId = tvFactoryId.createDatabase(); // save filename to database user data OdTvDatabaseUtils::writeFileNameToTvDatabase(tvDbId, pBimDatabaseSource->getFilename()); OdBmDBDrawingInfoPtr pDBDrawingInfo = pDb->getAppInfo(OdBm::ManagerType::DBDrawingInfo); OdTvBim2VisualizeVecorizationThreadContextPtr pThreadContext = OdTvBim2VisualizeVecorizationThreadContext::createObject(); //run over all DBDrawings OdMutexPtr databaseAccessMutex; OdMutexPtr setupDBDrawingViewsMutex; // VIS-1826: temporary solution OdGsDevicePtr pEmptyDevice = pGs->createDevice(); OdRxDictionaryPtr pEmptyProperties = pEmptyDevice->properties(); if (pEmptyProperties->has(OD_T("DisplayViaGLES2"))) pEmptyProperties->putAt(OD_T("DisplayViaGLES2"), OdRxVariantValue(false)); pEmptyDevice->update(); OdUInt32 nUniqNumber = 0; OdBmUserParamIteratorPtr drawingIterator = pDBDrawingInfo->createIteratorDBDrawings(true); while (!drawingIterator->done()) { // Get drawing from iterator and check if it was chosen for import OdBmObjectId bmObjectId = drawingIterator->object(); drawingIterator->next(); //get name OdBmDBDrawingPtr pDBDrawing = bmObjectId.openObject(); OdString strDrawindName = getNodeNameByViewType(pDBDrawing->getBaseViewType()) + OD_T("\\") + pDBDrawing->getName(); OdString strUniqueDrawingName = pDBDrawing->getUniqueName(); if (!filerFeedbackForChooseObject.find(OdTvFilerFeedbackItemForChoose(strDrawindName, strUniqueDrawingName, true))) continue; OdTvBim2VisualizeVecorizationContext* pContextForThread = new OdTvBim2VisualizeVecorizationContext(pGs, tvDbId, pDb, background, bmObjectId, m_properties, databaseAccessMutex.get(), setupDBDrawingViewsMutex.get(), m_properties->getViewsImportThreads(), &nUniqNumber ); pThreadContext->vectorizeDevice(pContextForThread); } //eo while... pThreadContext->wait(); timing.startMisc(); if (tvDbId.isValid() && m_properties->getClearEmptyObjects()) OdTvDatabaseCleaner::cleanTvDatabase(tvDbId); // Add cattegoryID to user data if (m_properties->getStoreCategoryId() && m_properties->getStoreSourceObjects()) // We can not get categoryID without stored handles const_cast(this)->storeCategoryId(tvDbId, pDb); timing.endMisc(); tvDbExternalTiming += timing.getMiscTime(); timing.endVectorizing(); } else { if (rc) *rc = tvFilerEmptyInternalDatabase; } if (m_properties->getNeedCDATree()) { timing.startMisc(); OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); if (!pTvDb.isNull()) createCommonDataAccessTree(pTvDb, pDb, pBimDatabaseSource->getFilename() + OD_T(".rvt")); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); } //Set units OdTvModelsIteratorPtr modelsIterPtr = tvDbId.openObject()->getModelsIterator(); while (!modelsIterPtr->done()) { OdTvModelPtr pModel = modelsIterPtr->getModel().openObject(); if (!pModel.isNull()) pModel->setUnits(OdTv::kFeet); modelsIterPtr->step(); } // get active device for (OdTvDevicesIteratorPtr pIt = tvDbId.openObject()->getDevicesIterator(); !pIt->done(); pIt->step()) { OdTvGsDeviceId devId = pIt->getDevice(); // get active view if (devId.isNull()) continue; OdTvGsDevicePtr pDev = devId.openObject(); for (int i = 0; i < pDev->numViews(); i++) { OdTvGsViewId viewId = pDev->viewAt(i); if (!viewId.isNull()) { // get visual style OdTvVisualStyleId visId = viewId.openObject()->getVisualStyle(); if (!visId.isNull()) { OdTvVisualStylePtr pVis = visId.openObject(OdTv::kForWrite); OdInt32 flag; pVis->getOption(OdTvVisualStyleOptions::kEdgeStyles, flag); OdInt32 nVal; pVis->getOption(OdTvVisualStyleOptions::kFaceLightingModel, nVal); if (nVal != (OdInt32)OdTvVisualStyleOptions::kInvisible) // for more correct work of condition while need to calcualte edges normals { if (m_properties->getUseSilhouettes() != GETBIT(flag, OdTvVisualStyleOptions::kSilhouette)) { SETBIT(flag, OdTvVisualStyleOptions::kSilhouette, m_properties->getUseSilhouettes()); pVis->setOption(OdTvVisualStyleOptions::kEdgeStyles, flag); } } } } } } //create preferable Visual style for isolines OdTvDatabaseUtils::createAndApplyPreferableVS(tvDbId, false, false); OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); //remove texture support removeTextureAndShadowSupportFromPrefferedVS(tvDbId); } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //unload Bim modules (try to emulate the OdUninitialized for BIM) //here we will unload all including Visualize device if (!m_bForeignDatabase) odrxDynamicLinker()->unloadUnreferenced(); else { odrxDynamicLinker()->unloadModule(OdTvVisualizeDeviceModuleName); } timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64(dbReadingTime * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((tvDbInternalTiming + tvDbExternalTiming) * 1000.)); #endif } return tvDbId; } OdTvDatabaseId OdTvVisualizeBimFiler::generate(OdTvFilerTimeProfiling* pProfileRes) const { OdTvDatabaseId tvDbId; // does nothing return tvDbId; } OdTvModelId OdTvVisualizeBimFiler::appendFrom(const OdTvDatabaseId& databaseId, OdDbBaseDatabase *pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeBimFilerSourceFromDb dl(pDatabase); if (!checkFileVersion(&dl, rc)) return OdTvModelId(); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizeBimFiler::appendFrom(const OdTvDatabaseId& databaseId, OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeBimFilerSourceFromStream dl(pBuffer, pProfileRes); if (!checkFileVersion(&dl, rc)) return OdTvModelId(); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizeBimFiler::appendFrom(const OdTvDatabaseId& databaseId, const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeBimFilerSourceFromFile dl(filePath, pProfileRes); if (!checkFileVersion(&dl, rc)) return OdTvModelId(); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeBimFiler::loadFrom(OdTvVisualizeBimFilerDbSource *pBimDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { ODCOLORREF background = *((ODCOLORREF*)m_properties->getBackgroundColor()); OdTvDatabaseId tvDbId; if (rc) *rc = tvOk; //check that time profiling is need bool bUseTimeProfiling = needTimer(pProfileRes); double dbReadingTime = 0; double tvDbExternalTiming = 0; double tvDbInternalTiming = 0.; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); try { timing.startMisc(); OdBmDatabasePtr pDb = pBimDatabaseSource->getDb(); // Create 3D view, if it's absent if (!pDb.isNull()) { if (m_properties->getCreate3DView()) create3DView(pDb.get()); } timing.endMisc(); dbReadingTime = timing.getMiscTime() + pBimDatabaseSource->getInitTime(); if (!pDb.isNull()) { // Get chosen views OdTvFilerFeedbackForChooseObject filerFeedbackForChooseObject(OD_T("Choose views for import")); bool bCanceled = false; getChosenViews(pDb, filerFeedbackForChooseObject, bCanceled); if (bCanceled) { if (rc) *rc = tvFilerEmptyInternalDatabase; //unload Bim modules (try to emulate the OdUninitialized for BIM) //here we will unload all including Visualize device pDb = NULL; if( !m_bForeignDatabase ) odrxDynamicLinker()->unloadUnreferenced(); return tvDbId; } timing.startVectorizing(); OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdTvVisualizeDeviceModuleName, false); if (pGs.isNull()) { if (rc) *rc = tvMissingVisualizeDeviceModule; return tvDbId; } //create empty tv database. OdTvFactoryId tvFactoryId = odTvGetFactory(); tvDbId = tvFactoryId.createDatabase(); // save filename to database user data OdTvDatabaseUtils::writeFileNameToTvDatabase(tvDbId, pBimDatabaseSource->getFilename()); OdBmDBDrawingInfoPtr pDBDrawingInfo = pDb->getAppInfo(OdBm::ManagerType::DBDrawingInfo); //run over all DBDrawings OdBmUserParamIteratorPtr drawingIterator = pDBDrawingInfo->createIteratorDBDrawings(true); unsigned int tvDeviceCount = 0; while (!drawingIterator->done()) { // Get drawing from iterator and check if it was chosen for import OdBmObjectId bmObjectId = drawingIterator->object(); drawingIterator->next(); //get name OdBmDBDrawingPtr pDBDrawing = bmObjectId.openObject(); OdDbBaseDatabasePEPtr pDbPE( pDb ); pDbPE->setCurrentLayout( pDb, pDBDrawing->getUniqueName() ); OdString strDrawindName = getNodeNameByViewType(pDBDrawing->getBaseViewType()) + OD_T("\\") + pDBDrawing->getName(); OdString strUniqueDrawingName = pDBDrawing->getUniqueName(); if (!filerFeedbackForChooseObject.find(OdTvFilerFeedbackItemForChoose(strDrawindName, strUniqueDrawingName, true))) continue; //create Ex Visualize device OdGsDevicePtr pDevice = pGs->createDevice(); //create geometry notifier OdTvBimGeomertyNotifier geometryNotifier; // setup ExVisualize device properties OdRxDictionaryPtr pProperties = pDevice->properties(); OdTvGsDeviceId activeTvDeviceId = OdTvGsDeviceId(); OdString tvModelName = OdString(); setupExVisualizeDeviceProp(pProperties, tvDbId, bUseTimeProfiling, tvModelName, m_properties, activeTvDeviceId , (int)pDBDrawing->getBaseViewType() == (int)OdBm::ViewType::ThreeD); if (pProperties->has(OD_T("GeometryNotifier"))) { pProperties->putAt(OD_T("GeometryNotifier"), OdRxVariantValue((OdIntPtr)(&geometryNotifier))); } //setup bim context OdGiDefaultContextPtr pBmContext = pDbPE->createGiContext(pDb); pBmContext->enableGsModel(true); //set the palette const ODCOLORREF* palette = odcmAcadPalette(background); OdArray > pPalCpy; pPalCpy.insert(pPalCpy.begin(), palette, palette + 256); pDevice->setLogicalPalette(pPalCpy.asArrayPtr(), 256); //set the background pDevice->setBackgroundColor(background); pBmContext->setPaletteBackground(background); //setup layout OdGsBmDBDrawingHelperPtr pDrawingHelper = OdGsBmDBDrawingHelper::setupDBDrawingViews(bmObjectId, pDevice, pBmContext); //set thin mode pDrawingHelper->setThinLinesMode(m_properties->getThinLines()); //SEA Here we already create GS views, so we can check ClipViewportContent OdArray< OdGsView* > clippedViews; if( m_properties->getClipViewportContent() ) { collectViewportViews( bmObjectId, clippedViews ); if( pProperties->has( OD_T( "ClippedByViewportViewList" ) ) && pProperties->has( OD_T( "ClippedByViewportViewCount" ) ) ) { pProperties->putAt( OD_T( "ClippedByViewportViewList" ), OdRxVariantValue( (OdIntPtr)( clippedViews.asArrayPtr() ) ) ); pProperties->putAt( OD_T( "ClippedByViewportViewCount" ), OdRxVariantValue( (OdInt32)( clippedViews.size() ) ) ); } } //call onsize OdTvDCRect* pRect = (OdTvDCRect*)m_properties->getDCRect(); if (pRect && (pRect->xmax > 0 || pRect->xmin > 0 || pRect->ymax > 0 || pRect->ymin > 0)) { OdGsDCRect gsRect(pRect->xmin, pRect->xmax, pRect->ymin, pRect->ymax); pDrawingHelper->onSize(gsRect); } //Guys from BimRv team in April remove zoomExtens from OdGsBmDBDrawingHelper::setupDBDrawingViews. //But it is need for Visualize import, thus we have added it here performZoomExtents(pDBDrawing); std::set< OdTvModelId > existModels; getExistModels( tvDbId, existModels ); // Unhide elements if (pDBDrawing->getBaseViewType() == OdBm::ViewType::ThreeD && m_properties->getForceImportLevelLinesAndBasePoints()) forceImportLevelLinesAndBasePoints(pDrawingHelper->DBDrawingId(), pDb); //call update (vectorization) pDrawingHelper->update(); // Process geometry notifier for (auto i : geometryNotifier.getIds()) { if (i.getType() == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = i.openObject(OdTv::kForWrite); pEntity->setNeedCheckShellsTopology(true); } } //setup connections between views in device and append non db lights if (tvDbId.isValid()) { timing.startMisc(); OdTvDevicesIteratorPtr pDevicesIterator = tvDbId.openObject()->getDevicesIterator(); if (!pDevicesIterator.isNull()) // here we have O(n^2) but it us not a problem { unsigned int nCount = 0; while (!pDevicesIterator->done()) { OdTvGsDeviceId tvDeviceId = pDevicesIterator->getDevice(); if (nCount == tvDeviceCount) { { OdTvGsDevicePtr pTvDevice = tvDeviceId.openObject(OdTv::kForWrite); if (!pTvDevice.isNull()) pTvDevice->setAllowShareable(false); } setupConnectionsBetweenTvViews(bmObjectId, pDevice, tvDeviceId, &existModels ); resetViewsModelsNames(tvDeviceId); break; } nCount++; pDevicesIterator->step(); } } timing.endMisc(); tvDbExternalTiming += timing.getMiscTime(); } //set need call isolines calculation if( (int)pDBDrawing->getBaseViewType() == (int)OdBm::ViewType::ThreeD ) { setCalculateIsolonesInShells( tvDbId, existModels ); } geometryNotifier.clearIds(); tvDeviceCount++; if (bUseTimeProfiling) { #if !defined(__APPLE__) if (pProperties->has(OD_T("TvElapsedTime"))) { tvDbInternalTiming += OdRxVariantValue(pProperties->getAt(OD_T("TvElapsedTime")).get())->getDouble(); } #endif } //SEA we have to unload device in specific order, so pDrawingHelper destructor releases GS nodes pProperties.release(); pDevice.release(); pDrawingHelper.release(); } //eo while... timing.startMisc(); //create preferable Visual style for isolines OdTvDatabaseUtils::createAndApplyPreferableVS(tvDbId, false, false); OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); //remove texture support removeTextureAndShadowSupportFromPrefferedVS(tvDbId); if (tvDbId.isValid() && m_properties->getClearEmptyObjects()) OdTvDatabaseCleaner::cleanTvDatabase(tvDbId); // Add cattegoryID to user data if (m_properties->getStoreCategoryId() && m_properties->getStoreSourceObjects()) // We can not get categoryID without stored handles const_cast(this)->storeCategoryId(tvDbId, pDb); timing.endMisc(); tvDbExternalTiming += timing.getMiscTime(); timing.endVectorizing(); } else { if (rc) *rc = tvFilerEmptyInternalDatabase; } if (m_properties->getNeedCDATree()) { timing.startMisc(); OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); if (!pTvDb.isNull()) createCommonDataAccessTree(pTvDb, pDb, pBimDatabaseSource->getFilename() + OD_T(".rvt")); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); } //Set units OdTvModelsIteratorPtr modelsIterPtr = tvDbId.openObject()->getModelsIterator(); while (!modelsIterPtr->done()) { OdTvModelPtr pModel = modelsIterPtr->getModel().openObject(); if (!pModel.isNull()) { pModel->setUnits(OdTv::kFeet); } modelsIterPtr->step(); } // get active device for (OdTvDevicesIteratorPtr pIt = tvDbId.openObject()->getDevicesIterator(); !pIt->done(); pIt->step()) { OdTvGsDeviceId devId = pIt->getDevice(); // get active view if (devId.isNull()) continue; OdTvGsDevicePtr pDev = devId.openObject(); for (int i = 0; i < pDev->numViews(); i++) { OdTvGsViewId viewId = pDev->viewAt(i); if (!viewId.isNull()) { // get visual style OdTvVisualStyleId visId = viewId.openObject()->getVisualStyle(); if (!visId.isNull()) { OdTvVisualStylePtr pVis = visId.openObject(OdTv::kForWrite); OdInt32 flag; pVis->getOption(OdTvVisualStyleOptions::kEdgeStyles, flag); OdInt32 nVal; pVis->getOption(OdTvVisualStyleOptions::kFaceLightingModel, nVal); if (nVal != (OdInt32)OdTvVisualStyleOptions::kInvisible) // for more correct work of condition while need to calcualte edges normals { if (m_properties->getUseSilhouettes() != GETBIT(flag, OdTvVisualStyleOptions::kSilhouette)) { SETBIT(flag, OdTvVisualStyleOptions::kSilhouette, m_properties->getUseSilhouettes()); pVis->setOption(OdTvVisualStyleOptions::kEdgeStyles, flag); } } } } } } } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //unload Bim modules (try to emulate the OdUninitialized for BIM) //here we will unload all including Visualize device //SEA if loadFrom does not load database by itself it is dangerous to unload unreferenced. if( !m_bForeignDatabase ) odrxDynamicLinker()->unloadUnreferenced(); else { odrxDynamicLinker()->unloadModule( OdTvVisualizeDeviceModuleName ); } timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64(dbReadingTime * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((tvDbInternalTiming + tvDbExternalTiming) * 1000.)); #endif } return tvDbId; } OdTvModelId OdTvVisualizeBimFiler::appendFrom(const OdTvDatabaseId& databaseId, OdTvVisualizeBimFilerDbSource *pBimDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvModelId tvModelId; if (rc) *rc = tvOk; //check that we are in the real append mode OdTvGsDeviceId activeTvGsDeviceId; { OdTvDatabasePtr pTvDb = databaseId.openObject(); OdTvDevicesIteratorPtr devicesIteratorPtr = pTvDb->getDevicesIterator(); while (!devicesIteratorPtr->done()) { activeTvGsDeviceId = devicesIteratorPtr->getDevice(); if (activeTvGsDeviceId.openObject()->getActive()) break; devicesIteratorPtr->step(); } } //get palette, background and device size ODCOLORREF background = ODRGB(0, 0, 0); OdTvDCRect rect(0, 0, 0, 0); OdArray > pPalCpy; bool bDeviceExist = false; if (!activeTvGsDeviceId.isNull()) { bDeviceExist = true; OdTvGsDevicePtr pTvDevice = activeTvGsDeviceId.openObject(); background = pTvDevice->getBackgroundColor(); pTvDevice->getSize(rect); int nColors; const ODCOLORREF* pPalette = pTvDevice->getLogicalPalette(nColors); if (nColors >= 256) pPalCpy.insert(pPalCpy.begin(), pPalette, pPalette + 256); else { pPalCpy.insert(pPalCpy.begin(), pPalette, pPalette + nColors); pPalCpy.insert(pPalCpy.begin() + nColors, 256 - nColors, ODRGB(0, 0, 0)); } } else { background = *((ODCOLORREF*)m_properties->getBackgroundColor()); OdTvDCRect* pRect = (OdTvDCRect*)m_properties->getDCRect(); if (pRect) rect = *pRect; const ODCOLORREF* palette = odcmAcadPalette(background); // black background pPalCpy.insert(pPalCpy.begin(), palette, palette + 256); } //collcet current models and blocks std::set foreignViews; std::set foreignModels; std::set foreignBlocks; OdTvDatabaseUtils::collectViewsModelsAndBlocks(databaseId, foreignViews, foreignModels, foreignBlocks); //check that time profiling is need bool bUseTimeProfiling = false; if (pProfileRes) bUseTimeProfiling = true; double dbReadingTime = 0; double tvDbExternalTiming = 0; double tvDbInternalTiming = 0.; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); //get file name OdString fileName = pBimDatabaseSource->getFilename(); try { timing.startMisc(); OdBmDatabasePtr pDb = pBimDatabaseSource->getDb(); // Create 3D view, if it's absent (for the append we should do it always) if (!pDb.isNull()) create3DView(pDb.get()); timing.endMisc(); dbReadingTime = timing.getMiscTime() + pBimDatabaseSource->getInitTime(); if (!pDb.isNull()) { timing.startVectorizing(); OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdTvVisualizeDeviceModuleName, false); if (pGs.isNull()) { if (rc) *rc = tvMissingVisualizeDeviceModule; return tvModelId; } // save filename to database user data OdTvDatabaseUtils::writeFileNameToTvDatabase(databaseId, fileName); OdBmDBDrawingInfoPtr pDBDrawingInfo = pDb->getAppInfo(OdBm::ManagerType::DBDrawingInfo); // Get 3d drawing OdBmObjectId bmObjectId; OdBmDBDrawingPtr pDBDrawing; OdBmUserParamIteratorPtr drawingIterator = pDBDrawingInfo->createIteratorDBDrawings(true); while (!drawingIterator->done()) { bmObjectId = drawingIterator->object(); pDBDrawing = bmObjectId.openObject(); if (pDBDrawing->getName() == OD_T("{3D}")) break; drawingIterator->next(); } if (bmObjectId.isNull()) { if (rc) *rc = tvInternal; return tvModelId; } // Generate model name OdString modelName = OdTvDatabaseUtils::generateModelName(databaseId, fileName); //create ExVisualize device OdGsDevicePtr pDevice = pGs->createDevice(); //create geometry notifier OdTvBimGeomertyNotifier geometryNotifier; // setup ExVisualize device properties OdRxDictionaryPtr pProperties = pDevice->properties(); setupExVisualizeDeviceProp(pProperties, databaseId, bUseTimeProfiling, modelName, m_properties, activeTvGsDeviceId, (int)pDBDrawing->getBaseViewType() == (int)OdBm::ViewType::ThreeD); if (pProperties->has(OD_T("GeometryNotifier"))) { pProperties->putAt(OD_T("GeometryNotifier"), OdRxVariantValue((OdIntPtr)(&geometryNotifier))); } //we don't need to setup extents inside appendFrom since we can have additional units transform matrix here if (pProperties->has(OD_T("DisableSettingExtents"))) pProperties->putAt(OD_T("DisableSettingExtents"), OdRxVariantValue(true)); //create BIM context OdDbBaseDatabasePEPtr pDbPE(pDb); OdGiDefaultContextPtr pBmContext = pDbPE->createGiContext(pDb); pBmContext->enableGsModel(true); //setup palette, background and device size //a.palette pDevice->setLogicalPalette(pPalCpy.asArrayPtr(), 256); //b. background pDevice->setBackgroundColor(background); pBmContext->setPaletteBackground(background); //setup layout OdGsBmDBDrawingHelperPtr pDrawingHelper = OdGsBmDBDrawingHelper::setupDBDrawingViews(bmObjectId, pDevice, pBmContext); //c. thin line mode pDrawingHelper->setThinLinesMode(m_properties->getThinLines()); //d. call onsize if (rect.xmax > 0 || rect.xmin > 0 || rect.ymax > 0 || rect.ymin > 0) { OdGsDCRect gsRect(rect.xmin, rect.xmax, rect.ymin, rect.ymax); pDrawingHelper->onSize(gsRect); } //Guys from BimRv team in April remove zoomExtens from OdGsBmDBDrawingHelper::setupDBDrawingViews. //But it is need for Visualize import, thus we have added it here performZoomExtents(pDBDrawing); //SEA Here we already create GS views, so we can check ClipViewportContent OdArray< OdGsView* > clippedViews; if( m_properties->getClipViewportContent() ) { collectViewportViews( bmObjectId, clippedViews ); if( pProperties->has( OD_T( "ClippedByViewportViewList" ) ) && pProperties->has( OD_T( "ClippedByViewportViewCount" ) ) ) { pProperties->putAt( OD_T( "ClippedByViewportViewList" ), OdRxVariantValue( (OdIntPtr)( clippedViews.asArrayPtr() ) ) ); pProperties->putAt( OD_T( "ClippedByViewportViewCount" ), OdRxVariantValue( (OdInt32)( clippedViews.size() ) ) ); } } // Unhide elements if (pDBDrawing->getBaseViewType() == OdBm::ViewType::ThreeD && m_properties->getForceImportLevelLinesAndBasePoints()) forceImportLevelLinesAndBasePoints(pDrawingHelper->DBDrawingId(), pDb); std::set< OdTvModelId > existModels; getExistModels( databaseId, existModels ); //call update (vectorization) pDrawingHelper->update(); // Process geometry notifier for (auto i : geometryNotifier.getIds()) { if (i.getType() == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = i.openObject(OdTv::kForWrite); pEntity->setNeedCheckShellsTopology(true); } } if (bUseTimeProfiling) { #if !defined(__APPLE__) if (pProperties->has(OD_T("TvElapsedTime"))) { tvDbInternalTiming = OdRxVariantValue(pProperties->getAt(OD_T("TvElapsedTime")).get())->getDouble(); } #endif } if (databaseId.isValid()) { timing.startMisc(); //get active device if need OdTvDatabaseId& tvDvId = const_cast(databaseId); if (activeTvGsDeviceId.isNull()) { for (OdTvDevicesIteratorPtr pIt = tvDvId.openObject()->getDevicesIterator(); !pIt->done(); pIt->step()) { OdTvGsDeviceId devId = pIt->getDevice(); if (devId.isNull()) continue; else { activeTvGsDeviceId = devId; setupConnectionsBetweenTvViews(bmObjectId, pDevice, activeTvGsDeviceId, &existModels ); break; } } } //set need call isolines calculation if( (int)pDBDrawing->getBaseViewType() == (int)OdBm::ViewType::ThreeD ) { setCalculateIsolonesInShells( databaseId, existModels ); } geometryNotifier.clearIds(); //clear empty objects (always) OdTvDatabaseCleaner::cleanTvDatabaseForAppend(tvDvId, foreignViews, foreignModels, foreignBlocks); //rename and get model OdString newModelName = resetModelNameForAppend(activeTvGsDeviceId, fileName, foreignModels); { OdTvDatabasePtr pTvDb = databaseId.openObject(); tvModelId = pTvDb->findModel(newModelName); } //apply transform if need OdTvMatrix* pTransfrom = (OdTvMatrix*)m_properties->getAppendTransform(); if (pTransfrom) { OdTvDatabaseId& tvDvId = const_cast(databaseId); OdTvDatabaseUtils::applyTransformToTheModel(tvDvId, newModelName, *pTransfrom); } //apply units if (!tvModelId.isNull()) { OdTvModelPtr pModel = tvModelId.openObject(OdTv::kForWrite); if (!pModel.isNull()) pModel->setUnits(OdTv::kFeet); } timing.endMisc(); tvDbExternalTiming = timing.getMiscTime(); // get active device if(!bDeviceExist) { for (OdTvDevicesIteratorPtr pIt = tvDvId.openObject()->getDevicesIterator(); !pIt->done(); pIt->step()) { OdTvGsDeviceId devId = pIt->getDevice(); // get active view if (devId.isNull()) continue; OdTvGsDevicePtr pDev = devId.openObject(); for (int i = 0; i < pDev->numViews(); i++) { OdTvGsViewId viewId = pDev->viewAt(i); if (!viewId.isNull()) { // get visual style OdTvVisualStyleId visId = viewId.openObject()->getVisualStyle(); if (!visId.isNull()) { OdTvVisualStylePtr pVis = visId.openObject(OdTv::kForWrite); OdInt32 flag; pVis->getOption(OdTvVisualStyleOptions::kEdgeStyles, flag); OdInt32 nVal; pVis->getOption(OdTvVisualStyleOptions::kFaceLightingModel, nVal); if (nVal != (OdInt32)OdTvVisualStyleOptions::kInvisible) // for more correct work of condition while need to calcualte edges normals { if (m_properties->getUseSilhouettes() != GETBIT(flag, OdTvVisualStyleOptions::kSilhouette)) { SETBIT(flag, OdTvVisualStyleOptions::kSilhouette, m_properties->getUseSilhouettes()); pVis->setOption(OdTvVisualStyleOptions::kEdgeStyles, flag); } } } } } } } { OdTvDatabaseId& tvDbId = const_cast(databaseId); if (activeTvGsDeviceId.isNull()) { //create preferable Visual style for isolines OdTvDatabaseUtils::createAndApplyPreferableVS(tvDbId, false, false); OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); //remove texture support removeTextureAndShadowSupportFromPrefferedVS(tvDbId); } else { if (tvDbId.openObject()->getPreferableVisualStyle(OdTvDatabase::kCustom).isNull()) OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); } } // Add cattegoryID to user data if (m_properties->getStoreCategoryId() && m_properties->getStoreSourceObjects()) // We can not get categoryID without stored handles const_cast(this)->storeCategoryId(databaseId, pDb); } timing.endVectorizing(); } else { if (rc) *rc = tvFilerEmptyInternalDatabase; } } catch (...) { if (rc) *rc = tvInternal; timing.endMisc(); timing.endVectorizing(); } //unload Bim modules (try to emulate the OdUninitialized for BIM) //here we will unload all including Visualize device odrxDynamicLinker()->unloadUnreferenced(); timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64(dbReadingTime * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((tvDbInternalTiming + tvDbExternalTiming) * 1000.)); #endif } return tvModelId; } OdTvResult OdTvVisualizeBimFiler::startActionsWithNativeProperties(const OdString& sFilePath, bool bIsPartial) { if (!m_pDatabaseForNativeProp.isNull() && m_pDatabaseForNativeProp->getFilename() != sFilePath) m_pDatabaseForNativeProp.release(); else if (!m_pDatabaseForNativeProp.isNull()) return tvOk; OdTvResult rc = tvOk; if( m_pFilerPtr.isNull() ) { m_pFilerPtr = new OdTvVisualizeBimFilerSourceFromFile( sFilePath, NULL ); } OdTvVisualizeBimFilerSourceFromFile* pFiler = (OdTvVisualizeBimFilerSourceFromFile*)( m_pFilerPtr.get() );// dl(sFilePath, NULL); if (m_pRxPropertiesModule.isNull()) m_pRxPropertiesModule = ::odrxDynamicLinker()->loadModule(L"RxProperties"); OdString strCustomCDAModule = m_properties->getCustomCDAModule(); bool bUseCustomCDA = false; if (!strCustomCDAModule.isEmpty()) { if (m_pBmPropertiesModule.isNull()) { m_pBmPropertiesModule = ::odrxDynamicLinker()->loadModule(strCustomCDAModule); if (!m_pBmPropertiesModule.isNull()) { m_moduleNameForCDA = strCustomCDAModule; bUseCustomCDA = true; } } } if (!bUseCustomCDA) { m_moduleNameForCDA = m_properties->getUseAlternativeCDATree() ? OdString("TB_CDA3DViewTree") : OdString("TB_CDAProperties"); if (m_pBmPropertiesModule.isNull()) m_pBmPropertiesModule = ::odrxDynamicLinker()->loadModule(m_moduleNameForCDA); } try { m_pDatabaseForNativeProp = pFiler->getDb(); if( m_properties->getCreate3DView() ) { create3DView( m_pDatabaseForNativeProp ); } //switch on level lines and base points if need OdBmDBDrawingInfoPtr pDBDrawingInfo = m_pDatabaseForNativeProp->getAppInfo(OdBm::ManagerType::DBDrawingInfo); if (!pDBDrawingInfo.isNull()) { //run over all DBDrawings OdBmUserParamIteratorPtr drawingIterator = pDBDrawingInfo->createIteratorDBDrawings(true); while (!drawingIterator->done()) { // Get drawing from iterator OdBmObjectId bmObjectId = drawingIterator->object(); OdBmDBDrawingPtr pDBDrawing = bmObjectId.openObject(); if (!pDBDrawing.isNull()) { // Unhide elements if (pDBDrawing->getBaseViewType() == OdBm::ViewType::ThreeD && m_properties->getForceImportLevelLinesAndBasePoints()) forceImportLevelLinesAndBasePoints(bmObjectId, m_pDatabaseForNativeProp); //iterator step drawingIterator->next(); } }// eo while... } } catch (...) { return tvFilerEmptyInternalDatabase; } return rc; } bool OdTvVisualizeBimFiler::isActionsWithNativePropertiesStarted(const OdString& sFilePath) { if (!m_pDatabaseForNativeProp.isNull() && m_pDatabaseForNativeProp->getFilename() == sFilePath) return true; return false; } OdTvResult OdTvVisualizeBimFiler::endActionsWithNativeProperties() { m_pFilerPtr = NULL; if (!m_pDatabaseForNativeProp.isNull()) m_pDatabaseForNativeProp.release(); if (!m_pBmPropertiesModule.isNull()) { m_pRxPropertiesModule.release(); m_pBmPropertiesModule.release(); ::odrxDynamicLinker()->unloadModule(L"RxProperties"); ::odrxDynamicLinker()->unloadModule(m_moduleNameForCDA); ::odrxDynamicLinker()->unloadUnreferenced(); } return tvOk; } OdRxMemberIteratorPtr OdTvVisualizeBimFiler::getNativePropertiesIterator(OdUInt64 dbHandle, OdTvResult* rc) { if (m_pDatabaseForNativeProp.isNull()) { if (rc) *rc = tvNativePropMissedDatabase; return OdRxMemberIteratorPtr(); } OdRxMemberIteratorPtr pIter; if (dbHandle == 0) pIter = OdRxMemberQueryEngine::theEngine()->newMemberIterator(m_pDatabaseForNativeProp.get()); else { OdBmObjectId dbObjectId = m_pDatabaseForNativeProp->getObjectId(OdDbHandle(dbHandle)); if (dbObjectId.isNull()) { if (rc) *rc = tvNativePropMissedObject; return OdRxMemberIteratorPtr(); } OdBmObjectPtr pDbObject = dbObjectId.safeOpenObject(); pIter = OdRxMemberQueryEngine::theEngine()->newMemberIterator(pDbObject.get()); } if (pIter.isNull()) { if (rc) *rc = tvInternal; return OdRxMemberIteratorPtr(); } if (rc) *rc = tvOk; return pIter; } OdRxValue OdTvVisualizeBimFiler::getNativePropertyValue(OdUInt64 dbHandle, const OdRxPropertyPtr& pProperty, bool* bReadOnly, OdTvResult* rc) { if (pProperty.isNull()) { if (rc) *rc = tvInvalidInput; return OdRxValue(); } if (m_pDatabaseForNativeProp.isNull()) { if (rc) *rc = tvNativePropMissedDatabase; return OdRxValue(); } OdBmObjectPtr pDbObject; if (dbHandle == 0) pDbObject = m_pDatabaseForNativeProp; else { OdBmObjectId dbObjectId = m_pDatabaseForNativeProp->getObjectId(OdDbHandle(dbHandle)); pDbObject = dbObjectId.safeOpenObject(); } if (pDbObject.isNull()) { if (rc) *rc = tvNativePropMissedObject; return OdRxValue(); } OdRxValue value; OdResult odRes = pProperty->getValue(pDbObject, value); if (bReadOnly) *bReadOnly = pProperty->isReadOnly(pDbObject); if (odRes != eOk) { if (rc) *rc = tvInternal; return OdRxValue(); } if (rc) *rc = tvOk; return value; } OdRxValueIteratorPtr OdTvVisualizeBimFiler::getNativeCollectionPropertyIterator(OdUInt64 dbHandle, const OdRxCollectionPropertyPtr& pCollectionProperty, bool* bReadOnly /*= NULL*/, OdTvResult* rc /*= NULL*/) { if (m_pDatabaseForNativeProp.isNull()) { if (rc) *rc = tvNativePropMissedDatabase; return OdRxValueIteratorPtr(); } if (pCollectionProperty.isNull()) { if (rc) *rc = tvInvalidInput; return OdRxValueIteratorPtr(); } OdRxValueIteratorPtr pValIter; if (dbHandle == 0) { pValIter = pCollectionProperty->newValueIterator(m_pDatabaseForNativeProp.get()); if (bReadOnly) *bReadOnly = pCollectionProperty->isReadOnly(m_pDatabaseForNativeProp); } else { OdBmObjectId dbObjectId = m_pDatabaseForNativeProp->getObjectId(OdDbHandle(dbHandle)); if (dbObjectId.isNull()) { if (rc) *rc = tvNativePropMissedObject; return OdRxValueIteratorPtr(); } OdBmObjectPtr pDbObject = dbObjectId.safeOpenObject(); pValIter = pCollectionProperty->newValueIterator(pDbObject.get()); if (bReadOnly) *bReadOnly = pCollectionProperty->isReadOnly(pDbObject.get()); } if (rc) *rc = tvOk; return pValIter; } OdTvResult OdTvVisualizeBimFiler::setNativePropertyValue(OdUInt64 dbHandle, OdRxPropertyPtr& pProperty, const OdRxValue& value) { if (pProperty.isNull()) return tvInvalidInput; if (m_pDatabaseForNativeProp.isNull()) return tvNativePropMissedDatabase; OdBmObjectPtr pDbObject; if (dbHandle == 0) pDbObject = m_pDatabaseForNativeProp; else { OdBmObjectId dbObjectId = m_pDatabaseForNativeProp->getObjectId(OdDbHandle(dbHandle)); pDbObject = dbObjectId.safeOpenObject(); } if (pDbObject.isNull()) return tvNativePropMissedObject; pProperty->setValue(pDbObject, value); return tvOk; } OdDbBaseDatabase* OdTvVisualizeBimFiler::getNativeDatabase(OdTvResult* rc ) const { if (m_pDatabaseForNativeProp.isNull()) { if (rc) *rc = tvNativePropMissedDatabase; return NULL; } return (OdDbBaseDatabase*)m_pDatabaseForNativeProp.get(); } void setView2d( OdTvGsViewPtr pView ) { if( pView.isNull() ) return; pView->set2dMode( true ); } void OdTvVisualizeBimFiler::setupConnectionsBetweenTvViews(OdBmObjectId idDBDrawing, OdGsDevice* pDevice, OdTvGsDeviceId idTVDevice, std::set< OdTvModelId >* pNonMainModels ) { //check existance of the tv device OdTvGsDevicePtr pTvDevice = idTVDevice.openObject(OdTv::kForWrite); if (pTvDevice.isNull()) return; OdBmDBDrawingPtr pDBDrawing = idDBDrawing.safeOpenObject(); OdBmObjectIdArray vpsArray; pDBDrawing->getViewports(vpsArray); ODA_ASSERT(0 != vpsArray.size()); if (vpsArray.size() == 0) return; //set name to the device pTvDevice->setName(pDBDrawing->getName()); //get main view (gs views and names) OdBmViewportPtr pViewport = vpsArray.getAt(0).safeOpenObject(); OdBmObjectId idDBMainView = pViewport->getDbViewId(); OdBmDBViewPtr pDBMainView = idDBMainView.safeOpenObject(); double dScale = pDBMainView->getScale(); OdString strMainViewName = correctName(pDBMainView->getViewName()); OdString strMainViewNameFront = strMainViewName + OD_T("_Front"); OdString strMainViewNameBack = strMainViewName + OD_T("_Back"); auto viewRoot = pDBDrawing->viewNode(); if( viewRoot != pViewport->viewNode() ) { strMainViewName = OD_T( "Root_" ) + strMainViewName; strMainViewNameFront = strMainViewName + OD_T( "_Front" ); strMainViewNameBack = strMainViewName + OD_T( "_Back" ); } OdGsView* pMainView = viewRoot->data().getMainView()->getGsView(); OdGsView* pMainViewFront = viewRoot->data().getFrontView()->getGsView(); OdGsView* pMainViewBack = viewRoot->data().getBackView()->getGsView(); if (!pMainView || !pMainViewFront || !pMainViewBack) return; //get world to Device matrix from main view OdGeMatrix3d matr = pMainView->worldToDeviceMatrix(); matr.invert(); //get appropriate Visualize main and front main views int mainViewId = getViewId(pDevice, pMainView); int mainFrontViewId = getViewId(pDevice, pMainViewFront); int mainBackViewId = getViewId(pDevice, pMainViewBack); OdTvGsViewId idTvMainView = pTvDevice->viewAt(mainViewId); OdTvGsViewId idTvMainFrontView = pTvDevice->viewAt(mainFrontViewId); OdTvGsViewId idTvMainBackView = pTvDevice->viewAt(mainBackViewId); if (idTvMainView.isNull() || idTvMainFrontView.isNull() || idTvMainBackView.isNull()) return; OdTvGsViewId rootView = idTvMainView; if( viewRoot->data().getMainView()->getNodeType() != OdBm::GsViewNodeType::Root ) { if( viewRoot->data().getFrontView()->getNodeType() == OdBm::GsViewNodeType::Root ) { matr = pMainViewFront->worldToDeviceMatrix(); matr.invert(); rootView = idTvMainFrontView; } else if( viewRoot->data().getBackView()->getNodeType() == OdBm::GsViewNodeType::Root ) { matr = pMainViewBack->worldToDeviceMatrix(); matr.invert(); rootView = idTvMainBackView; } } OdTvGsViewPtr pRootTvView = rootView.openObject( OdTv::kForWrite ); // Create app OdTvDatabaseId tvDatabaseId = idTVDevice.openObject()->getDatabase(); OdTvDatabasePtr pTvDatabase = tvDatabaseId.openObject(); bool bAlreadyExist = false; OdTvRegAppId appId = pTvDatabase->registerAppName(L"2Visualize", bAlreadyExist); OdTvGsViewPtr pTVViewMain = idTvMainView.openObject(OdTv::kForWrite); pTVViewMain->setName( strMainViewName ); if( rootView == idTvMainView ) { pTVViewMain->setActive( true ); pTVViewMain->addSibling( idTvMainFrontView ); pTVViewMain->addSibling( idTvMainBackView ); } else { pTVViewMain->setActive( false ); } pTVViewMain->setHatchScaleFor3DClippingSection(dScale); OdTvGsViewPtr pTVViewMainFront = idTvMainFrontView.openObject(OdTv::kForWrite); pTVViewMainFront->setName(strMainViewNameFront); if( rootView == idTvMainFrontView ) { pTVViewMainFront->setActive( true ); pTVViewMainFront->addSibling( idTvMainView ); pTVViewMainFront->addSibling( idTvMainBackView ); } else { pTVViewMainFront->setActive( false ); } OdTvGsViewPtr pTVViewMainBack = idTvMainBackView.openObject(OdTv::kForWrite); pTVViewMainBack->setName(strMainViewNameBack); if( rootView == idTvMainBackView ) { pTVViewMainBack->setActive( true ); pTVViewMainBack->addSibling( idTvMainView ); pTVViewMainBack->addSibling( idTvMainFrontView ); } else { pTVViewMainBack->setActive( false ); } if( pNonMainModels ) { if( !pTVViewMainFront.isNull() ) { for( int i = 0; i < pTVViewMainFront->numModels(); ++i ) pNonMainModels->insert( pTVViewMainFront->modelAt( i ) ); } if( !pTVViewMainBack.isNull() ) { for( int i = 0; i < pTVViewMainBack->numModels(); ++i ) pNonMainModels->insert( pTVViewMainBack->modelAt( i ) ); } } OdBm::ViewType::Enum vType = pDBDrawing->getBaseViewType(); //SEA: 2d means view dir == Z but this is incorrect for BIM case if (vType != OdBm::ViewType::ThreeD) { setView2d( pTVViewMain ); setView2d( pTVViewMainFront ); setView2d( pTVViewMainBack ); } //apply clipping applyClipping(pTVViewMain, pMainView, matr, vType == OdBm::ViewType::ThreeD); applyClipping(pTVViewMainFront, pMainViewFront, matr, vType == OdBm::ViewType::ThreeD); applyClipping(pTVViewMainBack, pMainViewBack, matr, vType == OdBm::ViewType::ThreeD); std::function&, std::function*) >) > enumEmbeddedViews = [&enumEmbeddedViews](OdBmTree& root, std::function*)> f) { for (auto& node : root.getChildren()) { f(&node); enumEmbeddedViews(node, f); } }; // Set of viewports for a sheet. OdGsPaperLayoutHelper is an example. enumEmbeddedViews(*viewRoot, [&](OdBmTree* node) { auto& node_data = node->data(); OdBmViewportPtr pEmbeddedViewport = node_data.getViewportId().safeOpenObject(); OdBmObjectId idDBView = pEmbeddedViewport->getDbViewId(); OdBmDBViewPtr pDBView = idDBView.safeOpenObject(); OdString strName = correctName(pDBView->getViewName()); OdGsView* pGsView = node_data.getMainView()->getGsView(); OdGsView* pGsBackView = node_data.getBackView() ? node_data.getBackView()->getGsView() : nullptr; OdGsView* pGsFrontView = node_data.getFrontView() ? node_data.getFrontView()->getGsView() : nullptr; int embeddedViewId = getViewId(pDevice, pGsView); int embeddedFrontViewId = getViewId(pDevice, pGsFrontView); int embeddedBackViewId = getViewId(pDevice, pGsBackView); OdTvGsViewId idTvEmbeddedView = idTVDevice.openObject()->viewAt(embeddedViewId); OdTvGsViewId idTvEmbeddedFrontView = idTVDevice.openObject()->viewAt(embeddedFrontViewId); OdTvGsViewId idTvEmbeddedBackView = idTVDevice.openObject()->viewAt(embeddedBackViewId); OdTvGsViewId embeddedRootView = idTvEmbeddedView; if( node_data.getFrontView() && node_data.getFrontView()->getNodeType() == OdBm::GsViewNodeType::Root ) embeddedRootView = idTvEmbeddedFrontView; else if( node_data.getBackView() && node_data.getBackView()->getNodeType() == OdBm::GsViewNodeType::Root ) embeddedRootView = idTvEmbeddedBackView; if (!idTvEmbeddedView.isNull() ) { OdTvGsViewPtr pTVViewEmbedded = idTvEmbeddedView.openObject(OdTv::kForWrite); OdTvGsViewPtr pTVViewEmbeddedBack; if( !idTvEmbeddedBackView.isNull() ) { pTVViewEmbeddedBack = idTvEmbeddedBackView.openObject( OdTv::kForWrite ); } OdTvGsViewPtr pTVViewEmbeddedFront; if (!idTvEmbeddedFrontView.isNull()) { pTVViewEmbeddedFront = idTvEmbeddedFrontView.openObject(OdTv::kForWrite); } OdString strNameFront = strName + OD_T("_Front"); OdString strNameBack = strName + OD_T("_Back"); pTVViewEmbedded->setName(strName); if( !pTVViewEmbeddedBack.isNull() ) pTVViewEmbeddedBack->setName(strNameBack); if (!pTVViewEmbeddedFront.isNull()) { pTVViewEmbeddedFront->setName(strNameFront); } //SEA: 2d means view dir == Z but this is incorrect for BIM case if ((int)pDBDrawing->getBaseViewType() != (int)OdBm::ViewType::ThreeD) { setView2d( pTVViewEmbedded ); setView2d( pTVViewEmbeddedBack ); setView2d( pTVViewEmbeddedFront ); } if( embeddedRootView == idTvEmbeddedView ) { if( !pTVViewEmbeddedFront.isNull() ) { pTVViewEmbedded->addSibling( idTvEmbeddedFrontView ); } if( !pTVViewEmbeddedBack.isNull() ) pTVViewEmbedded->addSibling( idTvEmbeddedBackView ); } else if( embeddedRootView == idTvEmbeddedFrontView ) { pTVViewEmbeddedFront->addSibling( idTvEmbeddedView ); pTVViewEmbeddedFront->addSibling( idTvEmbeddedBackView ); } else { if( !pTVViewEmbeddedFront.isNull() ) { pTVViewEmbeddedBack->addSibling( idTvEmbeddedFrontView ); } if( !pTVViewEmbeddedBack.isNull() ) pTVViewEmbeddedBack->addSibling( idTvEmbeddedView ); } pTVViewEmbedded->inheritClipRegionFrom( rootView ); if( !pTVViewEmbeddedFront.isNull() ) { pTVViewEmbeddedFront->inheritClipRegionFrom( rootView ); } if( !pTVViewEmbeddedBack.isNull() ) { pTVViewEmbeddedBack->inheritClipRegionFrom( rootView ); } OdTvGsView::ViewportObjectInfo vi; //get viewport parameters OdGsDCRect rect; pGsView->getViewport(rect); OdTvPoint ll, ur; ll.set(rect.m_min.x, rect.m_min.y, 0.); ur.set(rect.m_max.x, rect.m_max.y, 0.); ll.transformBy(matr); ur.transformBy(matr); vi.m_wcsLowerLeft = OdTvPoint2d(ll.x, ll.y); vi.m_wcsUpperRight = OdTvPoint2d(ur.x, ur.y); //get clipping parameters OdIntArray counts; OdGePoint2dArray vertices; pGsView->viewportClipRegion(counts, vertices); vi.m_numPtsInContours.resize(counts.size()); for (unsigned int i = 0; i < counts.size(); i++) { vi.m_numPtsInContours[i] = OdUInt32(counts[i]); } vi.m_wcsCountoursPts.resize(vertices.size()); for (unsigned int i = 0; i < vertices.size(); i++) { OdTvPoint vertices3d = OdTvPoint(vertices[i].x, vertices[i].y, 0.); vertices3d.transformBy(matr); vi.m_wcsCountoursPts[i] = OdTvPoint2d(vertices3d.x, vertices3d.y); } //add view as a viewport object pRootTvView->addViewportObject(idTvEmbeddedView, vi); OdBmGsView* pBmView = node->data().getMainView(); if( pBmView && pBmView->getViewInfo().isCeilingPlanMirrored ) { OdTvPoint2d ll1( 0., 0. ), ur1( 1., 1. ); if( pBmView->getViewInfo().viewportOrientation == OdBm::RotationOnSheet::None ) { std::swap( ll1.x, ur1.x ); } else { std::swap( ll1.y, ur1.y ); } idTvEmbeddedView.openObject( OdTv::kForWrite )->setViewport( ll1, ur1 ); } vi.m_wcsCountoursPts.clear(); vi.m_numPtsInContours.clear(); if( !pTVViewEmbeddedBack.isNull() ) { pTVViewMain->addViewportObject( idTvEmbeddedBackView, vi ); if( pBmView && pBmView->getViewInfo().isCeilingPlanMirrored ) { OdTvPoint2d ll1( 0., 0. ), ur1( 1., 1. ); if( pBmView->getViewInfo().viewportOrientation == OdBm::RotationOnSheet::None ) { std::swap( ll1.x, ur1.x ); } else { std::swap( ll1.y, ur1.y ); } idTvEmbeddedBackView.openObject( OdTv::kForWrite )->setViewport( ll1, ur1 ); } } if (!pTVViewEmbeddedFront.isNull()) { pTVViewMain->addViewportObject(idTvEmbeddedFrontView, vi); if (pBmView && pBmView->getViewInfo().isCeilingPlanMirrored) { OdTvPoint2d ll1(0., 0.), ur1(1., 1.); if (pBmView->getViewInfo().viewportOrientation == OdBm::RotationOnSheet::None) { std::swap(ll1.x, ur1.x); } else { std::swap(ll1.y, ur1.y); } idTvEmbeddedFrontView.openObject(OdTv::kForWrite)->setViewport(ll1, ur1); } } } }); return; } void OdTvVisualizeBimFiler::getExistModels( OdTvDatabaseId dbId, std::set& models ) { models.clear(); if( dbId.isNull() ) return; OdTvDatabasePtr pDb = dbId.openObject(); for( OdTvModelsIteratorPtr pModels = pDb->getModelsIterator(); !pModels->done(); pModels->step() ) { models.insert( pModels->getModel() ); } } void OdTvVisualizeBimFiler::setCalculateIsolonesInShells( OdTvDatabaseId dbId, std::set skipModels ) { if( dbId.isNull() ) return; OdTvDatabasePtr pDb = dbId.openObject( OdTv::kForWrite ); for( OdTvModelsIteratorPtr pModels = pDb->getModelsIterator(); !pModels->done(); pModels->step() ) { OdTvModelId modelId = pModels->getModel(); if( skipModels.find( modelId ) != skipModels.end() ) continue; OdTvModelPtr pModel = modelId.openObject( OdTv::kForWrite ); for( OdTvEntitiesIteratorPtr pEnts = pModel->getEntitiesIterator(); !pEnts->done(); pEnts->step() ) { OdTvEntityId entId = pEnts->getEntity(); if( entId.getType() != OdTvEntityId::kEntity ) continue; OdTvEntityPtr pEnt = entId.openObject( OdTv::kForWrite ); pEnt->setCalculateIsolinesForShells( true, 89.0 * OdaPI / 180.0, false ); } } } void OdTvVisualizeBimFiler::setCalculateIsolonesInShells( const OdVector< OdTvModelId >& models ) { for( unsigned int i = 0; i < models.size(); ++i ) { OdTvModelId modelId = models[ i ]; OdTvModelPtr pModel = modelId.openObject( OdTv::kForWrite ); for( OdTvEntitiesIteratorPtr pEnts = pModel->getEntitiesIterator(); !pEnts->done(); pEnts->step() ) { OdTvEntityId entId = pEnts->getEntity(); if( entId.getType() != OdTvEntityId::kEntity ) continue; OdTvEntityPtr pEnt = entId.openObject( OdTv::kForWrite ); pEnt->setCalculateIsolinesForShells( true, 89.0 * OdaPI / 180.0, false ); } } } OdTvGsViewId OdTvVisualizeBimFiler::getMainTvViewId( OdBmObjectId idDBDrawing, OdGsDevice* pDevice, OdTvGsDeviceId idTVDevice ) { //check existance of the tv device OdTvGsDevicePtr pTvDevice = idTVDevice.openObject( OdTv::kForWrite ); if( pTvDevice.isNull() ) return OdTvGsViewId(); OdBmDBDrawingPtr pDBDrawing = idDBDrawing.safeOpenObject(); OdBmObjectIdArray vpsArray; pDBDrawing->getViewports( vpsArray ); ODA_ASSERT( 0 != vpsArray.size() ); if( vpsArray.size() == 0 ) return OdTvGsViewId(); //get main view (gs views and names) OdBmViewportPtr pViewport = vpsArray.getAt( 0 ).safeOpenObject(); OdBmObjectId idDBMainView = pViewport->getDbViewId(); OdBmDBViewPtr pDBMainView = idDBMainView.safeOpenObject(); auto viewRoot = pDBDrawing->viewNode(); OdGsView* pMainView = viewRoot->data().getMainView()->getGsView(); if( !pMainView ) return OdTvGsViewId(); //get appropriate Visualize main and front main views int mainViewId = getViewId( pDevice, pMainView ); if( mainViewId < pTvDevice->numViews() ) return pTvDevice->viewAt( mainViewId ); return OdTvGsViewId(); } void OdTvVisualizeBimFiler::collectViewportViews( OdBmObjectId idDBDrawing, OdArray< OdGsView* >& result ) { OdBmDBDrawingPtr pDBDrawing = idDBDrawing.safeOpenObject(); OdBmObjectIdArray vpsArray; pDBDrawing->getViewports( vpsArray ); ODA_ASSERT( 0 != vpsArray.size() ); if( vpsArray.size() == 0 ) return; for( const OdBmObjectId& id : vpsArray ) { OdBmViewportPtr pViewport = id.safeOpenObject(); auto viewRoot = pViewport->viewNode(); OdBmObjectId idDBMainView = pViewport->getDbViewId(); OdBmDBViewPtr pDBMainView = idDBMainView.safeOpenObject(); OdBm::GsViewNodeType::Enum type = viewRoot->data().getType(); if( type > OdBm::GsViewNodeType::Perpsective ) { OdGsView* pMainView = viewRoot->data().getMainView()->getGsView(); result.push_back( pMainView ); } } } void OdTvVisualizeBimFiler::resetViewsModelsNames(OdTvGsDeviceId idTVDevice) { OdTvGsDevicePtr pDevice = idTVDevice.openObject(); for (int i = 0; i < pDevice->numViews(); i++) { OdTvGsViewId viewId = pDevice->viewAt(i); OdTvGsViewPtr pView = viewId.openObject(); if ( pView.isNull() ) continue; OdString viewName = pView->getName(); if( viewName.isEmpty() ) viewName = OD_T( "EmptyViewName" ); int nModels = pView->numModels(); bool bFoundMainModel = false; int nGenModels = 0; for (int j = 0; j < nModels; j++) { OdTvModelId modelId = pView->modelAt(j); OdTvModelPtr pModel = modelId.openObject(OdTv::kForWrite); if ( !pModel.isNull() ) { if (nModels == 1) pModel->setName(viewName); else { if( pModel->getModelType() == OdTvModel::kMain && !bFoundMainModel ) { bFoundMainModel = true; pModel->setName( viewName ); } else { OdString modelName; modelName.format( L"%s_%d", viewName.c_str(), ++nGenModels ); pModel->setName( modelName ); } } } } } return; } OdString OdTvVisualizeBimFiler::resetModelNameForAppend(OdTvGsDeviceId idTVDevice, const OdString& fileName, const std::set& foreignModels) const { OdTvGsDevicePtr pDevice = idTVDevice.openObject(); //here we will suppose that our model is in active view OdTvGsViewId viewId = pDevice->getActiveView(); if (viewId.isNull()) //bad case - we get first { for (int i = 0; i < pDevice->numViews(); i++) { OdTvGsViewId vId = pDevice->viewAt(i); if (vId.isNull()) continue; else { viewId = vId; break; } } } if (viewId.isNull()) return OdString(); OdString newModelName; { OdTvGsViewPtr pView = viewId.openObject(); OdString name = pView->getName(); int nModels = pView->numModels(); for (int j = 0; j < nModels; j++) { OdTvModelId modelId = pView->modelAt(j); if (foreignModels.find(modelId) == foreignModels.end()) { OdTvModelPtr pModel = modelId.openObject(OdTv::kForWrite); if (pModel->getNeedSaveInFile()) //means normal model { newModelName = name + OD_T("_"); newModelName += fileName; OdString baseModelName = newModelName; OdUInt32 modelIndex = 1; while ( pModel->setName(newModelName) != tvOk && modelIndex < 10) { OdString sModelIndex; sModelIndex.format(OD_T("%d"), modelIndex); newModelName = baseModelName + OD_T("_") + sModelIndex; modelIndex++; } break; } } } } return newModelName; } int OdTvVisualizeBimFiler::getViewId(OdGsDevice* pDevice, OdGsView* pView) { if (!pDevice || !pView) return -1; int num = pDevice->numViews(); int iViewId = -1; for (int i = 0; i < num; ++i) { OdGsView* pViewForFind = pDevice->viewAt(i); if (pViewForFind == pView) { iViewId = i; break; } } return iViewId; } void OdTvVisualizeBimFiler::applyClipping(OdTvGsViewPtr pTvView, OdGsView* pGsView, const OdGeMatrix3d& mDevToWorld, bool bIs3DView) { if ( pGsView == 0 || pTvView.isNull() ) return; //get clipping parameters OdIntArray counts; OdGePoint2dArray vertices; pGsView->viewportClipRegion(counts, vertices); if ( counts.size() == 0 ) //there is no clipping return; OdUInt32Array numPtsInContours; numPtsInContours.resize(counts.size()); for (unsigned int i = 0; i < counts.size(); i++) { numPtsInContours[i] = OdUInt32(counts[i]); } OdTvPointArray wcsPoints; wcsPoints.resize(vertices.size()); OdGePlane plane; OdTvPoint position; bool bProjectOnBackClip = false; if( pTvView->isPerspective() ) { double dBackClipDist = 0.; bProjectOnBackClip = pTvView->getBackClip( dBackClipDist ); if( bProjectOnBackClip ) { OdTvVector eyeDir = pTvView->target() - pTvView->position(); eyeDir.normalize(); OdTvVector moveDir = eyeDir * Od_abs( dBackClipDist ); plane = OdGePlane( pTvView->target() + moveDir, -1.0 * eyeDir ); moveDir = ( -1.0 * pTvView->focalLength() ) * eyeDir; position = pTvView->target() + moveDir; } } for (unsigned int i = 0; i < vertices.size(); i++) { OdGePoint3d vertices3d = OdGePoint3d(vertices[i].x, vertices[i].y, 0.); vertices3d.transformBy(mDevToWorld); if( bProjectOnBackClip ) { vertices3d = vertices3d.project( plane, vertices3d - position ); } wcsPoints[i] = vertices3d; } pTvView->setClipRegion(int(counts.size()), numPtsInContours.getPtr(), wcsPoints.getPtr() ); } void OdTvVisualizeBimFiler::getChosenViews(OdBmDatabasePtr pDb, OdTvFilerFeedbackForChooseObject& filerFeedbackForChoose, bool& bCanceled) const { OdTvFilerFeedbackItemForChooseArray* pFilerFeedbackForChooseArray = filerFeedbackForChoose.getFilerFeedbackItemForChooseArrayPtr(); OdBmDBDrawingInfoPtr pDBDrawingInfo = pDb->getAppInfo(OdBm::ManagerType::DBDrawingInfo); //run over all DBDrawings OdBmUserParamIteratorPtr drawingIterator = pDBDrawingInfo->createIteratorDBDrawings(true); while (!drawingIterator->done()) { // Get drawing from iterator and check if it was chosen for import OdBmObjectId bmObjectId = drawingIterator->object(); drawingIterator->next(); //get name OdBmDBDrawingPtr pDBDrawing = bmObjectId.openObject(); if (!pDBDrawing.isNull()) { OdString strDrawindName = getNodeNameByViewType(pDBDrawing->getBaseViewType()) + OD_T("\\") + pDBDrawing->getName(); OdString strUniqueDrawindName = pDBDrawing->getUniqueName(); OdTvFilerFeedbackItemForChoose filerFeedbackForChoose(strDrawindName, strUniqueDrawindName); if ( bmObjectId == pDBDrawingInfo->getActiveDBDrawingId() ) filerFeedbackForChoose.m_bChosen = true; pFilerFeedbackForChooseArray->append(filerFeedbackForChoose); } } if (m_properties->getFeedbackForChooseCallback() != 0) { ((OdTvFeedbackForChooseCallback)m_properties->getFeedbackForChooseCallback())(filerFeedbackForChoose); if (filerFeedbackForChoose.getFilerFeedbackItemForChooseArrayPtr()->length() == 0) bCanceled = true; } } void OdTvVisualizeBimFiler::setupExVisualizeDeviceProp(OdRxDictionaryPtr& pProperties, const OdTvDatabaseId& tvDbId, bool bUseTimeProfiling, const OdString& modelName, const OdTvVisualizeBimFilerPropertiesPtr& importProperties, OdTvGsDeviceId& tvDeviceIdForAppend, bool bIs3DView) const { if (pProperties.get()) { if (pProperties->has(OD_T("DisplayViaGLES2"))) pProperties->putAt(OD_T("DisplayViaGLES2"), OdRxVariantValue(false)); if (pProperties->has(OD_T("AllowNonPersistentObjects"))) pProperties->putAt(OD_T("AllowNonPersistentObjects"), OdRxVariantValue(false)); #if !defined(__APPLE__) if (pProperties->has(OD_T("EnableTiming"))) pProperties->putAt(OD_T("EnableTiming"), OdRxVariantValue(bUseTimeProfiling)); #endif if (pProperties->has(OD_T("TvDatabaseID"))) pProperties->putAt(OD_T("TvDatabaseID"), OdRxVariantValue((OdIntPtr)(&tvDbId))); if (pProperties->has(OD_T("WriteUserData"))) pProperties->putAt(OD_T("WriteUserData"), OdRxVariantValue(importProperties->getStoreSourceObjects())); if (pProperties->has(OD_T("GenerateEntityNames"))) pProperties->putAt(OD_T("GenerateEntityNames"), OdRxVariantValue(importProperties->getObjectNaming())); if (pProperties->has(OD_T("PerModelViews"))) pProperties->putAt(OD_T("PerModelViews"), OdRxVariantValue(true)); if (pProperties->has(OD_T("CompareUnnamedImages"))) pProperties->putAt(OD_T("CompareUnnamedImages"), OdRxVariantValue(true)); if (bIs3DView) { if (pProperties->has(OD_T("IgnoreColoredShape"))) pProperties->putAt(OD_T("IgnoreColoredShape"), OdRxVariantValue(true)); } if (pProperties->has(OD_T("ModelName"))) pProperties->putAt(OD_T("ModelName"), OdRxVariantValue(modelName)); if (!tvDeviceIdForAppend.isNull()) { if (pProperties->has(OD_T("IgnoreViewInfoFlags"))) pProperties->putAt(OD_T("IgnoreViewInfoFlags"), OdRxVariantValue(true)); if (pProperties->has(OD_T("NamePrefix"))) pProperties->putAt(OD_T("NamePrefix"), OdRxVariantValue(modelName)); if (pProperties->has(OD_T("TvDeviceDAM"))) pProperties->putAt(OD_T("TvDeviceDAM"), OdRxVariantValue((OdIntPtr)(&tvDeviceIdForAppend))); OdTvGsViewId viewId = tvDeviceIdForAppend.openObject()->getActiveView(); OdString name = viewId.openObject()->getName(); if (pProperties->has(OD_T("TvViewDAM"))) pProperties->putAt(OD_T("TvViewDAM"), OdRxVariantValue((OdIntPtr)(&viewId))); } //Write font file path as user data if( pProperties->has( OD_T("WriteFontFilePath") )) pProperties->putAt( OD_T("WriteFontFilePath"), OdRxVariantValue( true ) ); if (pProperties->has(OD_T("IgnoreFlags"))) { OdUInt16 flags = OdRxVariantValue(pProperties->getAt(OD_T("IgnoreFlags")).get())->getUInt16(); SETBIT(flags, DeviceIgnoreFlags::kIgnoreEdgesColors, m_properties->getIgnoreEdgesColors()); pProperties->putAt(OD_T("IgnoreFlags"), OdRxVariantValue(flags)); } //Support geometry inside lights if( pProperties->has( OD_T( "SupportGeometryInLight" ) ) ) pProperties->putAt( OD_T( "SupportGeometryInLight" ), OdRxVariantValue( true ) ); if( pProperties->has( OD_T( "DisableShellFaceFillPatterns" ) ) ) { pProperties->putAt( OD_T( "DisableShellFaceFillPatterns" ), OdRxVariantValue( m_properties->getDisableFaceFillPatterns() ) ); } if( pProperties->has( OD_T( "ReflectHierarchy" ) ) ) { pProperties->putAt( OD_T( "ReflectHierarchy" ), OdRxVariantValue( true ) ); } if( pProperties->has( OD_T( "RestoreRenderMode" ) ) ) { pProperties->putAt( OD_T( "RestoreRenderMode" ), OdRxVariantValue( true ) ); } if (m_properties->getUseCustomDeviation() && m_properties->getCustomDeviation() > 0.000001) { if (pProperties->has(OD_T("CustomDeviation"))) { pProperties->putAt(OD_T("CustomDeviation"), OdRxVariantValue(m_properties->getCustomDeviation())); } } if( pProperties->has( OD_T( "SupportDifferentGsModels" ) ) ) { pProperties->putAt( OD_T( "SupportDifferentGsModels" ), OdRxVariantValue( true ) ); } } } bool OdTvVisualizeBimFiler::checkFileVersion(OdTvVisualizeBimFilerDbSource* pBimFiler, OdTvResult* rc) const { if (!pBimFiler) return false; OdString errStr; if (!pBimFiler->isFileValid(errStr)) { OdTvFilerFeedbackForWarning warningFeedback(errStr); if (m_properties->getFeedbackForWarningCallback() != 0) { ((OdTvFeedbackForWarningCallback)m_properties->getFeedbackForWarningCallback())(warningFeedback); if (warningFeedback.isAborted()) { if (rc) *rc = tvUserAbort; return false; } } } return true; } void OdTvVisualizeBimFiler::create3DView(OdBmDatabase* pDb) const { OdBmViewTablePtr pViewTable = pDb->getAppInfo(OdBm::ManagerType::ViewTable); OdBmObjectId idView = pViewTable->findViewIdByName("{3D}"); if (idView.isNull()) { ODBM_TRANSACTION_BEGIN(tr, pDb) tr.start(); OdBmDBView3dPtr pDBView3d = OdBmDBView3d::createObject(); // element must be added to DB before setDefaultOrigin, setPerspective OdBmObjectId newElemId = pDb->addElement(pDBView3d); pDBView3d->setDefaultView3dName(); pDBView3d->setDefaultOrigin(); pDBView3d->setDisplayStyle((OdBm::ViewDisplayStyle::Enum)m_properties->getDefault3DViewDisplayStyle()); pDBView3d->setDetailLevel((OdBm::ViewDetailLevel::Enum)m_properties->getDefault3DViewDetailLevel()); tr.commit(); ODBM_TRANSACTION_END() //repeat find an object of 3D view idView = pViewTable->findViewIdByName("{3D}"); } //let view start to be active if (!idView.isNull()) { OdBmDBViewPtr pView = idView.safeOpenObject(); OdBmDBDrawingInfoPtr pDBDrawingInfo = pDb->getAppInfo(OdBm::ManagerType::DBDrawingInfo); pDBDrawingInfo->setActiveDBDrawingId(pView->getDbDrawingId()); } } void OdTvVisualizeBimFiler::forceImportLevelLinesAndBasePoints(OdBmObjectId currDrawingId, OdBmDatabasePtr pDb) const { OdBmDBDrawingPtr pCurrDrawing = currDrawingId.safeOpenObject(); OdBmDBViewPtr pBmView = pCurrDrawing->getBaseDBViewId().safeOpenObject(); ODBM_TRANSACTION_BEGIN(tr, pDb); tr.start(); OdBmObjectIdArray arrId; OdBmObjectId levelCategoryId = pBmView->database()->getObjectId(OdBm::BuiltInCategory::OST_Levels); if (!levelCategoryId.isNull()) arrId.append(levelCategoryId); OdBmObjectId basePointCategoryId = pBmView->database()->getObjectId(OdBm::BuiltInCategory::OST_ProjectBasePoint); if (!basePointCategoryId.isNull()) arrId.append(basePointCategoryId); OdBmObjectId surveyPointCategoryId = pBmView->database()->getObjectId(OdBm::BuiltInCategory::OST_SharedBasePoint); if (!surveyPointCategoryId.isNull()) arrId.append(surveyPointCategoryId); pBmView->setCategoryHidden(arrId, false); tr.commit(); ODBM_TRANSACTION_END(); } template bool getNativeDatabaseHandle(T pObject, OdTvRegAppId& exGsVisualizeDeviceAppId, OdUInt64& handle) { if (!pObject.isNull()) { OdTvByteUserData* pUserData = dynamic_cast(pObject->getUserData(exGsVisualizeDeviceAppId)); if (pUserData) { OdUInt64 pData = *((OdUInt64*)pUserData->getData()); odSwap8Bytes(&pData); handle = (OdInt64)pData; return true; } } return false; } template void addBimRvEntityData(T pObject, OdTvRegAppId& appId, OdTvBimRvEntityData& entityUserData) { //prepare stream OdStreamBufPtr pStreamBuff = OdMemoryStream::createNew(); entityUserData.write(pStreamBuff); pStreamBuff->rewind(); OdUInt8Array buffer; buffer.resize(pStreamBuff->length()); pStreamBuff->getBytes(buffer.asArrayPtr(), pStreamBuff->length()); // Add user data OdTvByteUserData* pByteUserData = new OdTvByteUserData(buffer.asArrayPtr(), pStreamBuff->length(), OdTvByteUserData::kCopyOwn, true); pObject->appendUserData(pByteUserData, appId); } void OdTvVisualizeBimFiler::storeCategoryIdInSubEntities(OdTvGeometryDataIteratorPtr pGeometriesIter, OdTvDatabasePtr pTvDb, OdBmDatabasePtr pDb) { while (!pGeometriesIter->done()) { OdTvGeometryDataId geomId = pGeometriesIter->getGeometryData(); if (geomId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEntity = geomId.openAsSubEntity(OdTv::kForWrite); OdUInt64 handle = 0; if (getNativeDatabaseHandle(pSubEntity, m_exGsVisualizeDeviceAppId, handle)) { OdBmObjectId elemId = pDb->getObjectId(handle); if (!elemId.isNull()) { OdBmElementPtr pElement = elemId.safeOpenObject(); OdTvBimRvEntityData entityUserData; OdBmObjectId headerCategoryId = pElement->getHeaderCategoryId(); if (!headerCategoryId.isNull()) { OdInt64 categoryId = (OdInt64)headerCategoryId.getHandle(); entityUserData.setCategoryId(categoryId); } OdBmObjectId idValue; if (pElement->getParam(OdBm::BuiltInParameter::SYMBOL_ID_PARAM, idValue) == OdResult::eOk && !idValue.isNull()) entityUserData.setSymbodIdParam((OdUInt64)idValue.getHandle()); if (entityUserData.isNotEmpty()) addBimRvEntityData(pSubEntity, m_Bim2VisualizeIdAppId, entityUserData); } } storeCategoryIdInSubEntities(pSubEntity->getGeometryDataIterator(), pTvDb, pDb); } pGeometriesIter->step(); } } void OdTvVisualizeBimFiler::storeCategoryIdInEntities(OdTvEntitiesIteratorPtr pEntitiesIter, OdTvDatabasePtr pTvDb, OdBmDatabasePtr pDb) { while (!pEntitiesIter->done()) { OdTvEntityId entityId = pEntitiesIter->getEntity(); OdUInt64 handle = 0; bool bHandleWasFound = false; switch (entityId.getType()) { case OdTvEntityId::kEntity: { bHandleWasFound = getNativeDatabaseHandle(entityId.openObject(), m_exGsVisualizeDeviceAppId, handle); storeCategoryIdInSubEntities(entityId.openObject()->getGeometryDataIterator(), pTvDb, pDb); break; } case OdTvEntityId::kInsert: bHandleWasFound = getNativeDatabaseHandle(entityId.openObjectAsInsert(), m_exGsVisualizeDeviceAppId, handle); break; case OdTvEntityId::kLight: bHandleWasFound = getNativeDatabaseHandle(entityId.openObjectAsLight(), m_exGsVisualizeDeviceAppId, handle); break; case OdTvEntityId::kCamera: bHandleWasFound = getNativeDatabaseHandle(entityId.openObjectAsCamera(), m_exGsVisualizeDeviceAppId, handle); break; case OdTvEntityId::kGroup: bHandleWasFound = getNativeDatabaseHandle(entityId.openObjectAsGroup(), m_exGsVisualizeDeviceAppId, handle); break; case OdTvEntityId::kUndefined: break; } if (bHandleWasFound) { OdBmObjectId elemId = pDb->getObjectId(handle); if (!elemId.isNull()) { OdBmElementPtr pElement = elemId.safeOpenObject(); OdTvBimRvEntityData entityUserData; OdBmObjectId headerCategoryId = pElement->getHeaderCategoryId(); if (!headerCategoryId.isNull()) { OdInt64 categoryId = (OdInt64)headerCategoryId.getHandle(); entityUserData.setCategoryId(categoryId); } OdBmObjectId idValue; if (pElement->getParam(OdBm::BuiltInParameter::SYMBOL_ID_PARAM, idValue) == OdResult::eOk && !idValue.isNull()) entityUserData.setSymbodIdParam((OdUInt64)idValue.getHandle()); if (entityUserData.isNotEmpty()) { switch (entityId.getType()) { case OdTvEntityId::kEntity: addBimRvEntityData(entityId.openObject(), m_Bim2VisualizeIdAppId, entityUserData); break; case OdTvEntityId::kInsert: addBimRvEntityData(entityId.openObjectAsInsert(), m_Bim2VisualizeIdAppId, entityUserData); break; case OdTvEntityId::kLight: addBimRvEntityData(entityId.openObjectAsLight(), m_Bim2VisualizeIdAppId, entityUserData); break; case OdTvEntityId::kCamera: addBimRvEntityData(entityId.openObjectAsCamera(), m_Bim2VisualizeIdAppId, entityUserData); break; case OdTvEntityId::kGroup: addBimRvEntityData(entityId.openObjectAsGroup(), m_Bim2VisualizeIdAppId, entityUserData); break; } } } } pEntitiesIter->step(); } } void OdTvVisualizeBimFiler::storeCategoryId(OdTvDatabaseId tvDbId, OdBmDatabasePtr pDb) { OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); bool alreadyExist = false; if (m_Bim2VisualizeIdAppId.isNull()) m_Bim2VisualizeIdAppId = pTvDb->registerAppName(OdTvBimRvUserData, alreadyExist); if (m_exGsVisualizeDeviceAppId.isNull()) m_exGsVisualizeDeviceAppId = pTvDb->registerAppName(L"ExGsVisualizeDevice", alreadyExist); OdTvModelsIteratorPtr pModelsIter = pTvDb->getModelsIterator(); while (!pModelsIter->done()) { OdTvModelPtr pModel = pModelsIter->getModel().openObject(); storeCategoryIdInEntities(pModel->getEntitiesIterator(), pTvDb, pDb); pModelsIter->step(); } OdTvBlocksIteratorPtr pBlocksIter = pTvDb->getBlocksIterator(); while (!pBlocksIter->done()) { OdTvBlockPtr pBlock = pBlocksIter->getBlock().openObject(); storeCategoryIdInEntities(pBlock->getEntitiesIterator(), pTvDb, pDb); pBlocksIter->step(); } } //***************************************************************************// // 'OdTvBimPropertiesLoader' methods implementation //***************************************************************************// OdTvBimPropertiesLoader::OdTvBimPropertiesLoader() { } OdTvBimPropertiesLoader::~OdTvBimPropertiesLoader() { } void OdTvBimPropertiesLoader::setNativeDatabase(const OdDbBaseDatabase* nativeDb) { m_bimDb = OdBmDatabase::cast(nativeDb); if (m_bimDb.isNull()) throw OdError("Invalid native database, need OdBimDatabase"); if (m_pLabelUtils.isNull()) m_pLabelUtils = OdBmObject::desc()->getX(OdBmLabelUtilsPE::desc()); } void OdTvBimPropertiesLoader::setNativeDatabase(const OdString& path) { OdStaticRxObject svcs; ::odrxDynamicLinker()->loadApp(OdBmLoaderModuleName, false); m_bimDb = svcs.readFile(path); if (m_bimDb.isNull()) throw OdError("Error during reading the native database"); if ( m_pLabelUtils.isNull() ) m_pLabelUtils = OdBmObject::desc()->getX(OdBmLabelUtilsPE::desc()); } OdTvObjectsPropertiesPtr OdTvBimPropertiesLoader::getAllProperties(const OdTvDatabaseId& dbId) { if (dbId.isNull()) throw OdError("OdTvDatabaseId is NULL"); if (m_bimDb.isNull()) return OdTvObjectsPropertiesPtr(); if (m_pLabelUtils.isNull()) return OdTvObjectsPropertiesPtr(); OdTvObjectsPropertiesPtr res = new OdTvObjectsProperties(); OdTvEntitiesIteratorPtr entitesItr; OdTvModelsIteratorPtr modelItr = dbId.openObject()->getModelsIterator(); OdTvEntityId entity; OdTvEntityPtr entityPtr; OdTvByteUserData* userData; OdUInt64 handle; OdString regAppName = L"ExGsVisualizeDevice"; bool exits; OdTvRegAppId regId = dbId.openObject()->registerAppName(regAppName, exits); if (!exits) throw OdError("Not found OdTvRegAppId"); for (; !modelItr->done(); modelItr->step()) { entitesItr = modelItr->getModel().openObject()->getEntitiesIterator(); for (; !entitesItr->done(); entitesItr->step()) { entity = entitesItr->getEntity(); if (entity.getType() == OdTvEntityId::kEntity) { entityPtr = entity.openObject(); userData = static_cast(entityPtr->getUserData(regId)); if (userData && userData->getSize() == sizeof(OdUInt64)) { memcpy(&handle, userData->getData(), userData->getSize()); if (res->find(handle) == res->end()) (*res)[handle] = getProperties(handle); } } } } return res; } OdTvNativeProperties OdTvBimPropertiesLoader::getProperties(OdUInt64 handle) { OdTvNativeProperties properties; if ( m_bimDb.isNull() ) return properties; if ( m_pLabelUtils.isNull() ) return properties; OdBmObjectId objId = m_bimDb->getObjectId(handle); OdBmElementPtr element = objId.safeOpenObject(); if (element.isNull()) return properties; OdTfVariant value; OdBmParameterSet paramSet; element->getListParams(paramSet); OdString name; OdString params; OdDbStub* pStub; for (OdBm::BuiltInParameter::Enum param : paramSet.getBuiltInParamsIterator()) { name = m_pLabelUtils->getLabelFor(param); if (name.isEmpty()) { name = OdBm::BuiltInParameter(param).toString(); } if (element->getParam(param, value) == eOk) { OdVariant::Type odType = value.type(); switch (odType) { case OdVariant::kInt32: { params.format(OD_T("%d"), value.getInt32()); } break; case OdVariant::kDouble: { params.format(OD_T("%.15f"), value.getDouble()); } break; case OdVariant::kString: { params.format(value.getString().c_str()); } break; default: { if (odType == OdTfVariant::kDbStubPtr) { pStub = value.getDbStubPtr(); if (pStub) { OdBmObjectId rawValue = OdBmObjectId(pStub); if (param == OdBm::BuiltInParameter::ELEM_CATEGORY_PARAM || param == OdBm::BuiltInParameter::ELEM_CATEGORY_PARAM_MT) { OdBm::BuiltInCategory::Enum builtInValue = static_cast((OdUInt64)rawValue.getHandle()); params.format(L"%ls", OdBm::BuiltInCategory(builtInValue).toString().c_str()); } else params.format(OD_T("%d"), (OdUInt64)(rawValue.getHandle())); } else params.format(OD_T("-1")); } } } } else { params.format(L"None"); } properties[name] = params; } return properties; } void OdTvVisualizeBimFiler::createCommonDataAccessTree(OdTvDatabasePtr pTvDb, OdDbBaseDatabase *pDatabase, const OdString& strTreeName) const { OdString strCustomCDAModule = m_properties->getCustomCDAModule(); bool bUseCustomCDA = false; if (!strCustomCDAModule.isEmpty()) { if (!::odrxDynamicLinker()->loadModule(strCustomCDAModule).isNull()) { m_moduleNameForCDA = strCustomCDAModule; bUseCustomCDA = true; } } if (!bUseCustomCDA) { m_moduleNameForCDA = m_properties->getUseAlternativeCDATree() ? OdString("TB_CDA3DViewTree") : OdString("TB_CDAProperties"); ::odrxDynamicLinker()->loadModule(m_moduleNameForCDA); } //Create CDA tree OdTvCDATreePtr pTree = OdTvCDATree::createObject(); pTree->createDatabaseHierarchyTree(pDatabase, m_properties->getNeedCollectPropertiesInCDA()); //Add tree to the Tv database OdTvResult rc; OdTvCDATreeStorageId cdaTreeId = pTvDb->addCDATreeStorage(strTreeName, pTree, &rc); if (rc == tvAlreadyExistSameName) { OdUInt32 i = 1; while (rc != tvOk && i < MAX_CDATREENAME_GENERATION_ATTEMPTS) { OdString str; str.format(L"%s_%d", strTreeName.c_str(), i++); //not to fast but it is not a "bottle neck" cdaTreeId = pTvDb->addCDATreeStorage(str, pTree, &rc); } } //Add new CDA tree to the appropriate models OdTvModelsIteratorPtr modelsIterPtr = pTvDb->getModelsIterator(); while (!modelsIterPtr->done()) { OdTvModelPtr pModel = modelsIterPtr->getModel().openObject(); if (!pModel.isNull()) { pModel->setCDATreeStorage(cdaTreeId); } modelsIterPtr->step(); } //mark all nodes that it is not need group nodes OdRxModelTreeBaseNodePtr pDbNode = pTree->getDatabaseNode(); if (!pDbNode.isNull()) OdTvDatabaseUtils::markCDANode(pDbNode.get()); } //***************************************************************************// // 'OdTvVisualizeBimFilerModule' methods implementation //***************************************************************************// ODRX_DEFINE_DYNAMIC_MODULE(OdTvVisualizeBimFilerModule); void OdTvVisualizeBimFilerModule::initApp() { // initialize the Visualize SDK odTvInitialize(); } void OdTvVisualizeBimFilerModule::uninitApp() { // Uninitialize the Visualize SDK odTvUninitialize(); } OdTvVisualizeFilerPtr OdTvVisualizeBimFilerModule::getVisualizeFiler() const { OdTvVisualizeFilerPtr pBimFiler = new OdTvVisualizeBimFiler(); return pBimFiler; } OdTvImportPropertiesLoaderPtr OdTvVisualizeBimFilerModule::getPropertiesLoader() const { OdTvImportPropertiesLoaderPtr loader = new OdTvBimPropertiesLoader(); return loader; }