/////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////// // ODA Platform #include "OdaCommon.h" #include "RxDynamicModule.h" #include "RxVariantValue.h" #include "RxObject.h" #include "RxInit.h" // #include "HatchPatternManager.h" #include "TvFactory.h" #include "TvFilerTimer.h" #include "Prc2Visualize.h" #include "TvModuleNames.h" #include "TvDatabaseCleaner.h" #include "TvDatabaseUtils.h" #include "TvImportUserData.h" #include "Prc2VisualizeDirectImport.h" #include "ColorMapping.h" #include "GiGs/PrcGiContext.h" #include "PrcBrepModel.h" #include "PrcPolyBrepModel.h" #include "PrcAnnotationSet.h" #include "PrcAnnotationItem.h" #include "DynamicLinker.h" #include "PrcAuditInfoImpl.h" #include "PrcMarkupTess.h" #include "PrcAnnotationReference.h" static unsigned int g_nBodies = 1; static unsigned int g_nMarkups = 1; typedef std::map prcHandlesBodiesMap; std::map< OdDbHandle, prcHandlesBodiesMap> prcNamingMap; struct ParamForImportDevice { ODCOLORREF m_background; OdTvDCRect m_rect; OdArray > m_PalCpy; bool m_bAppend; OdTvDatabaseId m_databaseId; OdString m_strModelName; OdTvGsDeviceId m_tvDeviceIdForAppend; ParamForImportDevice() { m_bAppend = false; m_rect = OdTvDCRect(0, 0, 0, 0); m_background = ODRGB(0, 0, 0); } }; //*************************************************************************************// // Implementation of the methods for 'OdPdf3DStreamExtractor' //*************************************************************************************// /** \details An abstract class that represents the interface for the extract 3D stream from a .pdf file. */ class OdPdf3DStreamExtractor : public OdRxObject { public: /** \details Defines a list with possible results of the extract 3D stream data operation. The result value is handled by a . */ enum ExtractResult { /** The extraction process has been successfully finished.*/ success, /**The extraction process failed.*/ fail, /** The extraction process failed because of an incorrect password.*/ bad_password, /** The extraction process failed because of an incorrect input .pdf file.*/ bad_file, /** The extraction process failed because of an invalid page number of the input .pdf file.*/ invalid_page_number, /** The extraction process failed because of an invalid stream number in the input .pdf file.*/ invalid_stream_number, /** The extraction process failed because the .pdf document was not loaded.*/ document_not_loaded }; /** \details Defines a list of 3D stream types to be extracted. Stream type value is handled by a . */ enum StreamType { /**PRC stream type.*/ ePRC, /**U3D stream type.*/ eU3D, /**Undefined stream type.*/ eUndefined }; /** \details Opens a PDF document. \param path [in] A reference to an OdString object that contains the path to the PDF document. \param password [in] A reference to an OdString object that contains the password for the PDF document. \returns A value of the enumeration that contains the result of the process. */ virtual ExtractResult openPdfDocument(const OdString& path, const OdString& password) = 0; /** \details Requests the number of pages in the PDF document. \param result [out] A reference to a value of the enumeration that contains the result of the method execution. \returns An unsigned 32-bit integer value that contains the number of pages in the PDF document. */ virtual OdUInt32 getPageCount(ExtractResult& result) const = 0; /** \details Requests the number of 3D streams that are contained within a specified page of the PDF document. \param page_index [in] A page index within the PDF document. \param result [out] A reference to a value of the enumeration that contains the result of the method execution. \returns An unsigned 32-bit integer value that contains the number of 3D streams within the specified page of the PDF document. */ virtual OdUInt32 getCount3DStreamForPage(const int page_index, ExtractResult& result) const = 0; /** \details Requests the type of a specified 3D stream. \param page_index [in] A page index within the PDF document. \param stream_index [in] An index of the stream contained in the PDF document. \param result [out] A reference to a value of the enumeration that contains the result of the method execution. \returns A value of the enumeration that contains the type of the specified 3D stream. */ virtual StreamType Get3DStreamType(const int page_index, const int stream_index, ExtractResult& result) const = 0; /** \details Requests the name of a specified 3D stream. \param page_index [in] A page index within the PDF document. \param stream_index [in] An index of the stream contained in the PDF document. \param result [out] A reference to a value of the enumeration that contains the result of the method execution. \returns An OdString object that contains the name of the specified 3D stream. \remarks If there is no name for the stream in the PDF document, the default name 3D_<stream_number_in_the_document> is returned (e.g. 3D_1, 3D_2, etc.). */ virtual OdString Get3DStreamName(const int page_index, const int stream_index, ExtractResult& result) const = 0; /** \details Fills a specified OdStreamBuf object with data from a specified 3D stream. \param page_index [in] A page index within the PDF document. \param stream_index [in] An index of the stream contained in the PDF document. \param stream [out] A reference to a smart pointer to an OdStreamBuf object to be filled with the 3D stream data. \returns A value of the enumeration that contains the result of the method execution. */ virtual ExtractResult fill3DStream(const int page_index, const int stream_index, OdStreamBufPtr& stream) const = 0; }; /** \details A data type that represents a smart pointer to a object. */ typedef OdSmartPtr OdPdf3DStreamExtractorPtr; /** \details An abstract class that provides an interface of a module containing the functionality for extraction 3D stream data from a PDF file. */ class OdPdf3DStreamExtractorModule : public OdRxModule { public: /** \details Creates an extractor object for 3D streams contained in a PDF file if it has not been created yet (at the moment of the method call). If the extractor object has already been created, the method only returns the smart pointer to it. \returns A smart pointer to the for 3D streams in a PDF file. */ virtual OdPdf3DStreamExtractorPtr create() = 0; }; /** \details A data type that represents a smart pointer to a . */ typedef OdSmartPtr OdPdf3DStreamExtractorModulePtr; /** \details Creates a new . \returns A smart pointer to the created instance of the class. */ inline OdPdf3DStreamExtractorPtr createExtractor() { OdPdf3DStreamExtractorModulePtr pModule = ::odrxDynamicLinker()->loadApp(OdPdf3DStreamExtractorModuleName); if (!pModule.isNull()) return pModule->create(); return (OdPdf3DStreamExtractor*)0; } /************************************************************************/ /* Get native identifier from user data of the entity */ /************************************************************************/ template OdInt64 getSourceDatabaseHandle(T pEntity, const OdString& appName) { if (pEntity.isNull()) return -1; OdTvDatabasePtr pDatabaseEntity = pEntity->getDatabase().openObject(OdTv::kForWrite); bool alreadyExist = false; OdTvRegAppId regAppId = pDatabaseEntity->registerAppName(appName, alreadyExist); OdTvUserData* usrData = pEntity->getUserData(regAppId); if (usrData) { OdTvByteUserData* data = dynamic_cast(usrData); if (data) { OdUInt64 handle = *((OdUInt64*)data->getData()); odSwap8Bytes(&handle); return (OdInt64)handle; } } return -1; } /************************************************************************/ /* Get native PRC entity name */ /************************************************************************/ OdString getSourceDatabaseEntityName(OdPrcFilePtr pDb, OdInt64 iNativeDbId, OdInt64 iNativeId) { OdUInt64 nativeId = OdUInt64(iNativeId); OdUInt64 nativeDbId = OdUInt64(iNativeDbId); //get database native database by id OdPrcObjectId prcDbId = pDb->getObjectId(nativeDbId); OdRxObjectPtr pRxDbObj = prcDbId.openObject(); OdPrcFileStructurePtr pPrcSourceDb; if (!pRxDbObj.isNull() && pRxDbObj->isKindOf(OdPrcFileStructure::desc())) pPrcSourceDb = pRxDbObj; if (pPrcSourceDb.isNull()) return OdString(); OdPrcObjectId prcObjId = pPrcSourceDb->getObjectId(nativeId); OdRxObjectPtr pRxObj = prcObjId.openObject(); if (!pRxObj.isNull() && pRxObj->isKindOf(OdPrcBase::desc())) { OdPrcObjectPtr pPrcObj = pRxObj; //special case for Breps OdString sBodyName; if (pRxObj->isKindOf(OdPrcBrepModel::desc()) || pRxObj->isKindOf(OdPrcPolyBrepModel::desc())) { OdPrcFileStructurePtr pFS = prcObjId.database(); OdDbHandle dbHandle = pFS->objectId().getHandle(); bool bFind = false; std::map< OdDbHandle, prcHandlesBodiesMap >::iterator it = prcNamingMap.find(dbHandle); if (it != prcNamingMap.end()) { prcHandlesBodiesMap::iterator itBodies = it->second.find(prcObjId.getHandle()); if (itBodies != it->second.end()) { sBodyName.format(OD_T("Body %d"), itBodies->second); bFind = true; } else { it->second[prcObjId.getHandle()] = g_nBodies; } } else { prcHandlesBodiesMap bodiesMap; bodiesMap[prcObjId.getHandle()] = g_nBodies; prcNamingMap[dbHandle] = bodiesMap; } if (!bFind) { sBodyName.format(OD_T("Body %d"), g_nBodies); g_nBodies++; } } //try to get the name OdString resStr; if (!pPrcObj.isNull()) resStr = pPrcObj->name().name(); if (!resStr.isEmpty()) return resStr; //special code for the case when there is no name. Try to check prototypes else if (pRxObj->isKindOf(OdPrcProductOccurrence::desc())) { OdPrcProductOccurrencePtr pProdOccur = pRxObj; const OdPrcObjectIdArray* pArrSons = &(pProdOccur->referencesOfProductOccurrence().getSonProductOccurrences()); { OdPrcObjectId protoId = pProdOccur->referencesOfProductOccurrence().getPrototypeID(); while (pArrSons->isEmpty() && !protoId.isNull()) { OdPrcProductOccurrencePtr pProtPO = protoId.safeOpenObject(); pArrSons = &pProtPO->referencesOfProductOccurrence().getSonProductOccurrences(); protoId = pProtPO->referencesOfProductOccurrence().getPrototypeID(); resStr = pProtPO->name().name(); } } return resStr; } //special case for Breps else if (pRxObj->isKindOf(OdPrcBrepModel::desc()) || pRxObj->isKindOf(OdPrcPolyBrepModel::desc())) { resStr = sBodyName; return resStr; } } return OdString(); } /************************************************************************************************************************************/ /* Checks that the PRC native entity, corresponding to the visualize entity is a Part Definition */ /************************************************************************************************************************************/ bool isPartDefinition(OdTvEntityPtr pEntity, OdPrcFilePtr pDb, const OdString& appName, const OdString& appName_db) { OdInt64 iNativeId = getSourceDatabaseHandle(pEntity, appName); if (iNativeId < 0) return false; OdInt64 iNativeDbId = getSourceDatabaseHandle(pEntity, appName_db); if (iNativeDbId < 0) return false; OdUInt64 nativeId = OdUInt64(iNativeId); OdUInt64 nativeDbId = OdUInt64(iNativeDbId); //get database native database by id OdPrcObjectId prcDbId = pDb->getObjectId(nativeDbId); OdRxObjectPtr pRxDbObj = prcDbId.openObject(); OdPrcFileStructurePtr pPrcSourceDb; if (!pRxDbObj.isNull() && pRxDbObj->isKindOf(OdPrcFileStructure::desc())) pPrcSourceDb = pRxDbObj; if (pPrcSourceDb.isNull()) return false; OdPrcObjectId prcObjId = pPrcSourceDb->getObjectId(nativeId); OdRxObjectPtr pRxObj = prcObjId.openObject(); if (!pRxObj.isNull() && pRxObj->isKindOf(OdPrcPartDefinition::desc())) return true; return false; } /************************************************************************************************************************************/ /* Checks that the PRC native entity, corresponding to the visualize entity is a CLOSED Brep Model */ /************************************************************************************************************************************/ bool isBrepModel(OdTvEntityPtr pEntity, OdPrcFilePtr pDb, const OdString& appName, const OdString& appName_db) { OdInt64 iNativeId = getSourceDatabaseHandle(pEntity, appName); if (iNativeId < 0) return false; OdInt64 iNativeDbId = getSourceDatabaseHandle(pEntity, appName_db); if (iNativeDbId < 0) return false; OdUInt64 nativeId = OdUInt64(iNativeId); OdUInt64 nativeDbId = OdUInt64(iNativeDbId); //get database native database by id OdPrcObjectId prcDbId = pDb->getObjectId(nativeDbId); OdRxObjectPtr pRxDbObj = prcDbId.openObject(); OdPrcFileStructurePtr pPrcSourceDb; if (!pRxDbObj.isNull() && pRxDbObj->isKindOf(OdPrcFileStructure::desc())) pPrcSourceDb = pRxDbObj; if (pPrcSourceDb.isNull()) return false; OdPrcObjectId prcObjId = pPrcSourceDb->getObjectId(nativeId); OdRxObjectPtr pRxObj = prcObjId.openObject(); if (!pRxObj.isNull() && pRxObj->isKindOf(OdPrcBrepModel::desc())) { OdPrcBrepModelPtr pBrepModel = pRxObj; return pBrepModel->isClosed(); } else if (!pRxObj.isNull() && pRxObj->isKindOf(OdPrcPolyBrepModel::desc())) { OdPrcPolyBrepModelPtr pPolyBrepModel = pRxObj; return pPolyBrepModel->isClosed(); } return false; } /************************************************************************************************************************************/ /* Checks that the PRC native entity, corresponding to the visualize entity is a Annotation set */ /************************************************************************************************************************************/ bool isAnnotationSet(OdTvEntityPtr pEntity, OdPrcFilePtr pDb, const OdString& appName, const OdString& appName_db) { OdInt64 iNativeId = getSourceDatabaseHandle(pEntity, appName); if (iNativeId < 0) return false; OdInt64 iNativeDbId = getSourceDatabaseHandle(pEntity, appName_db); if (iNativeDbId < 0) return false; OdUInt64 nativeId = OdUInt64(iNativeId); OdUInt64 nativeDbId = OdUInt64(iNativeDbId); //get database native database by id OdPrcObjectId prcDbId = pDb->getObjectId(nativeDbId); OdRxObjectPtr pRxDbObj = prcDbId.openObject(); OdPrcFileStructurePtr pPrcSourceDb; if (!pRxDbObj.isNull() && pRxDbObj->isKindOf(OdPrcFileStructure::desc())) pPrcSourceDb = pRxDbObj; if (pPrcSourceDb.isNull()) return false; OdPrcObjectId prcObjId = pPrcSourceDb->getObjectId(nativeId); OdRxObjectPtr pRxObj = prcObjId.openObject(); if (!pRxObj.isNull() && pRxObj->isKindOf(OdPrcAnnotationSet::desc())) { return true; } return false; } /************************************************************************************************************************************/ /* Checks that the PRC native entity, corresponding to the visualize entity is a Annotation Item */ /************************************************************************************************************************************/ bool isAnnotationItem(OdTvEntityPtr pEntity, OdPrcFilePtr pDb, const OdString& appName, const OdString& appName_db, OdString& name) { name = OdString(); OdInt64 iNativeId = getSourceDatabaseHandle(pEntity, appName); if (iNativeId < 0) return false; OdInt64 iNativeDbId = getSourceDatabaseHandle(pEntity, appName_db); if (iNativeDbId < 0) return false; OdUInt64 nativeId = OdUInt64(iNativeId); OdUInt64 nativeDbId = OdUInt64(iNativeDbId); //get database native database by id OdPrcObjectId prcDbId = pDb->getObjectId(nativeDbId); OdRxObjectPtr pRxDbObj = prcDbId.openObject(); OdPrcFileStructurePtr pPrcSourceDb; if (!pRxDbObj.isNull() && pRxDbObj->isKindOf(OdPrcFileStructure::desc())) pPrcSourceDb = pRxDbObj; if (pPrcSourceDb.isNull()) return false; OdPrcObjectId prcObjId = pPrcSourceDb->getObjectId(nativeId); OdRxObjectPtr pRxObj = prcObjId.openObject(); if (!pRxObj.isNull() && pRxObj->isKindOf(OdPrcAnnotationItem::desc())) { //get PRC native name OdString prcObjName = getSourceDatabaseEntityName(pDb, iNativeDbId, iNativeId); if (!prcObjName.isEmpty()) name = prcObjName; return true; } return false; } /************************************************************************/ /* Explodes annotation set */ /************************************************************************/ void explodeSubEntitesWithNativeHandle(OdTvEntityPtr pEntity, OdPrcFilePtr pDb, const OdString& appName, const OdString& appName_db) { if (pEntity.isNull()) return; bool bContinue = true; while (bContinue) { bContinue = false; OdTvGeometryDataIdsArray subEntitiesForRemove; OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); if (getSourceDatabaseHandle(pSubEnt, appName) >= 0) subEntitiesForRemove.append(geomDataId); } pIter->step(); } if (!subEntitiesForRemove.isEmpty()) { for (unsigned int i = 0; i < subEntitiesForRemove.size(); i++) pEntity->removeSubEntity(subEntitiesForRemove[i], false); bContinue = true; } } } /************************************************************************/ /* Explodes annotation set */ /************************************************************************/ void explodeAnnotationSet(OdPrcFilePtr pDb, OdTvEntityPtr pEntity, const OdString& appName, const OdString& appName_db) { if (pEntity.isNull()) return; //First main step bool bContinue = true; while (bContinue) { bContinue = false; OdTvGeometryDataIdsArray subEntitiesForRemove; OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); OdString annotationItemName; if (isAnnotationItem(pSubEnt, pDb, appName, appName_db, annotationItemName)) { if (annotationItemName.isEmpty()) { bool bHasNotPrcHandlesGeometry = false; //cycle through the subentity's childs OdTvGeometryDataIteratorPtr pIterSub = pSubEnt->getGeometryDataIterator(); while (!pIterSub->done()) { OdTvGeometryDataId geomDataIdSub = pIterSub->getGeometryData(); if (geomDataIdSub.getType() == OdTv::kSubEntity) { OdTvEntityPtr pChildSubEnt = geomDataIdSub.openAsSubEntity(OdTv::kForRead); if (getSourceDatabaseHandle(pChildSubEnt, appName) < 0) { bHasNotPrcHandlesGeometry = true; break; } } else { bHasNotPrcHandlesGeometry = true; break; } pIterSub->step(); } if (!bHasNotPrcHandlesGeometry) subEntitiesForRemove.append(geomDataId); else { OdString markupName; markupName.format(OD_T("Markup %d"), g_nMarkups); pSubEnt->setName(markupName); g_nMarkups++; } } } else if (isAnnotationSet(pSubEnt, pDb, appName, appName_db)) subEntitiesForRemove.append(geomDataId); } pIter->step(); } if (!subEntitiesForRemove.isEmpty()) { for (unsigned int i = 0; i < subEntitiesForRemove.size(); i++) pEntity->removeSubEntity(subEntitiesForRemove[i], false); bContinue = true; } } //Second step - explode all subentities with PRC handle OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); explodeSubEntitesWithNativeHandle(pSubEnt, pDb, appName, appName_db); } pIter->step(); }// eo while.. return; } /************************************************************************/ /* apply PRC entit name to the Visualize entity */ /************************************************************************/ void applyPRCEntityNaming_entity(OdPrcFilePtr pDb, OdTvEntityPtr pEntity, bool bRearrange) { if (pEntity.isNull()) return; if (pDb.isNull()) return; OdString appName(L"ExGsVisualizeDevice"); OdString appName_db(L"ExGsVisualizeDevice_DBID"); if (bRearrange) { //remove some subentities (ONLY ALONE) which //1. which have not native handle. It means that such subentity was created but applying some attributes //2. which has native handle but don't have PRC name bool bContinue = true; while (bContinue) { bContinue = false; OdUInt32 nGeometries = pEntity->getNumGeometries(); if (nGeometries != 1) break; OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); bool bNeedRemove = false; if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); OdInt64 iSubEntNativeId = getSourceDatabaseHandle(pSubEnt, appName); if (iSubEntNativeId < 0) bNeedRemove = true; else { OdInt64 iSubEntNativeDbId = getSourceDatabaseHandle(pSubEnt, appName_db); if (iSubEntNativeDbId >= 0) { OdString prcObjName = getSourceDatabaseEntityName(pDb, iSubEntNativeDbId, iSubEntNativeId); if (prcObjName.isEmpty()) bNeedRemove = true; } } } if (bNeedRemove) { pEntity->removeSubEntities(OdTvEntity::kRemoveAlone); bContinue = true; break; } pIter->step(); } } //eo while... } //iterate through geometries and apply names to subEntities OdArray sunEntityForRemove; OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); //additional checking for Partion Defition (need for example for the file "tire_example.prc") if (isPartDefinition(pSubEnt, pDb, appName, appName_db)) sunEntityForRemove.append(geomDataId); applyPRCEntityNaming_entity(pDb, pSubEnt, bRearrange); } pIter->step(); } //try to remove (explode) partDefiniton subentities if (!sunEntityForRemove.isEmpty()) { for (unsigned int i = 0; i < sunEntityForRemove.size(); i++) pEntity->removeSubEntity(sunEntityForRemove[i]); } //get native handles OdInt64 iNativeId = getSourceDatabaseHandle(pEntity, appName); if (iNativeId < 0) return; OdInt64 iNativeDbId = getSourceDatabaseHandle(pEntity, appName_db); if (iNativeDbId < 0) return; //get PRC native name OdString prcObjName = getSourceDatabaseEntityName(pDb, iNativeDbId, iNativeId); if (!prcObjName.isEmpty()) pEntity->setName(prcObjName); return; } /************************************************************************/ /* apply PRC entity name to the Visualize model's entities */ /************************************************************************/ void applyPRCEntityNaming(OdPrcFilePtr pDb, OdTvModelId tvModelId, bool bRearrange) { if (pDb.isNull()) return; if (tvModelId.isNull()) return; OdTvModelPtr pTvModel = tvModelId.openObject(); if (pTvModel.isNull()) return; g_nBodies = 1; prcNamingMap.clear(); // iterate through the entities OdTvEntitiesIteratorPtr pEntitiesIterator = pTvModel->getEntitiesIterator(); while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = entityId.openObject(OdTv::kForWrite); applyPRCEntityNaming_entity(pDb, pEntity, bRearrange); } pEntitiesIterator->step(); } g_nBodies = 1; prcNamingMap.clear(); } //*************************************************************************************// // explode all single entities fork of the entities tree // //*************************************************************************************// OdString explodeEntityFork(OdTvModelPtr pModel, OdTvEntityId tvEntityId) { if (tvEntityId.isNull()) return OdString(); OdTvEntityPtr pTvEntity = tvEntityId.openObject(OdTv::kForWrite); if (pTvEntity.isNull()) return OdString(); OdTvEntityIdsArray entities; pTvEntity->explodeSubEntities(&entities); OdString strRes; OdString entName = pTvEntity->getName(); if (entName != OD_T("OdPrcReferenceOnRootPO") && !entName.isEmpty()) strRes = entName; if (pTvEntity->isEmpty()) { pTvEntity.release(); pModel->removeEntity(tvEntityId); } //explode child if need if (entities.size() == 1) { OdString strName = explodeEntityFork(pModel, entities[0]); if (!strName.isEmpty()) strRes = strName; } return strRes; } //*************************************************************************************// // explode subentities //*************************************************************************************// bool explodeSubEntitiesForAloneEntity(OdPrcFilePtr pDb, OdTvModelPtr pModel) { bool bRes = false; if (pModel.isNull()) return false; //1. Explode all OdPrcReferenceOnRootPO if exists bool bModelNameWasUpdated = false; OdTvEntitiesIteratorPtr pEntitiesIterator = pModel->getEntitiesIterator(); while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity && !entityId.isNull() && !entityId.openObject()->isEmpty()) { OdString strName = entityId.openObject()->getName(); if (strName == OD_T("OdPrcReferenceOnRootPO")) { OdString strChildsName = explodeEntityFork(pModel, entityId); if (!strChildsName.isEmpty()) { pModel->setName(strChildsName); bModelNameWasUpdated = true; } } } pEntitiesIterator->step(); } //2. If still exists alone entities - try to explode them bool bContinue = true; while (bContinue) { bContinue = false; OdTvEntityId entIdForExplode; OdUInt32 nEntities = 0; OdTvEntitiesIteratorPtr pEntitiesIterator = pModel->getEntitiesIterator(); while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity && !entityId.openObject()->isEmpty()) { entIdForExplode = entityId; nEntities++; } pEntitiesIterator->step(); } //if we have only one entity if (nEntities == 1) { // Explode one level of sub entities OdTvEntityPtr pEntity = entIdForExplode.openObject(OdTv::kForWrite); pEntity->explodeSubEntities(); if (pEntity->isEmpty()) { OdString entName = pEntity->getName(); if (!entName.isEmpty() && !bModelNameWasUpdated) pModel->setName(entName); pEntity.release(); pModel->removeEntity(entIdForExplode); bContinue = true; //we need to repeat since we may continue to have alone entity } } } //3. Currently we have not a good structure for the PMI (annotation sets). Thus we will delete them except one called "PMI" OdString appName(L"ExGsVisualizeDevice"); OdString appName_db(L"ExGsVisualizeDevice_DBID"); pEntitiesIterator = pModel->getEntitiesIterator(); OdTvEntityIdsArray annotationsForDelete; g_nMarkups = 1; while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity && !entityId.openObject()->isEmpty()) { if (isAnnotationSet(entityId.openObject(), pDb, appName, appName_db)) { OdString strName = entityId.openObject()->getName(); if (strName != OD_T("PMI")) annotationsForDelete.append(entityId); else { explodeAnnotationSet(pDb, entityId.openObject(), appName, appName_db); } } else { OdTvGeometryDataIteratorPtr pIter = entityId.openObject()->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); if (isAnnotationSet(pSubEnt, pDb, appName, appName_db)) { annotationsForDelete.append(entityId); break; } } pIter->step(); } } } pEntitiesIterator->step(); } if (annotationsForDelete.size() > 0) { bRes = true; for (unsigned int id = 0; id < annotationsForDelete.size(); id++) pModel->removeEntity(annotationsForDelete[id]); } return bRes; } /**************************************************************************************************************************/ /* check entitiy about subentities (or itself) with flag 'need isolines calculation' */ /**************************************************************************************************************************/ bool processingDataForSetNeedCheckTopology_entity(OdTvEntityPtr pEntity) { if (pEntity.isNull()) return false; OdUInt32 nGeometries = pEntity->getNumGeometries(); if (nGeometries == 0) return false; bool bRes = false; if (pEntity->getCalculateIsolinesForShells()) bRes = true; //iterate through the geometries OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); bRes |= processingDataForSetNeedCheckTopology_entity(pSubEnt); } pIter->step(); } //eo while... return bRes; } /**************************************************************************************************************************/ /* find entities which has subentities with flag 'need isolines calculation' */ /**************************************************************************************************************************/ void processingDataForSetNeedCheckTopology(OdTvModelId tvModelId) { if (tvModelId.isNull()) return; OdTvModelPtr pTvModel = tvModelId.openObject(); if (pTvModel.isNull()) return; // iterate through the entities OdTvEntitiesIteratorPtr pEntitiesIterator = pTvModel->getEntitiesIterator(); while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = entityId.openObject(OdTv::kForWrite); if (processingDataForSetNeedCheckTopology_entity(pEntity)) pEntity->setNeedCheckShellsTopology(true); } pEntitiesIterator->step(); } } /**************************************************************************************************************************/ /* a) mark edges from closed OdPrcBrepModel or OdPrcPolyBrepModel as GiSilhouette for filtering via crease angle */ /* b) set flag about isolines calculation or about excluding from isolines draw for OdPrcBrepModel or OdPrcPolyBrepModel */ /**************************************************************************************************************************/ void processingDataForBrepTesselation_entity(OdPrcFilePtr pDb, OdTvEntityPtr pEntity, bool bParentIsBrepModel) { if (pEntity.isNull()) return; if (pDb.isNull()) return; OdString appName(L"ExGsVisualizeDevice"); OdString appName_db(L"ExGsVisualizeDevice_DBID"); OdUInt32 nGeometries = pEntity->getNumGeometries(); if (nGeometries == 0) return; bool bIsBrepModel = false; if (isBrepModel(pEntity, pDb, appName, appName_db)) { bIsBrepModel = true; pEntity->setCalculateIsolinesForShells(true, 89.0 * OdaPI / 180.0); } //iterate through the geometries OdTvGeometryDataIteratorPtr pIter = pEntity->getGeometryDataIterator(); while (!pIter->done()) { OdTvGeometryDataId geomDataId = pIter->getGeometryData(); if (geomDataId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEnt = geomDataId.openAsSubEntity(OdTv::kForWrite); processingDataForBrepTesselation_entity(pDb, pSubEnt, bIsBrepModel || bParentIsBrepModel); } else if (geomDataId.getType() == OdTv::kShell) { if (bParentIsBrepModel || bIsBrepModel) { OdTvShellDataPtr pShell = geomDataId.openAsShell(); if (!pShell.isNull()) { OdUInt32 nEdges = pShell->getEdgesCount(); OdInt32Array edges; edges.resize(nEdges); for (OdUInt32 i = 0; i < nEdges; i++) edges[i] = i; pShell->setIndexesOfSilhouetteEdges(edges); } } else { OdTvGeometryDataPtr pGeomDataPtr = geomDataId.openObject(); if (!pGeomDataPtr.isNull()) pGeomDataPtr->setTargetDisplayMode(OdTvGeometryData::kEveryWhereExceptIsolines); } } pIter->step(); } //eo while... return; } /**************************************************************************************************************************/ /* a) mark edges from closed OdPrcBrepModel or OdPrcPolyBrepModel as GiSilhouette for filtering via crease angle */ /* b) set flag about isolines calculation or about excluding from isolines draw for OdPrcBrepModel or OdPrcPolyBrepModel */ /**************************************************************************************************************************/ void processingDataForBrepTesselation(OdPrcFilePtr pDb, OdTvModelId tvModelId) { if (pDb.isNull()) return; if (tvModelId.isNull()) return; OdTvModelPtr pTvModel = tvModelId.openObject(); if (pTvModel.isNull()) return; // iterate through the entities OdTvEntitiesIteratorPtr pEntitiesIterator = pTvModel->getEntitiesIterator(); while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = entityId.openObject(OdTv::kForWrite); processingDataForBrepTesselation_entity(pDb, pEntity, false); } pEntitiesIterator->step(); } } //*************************************************************************************// // Create and setup device for import //*************************************************************************************// OdGsPrcLayoutHelperPtr createAndSetupImportDevice(OdGsModulePtr pGs, PRC2Visualize::OdTvVisualizePrcFilerPropertiesPtr pImportProperties, OdGiContextForPrcDatabasePtr pPrcContext, bool bUseTimeProfiling, const ParamForImportDevice& dataForImportDevice, OdRxDictionaryPtr& pProperties) { //create device OdGsDevicePtr pDevice = pGs->createDevice(); if (pDevice.isNull()) return OdGsPrcLayoutHelperPtr(); //setup properties pProperties = pDevice->properties(); if (pProperties.get()) { if (pImportProperties->getStoreSourceObjects()) { if (pProperties->has(OD_T("WriteDatabaseIDInUserData"))) pProperties->putAt(OD_T("WriteDatabaseIDInUserData"), OdRxVariantValue(true)); } if (dataForImportDevice.m_bAppend) { if (pProperties->has(OD_T("TvDatabaseID"))) pProperties->putAt(OD_T("TvDatabaseID"), OdRxVariantValue((OdIntPtr)(&(dataForImportDevice.m_databaseId)))); } 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("WriteUserData"))) pProperties->putAt(OD_T("WriteUserData"), OdRxVariantValue(pImportProperties->getStoreSourceObjects())); if (pProperties->has(OD_T("GenerateEntityNames"))) pProperties->putAt(OD_T("GenerateEntityNames"), OdRxVariantValue(pImportProperties->getObjectNaming())); if (pProperties->has(OD_T("CompareUnnamedImages"))) pProperties->putAt(OD_T("CompareUnnamedImages"), OdRxVariantValue(true)); if (dataForImportDevice.m_bAppend) { if (pProperties->has(OD_T("ModelName"))) pProperties->putAt(OD_T("ModelName"), OdRxVariantValue(dataForImportDevice.m_strModelName)); if (!dataForImportDevice.m_tvDeviceIdForAppend.isNull()) { if (pProperties->has(OD_T("IgnoreFlags"))) pProperties->putAt(OD_T("IgnoreFlags"), OdRxVariantValue(OdUInt16(1)/*DeviceIgnoreFlags::kIgnoreViewInfoFlags*/)); if (pProperties->has(OD_T("NamePrefix"))) pProperties->putAt(OD_T("NamePrefix"), OdRxVariantValue(dataForImportDevice.m_strModelName)); if (pProperties->has(OD_T("TvDeviceDAM"))) pProperties->putAt(OD_T("TvDeviceDAM"), OdRxVariantValue((OdIntPtr)(&(dataForImportDevice.m_tvDeviceIdForAppend)))); OdTvGsViewId viewId = dataForImportDevice.m_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)); //setup support direct draw of the breps bool bImportBrepAsBrep = pImportProperties->getImportBrepAsBrep(); if (bImportBrepAsBrep) { if (pProperties->has(OD_T("SupportBrepDraw"))) pProperties->putAt(OD_T("SupportBrepDraw"), OdRxVariantValue(true)); if (pProperties->has(OD_T("FullRegenDependentVectorization"))) pProperties->putAt(OD_T("FullRegenDependentVectorization"), OdRxVariantValue(false)); if (pProperties->has(OD_T("FacetResForBrep"))) pProperties->putAt(OD_T("FacetResForBrep"), OdRxVariantValue(pImportProperties->getBrepFacetRes())); if (pProperties->has(OD_T("UsePolyEdgesWithShadedModes"))) pProperties->putAt(OD_T("UsePolyEdgesWithShadedModes"), OdRxVariantValue(true)); } //we don't need to setup extents inside appendFrom since we can have additional units transform matrix here if (dataForImportDevice.m_bAppend) { if (pProperties->has(OD_T("DisableSettingExtents"))) pProperties->putAt(OD_T("DisableSettingExtents"), OdRxVariantValue(true)); } if (pProperties->has(OD_T("ReflectHierarchy"))) pProperties->putAt(OD_T("ReflectHierarchy"), OdRxVariantValue(true)); } //setup layout OdGsPrcLayoutHelperPtr pLayoutHelper = OdPrcGsManager::setupActiveLayoutViews(pDevice.get(), pPrcContext); pLayoutHelper->activeView()->setMode(OdGsView::kGouraudShaded); //set the palette pDevice->setLogicalPalette(dataForImportDevice.m_PalCpy.asArrayPtr(), 256); //setup background color pDevice->setBackgroundColor(dataForImportDevice.m_background); //setup background color for the context pPrcContext->setPaletteBackground(dataForImportDevice.m_background); //resize device OdTvDatabaseUtils::resizeImportDevice(pDevice, dataForImportDevice.m_rect); return pLayoutHelper; } //*************************************************************************************// // get units from PRC file //*************************************************************************************// OdTv::Units getPrcUnit(OdPrcFilePtr& pDb, double& addUnitCoefToMeters) { addUnitCoefToMeters = 1.0; OdPrcUnit prc_unit = pDb->unit(); if (prc_unit.unitFromCADFile()) { const double prc_unit_val = prc_unit.unit(); if (OdEqual(prc_unit_val, 1.0)) { return OdTv::kMillimeters; } if (OdEqual(prc_unit_val, 10.0)) { return OdTv::kCentimeters; } if (OdEqual(prc_unit_val, 1000.0)) { return OdTv::kMeters; } if (OdEqual(prc_unit_val, 0.001)) { return OdTv::kMicrometers; } if (OdEqual(prc_unit_val, 1000000.0)) { return OdTv::kKilometers; } if (OdEqual(prc_unit_val, 25.40)) { return OdTv::kInches; } if (OdEqual(prc_unit_val, 12.0 * 25.40)) { return OdTv::kFeet; } if (OdEqual(prc_unit_val, 25.40 / 1000.0)) { return OdTv::kMils; } if (OdEqual(prc_unit_val, 25.40 / 1000000.0)) { return OdTv::kMicroInches; } if (OdEqual(prc_unit_val, 914.4)) { return OdTv::kYards; } if (OdEqual(prc_unit_val, 1760.0 * 914.4)) { return OdTv::kMiles; } addUnitCoefToMeters = prc_unit_val * 1000.0; return OdTv::kUserDefined; } return OdTv::kMillimeters; } //*************************************************************************************// // Implementation of the methods of the inheritants of 'OdTvVisualizePrcFilerDbSource' //*************************************************************************************// class OdTvBaseVisualizePrcFilerSource : public OdTvVisualizePrcFilerDbSource { protected: OdTvResult* m_RC; public: OdTvBaseVisualizePrcFilerSource(OdTvResult* rc) :m_RC(rc) { } virtual ~OdTvBaseVisualizePrcFilerSource() {} virtual OdTvResult* getResult() { return m_RC; } virtual OdPrcFilePtr getDb() = 0; }; class OdTvVisualizePrcFilerSourceFromDb : public OdTvBaseVisualizePrcFilerSource { OdDbBaseDatabase *m_Database; public: OdTvVisualizePrcFilerSourceFromDb(OdDbBaseDatabase *pDatabase, OdTvResult* rc) :OdTvBaseVisualizePrcFilerSource(rc) ,m_Database(pDatabase) { }; virtual ~OdTvVisualizePrcFilerSourceFromDb() {} virtual OdPrcFilePtr getDb() { return m_Database; }; virtual bool odWasInitialized() const { return false; } virtual OdString getFilename() { OdPrcFilePtr pDb = m_Database; if (!pDb.isNull()) { OdString fileName = pDb->getFilename(); if (!fileName.isEmpty()) return fileName; } return OD_T("NoNamePrcDatabase"); } virtual bool isSourceU3D() { OdString fileName = getFilename(); OdString strExt = fileName.mid(fileName.reverseFind('.') + 1); strExt.makeUpper(); if (strExt.isEmpty() || strExt != OD_T("U3D")) return false; return true; } }; class OdTvBaseVisualizePrcU3DFilerSource : public OdTvBaseVisualizePrcFilerSource { protected: OdStaticRxObject m_SVCS; double m_initTime; #ifdef U3D_MODULE_ENABLED OdArray m_Lights; OdU3DMotionInfo m_MotionInfo; #endif public: OdTvBaseVisualizePrcU3DFilerSource(OdTvResult* rc) :OdTvBaseVisualizePrcFilerSource(rc) , m_initTime(0.) { } virtual ~OdTvBaseVisualizePrcU3DFilerSource() { } virtual OdPrcFilePtr getDb() = 0; virtual double getInitTime() const { return m_initTime; } void initialize(OdTvFilerTimeProfiling* pProfileRes) { OdTvFilerTimer timing(needTimer(pProfileRes)); timing.startTotal(); //load module ::odrxDynamicLinker()->loadApp(OdPrcModuleName, false); timing.endTotal(); m_initTime = timing.getTotalTime(); }; bool isU3D(const OdString& file_path) { OdString strExt = file_path.mid(file_path.reverseFind('.') + 1); strExt.makeUpper(); if (strExt.isEmpty() || strExt != OD_T("U3D")) return false; return true; } #ifdef U3D_MODULE_ENABLED void getLights(OdArray& light) { light = m_Lights; } void getMotionInfo(OdU3DMotionInfo& motion_info) { motion_info = m_MotionInfo; } #endif OdPrcFilePtr importFromU3D(const OdString& file_path) { #ifdef U3D_MODULE_ENABLED OdPrcFilePtr pFile = m_SVCS.createDatabase(); OdU3D2PrcImportModulePtr pModule = ::odrxDynamicLinker()->loadModule(OdU3D2PrcImportModuleName, false); if (!pModule.isNull()) { OdU3D2PrcImportPtr importer = pModule->create(); if (!importer.isNull()) { importer->properties()->putAt(L"Database", pFile); importer->properties()->putAt(L"U3DPath", OdRxVariantValue(file_path)); OdResult result = importer->import(); if (m_RC) { if (::eLoadFailed == result) *m_RC = tvErrorDuringOpenFile; } m_Lights = importer->getLights(); m_MotionInfo = importer->getMotionInfo(); } else { if (m_RC) { *m_RC = tvInternal; } } } else { if (m_RC) { *m_RC = tvMissingFilerModule; } } return pFile; #else if (m_RC) { *m_RC = tvMissingFilerModule; } return OdPrcFilePtr(); #endif } OdPrcFilePtr importFromU3D(OdStreamBufPtr pBuf) { #ifdef U3D_MODULE_ENABLED OdPrcFilePtr pFile = m_SVCS.createDatabase(); OdU3D2PrcImportModulePtr pModule = ::odrxDynamicLinker()->loadModule(OdU3D2PrcImportModuleName, false); if (!pModule.isNull()) { OdU3D2PrcImportPtr importer = pModule->create(); if (!importer.isNull()) { importer->properties()->putAt(L"Database", pFile); importer->properties()->putAt(L"SourceType", OdRxVariantValue((OdUInt8)1)); importer->properties()->putAt(L"InputStream", pBuf); OdResult result = importer->import(); if (result != eOk) { if (m_RC &&::eLoadFailed == result) *m_RC = tvErrorDuringOpenFile; return OdPrcFilePtr(); } m_Lights = importer->getLights(); m_MotionInfo = importer->getMotionInfo(); pBuf->rewind(); pFile->writeFile(pBuf); return pFile; } else { if (m_RC) { *m_RC = tvInternal; } } } else { if (m_RC) { *m_RC = tvMissingFilerModule; } } return pFile; #else if (m_RC) { *m_RC = tvMissingFilerModule; } return OdPrcFilePtr(); #endif } }; class OdTvVisualizePrcFilerSourceFromStream : public OdTvBaseVisualizePrcU3DFilerSource { OdStreamBufPtr m_StreamBuf; public: OdTvVisualizePrcFilerSourceFromStream(OdStreamBufPtr pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) :OdTvBaseVisualizePrcU3DFilerSource(rc) , m_StreamBuf(pBuffer) { initialize(pProfileRes); }; virtual OdPrcFilePtr getDb() { OdString strFileName = m_StreamBuf->fileName(); if(strFileName.isEmpty() || !isU3D(strFileName)) return m_SVCS.readFile(m_StreamBuf); return importFromU3D(strFileName); }; virtual OdString getFilename() { OdString strFileName = m_StreamBuf->fileName(); if (strFileName.isEmpty()) return OD_T("NoNamePrcDatabase"); //generate name for the stream file return OdTvDatabaseUtils::getFileNameFromPath(strFileName); }; virtual bool isSourceU3D() { OdString fileName = m_StreamBuf->fileName(); OdString strExt = fileName.mid(fileName.reverseFind('.') + 1); strExt.makeUpper(); if (strExt.isEmpty() || strExt != OD_T("U3D")) return false; return true; } }; class OdTvBaseVisualizePrc3DPdfFilerSource : public OdTvBaseVisualizePrcU3DFilerSource { protected: OdPdf3DStreamExtractorModulePtr m_pModule; OdPdf3DStreamExtractorPtr m_OdPdf3DStreamExtractor; int m_iPage; int m_iStream; OdIntPtr m_pCallback; public: OdTvBaseVisualizePrc3DPdfFilerSource(OdIntPtr pCallback, OdTvResult* rc) :OdTvBaseVisualizePrcU3DFilerSource(rc), m_pCallback(pCallback) { m_iPage = 0; m_iStream = 0; } virtual ~OdTvBaseVisualizePrc3DPdfFilerSource() { m_OdPdf3DStreamExtractor = NULL; m_pModule = NULL; } virtual OdPrcFilePtr getDb() = 0; bool is3DPdf(const OdString& file_path) { OdString strExt = file_path.mid(file_path.reverseFind('.') + 1); strExt.makeUpper(); if (strExt.isEmpty() || strExt != OD_T("PDF")) return false; return true; } OdPrcFilePtr importFrom3DPdf(const OdString& file_path) { try { m_pModule = ::odrxDynamicLinker()->loadModule(OdPdf3DStreamExtractorModuleName, false); } catch (OdError& ) { if (m_RC) *m_RC = tvMissingFilerModule; return OdPrcFilePtr(); } m_OdPdf3DStreamExtractor = m_pModule->create(); if (m_OdPdf3DStreamExtractor.isNull()) { if (m_RC) *m_RC = tvInternal; return OdPrcFilePtr(); } OdString password; OdPdf3DStreamExtractor::ExtractResult res = m_OdPdf3DStreamExtractor->openPdfDocument(file_path, password); if (OdPdf3DStreamExtractor::bad_password == res) { if (m_RC) *m_RC = tvErrorDuringOpenFile; return OdPrcFilePtr(); } // choose streams OdUInt32 nPages = m_OdPdf3DStreamExtractor->getPageCount(res); if (res != OdPdf3DStreamExtractor::success || nPages == 0) { if (m_RC) *m_RC = tvErrorDuringOpenFile; return OdPrcFilePtr(); } if (m_pCallback != 0) { OdTvFilerFeedbackForChooseObject filerFeedbackForChooseObject(OD_T("Choose streams for import")); OdTvFilerFeedbackItemForChooseArray* pFilerFeedbackForChooseArray = filerFeedbackForChooseObject.getFilerFeedbackItemForChooseArrayPtr(); for (OdUInt32 i = 0; i < nPages; i++) { OdString pageStr; pageStr.format(OD_T("Page_%d"), i + 1); OdUInt32 nStreams = m_OdPdf3DStreamExtractor->getCount3DStreamForPage(i, res); if (res != OdPdf3DStreamExtractor::success || nStreams == 0) continue; for (OdUInt32 j = 0; j < nStreams; j++) { OdString name = m_OdPdf3DStreamExtractor->Get3DStreamName(i, j, res); if (OdPdf3DStreamExtractor::success != res) continue; if (name.isEmpty()) name.format(OD_T("Stream_%d"), j); OdTvFilerFeedbackItemForChoose filerFeedbackForChoose(pageStr + OD_T("\\") + name, i == 0 && j == 0); pFilerFeedbackForChooseArray->append(filerFeedbackForChoose); } } ((OdTvFeedbackForChooseCallback)m_pCallback)(filerFeedbackForChooseObject); if (filerFeedbackForChooseObject.getFilerFeedbackItemForChooseArrayPtr()->length() == 0) // cancel { if (m_RC) *m_RC = tvFilerEmptyInternalDatabase; return OdPrcFilePtr(); } // find checked stream for (OdUInt32 i = 0; i < nPages; i++) { OdUInt32 nStreams = m_OdPdf3DStreamExtractor->getCount3DStreamForPage(i, res); if (res != OdPdf3DStreamExtractor::success || nStreams == 0) continue; OdString pageStr; pageStr.format(OD_T("Page_%d"), i + 1); for (OdUInt32 j = 0; j < nStreams; j++) { OdString name = m_OdPdf3DStreamExtractor->Get3DStreamName(i, j, res); if (name.isEmpty()) name.format(OD_T("Stream_%d"), j); if (!filerFeedbackForChooseObject.find(OdTvFilerFeedbackItemForChoose(pageStr + OD_T("\\") + name, true))) continue; else { m_iPage = i; m_iStream = j; } } } } OdStreamBufPtr pBuf = OdMemoryStream::createNew(); res = m_OdPdf3DStreamExtractor->fill3DStream(m_iPage, m_iStream, pBuf); if (res != OdPdf3DStreamExtractor::success) // just try to find valid page and stream { bool bValidStream = false; for (OdUInt32 i = 0; (i < nPages) && !bValidStream; i++) { OdUInt32 nStreams = m_OdPdf3DStreamExtractor->getCount3DStreamForPage(i, res); if (res != OdPdf3DStreamExtractor::success || nStreams == 0) continue; for (OdUInt32 j = 0; j < nStreams; j++) { pBuf = OdMemoryStream::createNew(); res = m_OdPdf3DStreamExtractor->fill3DStream(i, j, pBuf); if (OdPdf3DStreamExtractor::success == res) { bValidStream = true; m_iPage = i; m_iStream = j; break; } } } } pBuf->rewind(); OdPdf3DStreamExtractor::StreamType type = m_OdPdf3DStreamExtractor->Get3DStreamType(m_iPage, m_iStream, res); if (type == OdPdf3DStreamExtractor::eU3D) return importFromU3D(pBuf); else if (type == OdPdf3DStreamExtractor::ePRC) { OdPrcFilePtr pFile = m_SVCS.createDatabase(); OdPrcAuditInfoImplPtr auditInfo = OdPrcAuditInfoImpl::createObject(); auditInfo->setFixErrors(true); pFile->readFile(pBuf, auditInfo.get()); return pFile; } return OdPrcFilePtr(); } }; class OdTvVisualizePrcFilerSourceFromFile : public OdTvBaseVisualizePrc3DPdfFilerSource { OdString m_FilePath; public: OdTvVisualizePrcFilerSourceFromFile(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdIntPtr pCallback, OdTvResult* rc) :OdTvBaseVisualizePrc3DPdfFilerSource(pCallback, rc) ,m_FilePath(filePath) { initialize(pProfileRes); }; virtual OdPrcFilePtr getDb() { if (isU3D(m_FilePath)) return importFromU3D(m_FilePath); else if (is3DPdf(m_FilePath)) return importFrom3DPdf(m_FilePath); return m_SVCS.readFile(m_FilePath); }; virtual OdString getFilename() { //generate name for the stream file return OdTvDatabaseUtils::getFileNameFromPath(m_FilePath); }; virtual bool isSourceU3D() { OdString strExt = m_FilePath.mid(m_FilePath.reverseFind('.') + 1); strExt.makeUpper(); if (strExt.isEmpty() || strExt != OD_T("U3D")) return false; return true; } }; using namespace PRC2Visualize; //***************************************************************************// // 'OdTvVisualizePrcFilerProperties' methods implementation //***************************************************************************// OdTvVisualizePrcFilerProperties::OdTvVisualizePrcFilerProperties() : m_flags(kObjectNaming|kStoreSource|kClearEmptyObjects| kRearrangeObjects | kImportLightsFromU3D ) , m_pPalette(0) , m_dFACETRES(1.) , m_bNeedCDATree(false) , m_bNeedCollectPropertiesInCDA(false) , m_pCallback(nullptr) { m_importRect.xmax = 1; m_importRect.xmin = 0; m_importRect.ymax = 0; m_importRect.ymin = 1; } OdRxDictionaryPtr OdTvVisualizePrcFilerProperties::createObject() { return OdRxObjectImpl::createObject(); } void OdTvVisualizePrcFilerProperties::setPalette(OdIntPtr palette) { const ODCOLORREF* pPalette = (const ODCOLORREF*)(palette); m_pPalette = pPalette; } OdIntPtr OdTvVisualizePrcFilerProperties::getPalette() const { return (OdIntPtr)(m_pPalette); } OdTvVisualizePrcFilerProperties::~OdTvVisualizePrcFilerProperties() { } namespace PRC2Visualize { ODRX_DECLARE_PROPERTY(Palette) ODRX_DECLARE_PROPERTY(DCRect) ODRX_DECLARE_PROPERTY(ObjectNaming) ODRX_DECLARE_PROPERTY(StoreSourceObjects) ODRX_DECLARE_PROPERTY(ClearEmptyObjects) ODRX_DECLARE_PROPERTY(RearrangeObjects) ODRX_DECLARE_PROPERTY(ImportBrepAsBrep) ODRX_DECLARE_PROPERTY(BrepFacetRes) ODRX_DECLARE_PROPERTY(AppendTransform) ODRX_DECLARE_PROPERTY(NeedCDATree) ODRX_DECLARE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_DECLARE_PROPERTY(FeedbackForChooseCallback) ODRX_DECLARE_PROPERTY(ImportLightsFromU3D) ODRX_DECLARE_PROPERTY(ImportMotionFromU3D) ODRX_DECLARE_PROPERTY(ImportWithHierarchy) ODRX_DECLARE_PROPERTY(ImportPrcParams) ODRX_BEGIN_DYNAMIC_PROPERTY_MAP(OdTvVisualizePrcFilerProperties); ODRX_GENERATE_PROPERTY(Palette) ODRX_GENERATE_PROPERTY(DCRect) ODRX_GENERATE_PROPERTY(ObjectNaming) ODRX_GENERATE_PROPERTY(StoreSourceObjects) ODRX_GENERATE_PROPERTY(ClearEmptyObjects) ODRX_GENERATE_PROPERTY(RearrangeObjects) ODRX_GENERATE_PROPERTY(ImportBrepAsBrep) ODRX_GENERATE_PROPERTY(BrepFacetRes) ODRX_GENERATE_PROPERTY(AppendTransform) ODRX_GENERATE_PROPERTY(NeedCDATree) ODRX_GENERATE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_GENERATE_PROPERTY(FeedbackForChooseCallback) ODRX_GENERATE_PROPERTY(ImportLightsFromU3D) ODRX_GENERATE_PROPERTY(ImportMotionFromU3D) ODRX_GENERATE_PROPERTY(ImportWithHierarchy) ODRX_GENERATE_PROPERTY(ImportPrcParams) ODRX_END_DYNAMIC_PROPERTY_MAP(OdTvVisualizePrcFilerProperties); ODRX_DEFINE_PROPERTY_METHODS(Palette, OdTvVisualizePrcFilerProperties, getPalette, setPalette, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(DCRect, OdTvVisualizePrcFilerProperties, getDCRect, setDCRect, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ObjectNaming, OdTvVisualizePrcFilerProperties, getObjectNaming, setObjectNaming, getBool); ODRX_DEFINE_PROPERTY_METHODS(StoreSourceObjects, OdTvVisualizePrcFilerProperties, getStoreSourceObjects, setStoreSourceObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(ClearEmptyObjects, OdTvVisualizePrcFilerProperties, getClearEmptyObjects, setClearEmptyObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(RearrangeObjects, OdTvVisualizePrcFilerProperties, getRearrangeObjects, setRearrangeObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportBrepAsBrep, OdTvVisualizePrcFilerProperties, getImportBrepAsBrep, setImportBrepAsBrep, getBool); ODRX_DEFINE_PROPERTY_METHODS(BrepFacetRes, OdTvVisualizePrcFilerProperties, getBrepFacetRes, setBrepFacetRes, getDouble); ODRX_DEFINE_PROPERTY_METHODS(AppendTransform, OdTvVisualizePrcFilerProperties, getAppendTransform, setAppendTransform, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(NeedCDATree, OdTvVisualizePrcFilerProperties, getNeedCDATree, setNeedCDATree, getBool); ODRX_DEFINE_PROPERTY_METHODS(NeedCollectPropertiesInCDA, OdTvVisualizePrcFilerProperties, getNeedCollectPropertiesInCDA, setNeedCollectPropertiesInCDA, getBool); ODRX_DEFINE_PROPERTY_METHODS(FeedbackForChooseCallback, OdTvVisualizePrcFilerProperties, getFeedbackForChooseCallback, setFeedbackForChooseCallback, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ImportLightsFromU3D, OdTvVisualizePrcFilerProperties, getImportLightsFromU3D, setImportLightsFromU3D, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportMotionFromU3D, OdTvVisualizePrcFilerProperties, getImportMotionFromU3D, setImportMotionFromU3D, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportWithHierarchy, OdTvVisualizePrcFilerProperties, getImportWithHierarchy, setImportWithHierarchy, getBool); ODRX_DEFINE_PROPERTY_METHODS(ImportPrcParams, OdTvVisualizePrcFilerProperties, getImportPrcParams, setImportPrcParams, getBool); } void OdTvVisualizePrcFilerProperties::setDCRect(OdIntPtr rect) { OdTvDCRect* pRect = (OdTvDCRect*)(rect); if (!pRect) { ODA_ASSERT(false); } m_importRect = *pRect; } OdIntPtr OdTvVisualizePrcFilerProperties::getDCRect() const { return (OdIntPtr)(&m_importRect); } void OdTvVisualizePrcFilerProperties::setBrepFacetRes(double dFacetRes) { m_dFACETRES = dFacetRes; if (dFacetRes < 0.01) m_dFACETRES = 0.01; if (dFacetRes > 10.) m_dFACETRES = 10.; } double OdTvVisualizePrcFilerProperties::getBrepFacetRes() const { return m_dFACETRES; } void OdTvVisualizePrcFilerProperties::setAppendTransform(OdIntPtr pTransform) { const OdTvMatrix* pAppendTransform = (const OdTvMatrix*)(pTransform); if (pAppendTransform) { m_appendTransform = *pAppendTransform; } else { m_appendTransform = OdTvMatrix::kIdentity; } } OdIntPtr OdTvVisualizePrcFilerProperties::getAppendTransform() const { return (OdIntPtr)(&m_appendTransform); } //***************************************************************************// // 'OdTvVisualizePrcFiler' methods implementation //***************************************************************************// OdTvVisualizePrcFiler::OdTvVisualizePrcFiler() : m_properties(OdTvVisualizePrcFilerProperties::createObject()) { } OdTvDatabaseId OdTvVisualizePrcFiler::loadFrom(OdDbBaseDatabase *pDatabase, OdTvFilerTimeProfiling* pProfileRes /*= NULL*/, OdTvResult* rc /*= NULL*/) const { OdTvVisualizePrcFilerSourceFromDb dl(pDatabase, rc); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizePrcFiler::loadFrom(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes /*= NULL*/, OdTvResult* rc /*= NULL*/) const { OdTvVisualizePrcFilerSourceFromStream dl(pBuffer, pProfileRes, rc); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizePrcFiler::loadFrom(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { ; OdTvVisualizePrcFilerSourceFromFile dl(filePath, pProfileRes, m_properties->getFeedbackForChooseCallback(), rc); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizePrcFiler::generate(OdTvFilerTimeProfiling* pProfileRes) const { OdTvDatabaseId tvDbId; // does nothing return tvDbId; } OdTvModelId OdTvVisualizePrcFiler::appendFrom(const OdTvDatabaseId& databaseId, OdDbBaseDatabase *pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizePrcFilerSourceFromDb dl(pDatabase, rc); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizePrcFiler::appendFrom(const OdTvDatabaseId& databaseId, OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizePrcFilerSourceFromStream dl(pBuffer, pProfileRes, rc); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizePrcFiler::appendFrom(const OdTvDatabaseId& databaseId, const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizePrcFilerSourceFromFile dl(filePath, pProfileRes, m_properties->getFeedbackForChooseCallback(), rc); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizePrcFiler::loadFromEx(OdTvVisualizePrcFilerDbSource* pPrcDatabaseSource, OdTvFilerTimeProfiling* pProfileRes /*= NULL*/, OdTvResult* rc /*= NULL*/) const { OdTvDatabaseId tvDbId; if (!pPrcDatabaseSource) { if (rc) *rc = tvInvalidInput; return tvDbId; } if (rc) *rc = tvOk; //check that time profiling is need bool bUseTimeProfiling = pProfileRes != NULL ? true : false; double tvTiming = 0.; double tvTiming_1 = 0.; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); //try to perform direct import try { //load database OdPrcFilePtr pDb = pPrcDatabaseSource->getDb(); timing.startVectorizing(); //create Visualize database tvDbId = odTvGetFactory().createDatabase(); //apply name for the visualize database OdString modelFinalName = pPrcDatabaseSource->getFilename(); OdTvDatabaseUtils::writeFileNameToTvDatabase(tvDbId, modelFinalName); //perform import operation OdArray importedModels; prcViewNodeToTvViewMap importedViews; OdTvResult res = performDirectImport(pDb, tvDbId, m_properties->getClearEmptyObjects(), m_properties->getBrepFacetRes(), m_properties->getImportBrepAsBrep(), importedModels, importedViews, tvTiming); ////PRC UserData if (m_properties->getImportPrcParams()) { for(auto& modelId : importedModels) collectInfoToUserData(modelId, pPrcDatabaseSource); } timing.startMisc(); //resize device if (!importedViews.empty()) { OdTvDCRect* pRect = (OdTvDCRect*)m_properties->getDCRect(); if (pRect) { OdTvGsDeviceId devId = importedViews.begin()->second.openObject(OdTv::kForRead)->device(); OdTvGsDevicePtr pDevice = devId.openObject(OdTv::kForWrite); if (!pDevice.isNull()) pDevice->onSize(*pRect); } for (auto const& it : importedViews) { //setup lights #ifdef U3D_MODULE_ENABLED if (m_properties->getImportLightsFromU3D()) { setupLights(importedModels[0], pPrcDatabaseSource, it.second); } else { OdTvGsViewPtr pTvGsView = it.second.openObject(OdTv::kForWrite); pTvGsView->setDefaultLightingIntensity(1.); pTvGsView->setAmbientLightColor(OdTvColorDef(50, 50, 50)); } if (m_properties->getImportMotionFromU3D()) ImportMotionRes(importedModels[0], pPrcDatabaseSource); #else { OdTvGsViewPtr pTvGsView = it.second.openObject(OdTv::kForWrite); pTvGsView->setDefaultLightingIntensity(1.); pTvGsView->setAmbientLightColor(OdTvColorDef(50, 50, 50)); } #endif } } timing.endMisc(); tvTiming_1 = timing.getMiscTime(); if (m_properties->getNeedCDATree() && tvDbId.isValid()) { timing.startMisc(); if (!tvDbId.isNull()) createCommonDataAccessTree(tvDbId, modelFinalName); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); } timing.endVectorizing(); } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //finish timing timing.endTotal(); //write timing info if (pProfileRes) { pProfileRes->setImportTime(OdInt64((timing.getTotalTime() - timing.getVectorizingTime() + pPrcDatabaseSource->getInitTime()) * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((tvTiming + tvTiming_1) * 1000.)); #endif } return tvDbId; } OdTvDatabaseId OdTvVisualizePrcFiler::loadFrom(OdTvVisualizePrcFilerDbSource *pPrcDatabaseSource, OdTvFilerTimeProfiling* pProfileRes /*= NULL*/, OdTvResult* rc /*= NULL*/) const { if (m_properties->getImportWithHierarchy()) return loadFromEx(pPrcDatabaseSource, pProfileRes, rc); OdTvDatabaseId tvDbId; if (!pPrcDatabaseSource) { if (rc) *rc = tvInvalidInput; return tvDbId; } if (rc) *rc = tvOk; //check that time profiling is need bool bUseTimeProfiling = needTimer(pProfileRes); double internalTiming = 0.; double externalTiming = 0; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); //store visualize device module name OdString moduleName; try { //load database OdPrcFilePtr pDb = pPrcDatabaseSource->getDb(); timing.startVectorizing(); if (!pDb.isNull()) { //prepare PRC context OdGiContextForPrcDatabasePtr pPrcContext = OdGiContextForPrcDatabase::createObject(); pPrcContext->enableGsModel(true); pPrcContext->setDatabase(pDb); //get PRC units double addUnitCoefToMeters(1.0); OdTv::Units tvUnits = getPrcUnit(pDb, addUnitCoefToMeters); //get module with import device OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdTvVisualizeDeviceModuleName, false); if (pGs.isNull()) { if (rc) *rc = tvMissingVisualizeDeviceModule; return tvDbId; } moduleName = pGs->moduleName(); //create and setup device for import ParamForImportDevice dataForImportDevice; dataForImportDevice.m_background = ODRGB(64, 64, 64); dataForImportDevice.m_bAppend = false; OdTvDCRect* pRect = (OdTvDCRect*)m_properties->getDCRect(); if (pRect) dataForImportDevice.m_rect = *pRect; else dataForImportDevice.m_rect = OdTvDCRect(0, 0, 0, 0); OdTvDatabaseUtils::getPaletteForImportDevice((const ODCOLORREF*)m_properties->getPalette(), dataForImportDevice.m_PalCpy); OdRxDictionaryPtr pProperties; OdGsPrcLayoutHelperPtr pLayoutHelper = createAndSetupImportDevice(pGs, m_properties, pPrcContext, bUseTimeProfiling, dataForImportDevice, pProperties); //setup current active view pDb->applyCurrentView(); // set option for drawing breps if (m_properties->getImportBrepAsBrep() && pDb->getTESSDRAWMODE() == 0) pDb->setTESSDRAWMODE(1); //call update method for import pLayoutHelper->update(); if (pProperties->has(OD_T("TvDatabaseID"))) tvDbId = *(OdTvDatabaseId*)OdRxVariantValue(pProperties->getAt(OD_T("TvDatabaseID")).get())->getIntPtr(); if (bUseTimeProfiling) { #if !defined(__APPLE__) if (pProperties->has(OD_T("TvElapsedTime"))) { internalTiming = OdRxVariantValue(pProperties->getAt(OD_T("TvElapsedTime")).get())->getDouble(); } #endif } //setup active view timing.startMisc(); //START POSTPROCESSING OdString modelFinalName; bool bNeedResetViewToExtents = false; if (tvDbId.isValid()) { modelFinalName = pPrcDatabaseSource->getFilename(); //apply custom background applyCustomBackground(tvDbId, pLayoutHelper); // save filename to database user data OdTvDatabaseUtils::writeFileNameToTvDatabase(tvDbId, pPrcDatabaseSource->getFilename()); //rename the model (here we suppose that database contain only one model) OdTvModelsIteratorPtr pModelsIterator = tvDbId.openObject()->getModelsIterator(); if (!pModelsIterator.isNull() && !pModelsIterator->done()) { OdTvModelId modelId = pModelsIterator->getModel(); OdTvModelPtr pModel = modelId.openObject(OdTv::kForWrite); if (!pModel.isNull()) { pModel->setName(pPrcDatabaseSource->getFilename()); pModel->setUnits(tvUnits, tvUnits == OdTv::kUserDefined ? addUnitCoefToMeters : 1.); // a) mark edges from closed OdPrcBrepModel or OdPrcPolyBrepModel as GiSilhouette for filtering via crease angle // b) set flag about isolines calculation or about excluding from isolines draw for OdPrcBrepModel or OdPrcPolyBrepModel if (m_properties->getStoreSourceObjects()) processingDataForBrepTesselation(pDb, modelId); //apply normal naming to the objects and remove some subentities // here we apply PRC names and remove subentities if: //1. It is an alone subentity without native handle (create due to new traits) //2. It is an alone subentity without native PRC name. Here there is some special moment. // If name is empty and object is 'OdPrcProductOccurrence' we are trying to find name at 'prototypeID' //3. If subentity corresponds to the 'OdPrcPartDefinition', we remove such subentity if it has only one child if (m_properties->getStoreSourceObjects() && m_properties->getObjectNaming() ) applyPRCEntityNaming(pDb, modelId, m_properties->getRearrangeObjects()); //PRC UserData if (m_properties->getImportPrcParams()) collectInfoToUserData(modelId, pPrcDatabaseSource); // if we want animation, we need to keep the initial model tree!!! if (!m_properties->getImportMotionFromU3D()) { //clean empty objects (it is important to clean early than rearrange) if (m_properties->getClearEmptyObjects() || m_properties->getRearrangeObjects()) OdTvDatabaseCleaner::cleanTvDatabase(tvDbId); //explode alone subentities. This is need with purpose to receive a model with a few entities, //because by default model contains 1 entity which also contains 1 subentity. And only then we have a set of subentities if (m_properties->getRearrangeObjects()) bNeedResetViewToExtents = explodeSubEntitiesForAloneEntity(pDb, pModel); } //set flags about topology checking processingDataForSetNeedCheckTopology(modelId); modelFinalName = pModel->getName(); #ifdef U3D_MODULE_ENABLED int iActViewViewInd = getActiveViewId(pLayoutHelper.get()); OdTvDatabaseId tvDbId = pModel->getDatabase(); OdTvGsViewId tvViewId = getActiveTvView(tvDbId, iActViewViewInd); if (m_properties->getImportLightsFromU3D()) setupLights(modelId, pPrcDatabaseSource, tvViewId); if (m_properties->getImportMotionFromU3D()) ImportMotionRes(modelId, pPrcDatabaseSource); #endif } } } timing.endMisc(); externalTiming += timing.getMiscTime(); OdTvDatabaseUtils::createAndApplyPreferableVS(tvDbId, true, false); OdTvVisualStyleId visualStyleHiddenId = tvDbId.openObject(OdTv::kForWrite)->findVisualStyle(OD_T("Hidden Line Black")); if (!visualStyleHiddenId.isNull()) { OdTvVisualStylePtr pVisualStyle = visualStyleHiddenId.openObject(OdTv::kForWrite); if (!pVisualStyle.isNull()) pVisualStyle->setOption(OdTvVisualStyleOptions::kFaceColorMode, (OdInt32)OdTvVisualStyleOptions::kBackgroundTexture); } //apply visual style applyPreferrableVisualStyle(tvDbId, pLayoutHelper); // since the GS is not setup yet,we can call empty zoom to extens to mark the view. // The action will be performed inside first setupGs if (bNeedResetViewToExtents) { int iActViewViewInd = getActiveViewId(pLayoutHelper.get()); OdTvGsViewId tvViewId = getActiveTvView(tvDbId, iActViewViewInd); if (!tvViewId.isNull()) { OdTvGsViewPtr pActiveTvView = tvViewId.openObject(OdTv::kForWrite); OdTvPoint minPt, maxPt; pActiveTvView->zoomExtents(minPt, maxPt); } } if (m_properties->getNeedCDATree() && tvDbId.isValid()) { timing.startMisc(); if (!tvDbId.isNull()) createCommonDataAccessTree(tvDbId, modelFinalName); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); } timing.endVectorizing(); } else { if (rc && (tvOk == *rc)) *rc = tvFilerEmptyInternalDatabase; } } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //unload Prc modules (try to emulate the OdUninitialized for PRC) //here we will unload all including Visualize device if (!moduleName.isEmpty()) odrxDynamicLinker()->unloadUnreferenced(); timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64((timing.getTotalTime() - timing.getVectorizingTime() + pPrcDatabaseSource->getInitTime()) * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((internalTiming + externalTiming) * 1000.)); #endif } return tvDbId; } OdTvModelId OdTvVisualizePrcFiler::appendFrom(const OdTvDatabaseId& databaseId, OdTvVisualizePrcFilerDbSource *pPrcDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvModelId tvModelId; if (!pPrcDatabaseSource) { if (rc) *rc = tvInvalidInput; return 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 ParamForImportDevice dataForImportDevice; dataForImportDevice.m_background = ODRGB(0, 0, 0); dataForImportDevice.m_rect = OdTvDCRect(0, 0, 0, 0); dataForImportDevice.m_bAppend = true; if (!activeTvGsDeviceId.isNull()) { OdTvGsDevicePtr pTvDevice = activeTvGsDeviceId.openObject(); dataForImportDevice.m_background = pTvDevice->getBackgroundColor(); pTvDevice->getSize(dataForImportDevice.m_rect); int nColors; const ODCOLORREF* pPalette = pTvDevice->getLogicalPalette(nColors); if (nColors >= 256) dataForImportDevice.m_PalCpy.insert(dataForImportDevice.m_PalCpy.begin(), pPalette, pPalette + 256); else { dataForImportDevice.m_PalCpy.insert(dataForImportDevice.m_PalCpy.begin(), pPalette, pPalette + nColors); dataForImportDevice.m_PalCpy.insert(dataForImportDevice.m_PalCpy.begin() + nColors, 256 - nColors, ODRGB(0, 0, 0)); } } else { dataForImportDevice.m_background = ODRGB(171, 200, 232); OdTvDCRect* pRect = (OdTvDCRect*)m_properties->getDCRect(); if (pRect) dataForImportDevice.m_rect = *pRect; //set the palette OdTvDatabaseUtils::getPaletteForImportDevice((const ODCOLORREF*)m_properties->getPalette(), dataForImportDevice.m_PalCpy); } //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 = needTimer(pProfileRes); double internalTiming = 0.; double externalTiming = 0; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); OdString moduleName; try { //load database OdPrcFilePtr pDb = pPrcDatabaseSource->getDb(); timing.startVectorizing(); if (!pDb.isNull()) { //prepare PRC context OdGiContextForPrcDatabasePtr pPrcContext = OdGiContextForPrcDatabase::createObject(); pPrcContext->enableGsModel(true); pPrcContext->setDatabase(pDb); // get PRC units double addUnitCoefToMeters(1.0); OdTv::Units tvUnits = getPrcUnit(pDb, addUnitCoefToMeters); //get module with import device OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdTvVisualizeDeviceModuleName, false); if (pGs.isNull()) { if (rc) *rc = tvMissingVisualizeDeviceModule; return tvModelId; } moduleName = pGs->moduleName(); // Generate model name OdString modelName = OdTvDatabaseUtils::generateModelName(databaseId, pPrcDatabaseSource->getFilename()); //create and setup device for import dataForImportDevice.m_databaseId = databaseId; dataForImportDevice.m_strModelName = modelName; dataForImportDevice.m_tvDeviceIdForAppend = activeTvGsDeviceId; OdRxDictionaryPtr pProperties; OdGsPrcLayoutHelperPtr pLayoutHelper = createAndSetupImportDevice(pGs, m_properties, pPrcContext, bUseTimeProfiling, dataForImportDevice, pProperties); //setup current active view pDb->applyCurrentView(); // set option for drawing breps if (m_properties->getImportBrepAsBrep() && pDb->getTESSDRAWMODE() == 0) pDb->setTESSDRAWMODE(1); //call update method for import pLayoutHelper->update(); //get tv time if need if (bUseTimeProfiling) { #if !defined(__APPLE__) if (pProperties->has(OD_T("TvElapsedTime"))) { internalTiming = OdRxVariantValue(pProperties->getAt(OD_T("TvElapsedTime")).get())->getDouble(); } #endif } //setup active view timing.startMisc(); //START POSTPROCESSING bool bNeedResetViewToExtents = false; if (databaseId.isValid()) { timing.startMisc(); //get new model { OdTvDatabasePtr pTvDb = databaseId.openObject(); tvModelId = pTvDb->findModel(modelName); } // a) mark edges from closed OdPrcBrepModel or OdPrcPolyBrepModel as GiSilhouette for filtering via crease angle // b) set flag about isolines calculation or about excluding from isolines draw for OdPrcBrepModel or OdPrcPolyBrepModel if (m_properties->getStoreSourceObjects()) processingDataForBrepTesselation(pDb, tvModelId); //apply normal naming to the objects and remove some subentities // here we apply PRC names and remove subentities if: //1. It is an alone subentity without native handle (create due to new traits) //2. It is an alone subentity without native PRC name. Here there is some special moment. // If name is empty and object is 'OdPrcProductOccurrence' we are trying to find name at 'prototypeID' //3. If subentity corresponds to the 'OdPrcPartDefinition', we remove such subentity if it has only one child if (m_properties->getStoreSourceObjects() && m_properties->getObjectNaming()) applyPRCEntityNaming(pDb, tvModelId, m_properties->getRearrangeObjects()); //PRC UserData if (m_properties->getImportPrcParams()) collectInfoToUserData(tvModelId, pPrcDatabaseSource); // if we want animation, we need to keep the initial model tree!!! if (!m_properties->getImportMotionFromU3D()) { //clean some data (it is important to clean early than rearrange) OdTvDatabaseId& tvDvId = const_cast(databaseId); OdTvDatabaseCleaner::cleanTvDatabaseForAppend(tvDvId, foreignViews, foreignModels, foreignBlocks); //explode alone subentities. This is need with purpose to receive a model with a few entities, //because by default model contains 1 entity which also contains 1 subentity. And only then we have a set of subentities if (m_properties->getRearrangeObjects()) { OdTvModelPtr pModel = tvModelId.openObject(OdTv::kForWrite); bNeedResetViewToExtents = explodeSubEntitiesForAloneEntity(pDb, pModel); } } //set flags about topology checking processingDataForSetNeedCheckTopology(tvModelId); //apply transform if need OdTvMatrix* pTransfrom = (OdTvMatrix*)m_properties->getAppendTransform(); if (pTransfrom) { OdTvDatabaseId& tvDvId = const_cast(databaseId); OdTvDatabaseUtils::applyTransformToTheModel(tvDvId, modelName, *pTransfrom); } //apply units if (!tvModelId.isNull()) { OdTvModelPtr pModel = tvModelId.openObject(OdTv::kForWrite); if (!pModel.isNull()) { //set units pModel->setUnits(tvUnits, tvUnits == OdTv::kUserDefined ? addUnitCoefToMeters : 1.); #ifdef U3D_MODULE_ENABLED int iActViewViewInd = getActiveViewId(pLayoutHelper.get()); OdTvDatabaseId tvDbId = pModel->getDatabase(); OdTvGsViewId tvViewId = getActiveTvView(tvDbId, iActViewViewInd); if(m_properties->getImportLightsFromU3D()) setupLights(tvModelId, pPrcDatabaseSource, tvViewId); if (m_properties->getImportMotionFromU3D()) ImportMotionRes(tvModelId, pPrcDatabaseSource); #endif } } if (activeTvGsDeviceId.isNull()) { OdTvDatabaseId& tvDvId = const_cast(databaseId); OdTvDatabaseUtils::createAndApplyPreferableVS(tvDvId, true, false); OdTvVisualStyleId visualStyleHiddenId = tvDvId.openObject(OdTv::kForWrite)->findVisualStyle(OD_T("Hidden Line Black")); if (!visualStyleHiddenId.isNull()) { OdTvVisualStylePtr pVisualStyle = visualStyleHiddenId.openObject(OdTv::kForWrite); if (!pVisualStyle.isNull()) pVisualStyle->setOption(OdTvVisualStyleOptions::kFaceColorMode, (OdInt32)OdTvVisualStyleOptions::kBackgroundTexture); } //apply visual style applyPreferrableVisualStyle(const_cast(databaseId), pLayoutHelper); // since the GS is not setup yet,we can call empty zoom to extens to mark the view. // The action will be performed inside first setupGs if (bNeedResetViewToExtents) { int iActViewViewInd = getActiveViewId(pLayoutHelper.get()); OdTvGsViewId tvViewId = getActiveTvView(const_cast(databaseId), iActViewViewInd); if (!tvViewId.isNull()) { OdTvGsViewPtr pActiveTvView = tvViewId.openObject(OdTv::kForWrite); OdTvPoint minPt, maxPt; pActiveTvView->zoomExtents(minPt, maxPt); } } } if (m_properties->getNeedCDATree() && !tvModelId.isNull()) { timing.startMisc(); OdTvModelPtr pModel = tvModelId.openObject(); createCommonDataAccessTree(databaseId, pModel->getName()); timing.endMisc(); if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); } timing.endMisc(); externalTiming = timing.getMiscTime(); } timing.endVectorizing(); } else { if (rc && (tvOk == *rc)) *rc = tvFilerEmptyInternalDatabase; } } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //unload Prc modules (try to emulate the OdUninitialized for PRC) //here we will unload all including Visualize device if (!moduleName.isEmpty()) odrxDynamicLinker()->unloadUnreferenced(); timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64((timing.getTotalTime() - timing.getVectorizingTime() + pPrcDatabaseSource->getInitTime()) * 1000.)); pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((internalTiming + externalTiming) * 1000.)); #endif } return tvModelId; } int OdTvVisualizePrcFiler::getActiveViewId(OdGsPrcLayoutHelper* pLayoutHelper) const { if (!pLayoutHelper) return -1; OdGsViewPtr pActiveView = pLayoutHelper->activeView(); int num = pLayoutHelper->numViews(); int iActViewViewInd = 0; for (int i = 0; i < num; ++i) { OdGsView* pView = pLayoutHelper->viewAt(i); if (pView == pActiveView.get()) { iActViewViewInd = i; break; } } return iActViewViewInd; } OdTvGsViewId OdTvVisualizePrcFiler::getActiveTvView(OdTvDatabaseId& dbId, int iActViewViewInd) const { OdTvDevicesIteratorPtr pDevicesIterator = dbId.openObject()->getDevicesIterator(); if (!pDevicesIterator.isNull() && !pDevicesIterator->done()) { OdTvGsDevicePtr pTvDevice = pDevicesIterator->getDevice().openObject(); if (!pTvDevice.isNull()) { return pTvDevice->viewAt(iActViewViewInd); } } return OdTvGsViewId(); } void OdTvVisualizePrcFiler::applyPreferrableVisualStyle(OdTvDatabaseId& dbId, OdGsPrcLayoutHelperPtr pLayoutHelper) const { int iActViewViewInd = getActiveViewId(pLayoutHelper.get()); OdTvGsViewId tvViewId = getActiveTvView(dbId, iActViewViewInd); if (!tvViewId.isNull()) { OdTvGsViewPtr pActiveTvView = tvViewId.openObject(OdTv::kForWrite); if (!pActiveTvView.isNull()) { //set visual style preferable pActiveTvView->setVisualStyle(dbId.openObject()->getPreferableVisualStyle(OdTvDatabase::kShadedWithIsolines)); } } } #ifdef U3D_MODULE_ENABLED void OdTvVisualizePrcFiler::setupLights(OdTvModelId& tvModelId, OdTvVisualizePrcFilerDbSource* pPrcDatabaseSource, OdTvGsViewId tvViewId) const { OdArray lights; pPrcDatabaseSource->getLights(lights); OdTvModelPtr pModel = tvModelId.openObject(OdTv::kForWrite); if (0 != lights.size()) { if (!tvViewId.isNull()) { OdTvGsViewPtr pTvGsView = tvViewId.openObject(OdTv::kForWrite); pTvGsView->setDefaultLightingIntensity(1.); pTvGsView->setAmbientLightColor(OdTvColorDef(50, 50, 50)); pTvGsView->enableDefaultLighting(false, OdTvGsView::kTwoLights); } } else { OdTvGsViewPtr pTvGsView = tvViewId.openObject(OdTv::kForWrite); pTvGsView->setDefaultLightingIntensity(1.); pTvGsView->setAmbientLightColor(OdTvColorDef(50, 50, 50)); } int idx(0); for (auto& light : lights) { OdU3DLightInfo::LightType lightType = light.lightType; if (OdU3DLightInfo::AMBIENT == lightType) { if (!tvViewId.isNull()) { OdTvGsViewPtr pTvGsView = tvViewId.openObject(OdTv::kForWrite); pTvGsView->setAmbientLightColor(OdTvColorDef(ODGETRED(light.color), ODGETGREEN(light.color), ODGETBLUE(light.color))); } continue; } OdTvEntityId tvLightId = pModel->appendLight(light.name.isEmpty() ? OdString().format(OD_T("Light_%d"), ++idx) : light.name); OdTvLightPtr pTvLight = tvLightId.openObjectAsLight(OdTv::kForWrite); pTvLight->setOn(light.isEnabled); OdGePoint3d origin; OdGeVector3d xAxis, yAxis, zAxis; light.matrix.getCoordSystem(origin, xAxis, yAxis, zAxis); switch (lightType) { case OdU3DLightInfo::POINT: { pTvLight->setLightType(OdTvLight::kPointLight); pTvLight->setPosition(OdGePoint3d(OdGePoint3d::kOrigin).transformBy(light.matrix)); } break; case OdU3DLightInfo::DIRECTIONAL: { pTvLight->setLightType(OdTvLight::kDistantLight); pTvLight->setLightDirection((OdGePoint3d::kOrigin - OdGeVector3d::kZAxis).asVector().transformBy(light.matrix)); } break; case OdU3DLightInfo::SPOT: pTvLight->setLightType(OdTvLight::kSpotLight); pTvLight->setPosition(OdGePoint3d(OdGePoint3d::kOrigin).transformBy(light.matrix)); pTvLight->setLightDirection((OdGePoint3d::kOrigin - OdGeVector3d::kZAxis).asVector().transformBy(light.matrix)); pTvLight->setHotspotAndFalloff(OdaToRadian(light.spotAngle), 0); break; default: continue; } if (lightType == OdU3DLightInfo::POINT || lightType == OdU3DLightInfo::SPOT) { OdTvLightAttenuation tvLightAttenuation; switch (light.attenuation) { case OdU3DLightInfo::CONSTANT: tvLightAttenuation.setAttenuationType(OdTvLightAttenuation::kNone); break; case OdU3DLightInfo::LINEAR: tvLightAttenuation.setAttenuationType(OdTvLightAttenuation::kInverseLinear); break; case OdU3DLightInfo::QUADRADIC: tvLightAttenuation.setAttenuationType(OdTvLightAttenuation::kInverseSquare); default: break; } pTvLight->setLightAttenuation(tvLightAttenuation); } pTvLight->setIntensity(light.intensity); pTvLight->setLightColor(OdTvColorDef(ODGETRED(light.color), ODGETGREEN(light.color), ODGETBLUE(light.color))); OdTvShadowParameters shadow_parameters; shadow_parameters.setShadowsOn(false); pTvLight->setShadowParameters(shadow_parameters); } } bool u3dMatr2Angles(OdGeMatrix3d& R, double& x, double& y, double& z) { if (!OdEqual(R[2][0], 1.) && !OdEqual(R[2][0], -1.)) { double pitch_1 = -1. * asin(R[2][0]); double pitch_2 = OdaPI - pitch_1; double cosPitch1 = cos(pitch_1); double cosPitch2 = cos(pitch_2); if (OdZero(cosPitch1) || OdZero(cosPitch2)) return false; double roll_1 = atan2(R[2][1] / cosPitch1, R[2][2] / cosPitch1); double roll_2 = atan2(R[2][1] / cosPitch2, R[2][2] / cosPitch2); double yaw_1 = atan2(R[1][0] / cosPitch1, R[0][0] / cosPitch1); double yaw_2 = atan2(R[1][0] / cosPitch2, R[0][0] / cosPitch2); if (OdLessOrEqual(std::abs(roll_1) + std::abs(pitch_1) + std::abs(yaw_1), std::abs(roll_2) + std::abs(pitch_2) + std::abs(yaw_2))) { y = pitch_1; x = roll_1; z = yaw_1; return true; } else { y = pitch_2; x = roll_2; z = yaw_2; return true; } } else { z = 0; // anything(we default this to zero) if (OdEqual(R[2][0], -1.)) { y = OdaPI2; x = z + atan2(R[0][1], R[0][2]); } else { y = -OdaPI2; x = -1. * z + atan2(-1. * R[0][1], -1. * R[0][2]); } } return true; } struct U3DTrackInfo { OdUInt32 start_time{ 0 }; OdTvAnimationActionId id; }; void appendEntitiesIds(const OdTvEntityId entityId, OdTvSubItemPath& actor) { actor.entitiesIds().push_back(entityId); } void appendEntitiesIds(const OdTvGeometryDataId entityId, OdTvSubItemPath& actor) { actor.geometryDatasIds().push_back(entityId); } template bool addAnimationToContainer(const T entityId, OdTvEntityPtr& pEntity, OdTvDatabasePtr& pTvDb, std::map>& action_map, OdU3DMotionInfo& motion_info, OdTvEntityId* parentEntityId = nullptr) { OdString appName(L"ExGsVisualizeDevice"); OdInt64 iSubEntNativeId = getSourceDatabaseHandle(pEntity, appName); auto motion_info_iter = motion_info.motion_info_map.find(iSubEntNativeId); if (motion_info.motion_info_map.end() != motion_info_iter) { if (0 != motion_info_iter->second.mixerID) { OdUInt32 u3d_res_ID = motion_info.mixer_res_info[motion_info_iter->second.mixerID].res_info; if (0 != u3d_res_ID) { OdTvAnimationContainerId contId = pTvDb->createAnimationContainer(pEntity->getName()); if (contId.isNull()) return true; OdTvAnimationContainerPtr pContainer = contId.openObject(OdTv::kForWrite); OdTvSubItemPath actor; appendEntitiesIds(entityId, actor); if(nullptr != parentEntityId) appendEntitiesIds(*parentEntityId, actor); OdGePoint3d origin; OdGeVector3d xAxis, yAxis, zAxis; motion_info_iter->second.matrix.getCoordSystem(origin, xAxis, yAxis, zAxis); OdTvAnimationContainer::OdTvActorBasis basis(origin, xAxis, yAxis, zAxis); for (const auto& u3d_track_action_map : action_map[u3d_res_ID]) { pContainer->addAnimation(actor, u3d_track_action_map.id, 0, u3d_track_action_map.start_time, &basis); } } } return true; } return false; } void OdTvVisualizePrcFiler::ImportMotionRes(OdTvModelId& tvModelId, OdTvVisualizePrcFilerDbSource* pPrcDatabaseSource) const { OdU3DMotionInfo motion_info; pPrcDatabaseSource->getMotionInfo(motion_info); if (tvModelId.isNull()) return; OdTvModelPtr pTvModel = tvModelId.openObject(); if (pTvModel.isNull()) return; OdTvDatabaseId tvDbId = pTvModel->getDatabase(); OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); if (motion_info.motion_res_info.size() < 2) return; std::map> action_map; for (OdUInt32 i = 1; i < motion_info.motion_res_info.size(); ++i) { for (OdUInt32 j = 0; j < motion_info.motion_res_info[i].track_info.size(); ++j) { if(motion_info.motion_res_info[i].track_info[j].size() == 0) continue; const bool is_single_track = (motion_info.motion_res_info[i].track_info.size() == 1); OdString action_name = is_single_track ? motion_info.motion_res_info[i].name : motion_info.motion_res_info[i].name + OdString(L"_") + motion_info.motion_res_info[i].track_names[j]; OdTvAnimationActionId translateActionId = pTvDb->createAnimationAction(action_name); OdTvAnimationActionPtr pTranslateAction = translateActionId.openObject(OdTv::kForWrite); double kps = 30; const double duration = motion_info.motion_res_info[i].track_info[j].last().time; pTranslateAction->setFPS(kps); pTranslateAction->setNumFrames(ceil(duration* kps) + 1); U3DTrackInfo track_info; track_info.start_time = OdRoundToLong(motion_info.motion_res_info[i].track_info[j].first().time * kps); track_info.id = translateActionId; action_map[i].emplace_back(track_info); for (OdUInt32 k = 0; k < motion_info.motion_res_info[i].track_info[j].size(); ++k) { const auto& frame = motion_info.motion_res_info[i].track_info[j][k]; int kftl = ceil(frame.time * kps); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kTranslationX, frame.location.x, OdTvAnimationAction::kLinear); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kTranslationY, frame.location.y, OdTvAnimationAction::kLinear); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kTranslationZ, frame.location.z, OdTvAnimationAction::kLinear); if (!frame.scale.isZeroLength(1e-7)) { pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kScaleX, frame.scale.x, OdTvAnimationAction::kLinear); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kScaleY, frame.scale.y, OdTvAnimationAction::kLinear); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kScaleZ, frame.scale.z, OdTvAnimationAction::kLinear); } OdGeQuaternion rotationQuat = frame.rotation; OdGeMatrix3d rotationMatr = rotationQuat.normalize().getMatrix(); double rollX, pitchY, yawZ; if (u3dMatr2Angles(rotationMatr, rollX, pitchY, yawZ)) { pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kRotationX, rollX, OdTvAnimationAction::kLinear); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kRotationY, pitchY, OdTvAnimationAction::kLinear); pTranslateAction->setKeypoint(kftl, OdTvAnimationAction::kRotationZ, yawZ, OdTvAnimationAction::kLinear); } } } } std::function iterate_sub_entities = [&pTvDb, &motion_info, &action_map, &iterate_sub_entities](OdTvGeometryDataIteratorPtr& pGeomIter, OdTvEntityId* parentEntityId) { bool ret = false; while (!pGeomIter->done()) { OdTvGeometryDataId curGeometryId = pGeomIter->getGeometryData(); if (curGeometryId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEntity = curGeometryId.openAsSubEntity(); if (addAnimationToContainer(curGeometryId, pSubEntity, pTvDb, action_map, motion_info, parentEntityId)) { ret = true; } else { OdTvGeometryDataIteratorPtr geomDataIt = pSubEntity->getGeometryDataIterator(); if (iterate_sub_entities(geomDataIt, parentEntityId)) ret = true; } } pGeomIter->step(); } return ret; }; // iterate through the entities bool ret_val = false; OdTvEntitiesIteratorPtr pEntitiesIterator = pTvModel->getEntitiesIterator(); while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); if (entityId.getType() == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = entityId.openObject(OdTv::kForRead); if (addAnimationToContainer(entityId, pEntity, pTvDb, action_map, motion_info)) { ret_val = true; break; } else { OdTvGeometryDataIteratorPtr pGeomIter = pEntity->getGeometryDataIterator(); if (iterate_sub_entities(pGeomIter, &entityId)) { ret_val = true; break; } } } pEntitiesIterator->step(); } } #endif void OdTvVisualizePrcFiler::applyCustomBackground(OdTvDatabaseId& dbId, OdGsPrcLayoutHelperPtr pLayoutHelper) const { int iActViewViewInd = getActiveViewId(pLayoutHelper.get()); OdTvGsViewId tvViewId = getActiveTvView(dbId, iActViewViewInd); if (!tvViewId.isNull()) { OdTvGsViewPtr pActiveTvView = tvViewId.openObject(OdTv::kForWrite); if (!pActiveTvView.isNull()) { pActiveTvView->setActive(true); pActiveTvView->setName(OD_TV_COMMON_VIEW_NAME); OdTvDatabasePtr pDb = dbId.openObject(OdTv::kForWrite); pDb->getDevicesIterator()->getDevice().openObject(OdTv::kForWrite)->setName(OD_TV_COMMON_DEVICE_NAME); //set gradient background to the active view OdTvGsViewBackgroundId bkgId = pDb->createBackground(OD_T("PRC2VISUALIZE"), OdTvGsViewBackgroundId::kGradient); if (!bkgId.isNull()) { { OdTvGsViewGradientBackgroundPtr pGradientBackground = bkgId.openAsGradientBackground(OdTv::kForWrite); pGradientBackground->setColorTop(OdTvColorDef(33, 108, 170)); pGradientBackground->setColorMiddle(OdTvColorDef(109, 158, 200)); pGradientBackground->setColorBottom(OdTvColorDef(184, 208, 230)); pGradientBackground->setHeight(0.33); pGradientBackground->setHorizon(0.5); } pActiveTvView->setBackground(bkgId); pActiveTvView->setDefaultLightingIntensity(1.); pActiveTvView->setAmbientLightColor(OdTvColorDef(50, 50, 50)); } } } } void OdTvVisualizePrcFiler::createCommonDataAccessTree(const OdTvDatabaseId& tvDbId, const OdString& strTreeName) const { OdTvDatabasePtr pDb = tvDbId.openObject(OdTv::kForWrite); OdTvCDATreePtr pTree = OdTvCDATree::createObject(); pTree->createTvDatabaseHierarchyTree(tvDbId, m_properties->getNeedCollectPropertiesInCDA()); //Add tree to the Tv database OdTvResult rc; OdTvCDATreeStorageId cdaTreeId = pDb->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 = pDb->addCDATreeStorage(str, pTree, &rc); } } //Add new CDA tree to the appropriate models OdTvModelsIteratorPtr modelsIterPtr = pDb->getModelsIterator(); if (!modelsIterPtr->done()) { OdTvModelPtr pModel = modelsIterPtr->getModel().openObject(); if (!pModel.isNull()) { pModel->setCDATreeStorage(cdaTreeId); } } } //***************************************************************************// // 'OdTvVisualizePrcFilerModule' methods implementation //***************************************************************************// ODRX_DEFINE_DYNAMIC_MODULE(OdTvVisualizePrcFilerModule); void OdTvVisualizePrcFilerModule::initApp() { // initialize the Visualize SDK odTvInitialize(); } void OdTvVisualizePrcFilerModule::uninitApp() { // Uninitialize the Visualize SDK odTvUninitialize(); } OdTvVisualizeFilerPtr OdTvVisualizePrcFilerModule::getVisualizeFiler() const { OdTvVisualizeFilerPtr pDwgFiler = new OdTvVisualizePrcFiler(); return pDwgFiler; } namespace { //Filling UserData for each entity template void collectPrcInfo(T& pEntity, const OdTvRegAppId& appId_PRCInfo, const OdRxObjectPtr pPRCObj, const OdPrcProductOccurrencePtr pParentPO) { if(pPRCObj.isNull()) return; OdString entName = pEntity->getName(); if(entName == OD_T("OdPrcReferenceOnRootPO")) return; OdPrcBasePtr pPrcBase; if (!pPRCObj->isKindOf(OdPrcBase::desc())) return; pPrcBase = pPRCObj; OdTvPrcUserData user_data; user_data.m_Type = pPrcBase->prcType(); user_data.m_Name = pPrcBase->name().name(); const OdPrcAttributeData& attribute_data = pPrcBase->attributeData(); const OdPrcAttributeArray& attributes = attribute_data.attributes(); user_data.m_Attributes.resize(attributes.size()); for (OdUInt32 a_idx = 0; a_idx < attributes.size(); ++a_idx) { const OdPrcAttributeEntry& attr_title = attributes[a_idx].attributeEntry(); if(attr_title.titleIsInteger()) user_data.m_Attributes[a_idx].m_Title.setData((OdTvPrcUserData::PrcAttributeTitle::ePRCAttributeEntry)attr_title.getIndex()); else user_data.m_Attributes[a_idx].m_Title.setData(attr_title.getTitle()); const OdPrcContentSingleAttributeArray& single_attrs = attributes[a_idx].contentSingleAttribute(); user_data.m_Attributes[a_idx].m_Attributes.resize(single_attrs.size()); for (OdUInt32 sa_idx = 0; sa_idx < single_attrs.size(); ++sa_idx) { const OdPrcAttributeEntry& single_attr_title = single_attrs[sa_idx].attributeEntry(); if (single_attr_title.titleIsInteger()) user_data.m_Attributes[a_idx].m_Attributes[sa_idx].attributeEntry().setData((OdTvPrcUserData::PrcAttributeTitle::ePRCAttributeEntry)single_attr_title.getIndex()); else user_data.m_Attributes[a_idx].m_Attributes[sa_idx].attributeEntry().setData(single_attr_title.getTitle()); switch (single_attrs[sa_idx].getType()) { case KEPRCModellerAttributeTypeInt: user_data.m_Attributes[a_idx].m_Attributes[sa_idx].setData(single_attrs[sa_idx].getDataInt32()); break; case KEPRCModellerAttributeTypeReal: user_data.m_Attributes[a_idx].m_Attributes[sa_idx].setData(single_attrs[sa_idx].getDataDouble()); break; case KEPRCModellerAttributeTypeTime: user_data.m_Attributes[a_idx].m_Attributes[sa_idx].setData(single_attrs[sa_idx].getDataTime()); break; case KEPRCModellerAttributeTypeString: user_data.m_Attributes[a_idx].m_Attributes[sa_idx].setData(single_attrs[sa_idx].getDataStr()); break; default: break; } } } OdPrcReferencedBasePtr pPrcRefBase; if (!pPRCObj->isKindOf(OdPrcReferencedBase::desc())) return; pPrcRefBase = pPRCObj; user_data.m_cardPersistentIndentifier = pPrcRefBase->cadPersistentIdentifier(); user_data.m_cadIdentifier = pPrcRefBase->cadIdentifier(); if (pPRCObj->isKindOf(OdPrcBaseWithGraphics::desc())) { OdPrcBaseWithGraphicsPtr pPrcRefBaseWGr = pPrcRefBase; if(!GETBIT(pPrcRefBaseWGr->behaviourBitField(), PRC_GRAPHICS_Removed)) { //filling in UIDs of objects in accordance with the possibility of their use in Adobe if (!pPRCObj->isKindOf(OdPrcPartDefinition::desc()) && !pPRCObj->isKindOf(OdPrcAnnotationReference::desc()) && !pPRCObj->isKindOf(OdPrcAnnotationSet::desc()) && !pPRCObj->isKindOf(OdPrcAnnotationItem::desc())) user_data.m_UnicID = pPrcRefBase->calculateUniqueName(pParentPO); //Collect text data from OdPrcMarkup and represent it as a single string if (pPRCObj->isKindOf(OdPrcMarkup::desc())) { OdPrcMarkupPtr pMarkup = pPRCObj; OdPrcBaseTessDataPtr pTess = pMarkup->tessellation(); if (!pTess.isNull()) { OdPrcMarkupTessPtr pMT = OdPrcMarkupTess::cast(pTess); if (!pMT.isNull()) { for (const auto& elem : pMT->text()) user_data.m_MarkupText += elem; } } } } } //prepare stream OdStreamBufPtr pStreamBuff = OdMemoryStream::createNew(); user_data.write(pStreamBuff); pStreamBuff->rewind(); OdUInt8Array buffer; buffer.resize(pStreamBuff->length()); pStreamBuff->getBytes(buffer.asArrayPtr(), pStreamBuff->length()); // Add user data OdTvByteUserData* pLayoutUserData = new OdTvByteUserData(buffer.asArrayPtr(), pStreamBuff->length(), OdTvByteUserData::kCopyOwn, true); pEntity->appendUserData(pLayoutUserData, appId_PRCInfo); } } void OdTvVisualizePrcFiler::collectInfoToUserData(OdTvModelId& tvModelId, OdTvVisualizePrcFilerDbSource* pPrcDatabaseSource) const { if (tvModelId.isNull()) return; OdTvModelPtr pTvModel = tvModelId.openObject(); if (pTvModel.isNull()) return; OdTvDatabaseId tvDbId = pTvModel->getDatabase(); OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); bool alreadyExistDb = false; OdTvRegAppId appId_PRCInfo = pTvDb->registerAppName(OdTvPRCUserData, alreadyExistDb); OdPrcFilePtr pPRCFile = pPrcDatabaseSource->getDb(); std::function iterate_sub_entities = [&pPRCFile, &iterate_sub_entities, &appId_PRCInfo](OdTvGeometryDataIteratorPtr pGeomIter, OdRxObjectPtr parentPrcObj, OdPrcProductOccurrencePtr pParentPO) { while (!pGeomIter->done()) { OdTvGeometryDataId curGeometryId = pGeomIter->getGeometryData(); if (curGeometryId.getType() == OdTv::kSubEntity) { OdTvEntityPtr pSubEntity = curGeometryId.openAsSubEntity(); OdRxObjectPtr pPRCObj = OdTvVisualizePrcFiler::getPrcObject(pSubEntity, pPRCFile); if (pPRCObj == parentPrcObj) return; if (!pPRCObj.isNull()) { collectPrcInfo(pSubEntity, appId_PRCInfo, pPRCObj, pParentPO); OdTvGeometryDataIteratorPtr geomDataIt = pSubEntity->getGeometryDataIterator(); iterate_sub_entities(geomDataIt, pPRCObj, !pPRCObj.isNull() && pPRCObj->isKindOf(OdPrcProductOccurrence::desc()) ? OdPrcProductOccurrence::cast(pPRCObj) : pParentPO); } } pGeomIter->step(); } }; std::function iterate_entities = [&pPRCFile, &iterate_entities , &iterate_sub_entities, &appId_PRCInfo](OdTvEntitiesIteratorPtr pEntitiesIterator, OdRxObjectPtr parentPrcObj, OdPrcProductOccurrencePtr pParentPO) { while (!pEntitiesIterator->done()) { OdTvEntityId entityId = pEntitiesIterator->getEntity(); const auto ent_type = entityId.getType(); if (ent_type == OdTvEntityId::kGroup) { OdTvGroupPtr pGroup = entityId.openObjectAsGroup(OdTv::kForWrite); OdRxObjectPtr pPRCObj = OdTvVisualizePrcFiler::getPrcObject(pGroup, pPRCFile); collectPrcInfo(pGroup, appId_PRCInfo, pPRCObj, pParentPO); iterate_entities(pGroup->getEntitiesIterator(), pPRCObj, !pPRCObj.isNull() && pPRCObj->isKindOf(OdPrcProductOccurrence::desc()) ? OdPrcProductOccurrence::cast(pPRCObj) : pParentPO); } if (ent_type == OdTvEntityId::kInsert) { OdTvInsertPtr pInsert = entityId.openObjectAsInsert(OdTv::kForWrite); OdRxObjectPtr pPRCObj = OdTvVisualizePrcFiler::getPrcObject(pInsert, pPRCFile); collectPrcInfo(pInsert, appId_PRCInfo, pPRCObj, pParentPO); OdTvBlockId blockId = pInsert->getBlock(); if (!blockId.isNull()) { OdTvBlockPtr pBlock = blockId.openObject(OdTv::kForWrite); OdRxObjectPtr pPRCObj = OdTvVisualizePrcFiler::getPrcObject(pBlock, pPRCFile); collectPrcInfo(pBlock, appId_PRCInfo, pPRCObj, pParentPO); iterate_entities(pBlock->getEntitiesIterator(), pPRCObj, !pPRCObj.isNull() && pPRCObj->isKindOf(OdPrcProductOccurrence::desc()) ? OdPrcProductOccurrence::cast(pPRCObj) : pParentPO); } } if (ent_type == OdTvEntityId::kEntity) { OdTvEntityPtr pEntity = entityId.openObject(OdTv::kForWrite); OdRxObjectPtr pPRCObj = OdTvVisualizePrcFiler::getPrcObject(pEntity, pPRCFile); if (!pPRCObj.isNull()) { collectPrcInfo(pEntity, appId_PRCInfo, pPRCObj, pParentPO); OdTvGeometryDataIteratorPtr pGeomIter = pEntity->getGeometryDataIterator(); iterate_sub_entities(pGeomIter, pPRCObj, !pPRCObj.isNull() && pPRCObj->isKindOf(OdPrcProductOccurrence::desc()) ? OdPrcProductOccurrence::cast(pPRCObj) : pParentPO); } } pEntitiesIterator->step(); } }; // iterate through the entities OdRxObjectPtr pPRCObj = OdTvVisualizePrcFiler::getPrcObject(pTvModel, pPRCFile); collectPrcInfo(pTvModel, appId_PRCInfo, pPRCObj, OdPrcProductOccurrencePtr()); iterate_entities(pTvModel->getEntitiesIterator(), pPRCFile, !pPRCObj.isNull() && pPRCObj->isKindOf(OdPrcProductOccurrence::desc()) ? OdPrcProductOccurrence::cast(pPRCObj) : OdPrcProductOccurrencePtr()); } template OdRxObjectPtr OdTvVisualizePrcFiler::getPrcObject(T pEntity, OdPrcFilePtr pDb) { const OdString appName(L"ExGsVisualizeDevice"); const OdString appName_db(L"ExGsVisualizeDevice_DBID"); OdUInt64 PrcNativeId = static_cast(getSourceDatabaseHandle(pEntity, appName)); OdInt64 prcNativeDbId = getSourceDatabaseHandle(pEntity, appName_db); OdPrcObjectId prcObjId; if (-1 == prcNativeDbId) // OK in case of one FS { prcObjId = pDb->getObjectId(PrcNativeId); } else { OdUInt64 PrcNativeDbId = static_cast(prcNativeDbId); OdPrcObjectId prcDbId = pDb->getObjectId(PrcNativeDbId); OdRxObjectPtr pRxDbObj = prcDbId.openObject(); if (pRxDbObj.isNull()) return OdRxObjectPtr(); OdPrcFileStructurePtr pPrcSourceDb; if (pRxDbObj->isKindOf(OdPrcFileStructure::desc())) pPrcSourceDb = pRxDbObj; if (pPrcSourceDb.isNull()) return OdRxObjectPtr(); prcObjId = pPrcSourceDb->getObjectId(PrcNativeId); } return prcObjId.openObject(); } namespace { OdTvPrcUserData getPrcUserDataFromTVDb(OdTvEntityPtr& pEntity, OdTvDatabasePtr& pTvDb) { OdTvPrcUserData user_data; if (pEntity.isNull()) return user_data; //try to find the reg app bool alreadyExist = false; OdTvRegAppId appId = pTvDb->registerAppName(OdTvPRCUserData, alreadyExist); if (appId.isNull()) return user_data; OdTvByteUserData* pUserData = dynamic_cast(pEntity->getUserData(appId)); if (!pUserData) return user_data; OdStreamBufPtr pStreamBuff = OdMemoryStream::createNew(); pStreamBuff->putBytes(pUserData->getData(), pUserData->getSize()); pStreamBuff->rewind(); //read data from stream user_data.read(pStreamBuff); return user_data; } }