/////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////// #ifndef _WIN32_WCE #include #endif #include //#include #include "OdaCommon.h" #define STL_USING_VECTOR #define STL_USING_FUNCTIONAL #include "OdaSTL.h" #include "RxDynamicModule.h" #include "NwModuleNames.h" #include "TvFactory.h" #include "ExVisualizeDeviceExtensions.h" #include "DynamicLinker.h" // Tv #include "TvGeomCollector.h" #include "TvFilerTimer.h" #include "TvDatabaseUtils.h" #include "TvDatabaseCleaner.h" // Nw2Tv #include "Nw2Visualize.h" #include "NwViewsImport.h" #include "NwGeometryImport.h" #include "Animation.h" // Nw #include "NwDatabase.h" #include "NwPartition.h" #include "NwBackgroundElement.h" #include "NwModel.h" #include "NwUnitUtils.h" #include "NwPathUtils.h" #include "NwSheetInfo.h" #ifdef NW_CDAPROPERTIES_ENABLED #include "NwPropertiesModule.h" #endif //NW_CDAPROPERTIES_ENABLED #include "ADSKRegistry.h" //nw grid #include "Grid/NwGridSystem.h" #include "Grid/NwGridLine.h" #include "Grid/NwGridLineSegment.h" #include "Grid/NwGridLevel.h" #include "Grid/NwGridSystemElement.h" #include "Grid/NwGridTypes.h" #include "Plot/NwPlotPaperStyle.h" #include "MemoryStream.h" #define START_TV_NW_TIMER \ if (pTvTimer) \ pTvTimer->start(); #define END_TV_NW_TIMER \ if (pTvTimer) \ { \ nTotalTvTime += pTvTimer->permanentSec(); \ pTvTimer->stop(); \ } static OdString nwSanitizePath(const OdString& path); static OdString nwExtractFileName(const OdString& path); static OdString nwExtractFileDir(const OdString& path); static OdResult findPathToFile(const OdString& sCurrentPath, OdString &sFileToFind); void createAndApplyPreferableVS_NW(OdTvDatabaseId & tvDbId); class OdTvVisualizeNwFilerSourceFromDb : public OdTvVisualizeNwFilerDbSource { OdDbBaseDatabase *mDatabase; public: OdTvVisualizeNwFilerSourceFromDb(OdDbBaseDatabase *pDatabase) : mDatabase(pDatabase) {}; virtual OdNwDatabasePtr getDb() { return mDatabase; }; virtual bool odWasInitialized() const { return false; } virtual OdString getFilename() { OdNwDatabasePtr pDb = mDatabase; if (!pDb.isNull()) { OdString fileName = pDb->getFilename(); if (!fileName.isEmpty()) return fileName; } return OD_T("NoNameNwDatabase"); } }; class OdTvVisualizeNwFilerSourceFromBuffer : public OdTvVisualizeNwFilerDbSource { OdStaticRxObject svcs; OdStreamBuf* mBuffer; public: OdTvVisualizeNwFilerSourceFromBuffer(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes) : mBuffer(pBuffer) , m_initTime(0) { initialize(pBuffer, pProfileRes); }; virtual OdNwDatabasePtr getDb() { svcs.setOption(NwOpenOptions::kOptionCacheGeometry, 0); svcs.setOption(NwOpenOptions::kOptionSaveEmbd2TmpForView, 0); return svcs.readFile(mBuffer); }; virtual bool odWasInitialized() const { return false; } virtual OdString getFilename() { if (mBuffer) { OdString fileName = mBuffer->fileName(); if (!fileName.isEmpty()) return fileName; } return OD_T("NoNameNwDatabase"); } protected: OdTvVisualizeNwFilerSourceFromBuffer() : OdTvVisualizeNwFilerDbSource() , mBuffer(nullptr) , m_initTime(0.) {} void initialize(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes) { if (!pBuffer) return; OdTvFilerTimer timing(needTimer(pProfileRes)); timing.startTotal(); svcs.setTextureDirectoryPath(nwExtractFileDir(pBuffer->fileName()) + OD_T("/"), false); //load module ::odrxDynamicLinker()->loadModule(OdNwDbModuleName, false); timing.endTotal(); m_initTime = timing.getTotalTime(); }; protected: double m_initTime; }; class OdTvVisualizeNwFilerSourceFromFile : public OdTvVisualizeNwFilerDbSource { OdStaticRxObject svcs; OdString mFilePath; OdString m_strTempDirectoryPath; protected: double m_initTime; public: OdTvVisualizeNwFilerSourceFromFile(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, const OdString& strTempDirPath = OdString::kEmpty) : m_strTempDirectoryPath(strTempDirPath) { initialize(filePath, pProfileRes); }; virtual OdNwDatabasePtr getDb() { svcs.setOption(NwOpenOptions::kOptionCacheGeometry, 0); // Set temp directory path and save embedded to temp option if path is not empty if (!m_strTempDirectoryPath.isEmpty()) { svcs.setTempDirectoryPath(m_strTempDirectoryPath); svcs.setOption(NwOpenOptions::kOptionSaveEmbd2TmpForView, 1); } return svcs.readFile(mFilePath); }; virtual double getInitTime() const { return m_initTime; } virtual OdString getFilename() { //generate name for the stream file return OdTvDatabaseUtils::getFileNameFromPath(mFilePath); }; protected: OdTvVisualizeNwFilerSourceFromFile() : OdTvVisualizeNwFilerDbSource() , m_strTempDirectoryPath(OdString::kEmpty) , m_initTime(0.) {} void initialize(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes) { mFilePath = filePath; OdTvFilerTimer timing(needTimer(pProfileRes)); timing.startTotal(); svcs.setTextureDirectoryPath(nwExtractFileDir(mFilePath) + OD_T("/"), false); //load module ::odrxDynamicLinker()->loadModule(OdNwDbModuleName, false); timing.endTotal(); m_initTime = timing.getTotalTime(); }; }; /** \details class for storing the information about the opened file */ class OdTvViewerDatabaseInfo : public OdTvFilerTimeProfiling { public: enum Type { kNew = 0, kBuiltIn = 1, kFromFile = 2, kImport = 4, kImportRevisions = 5, }; OdTvViewerDatabaseInfo() : OdTvFilerTimeProfiling() , m_iLoadTime(0) , m_iVectorizingTime(0) , m_iTvCreationTime(0) , m_iFirstUpdateTime(0) , m_iMiscTime(0) , m_iCDACreationTime(0) , m_type(kNew) {} ~OdTvViewerDatabaseInfo() {} // returns the time of file loading (in milliseconds) virtual OdInt64 getImportTime() const { return m_iLoadTime; } // returns the total vectorizing time (in milliseconds) virtual OdInt64 getVectorizingTime() const { return m_iVectorizingTime; } // returns the total tv calling time (in milliseconds) virtual OdInt64 getTvTime() const { return m_iTvCreationTime; } // returns the total time of the CDA tree (and properties cache) creation virtual OdInt64 getCDATreeCreationTime() const { return m_iCDACreationTime; } // returns the misc tv calling time (in milliseconds) virtual OdInt64 getMiscTime() const { return m_iMiscTime; } // return the time of calling (in milliseconds) OdInt64 getFirstUpdateTime() const { return m_iFirstUpdateTime; } OdInt64 getTotalTime() const { return m_iLoadTime + m_iVectorizingTime + m_iTvCreationTime + m_iFirstUpdateTime; } // set the type Type getType() const { return m_type; } //set file path OdString getFilePath() const { return m_strPath; } // set the time of file loading (in milliseconds) virtual void setImportTime(OdInt64 time) { m_iLoadTime = time; } // set the time of vectorizing (in milliseconds) virtual void setVectorizingTime(OdInt64 time) { m_iVectorizingTime = time; } // set the time of calling (in milliseconds) virtual void setTvTime(OdInt64 time) { m_iTvCreationTime = time; } // set the time of calling (in milliseconds) void setFirstUpdateTime(OdInt64 time) { m_iFirstUpdateTime = time; } //Sets a new time occupied by the CDA tree (and properties cache) creation void setCDATreeCreationTime(OdInt64 time) { m_iCDACreationTime = time; } // set the misc time (in milliseconds) virtual void setMiscTime(OdInt64 time) { m_iMiscTime = time; } // set the type void setType(Type type) { m_type = type; } //set file path void setFilePath(const OdString& path) { m_strPath = path; } private: OdInt64 m_iLoadTime; OdInt64 m_iVectorizingTime; OdInt64 m_iTvCreationTime; OdInt64 m_iCDACreationTime; OdInt64 m_iFirstUpdateTime; OdInt64 m_iMiscTime; Type m_type; OdString m_strPath; }; //***************************************************************************// // 'OdTvVisualizeNwFilerProperties' methods implementation //***************************************************************************// using namespace NW2Visualize; typedef std::map mapNwObjectId2EntityIdType; OdTvVisualizeNwFilerProperties::OdTvVisualizeNwFilerProperties() : OdRxDispatchImpl<>() , m_importRect(0,1,1,0) , m_background(ODRGB(0, 0, 0)) , m_defaultColor(ODRGB(191, 191, 191)) , m_flags(0) , m_appendTransform(OdGeMatrix3d::kIdentity) , m_appendDevice() , m_pCallback(nullptr) , m_pFileCallback(nullptr) , m_strPartialImportDumpFile(OdString::kEmpty) , m_multiThreadsCnt(0) , m_strReflectionEnvFile(OdString::kEmpty) { } OdRxDictionaryPtr OdTvVisualizeNwFilerProperties::createObject() { return OdRxObjectImpl::createObject(); } OdTvVisualizeNwFilerProperties::~OdTvVisualizeNwFilerProperties() { } ODRX_DECLARE_PROPERTY(DCRect) ODRX_DECLARE_PROPERTY(BackgroundColor) ODRX_DECLARE_PROPERTY(DefaultNwColor) ODRX_DECLARE_PROPERTY(AppendTransform) ODRX_DECLARE_PROPERTY(DeviceToAppend) ODRX_DECLARE_PROPERTY(NeedCDATree) ODRX_DECLARE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_DECLARE_PROPERTY(ReplaceByNwc) ODRX_DECLARE_PROPERTY(StoreSourceObjects) ODRX_DECLARE_PROPERTY(ImportCuttingPlanes) ODRX_DECLARE_PROPERTY(FeedbackForChooseCallback) ODRX_DECLARE_PROPERTY(FeedbackForChooseFileCallback) ODRX_DECLARE_PROPERTY(ImportGrid) ODRX_DECLARE_PROPERTY(ImportAnimation) ODRX_DECLARE_PROPERTY(ImportRecap) ODRX_DECLARE_PROPERTY(ImportRecapAsRcsPointCloud) ODRX_DECLARE_PROPERTY(ImportSavedViewpoints) ODRX_DECLARE_PROPERTY(ImportLights) ODRX_DECLARE_PROPERTY(PartialImportDumpFile) ODRX_DECLARE_PROPERTY(LowMemoryImportToVSF) ODRX_DECLARE_PROPERTY(NeedGroupsUsing) ODRX_DECLARE_PROPERTY(ImportRefGeomAsInserts) ODRX_DECLARE_PROPERTY(TempDirectoryPath) ODRX_DECLARE_PROPERTY(MultiThreadsCnt) ODRX_DECLARE_PROPERTY(ReflectionEnvFile) ODRX_BEGIN_DYNAMIC_PROPERTY_MAP(OdTvVisualizeNwFilerProperties); ODRX_GENERATE_PROPERTY(DCRect) ODRX_GENERATE_PROPERTY(BackgroundColor) ODRX_GENERATE_PROPERTY(DefaultNwColor) ODRX_GENERATE_PROPERTY(AppendTransform) ODRX_GENERATE_PROPERTY(DeviceToAppend) ODRX_GENERATE_PROPERTY(NeedCDATree) ODRX_GENERATE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_GENERATE_PROPERTY(ReplaceByNwc) ODRX_GENERATE_PROPERTY(StoreSourceObjects) ODRX_GENERATE_PROPERTY(ImportCuttingPlanes) ODRX_GENERATE_PROPERTY(FeedbackForChooseCallback) ODRX_GENERATE_PROPERTY(FeedbackForChooseFileCallback) ODRX_GENERATE_PROPERTY(ImportGrid) ODRX_GENERATE_PROPERTY(ImportAnimation) ODRX_GENERATE_PROPERTY(ImportRecap) ODRX_GENERATE_PROPERTY(ImportRecapAsRcsPointCloud) ODRX_GENERATE_PROPERTY(ImportSavedViewpoints) ODRX_GENERATE_PROPERTY(ImportLights) ODRX_GENERATE_PROPERTY(PartialImportDumpFile) ODRX_GENERATE_PROPERTY(LowMemoryImportToVSF) ODRX_GENERATE_PROPERTY(NeedGroupsUsing) ODRX_GENERATE_PROPERTY(ImportRefGeomAsInserts) ODRX_GENERATE_PROPERTY(TempDirectoryPath) ODRX_GENERATE_PROPERTY(MultiThreadsCnt) ODRX_GENERATE_PROPERTY(ReflectionEnvFile) ODRX_END_DYNAMIC_PROPERTY_MAP(OdTvVisualizeNwFilerProperties); ODRX_DEFINE_PROPERTY_METHODS(DCRect, OdTvVisualizeNwFilerProperties, getDCRect, setDCRect, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(BackgroundColor, OdTvVisualizeNwFilerProperties, getBackgroundColor, setBackgroundColor, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(DefaultNwColor, OdTvVisualizeNwFilerProperties, getDefaultNwColor, setDefaultNwColor, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(AppendTransform, OdTvVisualizeNwFilerProperties, getAppendTransform, setAppendTransform, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(DeviceToAppend, OdTvVisualizeNwFilerProperties, getDeviceToAppend, setDeviceToAppend, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(NeedCDATree, OdTvVisualizeNwFilerProperties, getNeedCDATree, setNeedCDATree, getBool); ODRX_DEFINE_PROPERTY_METHODS(NeedCollectPropertiesInCDA, OdTvVisualizeNwFilerProperties, getNeedCollectPropertiesInCDA, setNeedCollectPropertiesInCDA, getBool); ODRX_DEFINE_PROPERTY_METHODS(ReplaceByNwc, OdTvVisualizeNwFilerProperties, getReplaceByNwc, setReplaceByNwc, getBool); ODRX_DEFINE_PROPERTY_METHODS(StoreSourceObjects, OdTvVisualizeNwFilerProperties, getStoreSourceObjects, setStoreSourceObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportCuttingPlanes, OdTvVisualizeNwFilerProperties, getImportCuttingPlanes, setImportCuttingPlanes, getBool); ODRX_DEFINE_PROPERTY_METHODS(FeedbackForChooseCallback, OdTvVisualizeNwFilerProperties, getFeedbackForChooseCallback, setFeedbackForChooseCallback, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(FeedbackForChooseFileCallback, OdTvVisualizeNwFilerProperties, getFeedbackForChooseFileCallback, setFeedbackForChooseFileCallback, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ImportGrid, OdTvVisualizeNwFilerProperties, getImportGrid, setImportGrid, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportAnimation, OdTvVisualizeNwFilerProperties, getImportAnimation, setImportAnimation, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportRecap, OdTvVisualizeNwFilerProperties, getImportRecap, setImportRecap, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportRecapAsRcsPointCloud, OdTvVisualizeNwFilerProperties, getImportRecapAsRcsPointCloud, setImportRecapAsRcsPointCloud, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportSavedViewpoints, OdTvVisualizeNwFilerProperties, getImportSavedViewpoints, setImportSavedViewpoints, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportLights, OdTvVisualizeNwFilerProperties, getImportLights, setImportLights, getBool); ODRX_DEFINE_PROPERTY_METHODS(PartialImportDumpFile, OdTvVisualizeNwFilerProperties, getPartialImportDumpFile, setPartialImportDumpFile, getString); ODRX_DEFINE_PROPERTY_METHODS(LowMemoryImportToVSF, OdTvVisualizeNwFilerProperties, getLowMemoryImportToVSF, setLowMemoryImportToVSF, getBool); ODRX_DEFINE_PROPERTY_METHODS(NeedGroupsUsing, OdTvVisualizeNwFilerProperties, getNeedGroupsUsing, setNeedGroupsUsing, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportRefGeomAsInserts, OdTvVisualizeNwFilerProperties, getImportRefGeomAsInserts, setImportRefGeomAsInserts, getBool); ODRX_DEFINE_PROPERTY_METHODS(TempDirectoryPath, OdTvVisualizeNwFilerProperties, getTempDirectoryPath, setTempDirectoryPath, getString); ODRX_DEFINE_PROPERTY_METHODS(MultiThreadsCnt, OdTvVisualizeNwFilerProperties, getMultiThreadsCnt, setMultiThreadsCnt, getInt32) ODRX_DEFINE_PROPERTY_METHODS(ReflectionEnvFile, OdTvVisualizeNwFilerProperties, getReflectionEnvFile, setReflectionEnvFile, getString) void OdTvVisualizeNwFilerProperties::setDCRect(OdIntPtr rect) { OdTvDCRect* pRect = (OdTvDCRect*)(rect); if (!pRect) { ODA_ASSERT(false); } m_importRect = *pRect; } OdIntPtr OdTvVisualizeNwFilerProperties::getDCRect() const { return (OdIntPtr)(&m_importRect); } void OdTvVisualizeNwFilerProperties::setBackgroundColor(OdIntPtr ptr) { ODCOLORREF* pColor = (ODCOLORREF*)(ptr); if (!pColor) { ODA_ASSERT(false); } m_background = *pColor; } OdIntPtr OdTvVisualizeNwFilerProperties::getBackgroundColor() const { return (OdIntPtr)(&m_background); } void OdTvVisualizeNwFilerProperties::setDefaultNwColor(OdIntPtr ptr) { ODCOLORREF* pColor = (ODCOLORREF*)(ptr); if (!pColor) { ODA_ASSERT(false); } m_defaultColor = *pColor; } OdIntPtr OdTvVisualizeNwFilerProperties::getDefaultNwColor() const { return (OdIntPtr)(&m_defaultColor); } void OdTvVisualizeNwFilerProperties::setDeviceToAppend(OdIntPtr pDevice) { OdTvGsDeviceId* pId = (OdTvGsDeviceId*)pDevice; if (pId == NULL || pId->isNull()) { m_appendDevice = OdTvGsDeviceId(); } else { m_appendDevice = *pId; } } OdIntPtr OdTvVisualizeNwFilerProperties::getDeviceToAppend() const { if (m_appendDevice.isNull()) return 0; return (OdIntPtr)(&m_appendDevice); } void OdTvVisualizeNwFilerProperties::setAppendTransform(OdIntPtr pTransform) { const OdTvMatrix* pAppendTransform = (const OdTvMatrix*)(pTransform); if (pAppendTransform) { m_appendTransform = *pAppendTransform; } else { m_appendTransform = OdTvMatrix::kIdentity; } } OdIntPtr OdTvVisualizeNwFilerProperties::getAppendTransform() const { return (OdIntPtr)(&m_appendTransform); } ///////////////////////////////////////////////// void OdTvVisualizeNwFilerProperties::setFeedbackForChooseCallback(OdIntPtr pCallback) { m_pCallback = (OdTvFeedbackForChooseCallback)pCallback; } OdIntPtr OdTvVisualizeNwFilerProperties::getFeedbackForChooseCallback() const { return (OdIntPtr)m_pCallback; } void OdTvVisualizeNwFilerProperties::setFeedbackForChooseFileCallback(OdIntPtr pCallback) { m_pFileCallback = (OdNwChooseFileCallback)pCallback; } OdIntPtr OdTvVisualizeNwFilerProperties::getFeedbackForChooseFileCallback() const { return (OdIntPtr)m_pFileCallback; } //***************************************************************************// // 'OdTvVisualizeNwFiler' methods implementation //***************************************************************************// //low memory import functions template OdTvResult initLowMemoryImportTableRecord(const T& tvTableRecordId) { OdTvResult res = tvOk; auto pTvTableRecord = tvTableRecordId.openObject(OdTv::kForWrite); res = pTvTableRecord->addPartialViewIndex(false); return res; } // OdTvVisualizeNwFiler::OdTvVisualizeNwFiler() : OdTvVisualizeFiler() , m_properties(OdTvVisualizeNwFilerProperties::createObject()) , m_pDl(nullptr) { } OdTvVisualizeNwFiler::~OdTvVisualizeNwFiler() { } OdTvDatabaseId OdTvVisualizeNwFiler::loadFrom(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { LoadNwOptions opt(filePath); return importFile(opt, pProfileRes, rc); } static bool isFileReadable(const OdString& pcFilename) { int mode = Oda::kFileRead; #if defined(_MSC_VER) && !defined(_WIN32_WCE) // SetErrorMode() function is used to avoid the message box // if there is no floppy disk in the floppy drive (CR 2122). int oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); bool res = (_waccess(pcFilename, (GETBIT(mode, Oda::kFileRead) ? 0x04 : 0x00) | (GETBIT(mode, Oda::kFileWrite) ? 0x02 : 0x00)) == 0); SetErrorMode(oldErrorMode); if (res) { struct _stat st; _wstat(pcFilename, &st); if (st.st_mode & _S_IFDIR) return false; } return res; #elif defined(sgi) // Use this version, since try/catch below results in memory leaks on sgi (OdError destructor doesn't get called). OdString sMode = (mode == Oda::kFileRead) ? OD_T("rb") : OD_T("wb"); FILE* fp = fopen((const char*)pcFilename, (const char*)sMode); if (fp) { fclose(fp); return true; } return false; #elif defined(__linux__) bool res = false; if (GETBIT(mode, Oda::kFileRead) != 0x00) { std::ifstream ifile(OdAnsiString(pcFilename).c_str()); res = (bool)ifile; } if (res && (GETBIT(mode, Oda::kFileWrite) != 0x00)) { std::ofstream ofile(OdAnsiString(pcFilename).c_str()); res = (bool)ofile; } return res; #elif defined(__APPLE__) struct stat buf; return (stat(OdAnsiString(pcFilename).c_str(), &buf) == 0); #else ODA_ASSERT(false); #endif } static OdString nwSanitizePath(const OdString& path) { OdString sToFindSanitized = path; sToFindSanitized.replace('\\', '/'); // win to lin return sToFindSanitized; } static OdString nwExtractFileName(const OdString& path) { // get filename with extension OdString sToFindSanitized = nwSanitizePath(path); const int lastDelimiter = sToFindSanitized.reverseFind('/'); if (-1 == lastDelimiter) return path; // no delimiter return sToFindSanitized.mid(lastDelimiter + 1); } static OdString nwExtractFileDir(const OdString& path) { // get filename with extension OdString sToFindSanitized = nwSanitizePath(path); const int lastDelimiter = sToFindSanitized.reverseFind('/'); if (-1 == lastDelimiter) return L""; // no folder return sToFindSanitized.left(lastDelimiter); } static OdResult findPathToFile(const OdString& sCurrentPath, OdString &sFileToFind) { // if original file exists return it if (isFileReadable(sFileToFind)) return eOk; // get filename with extension OdString sToFindSanitized = nwSanitizePath(sFileToFind); const int lastDelimiter = sToFindSanitized.reverseFind('/'); if (-1 == lastDelimiter) return eFileAccessErr; // no delimiter - no file // At this moment there is no file in current folder // gte name ie. test.txt OdString sStrippedName = nwExtractFileName(sToFindSanitized); if (sStrippedName.isEmpty()) return eFileAccessErr; OdString sFileInCurrentPath = (sCurrentPath); if (sFileInCurrentPath.isEmpty() || ('/' != sFileInCurrentPath[sFileInCurrentPath.getLength() - 1])) { sFileInCurrentPath += "/"; } sFileInCurrentPath += sStrippedName; const bool bFound = isFileReadable(sFileInCurrentPath); if (bFound) { sFileToFind = sFileInCurrentPath; } return bFound ? eOk : eFileAccessErr; } static OdString convertFormatToNwc(const OdString& pathToFile) { OdString res; if (pathToFile.find('.') > 0) res = pathToFile.left(pathToFile.reverseFind('.')) + OD_T(".nwc"); return res; } void OdTvVisualizeNwFiler::loadNwf(OdTvDatabaseId tvDbId, OdNwDatabasePtr pNwDb, OdTvFilerTimer &timing, OdTvFilerTimeProfiling* pProfileRes) const { OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); // // prepare Visualize timing object // OdPerfTimerBase* pTvTimer = nullptr; double nTotalTvTime = 0.; bool bUseTimeProfiling = (NULL != pProfileRes); if (bUseTimeProfiling) pTvTimer = OdPerfTimerBase::createTiming(); START_TV_NW_TIMER OdTvGsViewId tvViewId; OdTvGsViewPtr pTvView; if (auto nwViewId = pNwDb->getCurrentViewId()) { OdTvGsViewBackgroundId bkgId = setupBackground(pNwDb->getBackgroundElementId(), pTvDb); OdString deviceName; if (auto nwCurrSheetId = pNwDb->getActiveSheetId()) { OdNwSheetInfoPtr pNwCurrSheet = nwCurrSheetId.safeOpenObject(); deviceName = pNwCurrSheet->getDisplayName(); } if (deviceName.isEmpty()) deviceName = OD_T("Window_NW"); OdTvGsDeviceId tvDeviceId = pTvDb->createDevice(deviceName); // sheet name // apply background color ODCOLORREF* pColor = (ODCOLORREF*)(m_properties->getBackgroundColor()); tvDeviceId.openObject(OdTv::kForWrite)->setBackgroundColor(*pColor); OdNwSheetInfoPtr pSheetInfo = pNwDb->getActiveSheetId().safeOpenObject(); tvViewId = setupCurrentView(nwViewId, tvDeviceId, OdTvModelId(), bkgId, pSheetInfo->getSheetType() == NwSheetType::Sheet3d, pNwDb->getHeadlightElementId(), !m_properties->getImportLights()); // get Clipping planes if (m_properties->getImportCuttingPlanes()) { if (auto nwClipPlaneSetId = pNwDb->getCurrrentViewClippingPlanesId()) setupCurrentClipPlane(nwClipPlaneSetId, tvViewId); } } //2. Prepare profiling structure OdTvViewerDatabaseInfo databaseInfo; databaseInfo.setFilePath(pNwDb->getFilename().c_str()); databaseInfo.setType(OdTvViewerDatabaseInfo::kImport); END_TV_NW_TIMER // destroy tv timer if (pTvTimer) OdPerfTimerBase::destroyTiming(pTvTimer); OdNwObjectIdArray aModels; pNwDb->getModels(aModels); OdString strBaseFileDir = nwExtractFileDir(pNwDb->getFilename()); NwModelUnits::Enum databaseUnits = pNwDb->getUnits(); //VAS: since tv database hasn't api method like setUnits and set units for tv db from first tv model - we make such 'hack' for setting units from nwf file for correct work with viewpoint data(wich in wcs with units from nwf) //for example there can be case when units for model from nwf will be not eqaul to model from _2Visualize, such as in .ifc files(maybe this is bug of naviswork) auto tvTempModelForUnits = pTvDb->createModel(OD_T("tempForUnits")); auto convertNwUnitsToTv = [](NwModelUnits::Enum nwUnits)->OdTv::Units { switch (nwUnits) { case NwModelUnits::UNITS_METERS: return OdTv::kMeters; break; case NwModelUnits::UNITS_CENTIMETERS: return OdTv::kCentimeters; break; case NwModelUnits::UNITS_MILLIMETERS: return OdTv::kMillimeters; break; case NwModelUnits::UNITS_FEET: return OdTv::kFeet; break; case NwModelUnits::UNITS_INCHES: return OdTv::kInches; break; case NwModelUnits::UNITS_YARDS: return OdTv::kYards; break; case NwModelUnits::UNITS_KILOMETERS: return OdTv::kKilometers; break; case NwModelUnits::UNITS_MILES: return OdTv::kMiles; break; case NwModelUnits::UNITS_MICROMETERS: return OdTv::kMicrometers; break; case NwModelUnits::UNITS_MILS: return OdTv::kMils; break; case NwModelUnits::UNITS_MICROINCHES: return OdTv::kMicroInches; break; default: return OdTv::kUserDefined; break; } }; auto convertTvUnitsToNv = [](OdTv::Units tvUnits)->NwModelUnits::Enum { switch (tvUnits) { case OdTv::kMeters: return NwModelUnits::UNITS_METERS; break; case OdTv::kCentimeters: return NwModelUnits::UNITS_CENTIMETERS; break; case OdTv::kMillimeters: return NwModelUnits::UNITS_MILLIMETERS; break; case OdTv::kFeet: return NwModelUnits::UNITS_FEET; break; case OdTv::kInches: return NwModelUnits::UNITS_INCHES; break; case OdTv::kYards: return NwModelUnits::UNITS_YARDS; break; case OdTv::kKilometers: return NwModelUnits::UNITS_KILOMETERS; break; case OdTv::kMiles: return NwModelUnits::UNITS_MILES; break; case OdTv::kMicrometers: return NwModelUnits::UNITS_MICROMETERS; break; case OdTv::kMils: return NwModelUnits::UNITS_MILS; break; case OdTv::kMicroInches: return NwModelUnits::UNITS_MICROINCHES; break; default: return NwModelUnits::UNITS_METERS; break; } }; tvTempModelForUnits.openObject()->setUnits(convertNwUnitsToTv(databaseUnits)); OdInt64 iReadTime = 0; OdInt64 iCdaTime = 0; OdInt64 iTvTime = 0; OdTvDCRect rectDC = *(OdTvDCRect*)m_properties->getDCRect(); bool isNeedCdaTree = m_properties->getNeedCDATree(); bool isNeedCdaProps = m_properties->getNeedCollectPropertiesInCDA(); auto fillTbBaseParams = [isNeedCdaTree, isNeedCdaProps, &databaseInfo](OdTvBaseImportParams& tvBaseImportParams, const OdString& strSubFilePath) { tvBaseImportParams.setFilePath(strSubFilePath); tvBaseImportParams.setProfiling(&databaseInfo); tvBaseImportParams.setNeedCDATree(isNeedCdaTree); tvBaseImportParams.setNeedCollectPropertiesInCDA(isNeedCdaProps); }; for (OdNwObjectIdArray::const_iterator it = aModels.begin(); it != aModels.end(); ++it) { if (!*it) continue; OdNwModelPtr pModel = it->safeOpenObject(); if (pModel.isNull()) continue; OdTvModelId lastTvModelId; bool isRv = false; { OdTvMatrix modelTrm = pModel->getTransform(); if (pModel->getUnits() != databaseUnits) OdNwUnitUtils::convertMatrix3d(modelTrm, databaseUnits, pModel->getUnits()); OdString strSubFilePath = pModel->getPath(); OdString sPluginName = pModel->getPluginName(); //check by plugin name - is reference to nwd/nwc model bool isNw = !sPluginName.iCompare(OD_T("lcodpody")) || !sPluginName.iCompare(OD_T("lcodpody_13")) || !sPluginName.iCompare(OD_T("nwexportrevit")) || !sPluginName.iCompare(OD_T("LcOpNwcPlugin")); OdResult isPathValid = findPathToFile(strBaseFileDir, strSubFilePath); if (isPathValid != eOk) { //if path to model is not valid - try to find it by callback with file choosing auto pChooseDirCallback = (OdNwChooseFileCallback)m_properties->getFeedbackForChooseFileCallback(); if (pChooseDirCallback) { strSubFilePath = pChooseDirCallback(strSubFilePath); if (!strSubFilePath.isEmpty()) isPathValid = eOk; } } if (!isNw && m_properties->getReplaceByNwc()) { strSubFilePath = convertFormatToNwc(strSubFilePath); isPathValid = findPathToFile(strBaseFileDir, strSubFilePath); isNw = isPathValid == eOk; } if (isPathValid == eOk) { OdTvResult res = tvOk; if (isNw) { OdTvNwAppendParams oImportParams; fillTbBaseParams(oImportParams, strSubFilePath); oImportParams.setTransform(modelTrm); oImportParams.setDCRect(rectDC); oImportParams.setImportRecap(m_properties->getImportRecap()); oImportParams.setFeedbackForChooseFileCallback((OdNwChooseFileCallback)m_properties->getFeedbackForChooseFileCallback()); oImportParams.setReflectionEnvironmentFileName(m_properties->getReflectionEnvFile()); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lclddwg"))) { OdTvDwgAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); oImportParams.setDCRect(rectDC); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lclddgn"))) { OdTvDgnAppendParams oImportParams; oImportParams.setTransform(modelTrm); oImportParams.setFilePath(strSubFilePath.c_str()); oImportParams.setProfiling(&databaseInfo); oImportParams.setDCRect(rectDC); oImportParams.setNeedCDATree(m_properties->getNeedCDATree()); oImportParams.setNeedCollectPropertiesInCDA(m_properties->getNeedCollectPropertiesInCDA()); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldrevit"))) { isRv = true; OdTvBimAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); oImportParams.setDCRect(rectDC); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldfeaifc")) || !sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldifc"))) { OdTvIfcAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldrc"))) { OdTvRcsAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldsw"))) { OdTvSwAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); oImportParams.setDCRect(rectDC); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldstl"))) { OdTvStlAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldobj"))) { OdTvObjAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); lastTvModelId = pTvDb->append(&oImportParams, &res); } else if (!sPluginName.iCompare(OD_T("LcNwcLoaderPlugin:lcldstep"))) { OdTvStepAppendParams oImportParams; oImportParams.setTransform(modelTrm); fillTbBaseParams(oImportParams, strSubFilePath); oImportParams.setDCRect(rectDC); lastTvModelId = pTvDb->append(&oImportParams, &res); } else { ODA_ASSERT(!OD_T("Currently unsupported file format for export with .nwf.\n")); } ODA_ASSERT(tvOk == res); } } //if model is added - then need to process it for correct work in .nwf if (!lastTvModelId.isNull()) { //add model to view if (!pTvView.isNull()) pTvView->addModel(lastTvModelId); OdTvModelPtr pTvModel = lastTvModelId.openObject(OdTv::kForWrite); if (!pTvModel.isNull()) { //if there is override units then set it if (pModel->hasOverride(NwModelOverrideFlags::kUnitOverride)) { auto tvOverrideModelUnits = convertNwUnitsToTv(pModel->getUnits()); pTvModel->setUnits(tvOverrideModelUnits); } //need to remove all lights from tv model if there is such auto tvModelEntityIterator = pTvModel->getEntitiesIterator(); while (!tvModelEntityIterator->done()) { auto tvEntId = tvModelEntityIterator->getEntity(); if (tvEntId.getType() == OdTvEntityId::kLight) pTvModel->removeEntity(tvEntId); else if (isRv && tvEntId.getType() == OdTvEntityId::kEntity) { //revit files has their own visual style on entities and subentities - set them ignore visual style for all of them auto pTvEnt = tvEntId.openObject(OdTv::kForWrite); pTvEnt->setIgnoreVisualStyle(true); } tvModelEntityIterator->step(); } //add ligtings from .nwf to first tv model, if there is option for lights import in true if (m_properties->getImportLights() && it == aModels.begin()) { setupLights(lastTvModelId, [pNwDb]() { return pNwDb->getSavedItemsElement(NwSavedItemsElementType::kLights); }, [this, strBaseFileDir](OdString& sIES) { if (findPathToFile(strBaseFileDir, sIES) == eOk) return true; auto pChooseDirCallback = (OdNwChooseFileCallback)m_properties->getFeedbackForChooseFileCallback(); if (pChooseDirCallback) { auto sNewIES = pChooseDirCallback(sIES); if (!sNewIES.isEmpty()) { sIES = sNewIES; return true; } } return false; }, pNwDb->getCurrentViewId(), tvViewId); } } } iReadTime += databaseInfo.getImportTime(); iCdaTime += databaseInfo.getCDATreeCreationTime(); iTvTime += databaseInfo.getTvTime(); } //VAS: remove unnecesary temp model pTvDb->removeModel(tvTempModelForUnits); // fill time profiling if (pProfileRes) { pProfileRes->setImportTime(iReadTime); pProfileRes->setCDATreeCreationTime(iCdaTime); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64(nTotalTvTime * 1000.) + iTvTime); #endif } } void OdTvVisualizeNwFiler::loadNwd(OdTvDatabaseId tvDbId, OdNwDatabasePtr pNwDb, OdTvFilerTimer &timing, OdTvFilerTimeProfiling* pProfileRes) const { OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); // get default color from properties ODCOLORREF* pDefColor = (ODCOLORREF*)m_properties->getDefaultNwColor(); OdUInt8 r, g, b; r = ODGETRED(*pDefColor); g = ODGETGREEN(*pDefColor); b = ODGETBLUE(*pDefColor); // // prepare Visualize timing object // OdPerfTimerBase* pTvTimer = nullptr; double nTotalTvTime = 0.; bool bUseTimeProfiling = (NULL != pProfileRes); if (bUseTimeProfiling) pTvTimer = OdPerfTimerBase::createTiming(); START_TV_NW_TIMER //generate model name OdString modelName; bool bSheet3d = true; if (auto nwCurrSheetId = pNwDb->getActiveSheetId()) { OdNwSheetInfoPtr pNwCurrSheet = nwCurrSheetId.safeOpenObject(); modelName = pNwCurrSheet->getDisplayName(); bSheet3d = NwSheetType::Sheet3d == pNwCurrSheet->getSheetType(); } modelName.replace('.', '_'); if (modelName.isEmpty()) modelName = OD_T("nwModel"); //create tv model OdTvResult tvRes = tvOk; OdTvModelId tvModelId = pTvDb->createModel(modelName, OdTvModel::kMain, true, &tvRes); if (tvRes == tvInvalidName) { //it's forrbiden to create tv unique objects(layers, blocks, materials, backgrounds and etc.) with inadmissible control letters, so for correct export need to remove those characters from name for (auto ch : { '<', '>', '\\', '/', ':', ';', '?', ',', '*', '|', '=', '\'', ' ', '\"' }) modelName.remove(ch); tvModelId = pTvDb->createModel(modelName, OdTvModel::kMain, true, &tvRes); } //here we also will create a device and view, becuase we want the Shaded initial mode OdTvGsDeviceId tvDeviceId = pTvDb->createDevice(modelName); ODCOLORREF* pColor = (ODCOLORREF*)(m_properties->getBackgroundColor()); tvDeviceId.openObject(OdTv::kForWrite)->setBackgroundColor(*pColor); OdTvGsViewBackgroundId bkgId = setupBackground(pNwDb->getBackgroundElementId(), pTvDb); OdTvGsViewId viewId = setupCurrentView(pNwDb->getCurrentViewId(), tvDeviceId, tvModelId, bkgId, bSheet3d, pNwDb->getHeadlightElementId(), !m_properties->getImportLights()); END_TV_NW_TIMER if (m_properties->getLowMemoryImportToVSF()) { initLowMemoryImportTableRecord(tvModelId); } OdTvGeomCollector wd(bUseTimeProfiling); OdNwObjectIdArray aModels; if (pNwDb->getModels(aModels) != eOk) return; ODA_ASSERT(aModels.size() == 1); OdNwModelPtr pModel = aModels[0].openObject(); //map for connection between nw objects and tv objects, for current moment is need only for animation mapNwObjId2TvIdsType mNwObjId2TvObjId; { std::function m_findReferenceCallback = [pNwDb, this](OdString& sPath, OdStreamBufPtr& pStreamBuf) mutable { return this->getEmbeddedFileResolver(pNwDb, sPath, pStreamBuf); }; const OdString& sTempPath = m_properties->getTempDirectoryPath(); OdNwGeometryImport(tvDbId, pTvTimer, nTotalTvTime, (ODCOLORREF*)m_properties->getDefaultNwColor(), { m_properties->getNeedCDATree(), m_properties->getStoreSourceObjects(), m_properties->getLowMemoryImportToVSF(), m_properties->getNeedGroupsUsing(), m_properties->getImportRefGeomAsInserts(), m_properties->getImportRecap(), m_properties->getImportRecapAsRcsPointCloud(), m_findReferenceCallback }, m_properties->getReflectionEnvFile(), m_properties->getImportAnimation() ? &mNwObjId2TvObjId : nullptr, pModel->getUnits(), pNwDb->getSavedItemsElement(NwSavedItemsElementType::kMaterial), !sTempPath.isEmpty() ? [sTempPath](const OdString& sFileName, const OdString& sExt) -> OdString { if (sTempPath.isEmpty()) return OdString::kEmpty; return NwPathUtils::join(sTempPath, sFileName + sExt); } : std::function() ).importLH(pModel->getRootItem(), tvModelId); } { //get ambient scene light from root partition - in case if current viewpoint is set in 'scene light' mode and there is no original cad lights OdNwPartitionPtr pPartition = pModel->getRootItem().openObject(); auto ambientSceneLight = pPartition->getAmbientSceneLights(); setupLights(tvModelId, [this, pNwDb]() { if (m_properties->getImportLights()) return pNwDb->getSavedItemsElement(NwSavedItemsElementType::kLights); else return OdNwObjectId(); },[this, pNwDb](OdString& sIES) mutable { if (auto pAppSrv = pNwDb->appServices()) { auto sNewIES = pAppSrv->findFile(sIES, pNwDb, OdDbBaseHostAppServices::kPhotometricWebFile); if (!sNewIES.isEmpty()) { sIES = sNewIES; return true; } } auto pChooseDirCallback = (OdNwChooseFileCallback)m_properties->getFeedbackForChooseFileCallback(); if (pChooseDirCallback) { auto sNewIES = pChooseDirCallback(sIES); if (!sNewIES.isEmpty()) { sIES = sNewIES; return true; } } return false; } , pNwDb->getCurrentViewId(), viewId, &ambientSceneLight); } START_TV_NW_TIMER if (m_properties->getImportAnimation()) { OdTvNwSavedAnimationEnumerator savedAnimEnum(pNwDb->getSavedItemsElement(NwSavedItemsElementType::kSavedAnimation), pTvDb, tvModelId, std::move(mNwObjId2TvObjId)); savedAnimEnum.feedAnimation(); } if (m_properties->getImportGrid()) { setupGrid(pNwDb, tvDbId, viewId, tvModelId.openObject()->getName()); } //import saved views if (m_properties->getImportSavedViewpoints()) { setupSavedViews(pNwDb->getSavedItemsElement(NwSavedItemsElementType::kSavedViews), tvDeviceId, tvModelId); } // get Clipping planes if (m_properties->getImportCuttingPlanes()) { if (auto nwClipPlaneSetId = pNwDb->getCurrrentViewClippingPlanesId()) setupCurrentClipPlane(nwClipPlaneSetId, viewId); } END_TV_NW_TIMER // destroy tv timer if (pTvTimer) OdPerfTimerBase::destroyTiming(pTvTimer); if (m_properties->getNeedCDATree()) { timing.startMisc(); createCommonDataAccessTree(pTvDb, pNwDb, modelName + OD_T(".nwd"), tvModelId); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(pProfileRes->getCDATreeCreationTime() + OdInt64((timing.getMiscTime()) * 1000.)); } if (pProfileRes) { #if !defined(__APPLE__) pProfileRes->setTvTime(pProfileRes->getTvTime() + OdInt64(nTotalTvTime * 1000.)); #endif } } OdTvDatabaseId OdTvVisualizeNwFiler::loadFrom(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { LoadNwOptions opt(pBuffer); return importFile(opt, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeNwFiler::loadFrom(OdDbBaseDatabase* pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { LoadNwOptions opt(pDatabase); return importFile(opt, pProfileRes, rc); } OdTvModelId OdTvVisualizeNwFiler::appendFrom(const OdTvDatabaseId& databaseId, OdTvVisualizeNwFilerDbSource *pNwDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvModelId tvModelId; if (rc) *rc = tvOk; 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; if (!activeTvGsDeviceId.isNull()) { 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)); } } //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 internalTiming = 0.; double externalTiming = 0; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); // Generate model name OdString modelName = OdTvDatabaseUtils::generateModelName(databaseId, pNwDatabaseSource->getFilename()); //store visualize device module name OdString moduleName; try { OdNwDatabasePtr pNwDb = pNwDatabaseSource->getDb(); if (!pNwDb.isNull()) { timing.startVectorizing(); // // prepare Visualize timing object // OdPerfTimerBase* pTvTimer = nullptr; double nTotalTvTime = 0.; bool bUseTimeProfiling = (NULL != pProfileRes); if (bUseTimeProfiling) pTvTimer = OdPerfTimerBase::createTiming(); START_TV_NW_TIMER //create tv model OdTvDatabasePtr pTvDb = databaseId.openObject(OdTv::kForWrite); tvModelId = pTvDb->createModel(modelName); END_TV_NW_TIMER OdTvGeomCollector wd(bUseTimeProfiling); mapNwObjId2TvIdsType selectedModels; OdNwSheetInfoPtr pSheetInfo = pNwDb->getActiveSheetId().safeOpenObject(); OdNwObjectIdArray aModels; if (pNwDb->getModels(aModels) != eOk) return OdTvModelId(); ODA_ASSERT(aModels.size() == 1); OdNwModelPtr pModel = aModels[0].openObject(); std::function m_findReferenceCallback = [pNwDb, this](OdString& sPath, OdStreamBufPtr& pStreamBuf) mutable { return this->getEmbeddedFileResolver(pNwDb, sPath, pStreamBuf); }; const OdString& sTempPath = m_properties->getTempDirectoryPath(); OdNwGeometryImport(databaseId, pTvTimer, nTotalTvTime, (ODCOLORREF*)m_properties->getDefaultNwColor(), { m_properties->getNeedCDATree(), m_properties->getStoreSourceObjects(), m_properties->getLowMemoryImportToVSF(), m_properties->getNeedGroupsUsing(), m_properties->getImportRefGeomAsInserts(), m_properties->getImportRecap(), m_properties->getImportRecapAsRcsPointCloud(), m_findReferenceCallback }, m_properties->getReflectionEnvFile(), nullptr, pModel->getUnits(), pNwDb->getSavedItemsElement(NwSavedItemsElementType::kMaterial), !sTempPath.isEmpty() ? [sTempPath](const OdString& sFileName, const OdString& sExt) -> OdString { if (sTempPath.isEmpty()) return OdString::kEmpty; return NwPathUtils::join(sTempPath, sFileName + sExt); } : std::function() ).importLH(pModel->getRootItem(), tvModelId); START_TV_NW_TIMER //VAS: if properties has device for append then need to add model to active view from this device(need to correct work appendFrom functionality) if (!m_properties->getTvDeviceToAppend().isNull()) { OdTvGsDevicePtr pTvDeviceToAppend = m_properties->getTvDeviceToAppend().openObject(OdTv::kForWrite); if (!pTvDeviceToAppend.isNull()) { OdTvGsViewId viewId = pTvDeviceToAppend->getActiveView(); if (!viewId.isNull()) { OdTvGsViewPtr pView = viewId.openObject(OdTv::kForWrite); pView->addModel(tvModelId, rc); } } } END_TV_NW_TIMER // destroy tv timer if (pTvTimer) OdPerfTimerBase::destroyTiming(pTvTimer); //pTvDevice->update(&rect); if (databaseId.isValid()) { timing.startMisc(); OdTvDatabaseId& tvDvId = const_cast(databaseId); OdTvDatabaseCleaner::cleanTvDatabaseForAppend(tvDvId, foreignViews, foreignModels, foreignBlocks); //apply transform if need OdTvMatrix* pTransfrom = (OdTvMatrix*)m_properties->getAppendTransform(); if (pTransfrom) { OdTvDatabaseId& tvDvId = const_cast(databaseId); if (m_properties->getReplaceByNwc()) OdTvDatabaseUtils::applyTransformToTheModel(tvDvId, modelName, *pTransfrom); else OdTvDatabaseUtils::applyTransformToTheModel(tvDvId, modelName, *pTransfrom); } timing.endMisc(); } // save file name to database user data OdTvDatabaseUtils::writeFileNameToTvDatabase(databaseId, pNwDatabaseSource->getFilename()); //initialize cache and switch it to the "write only" mode ExGsVisualizeDeviceCache deviceCache; deviceCache.m_bApplyCacheData = false; externalTiming = timing.getMiscTime(); timing.endVectorizing(); { OdTvDatabaseId& tvDbId = const_cast(databaseId); if (activeTvGsDeviceId.isNull()) { //create preferable Visual styles createAndApplyPreferableVS_NW(tvDbId); OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); } else { if (tvDbId.openObject()->getPreferableVisualStyle(OdTvDatabase::kCustom).isNull()) OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); } } if (m_properties->getNeedCDATree()) { timing.startMisc(); OdTvDatabasePtr pTvDb = databaseId.openObject(); createCommonDataAccessTree(pTvDb, pNwDb, modelName + OD_T(".nwd"), tvModelId); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); } } else { if (rc) *rc = tvFilerEmptyInternalDatabase; } } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //unload Dgn modules (try to emulate the OdUninitialized for Nw) //here we will unload all including Visualize device odrxDynamicLinker()->unloadUnreferenced(); timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64((timing.getTotalTime() - timing.getVectorizingTime() + pNwDatabaseSource->getInitTime()) * 1000.)); pProfileRes->setVectorizingTime(OdInt64(timing.getVectorizingTime() * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((internalTiming + externalTiming) * 1000.)); #endif } return tvModelId; } static void addBoundingBoxVisualization(OdTvEntityPtr entity, const OdGeExtents3d& bbox, const OdTvColorDef& color, OdGeMatrix3d trf = OdGeMatrix3d::kIdentity) { entity->setColor(color); const OdGePoint3d& minP = bbox.minPoint(); const OdGePoint3d& maxP = bbox.maxPoint(); OdTvPoint points_top[4] = { {minP.x, maxP.y, maxP.z}, {minP.x, minP.y, maxP.z}, {maxP.x, minP.y, maxP.z}, {maxP.x, maxP.y, maxP.z} }; OdTvPoint points_bottom[4] = { {maxP.x, minP.y, minP.z}, {maxP.x, maxP.y, minP.z}, {minP.x, maxP.y, minP.z}, {minP.x, minP.y, minP.z} }; OdTvPoint points_right[4] = { {minP.x, minP.y, maxP.z}, {minP.x, minP.y, minP.z}, {maxP.x, minP.y, minP.z}, {maxP.x, minP.y, maxP.z} }; OdTvPoint points_left[4] = { {maxP.x, maxP.y, minP.z}, {maxP.x, maxP.y, maxP.z}, {minP.x, maxP.y, maxP.z}, {minP.x, maxP.y, minP.z} }; entity->appendPolyline(4, points_top); entity->appendPolyline(4, points_bottom); entity->appendPolyline(4, points_right); entity->appendPolyline(4, points_left); if (trf != OdGeMatrix3d::kIdentity) entity->setModelingMatrix(trf); } static bool isModelItemClipped(const OdNwModelItemPtr& item, const OdGeMatrix3d& clipMatr) { OdGeExtents3d bbox = item->getBoundingBox(); OdGeMatrix3d invertMatrix = clipMatr; bbox.transformBy(invertMatrix.invert()); static const OdGeExtents3d clipbox ( OdGePoint3d(-0.5, -0.5, -0.5), OdGePoint3d(0.5, 0.5, 0.5)); return bbox.intersectWith(clipbox) == OdGeExtents3d::kIntersectNot; } OdTvGsViewBackgroundId OdTvVisualizeNwFiler::setupBackground(const OdNwObjectId& nwBackGroundId, OdTvDatabasePtr pTvDb) const { OdTvGsViewBackgroundId tvBckId; if (nwBackGroundId) { OdNwBackgroundElementPtr pNwBackGround = nwBackGroundId.safeOpenObject(); switch (pNwBackGround->getBackgroundType()) { case NwBackgroundType::HORIZON: { tvBckId = pTvDb->createBackground(OdString().format(OD_T("HorizonColor_%llu"), (OdUInt64)nwBackGroundId.getHandle()), OdTvGsViewBackgroundId::kGradient); if (!tvBckId.isNull()) { OdTvGsViewGradientBackgroundPtr pGradientBackground = tvBckId.openAsGradientBackground(OdTv::kForWrite); OdNwColor skyColor, skyHorizonColor, groundColor, groundHorizonColor; pNwBackGround->getHorizonColor(skyColor, skyHorizonColor, groundHorizonColor, groundColor); pGradientBackground->setColorTop(OdTvColorDef(ODGETRED(skyColor.ToColor()), ODGETGREEN(skyColor.ToColor()), ODGETBLUE(skyColor.ToColor()))); pGradientBackground->setColorMiddle(OdTvColorDef(ODGETRED(groundHorizonColor.ToColor()), ODGETGREEN(groundHorizonColor.ToColor()), ODGETBLUE(groundHorizonColor.ToColor()))); pGradientBackground->setColorBottom(OdTvColorDef(ODGETRED(groundColor.ToColor()), ODGETGREEN(groundColor.ToColor()), ODGETBLUE(groundColor.ToColor()))); pGradientBackground->setHeight(0.33); pGradientBackground->setHorizon(0.5); } break; } case NwBackgroundType::GRADUATED: { tvBckId = pTvDb->createBackground(OdString().format(OD_T("GraduatedColor_%llu"), (OdUInt64)nwBackGroundId.getHandle()), OdTvGsViewBackgroundId::kGradient); if (!tvBckId.isNull()) { OdTvGsViewGradientBackgroundPtr pGradientBackground = tvBckId.openAsGradientBackground(OdTv::kForWrite); OdNwColor topColor, bottomColor, plainColor; pNwBackGround->getGraduatedColor(topColor, bottomColor); pNwBackGround->getPlainColor(plainColor); pGradientBackground->setColorTop(OdTvColorDef(ODGETRED(topColor.ToColor()), ODGETGREEN(topColor.ToColor()), ODGETBLUE(topColor.ToColor()))); pGradientBackground->setColorMiddle(OdTvColorDef(ODGETRED(plainColor.ToColor()), ODGETGREEN(plainColor.ToColor()), ODGETBLUE(plainColor.ToColor()))); pGradientBackground->setColorBottom(OdTvColorDef(ODGETRED(bottomColor.ToColor()), ODGETGREEN(bottomColor.ToColor()), ODGETBLUE(bottomColor.ToColor()))); pGradientBackground->setHeight(0.33); pGradientBackground->setHorizon(0.5); } break; } case NwBackgroundType::PLAIN: { tvBckId = pTvDb->createBackground(OdString().format(OD_T("PlainColor_%llu"), (OdUInt64) nwBackGroundId.getHandle()), OdTvGsViewBackgroundId::kSolid); if (!tvBckId.isNull()) { OdTvGsViewSolidBackgroundPtr pGradientBackground = tvBckId.openAsSolidBackground(OdTv::kForWrite); OdNwColor plainColor; pNwBackGround->getPlainColor(plainColor); OdNwPlotPaperStylePtr pPaperStyle = pNwBackGround->getPaperStyle(); if (!pPaperStyle.isNull()) { OdNwColor color = pPaperStyle->getColor(); pGradientBackground->setColorSolid(OdTvColorDef(255.0 * color.R(), 255.0 * color.G(), 255.0 * color.B())); } else { pGradientBackground->setColorSolid(OdTvColorDef(ODGETRED(plainColor.ToColor()), ODGETGREEN(plainColor.ToColor()), ODGETBLUE(plainColor.ToColor()))); } } break; } default: break; } } return tvBckId; } OdTvDatabaseId OdTvVisualizeNwFiler::generate(OdTvFilerTimeProfiling* pProfileRes) const { OdTvDatabaseId tvDbId; // does nothing return tvDbId; } OdTvModelId OdTvVisualizeNwFiler::appendFrom(const OdTvDatabaseId& databaseId, const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeNwFilerSourceFromFile dl(filePath, pProfileRes, m_properties->getTempDirectoryPath()); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizeNwFiler::appendFrom(const OdTvDatabaseId& databaseId, OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeNwFilerSourceFromBuffer dl(pBuffer, pProfileRes); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizeNwFiler::appendFrom(const OdTvDatabaseId& databaseId, OdDbBaseDatabase* pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeNwFilerSourceFromDb dl(pDatabase); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvResult OdTvVisualizeNwFiler::startActionsWithNativeProperties(const OdString& sFilePath, bool bPartial) { if (!m_pDatabaseForNativeProp.isNull() && m_pDatabaseForNativeProp->getFilename() != sFilePath) m_pDatabaseForNativeProp.release(); else if (!m_pDatabaseForNativeProp.isNull()) return tvOk; OdTvResult rc = tvOk; const_cast(this)->m_pDl = new OdTvVisualizeNwFilerSourceFromFile(sFilePath, NULL, m_properties->getTempDirectoryPath()); { if (m_pRxPropertiesModule.isNull()) m_pRxPropertiesModule = ::odrxDynamicLinker()->loadModule(L"RxProperties"); if (m_pNwPropertiesModule.isNull()) m_pNwPropertiesModule = ::odrxDynamicLinker()->loadModule(OdNwPropertiesModuleName); if (m_pNwDatabaseModule.isNull()) m_pNwDatabaseModule = ::odrxDynamicLinker()->loadModule(OdNwDbModuleName); try { m_pDatabaseForNativeProp = m_pDl->getDb(); } catch (...) { return tvFilerEmptyInternalDatabase; } } return rc; } bool OdTvVisualizeNwFiler::isActionsWithNativePropertiesStarted(const OdString& sFilePath) { if (!m_pDatabaseForNativeProp.isNull() && m_pDatabaseForNativeProp->getFilename() == sFilePath) return true; return false; } OdTvResult OdTvVisualizeNwFiler::endActionsWithNativeProperties() { if (!m_pDatabaseForNativeProp.isNull()) m_pDatabaseForNativeProp.release(); if (!m_pNwPropertiesModule.isNull()) { m_pRxPropertiesModule.release(); m_pNwPropertiesModule.release(); m_pNwDatabaseModule.release(); ::odrxDynamicLinker()->unloadModule(L"RxProperties"); ::odrxDynamicLinker()->unloadModule(OdNwPropertiesModuleName); ::odrxDynamicLinker()->unloadModule(OdNwDbModuleName); ::odrxDynamicLinker()->unloadUnreferenced(); if (m_pDl) { delete m_pDl; m_pDl = NULL; } } return tvOk; } OdRxMemberIteratorPtr OdTvVisualizeNwFiler::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); else { OdNwObjectId objectId = m_pDatabaseForNativeProp->getObjectId(dbHandle); if (objectId.isNull()) { if (rc) *rc = tvNativePropMissedObject; return OdRxMemberIteratorPtr(); } pIter = OdRxMemberQueryEngine::theEngine()->newMemberIterator(objectId.openObject()); } if (pIter.isNull()) { if (rc) *rc = tvInternal; return OdRxMemberIteratorPtr(); } if (rc) *rc = tvOk; return pIter; } OdRxValue OdTvVisualizeNwFiler::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(); } OdRxObjectPtr pElement; if (dbHandle == 0) pElement = m_pDatabaseForNativeProp; else { OdNwObjectId objectId = m_pDatabaseForNativeProp->getObjectId(dbHandle); pElement = objectId.openObject(); } if (pElement.isNull()) { if (rc) *rc = tvNativePropMissedObject; return OdRxValue(); } OdRxValue value; OdResult odRes = pProperty->getValue(pElement, value); if (bReadOnly) *bReadOnly = pProperty->isReadOnly(pElement); if (odRes != eOk) { if (rc) *rc = tvInternal; return OdRxValue(); } if (rc) *rc = tvOk; return value; } OdRxValueIteratorPtr OdTvVisualizeNwFiler::getNativeCollectionPropertyIterator(OdUInt64 dbHandle, const OdRxCollectionPropertyPtr& pCollectionProperty, bool* bReadOnly, OdTvResult* rc) { 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); if (bReadOnly) *bReadOnly = pCollectionProperty->isReadOnly(m_pDatabaseForNativeProp); } else { OdNwObjectId objectId = m_pDatabaseForNativeProp->getObjectId(dbHandle); if (objectId.isNull()) { if (rc) *rc = tvNativePropMissedObject; return OdRxValueIteratorPtr(); } pValIter = pCollectionProperty->newValueIterator(objectId.openObject()); if (bReadOnly) *bReadOnly = pCollectionProperty->isReadOnly(objectId.openObject()); } if (rc) *rc = tvOk; return pValIter; } OdTvResult OdTvVisualizeNwFiler::setNativePropertyValue(OdUInt64 dbHandle, OdRxPropertyPtr& pProperty, const OdRxValue& value) { if (pProperty.isNull()) return tvInvalidInput; if (m_pDatabaseForNativeProp.isNull()) return tvNativePropMissedDatabase; OdRxObjectPtr pElement; if (dbHandle == 0) pElement = m_pDatabaseForNativeProp; else { OdNwObjectId objectId = m_pDatabaseForNativeProp->getObjectId(dbHandle); pElement = objectId.openObject(); } if (pElement.isNull()) return tvNativePropMissedObject; pProperty->setValue(pElement, value); return tvOk; } OdDbBaseDatabase* OdTvVisualizeNwFiler::getNativeDatabase(OdTvResult* rc) const { if (m_pDatabaseForNativeProp.isNull()) { if (rc) *rc = tvNativePropMissedDatabase; return NULL; } return (OdDbBaseDatabase*)m_pDatabaseForNativeProp.get(); } void OdTvVisualizeNwFiler::createCommonDataAccessTree(OdTvDatabasePtr pTvDb, OdDbBaseDatabase *pDatabase, const OdString& strTreeName, const OdTvModelId& modelId) const { ::odrxDynamicLinker()->loadModule(OdNwPropertiesModuleName); #ifdef NW_CDAPROPERTIES_ENABLED NwCdaProperties::setDynamicProperties(m_properties->getNeedCollectPropertiesInCDA()); #endif // NW_CDAPROPERTIES_ENABLED //Create CDA tree OdTvCDATreePtr pTree = OdTvCDATree::createObject(); pTree->createDatabaseHierarchyTree(pDatabase, m_properties->getNeedCollectPropertiesInCDA(), true); //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 if (!modelId.isNull()) { OdTvModelPtr pModel = modelId.openObject(); pModel->setCDATreeStorage(cdaTreeId); OdTvCDATreeNodePtr pTvNode = pTree->getDatabaseNode(); if (!pTvNode.isNull()) { const OdRxModelTreeBaseNodePtrArray nodes = pTvNode->getChildren(); for (OdRxModelTreeBaseNodePtrArray::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { OdTvCDATreeNodePtr pNode = *it; if (pNode.isNull()) continue; pNode->setTvModelId(modelId); } } } //mark all nodes that it is not need group nodes OdRxModelTreeBaseNodePtr pDbNode = pTree->getDatabaseNode(); if (!pDbNode.isNull()) OdTvDatabaseUtils::markCDANode(pDbNode.get()); ::odrxDynamicLinker()->unloadModule(OdNwPropertiesModuleName); } OdTvDatabaseId OdTvVisualizeNwFiler::importFile(const LoadNwOptions& opt, OdTvFilerTimeProfiling* pProfileRes /*= NULL*/, OdTvResult* rc /*= NULL*/) const { if (rc) *rc = tvOk; // // prepare Nw Importer timing object // OdTvFilerTimer timing(NULL != pProfileRes); timing.startTotal(); // load Nw database OdStaticRxObject svcs; svcs.setOption(NwOpenOptions::kOptionCacheGeometry, 0); OdUInt32 nMode = 0; if (m_properties->getMultiThreadsCnt() > 1) { SETBIT_1(nMode, 1);// mt load svcs.setNumThreads(m_properties->getMultiThreadsCnt()); } svcs.setMtMode(nMode); const OdString& sTempPath = m_properties->getTempDirectoryPath(); if (!sTempPath.isEmpty()) { svcs.setTempDirectoryPath(sTempPath); svcs.setOption(NwOpenOptions::kOptionSaveEmbd2TmpForView, 1); } OdRxModulePtr pBimNvModule; try { pBimNvModule = ::odrxDynamicLinker()->loadModule(OdNwDbModuleName, false); } catch (...) { if (rc) *rc = tvInternal; timing.endTotal(); } OdNwDatabasePtr pNwDb; switch (opt.m_type) { case LoadNwOptions::kFilePath: { OdString textureFolder = GetRegistryADSKLocation(OdNw::RegistryADSKLocation::TextureLibrary); if (0 == textureFolder.iCompare(L"/") || 0 == textureFolder.iCompare(L"\\")) // if no assets in windows or it is unix textureFolder = nwExtractFileDir(opt.m_filePath) + OD_T("/"); svcs.setTextureDirectoryPath(textureFolder, false); pNwDb = svcs.readFile(opt.m_filePath); break; } case LoadNwOptions::kDatabase: pNwDb = OdNwDatabase::cast(opt.m_pDatabase); break; case LoadNwOptions::kBuffer: pNwDb = svcs.readFile(opt.m_pBuffer); break; } if (pNwDb.isNull()) { if (rc) *rc = tvFilerEmptyInternalDatabase; timing.endTotal(); return OdTvDatabaseId(); } // create tv database OdTvFactoryId tvFactoryId = odTvGetFactory(); OdTvDatabaseId tvDbId = tvFactoryId.createDatabase(); if (m_properties->getLowMemoryImportToVSF()) { auto pTvDb = tvDbId.openObject(OdTv::kForWrite); pTvDb->beginPartialImport(m_properties->getPartialImportDumpFile()); } OdNwObjectIdArray aSheets; OdResult resSheet = pNwDb->getSheets(aSheets); ODA_ASSERT(resSheet == eOk); OdTvFilerFeedbackForChooseObject filerFeedbackForChooseObject(OD_T("Choose sheets for import")); OdTvFilerFeedbackItemForChooseArray* pFilerFeedbackForChooseArray = filerFeedbackForChooseObject.getFilerFeedbackItemForChooseArrayPtr(); for (auto sheetId : aSheets) { if (!sheetId) continue; OdString sSheetName = OdNwSheetInfo::cast(sheetId.safeOpenObject())->getDisplayName(); OdTvFilerFeedbackItemForChoose filerFeedbackForChoose(sSheetName); filerFeedbackForChoose.m_bChosen = true; pFilerFeedbackForChooseArray->append(filerFeedbackForChoose); } timing.endTotal(); double nTotal = timing.getTotalTime(); if (m_properties->getFeedbackForChooseCallback() != 0 && aSheets.size() > 1) { ((OdTvFeedbackForChooseCallback)m_properties->getFeedbackForChooseCallback())(filerFeedbackForChooseObject); if (filerFeedbackForChooseObject.getFilerFeedbackItemForChooseArrayPtr()->length() == 0) { pNwDb.release(); pBimNvModule.release(); ::odrxDynamicLinker()->unloadModule(OdNwDbModuleName); timing.endTotal(); return tvDbId; } timing.startTotal(); timing.startVectorizing(); for (auto sheetId : aSheets) { if (!sheetId) continue; OdNwSheetInfoPtr pNwSheetInfo = sheetId.safeOpenObject(); if (!filerFeedbackForChooseObject.find(OdTvFilerFeedbackItemForChoose(pNwSheetInfo->getDisplayName(), true))) continue; OdString sSheetName = pNwSheetInfo->getSheetId(); pNwDb->setActiveSheet(sSheetName); pNwDb->isComposite() ? loadNwf(tvDbId, pNwDb, timing, pProfileRes) : loadNwd(tvDbId, pNwDb, timing, pProfileRes); } timing.endVectorizing(); } else { timing.startTotal(); // load all sheets timing.startVectorizing(); for (auto sheetId : aSheets) { if (!sheetId) continue; OdNwSheetInfoPtr pNwSheetInfo = sheetId.safeOpenObject(); OdString sSheetName = pNwSheetInfo->getSheetId(); pNwDb->setActiveSheet(sSheetName); pNwDb->isComposite() ? loadNwf(tvDbId, pNwDb, timing, pProfileRes) : loadNwd(tvDbId, pNwDb, timing, pProfileRes); } timing.endVectorizing(); } if (m_properties->getLowMemoryImportToVSF()) { auto pTvDb = tvDbId.openObject(OdTv::kForWrite); pTvDb->endPartialImport(); } //create preferable Visual style for isolines createAndApplyPreferableVS_NW(tvDbId); OdTvDatabaseUtils::checkAndApplyCustomPreferableVS(tvDbId, false); timing.startMisc(); OdTvDatabaseCleaner::cleanTvDatabase(tvDbId); timing.endMisc(); timing.endTotal(); nTotal += timing.getTotalTime(); if (pProfileRes) { OdInt64 iReadTime = pProfileRes->getImportTime(); pProfileRes->setImportTime(iReadTime + OdInt64((nTotal - timing.getVectorizingTime()) * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.) - pProfileRes->getCDATreeCreationTime() - pProfileRes->getTvTime() - iReadTime); } pNwDb = NULL; pBimNvModule.release(); ::odrxDynamicLinker()->unloadModule(OdNwDbModuleName); //here we will unload all including Visualize device odrxDynamicLinker()->unloadUnreferenced(); return tvDbId; } void OdTvVisualizeNwFiler::setupGrid(OdNwDatabasePtr pNwDb, OdTvDatabaseId tvDbId, OdTvGsViewId viewId, OdString modelName) const { OdNwGridSystemElementPtr grsysel = pNwDb->getGridSystemElement(); if (grsysel.isNull()) return; OdArray grsysList; if (grsysel->getGridSystemList(grsysList) != eOk) { return; } OdTvGsViewPtr pTvView = viewId.openObject(OdTv::OpenMode::kForWrite); struct gridLineType { OdGePoint3d a, b, c; NwGridLineSegmentType::Enum type = NwGridLineSegmentType::UNKNOWN; OdString caption; }; typedef std::vector gridType; struct gridLevelType { OdGePoint3d level; OdString name; gridType grid; }; typedef std::vector drawDatagridLevelListType; drawDatagridLevelListType drawDataGridLevelList; OdTvResult textStyleRes; OdTvTextStyleId tvTextStyleId = tvDbId.openObject(OdTv::kForWrite)->createTextStyle(modelName, &textStyleRes); if (textStyleRes != tvOk) { return; } OdTvTextStylePtr pTvTextStyle = tvTextStyleId.openObject(OdTv::kForWrite); OdString typeface = L"Algerian"; OdInt16 charset = 0; OdInt16 family = 34; bool bold = false; bool italic = false; pTvTextStyle->setFont(typeface, bold, italic, charset, family); pTvTextStyle->setAlignmentMode(OdTvTextStyle::kMiddleCenter); pTvTextStyle->setTextSize(2.5); for (OdUInt32 i = 0; i < grsysList.size(); i++) { gridType grid; OdArray gridLineList; OdGeMatrix3d gridSysMatrix = grsysList[i]->getTransform(); OdTvResult gridModelRes; OdTvModelId tvModelId = tvDbId.openObject(OdTv::kForWrite)->createModel(modelName + OD_T("-") + grsysList[i]->getName() + OD_T("_grid"), OdTvModel::Type::kDirect, false, &gridModelRes); pTvView->addModel(tvModelId); OdTvModelPtr pTvModel = tvModelId.openObject(OdTv::OpenMode::kForWrite); OdTvResult titleEntityRes; OdTvEntityId tvTitleId = pTvModel->appendEntity(OD_T("Title"), &titleEntityRes); if (titleEntityRes != tvOk) { return; } OdTvEntityPtr pTvTitle = tvTitleId.openObject(OdTv::kForWrite); pTvTitle->setColor(OdTvColorDef(255, 255, 255)); pTvTitle->setTextStyle(tvTextStyleId); pTvTitle->setAutoRegen(true); if (gridModelRes != tvOk) { return; } if (grsysList[i]->getGridLineList(gridLineList) != eOk) { continue; } for (OdUInt32 j = 0; j < gridLineList.size(); ++j) { gridLineType gridLine; gridLine.caption = gridLineList[j]->getName(); OdArray gridLineSegList; if (gridLineList[j]->getGridLineSegmentList(gridLineSegList) != eOk) { continue; } for (OdUInt32 k = 0; k < gridLineSegList.size(); k++) { gridLine.type = gridLineSegList[k]->getType(); if (gridLineSegList[k]->getType() == NwGridLineSegmentType::Enum::LINE) { OdGePoint2dArray pl = gridLineSegList[k]->getPrimPointList(); gridLine.a = OdGePoint3d(pl[0].x, pl[0].y, 0); gridLine.a.transformBy(gridSysMatrix); gridLine.b = OdGePoint3d(pl[1].x, pl[1].y, 0); gridLine.b.transformBy(gridSysMatrix); } else if (gridLineSegList[k]->getType() == NwGridLineSegmentType::Enum::CIRCLE) { OdGePoint2dArray pl = gridLineSegList[k]->getPrimPointList(); gridLine.a = OdGePoint3d(pl[2].x, pl[2].y, 0); gridLine.b = OdGePoint3d(pl[1].x, pl[1].y, 0); gridLine.c = OdGePoint3d(pl[0].x, pl[0].y, 0); gridLine.a.transformBy(gridSysMatrix); gridLine.b.transformBy(gridSysMatrix); gridLine.c.transformBy(gridSysMatrix); } grid.push_back(gridLine); } } OdArray gridLevelList; if (grsysList[i]->getGridLevelList(gridLevelList) != eOk) { continue; } for (OdUInt32 m = 0; m < gridLevelList.size(); ++m) { OdTvResult gridLevelEntityRes; OdString entName = grsysList[i]->getName(); OdTvEntityId tvGridLevelEntityId = tvModelId.openObject(OdTv::kForWrite)->appendEntity(entName, &gridLevelEntityRes); if (gridLevelEntityRes != tvOk) { continue; } auto pTvGridLevelEntity = tvGridLevelEntityId.openObject(OdTv::OpenMode::kForWrite); pTvGridLevelEntity->setColor(OdTvColorDef(255, 0, 0), OdTvGeometryData::kAll); for (auto & l : grid) { if (l.type == NwGridLineSegmentType::Enum::LINE) { l.a.z = gridLevelList[m]->getLevel(); l.b.z = gridLevelList[m]->getLevel(); pTvGridLevelEntity->appendPolyline(l.a, l.b); OdTvResult captionTextRes; OdTvGeometryDataId captBeg = pTvTitle->appendText(l.a, l.caption, &captionTextRes); if (captionTextRes != tvOk) { continue; } OdTvTextDataPtr textPtr = captBeg.openAsText(); textPtr->setNonRotatable(true); OdTvGeometryDataId tvCaptEnd = pTvTitle->appendText(l.b, l.caption, &captionTextRes); if (captionTextRes != tvOk) { continue; } tvCaptEnd.openAsText()->setNonRotatable(true); } else if (l.type == NwGridLineSegmentType::Enum::CIRCLE) { l.a.z = gridLevelList[m]->getLevel(); l.b.z = gridLevelList[m]->getLevel(); l.c.z = gridLevelList[m]->getLevel(); double r = std::sqrt(std::pow(l.a.x - l.c.x, 2) + std::pow(l.a.y - l.c.y, 2)); double xb0a = (l.a.x - l.c.x) / r; double anga = OD_ACOS(xb0a); double anga_deg = OdaToDegree(anga); double angn = OdaToRadian(anga_deg - 5); double xn = r * cos(angn) + l.c.x; double yn = r * sin(angn) + l.c.y; OdTvPoint startPoint(l.a.x, l.a.y, gridLevelList[m]->getLevel()); OdTvPoint middlePoint(xn, yn, gridLevelList[m]->getLevel()); OdTvPoint endPoint(l.b.x, l.b.y, gridLevelList[m]->getLevel()); OdTvResult tvCircleArcRes; OdTvGeometryDataId tvCircleArcId = pTvGridLevelEntity->appendCircleArc(startPoint, middlePoint, endPoint, &tvCircleArcRes); if (tvCircleArcRes != tvOk) { continue; } OdTvResult tvArcCaptionRes; OdTvGeometryDataId tvArcCaption = pTvTitle->appendText(l.a, l.caption, &tvArcCaptionRes); if (tvArcCaptionRes != tvOk) { return; } tvArcCaption.openAsText()->setNonRotatable(true); } } } } } void createAndApplyPreferableVS_NW(OdTvDatabaseId& tvDbId) { if (tvDbId.isNull()) return; OdTvDatabasePtr pTvDatabase = tvDbId.openObject(OdTv::kForWrite); if (pTvDatabase.isNull()) return; //1. Check which background we have - it is important from Hidden Line mode bool bViewHasBackground = false; OdTvDevicesIteratorPtr pDevicesIterator = tvDbId.openObject()->getDevicesIterator(); while (!pDevicesIterator->done()) { OdTvGsDeviceId deviceId = pDevicesIterator->getDevice(); OdTvGsDevicePtr pDevice = deviceId.openObject(); if (pDevice.isNull() || pDevice->isBitmap()) { pDevicesIterator->step(); continue; } if (pDevice->getActive()) { OdTvGsViewId activeViewId = pDevice->getActiveView(); if (activeViewId.isNull()) continue; if (!activeViewId.openObject(OdTv::kForRead)->getBackground().isNull()) bViewHasBackground = true; break; } pDevicesIterator->step(); } //1. Shaded with isolines OdTvVisualStyleId visualStyleIsolinesId = pTvDatabase->createVisualStyle(OD_T("ShadedWithIsolines"), pTvDatabase->findVisualStyle(OD_T("GouraudWithEdges"))); { OdTvVisualStylePtr pVisualStyle = visualStyleIsolinesId.openObject(OdTv::kForWrite); if (!pVisualStyle.isNull()) { pVisualStyle->setOption(OdTvVisualStyleOptions::kEdgeModifiers, (OdInt32)OdTvVisualStyleOptions::kEdgeColor); pVisualStyle->setOption(OdTvVisualStyleOptions::kEdgeColorValue, OdTvColorDef(0, 0, 0)); //not show texture OdInt32 iVal = 0; pVisualStyle->getOption(OdTvVisualStyleOptions::kDisplayStyles, iVal); SETBIT(iVal, OdTvVisualStyleOptions::kTextures, false); pVisualStyle->setOption(OdTvVisualStyleOptions::kDisplayStyles, iVal); } } pTvDatabase->setPreferableVisualStyle(OdTvDatabase::kShadedWithIsolines, visualStyleIsolinesId); //2. Shaded with tesselation OdTvVisualStyleId visualStyleTessalationId = pTvDatabase->findVisualStyle(OD_T("ShadedWithTessellation")); { OdTvVisualStylePtr pVisualStyle = visualStyleTessalationId.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); } } //3. Shaded OdTvVisualStyleId visualStyleShadedId = pTvDatabase->findVisualStyle(OD_T("Shaded")); { OdTvVisualStylePtr pVisualStyle = visualStyleShadedId.openObject(OdTv::kForWrite); if (!pVisualStyle.isNull()) { pVisualStyle->setOption(OdTvVisualStyleOptions::kEdgeModifiers, (OdInt32)OdTvVisualStyleOptions::kNoEdgeModifiers); //remove obscured OdInt32 iVal = 0; pVisualStyle->getOption(OdTvVisualStyleOptions::kEdgeStyles, iVal); SETBIT(iVal, OdTvVisualStyleOptions::kObscured, false); pVisualStyle->setOption(OdTvVisualStyleOptions::kEdgeStyles, iVal); } } pTvDatabase->setPreferableVisualStyle(OdTvDatabase::kShaded, visualStyleShadedId); //4. Hidden Line OdTvVisualStyleId visualStyleHiddenId = pTvDatabase->findVisualStyle(OD_T("Hidden")); if (!visualStyleHiddenId.isNull()) { OdTvVisualStylePtr pVisualStyle = visualStyleHiddenId.openObject(OdTv::kForWrite); if (!pVisualStyle.isNull()) { pVisualStyle->setOption(OdTvVisualStyleOptions::kEdgeCreaseAngle, 89.); if (bViewHasBackground) pVisualStyle->setOption(OdTvVisualStyleOptions::kFaceColorMode, (OdInt32)OdTvVisualStyleOptions::kBackgroundTexture); } pTvDatabase->setPreferableVisualStyle(OdTvDatabase::kHiddenLine, visualStyleHiddenId); } //5. Realistic as custom OdTvVisualStyleId visualStyleRealisticId = pTvDatabase->findVisualStyle(OD_T("Realistic")); if (!visualStyleRealisticId.isNull()) pTvDatabase->setPreferableVisualStyle(OdTvDatabase::kCustom, visualStyleRealisticId); return; } //***************************************************************************// // 'OdTvVisualizeRcsFilerModule' methods implementation //***************************************************************************// ODRX_DEFINE_DYNAMIC_MODULE(OdTvVisualizeNwFilerModule); void OdTvVisualizeNwFilerModule::initApp() { // initialize the Visualize SDK odTvInitialize(); } void OdTvVisualizeNwFilerModule::uninitApp() { // Uninitialize the Visualize SDK odTvUninitialize(); } OdTvVisualizeFilerPtr OdTvVisualizeNwFilerModule::getVisualizeFiler() const { OdTvVisualizeFilerPtr pFiler = new OdTvVisualizeNwFiler(); return pFiler; } OdString OdTvNw2VisService::handleEmbeddedFile(const OdString& sPath, OdStreamBufPtr pEmbFile, OdString sType) const { if (!m_TempDirectoryPath.isEmpty() && !sPath.isEmpty() && !sType.isEmpty()) { if (!pEmbFile.isNull()) { const OdString& tmpfullPath = NwPathUtils::join(m_TempDirectoryPath, NwPathUtils::basename(sPath) + L"." + sType); auto pStream = odrxSystemServices()->createFile(tmpfullPath, Oda::kFileWrite, Oda::kShareDenyWrite, Oda::kOpenAlways); pEmbFile->seek(0, OdDb::kSeekFromStart); pEmbFile->copyDataTo(pStream); return tmpfullPath; } } return OdString::kEmpty; } bool OdTvVisualizeNwFiler::getEmbeddedFileResolver(OdNwDatabasePtr pNwDb, OdString& sPath, OdStreamBufPtr& pStreamBuf) const { if (!pNwDb) return false; OdResult resCode = eOk; auto pTempStreamBuf = pNwDb->getEmbeddedStream(sPath, &resCode); if (resCode == eOk && !pTempStreamBuf.isNull()) { bool bSaveToTempDir = !m_properties->getTempDirectoryPath().isEmpty(); bool bRecapAsRcs = m_properties->getImportRecapAsRcsPointCloud(); if (bSaveToTempDir) { OdString sHead, sExt; NwPathUtils::splitExt(sPath, sHead, sExt); auto sExtL = sExt.getLength(); if (sExtL) { OdString sRemappedPath = pNwDb->appServices()->handleEmbeddedFile(sPath, pTempStreamBuf, sExt.right(sExtL - 1)); if (!sRemappedPath.isEmpty()) { sPath = sRemappedPath; return true; } } } if (bRecapAsRcs) { OdMemoryStreamPtr pMemStream = OdMemoryStream::createNew(); pTempStreamBuf->rewind(); OdUInt64 nSize = pTempStreamBuf->length(); if (nSize > 0) { pMemStream->reserve(nSize); pTempStreamBuf->copyDataTo(pMemStream); pMemStream->rewind(); pStreamBuf = pMemStream; } else { pStreamBuf = pTempStreamBuf; } } else { pStreamBuf = pTempStreamBuf; } return true; } else { OdString sRemappedPath; if (auto pAppSrv = pNwDb->appServices()) { sRemappedPath = pAppSrv->findFile(sPath, pNwDb, OdDbBaseHostAppServices::kUnderlayFile); } if (sRemappedPath.isEmpty()) { auto pChooseDirCallback = (OdNwChooseFileCallback)m_properties->getFeedbackForChooseFileCallback(); if (pChooseDirCallback) sRemappedPath = pChooseDirCallback(sPath); } if (!sRemappedPath.isEmpty()) { sPath = sRemappedPath; return true; } } return false; }