//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : Export3MF.cpp Data : 01.09.21 Versione : 2.3i1 // Contenuto : Implementazione della classe per l'esportazione in formato 3MF. // // // // Modifiche : 07.08.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Export3MF.h" #include "DllMain.h" #include "/EgtDev/Include/EExDllMain.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkSurfFlatRegion.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/SELkKeyProc.h" #include "/EgtDev/Include/EgtKeyCodes.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; using namespace Lib3MF ; //---------------------------------------------------------------------------- static string sInfoNamespace = "CustomInfo" ; //---------------------------------------------------------------------------- IExport3MF* CreateExport3MF( void) { // verifico la chiave e le opzioni if ( ! VerifyKey( KEYOPT_EEX_EXPBASE)) return nullptr ; // creo l'oggetto return static_cast ( new(nothrow) Export3MF) ; } //---------------------------------------------------------------------------- bool Export3MF::SetOptions( int nFilter) { m_nFilter = nFilter ; return true ; } //---------------------------------------------------------------------------- bool Export3MF::Export( IGeomDB* pGDB, int nId, const string& sFile) { // verifico il DB geometrico if ( pGDB == nullptr) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on GeomDB") return false ; } // verifico l'Id dell'oggetto da esportare if ( ! pGDB->ExistsObj( nId)) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on Id") return false ; } // libreria 3MF m_wrapper = CWrapper::loadLibrary() ; if ( ! m_wrapper) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on lib3mf Wrapper") return false ; } // creo model per 3MF m_model = m_wrapper->CreateModel() ; if ( ! m_model) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on lib3mf Model") return false ; } if ( ! m_model->AddColorGroup()) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on lib3mf Color Group") return false ; } // creo un iteratore PtrOwner pIter( CreateGdbIterator( pGDB)) ; if ( IsNull( pIter)) return false ; pIter->GoTo( nId) ; // assegno le info dell'oggetto al modello PMetaDataGroup metaDataGrp = m_model->GetMetaDataGroup() ; STRVECTOR vInfo ; pIter->GetAllInfo( vInfo) ; for ( const string& sInfo : vInfo) { string sKey, sVal ; SplitFirst( sInfo, "=", sKey, sVal) ; metaDataGrp->AddMetaData( sInfoNamespace, sKey, sVal, "xs:string", 0) ; } // esporto l'oggetto e i suoi eventuali figli if ( ! ExportObject( *pIter)) return false ; // scrivo il file try { PWriter writer = m_model->QueryWriter( "3mf") ; writer->WriteToFile( sFile) ; } catch ( ELib3MFException &e) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on writing") string s = e.what() ; LOG_ERROR( GetEExLogger(), ( " " + s).c_str()) ; return false ; } return true ; } //---------------------------------------------------------------------------- bool Export3MF::ExportObject( const IGdbIterator& iIter) { switch ( iIter.GetGdbType()) { case GDB_TY_GEO : { // recupero l'oggetto geometrico const IGeoObj* pGeoObj = iIter.GetGeoObj() ; if ( pGeoObj == nullptr) return true ; // se non è una superficie esco if ( pGeoObj->GetType() != SRF_TRIMESH && pGeoObj->GetType() != SRF_FLATRGN) return true ; // recupero il riferimento globale dell'oggetto Frame3d frFrame ; if ( ! iIter.GetGlobFrame( frFrame)) return false ; // recupero il livello dell'oggetto int nLev = GDB_LV_USER ; iIter.GetCalcLevel( nLev) ; // recupero il modo dell'oggetto int nMode = GDB_MD_STD ; iIter.GetCalcMode( nMode) ; // recupero lo stato dell'oggetto int nStat = GDB_ST_ON ; iIter.GetCalcStatus( nStat) ; // se il filtro lo abilita if ( TestFilter( nLev, nMode, nStat)) { // recupero eventuale nome string sName ; if ( ! iIter.GetName( sName)) sName = ToString( iIter.GetId()) ; // recupero il colore Color cCol ; bool bCol = GetColor( cCol, iIter.GetGDB(), iIter.GetId()) ; // recupero le proprietà STRVECTOR vInfo ; iIter.GetAllInfo( vInfo) ; // emetto l'oggetto switch ( pGeoObj->GetType()) { case SRF_TRIMESH : if ( ! ExportSTM( sName, pGeoObj, frFrame, bCol ? &cCol : nullptr, vInfo)) return false ; break ; case SRF_FLATRGN : if ( ! ExportSFR( sName, pGeoObj, frFrame, bCol ? &cCol : nullptr, vInfo)) return false ; break ; default : break ; } } } return true ; case GDB_TY_GROUP : // esploro il gruppo return ScanGroup( iIter) ; default : return false ; } } //---------------------------------------------------------------------------- bool Export3MF::TestFilter( int nLev, int nMode, int nStat) { if ( ( nLev == GDB_LV_USER && ( m_nFilter & EEXFLT_LEVUSER) == 0) || ( nLev == GDB_LV_SYSTEM && ( m_nFilter & EEXFLT_LEVSYSTEM) == 0) || ( nLev == GDB_LV_TEMP && ( m_nFilter & EEXFLT_LEVTEMP) == 0)) return false ; if ( ( nMode == GDB_MD_STD && ( m_nFilter & EEXFLT_MODESTD) == 0) || ( nMode == GDB_MD_LOCKED && ( m_nFilter & EEXFLT_MODELOCKED) == 0) || ( nMode == GDB_MD_HIDDEN && ( m_nFilter & EEXFLT_MODEHIDDEN) == 0)) return false ; if ( ( nStat == GDB_ST_OFF && ( m_nFilter & EEXFLT_STAOFF) == 0) || ( nStat == GDB_ST_ON && ( m_nFilter & EEXFLT_STAON) == 0) || ( nStat == GDB_ST_SEL && ( m_nFilter & EEXFLT_STASEL) == 0)) return false ; return true ; } //---------------------------------------------------------------------------- bool Export3MF::ExportSFR( const string& sName, const IGeoObj* pGeoObj, const Frame3d& frFrame, const Color* pCol, const STRVECTOR& vInfo) { // verifico oggetto const ISurfFlatRegion* pSFR = GetSurfFlatRegion( pGeoObj) ; if ( pSFR == nullptr) return false ; // ricavo la trimesh equivalente const ISurfTriMesh* pStm = pSFR->GetAuxSurf() ; return ExportSTM( sName, pStm, frFrame, pCol, vInfo) ; } //---------------------------------------------------------------------------- bool Export3MF::ExportSTM( const string& sName, const IGeoObj* pGeoObj, const Frame3d& frFrame, const Color* pCol, const STRVECTOR& vInfo) { // verifico oggetto const ISurfTriMesh* pSTM = GetSurfTriMesh( pGeoObj) ; if ( pSTM == nullptr) return false ; // ciclo sui vertici della trimesh vector vVertices( pSTM->GetVertexSize()) ; for ( int i = 0 ; i < pSTM->GetVertexSize() ; i++) { Point3d pt ; pSTM->GetVertex( i, pt) ; pt.ToGlob( frFrame) ; vVertices[i].m_Coordinates[0] = Lib3MF_single( pt.x) ; vVertices[i].m_Coordinates[1] = Lib3MF_single( pt.y) ; vVertices[i].m_Coordinates[2] = Lib3MF_single( pt.z) ; } // ciclo sui triangoli della trimesh vector vTriangles( pSTM->GetTriangleCount()) ; int k = 0 ; for ( int i = 0 ; i < pSTM->GetTriangleSize() ; i++) { int nIdVert[3] ; // se il triangolo non è valido passo al successivo if ( ! pSTM->GetTriangle( i, nIdVert)) continue ; // assegno gli indici dei vertici vTriangles[k].m_Indices[0] = nIdVert[0] ; vTriangles[k].m_Indices[1] = nIdVert[1] ; vTriangles[k].m_Indices[2] = nIdVert[2] ; k ++ ; } if ( vVertices.size() == 0 || vTriangles.size() == 0) { LOG_ERROR( GetEExLogger(), ( "Export3MF : surface \"" + sName + "\" is empty. Ignored.").c_str()) ; return true ; } // creo mesh 3MF PMeshObject meshObject = m_model->AddMeshObject() ; if ( ! meshObject) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on lib3mf Mesh Object") return false ; } meshObject->SetName( sName) ; meshObject->SetGeometry( vVertices, vTriangles) ; // assegno il colore if ( pCol != nullptr) { Lib3MF_uint32 nColId = ColorHandler3MF( pCol) ; meshObject->SetObjectLevelProperty( 1, nColId) ; } // assegno le info PMetaDataGroup metaDataGrp = meshObject->GetMetaDataGroup() ; for ( const string& sInfo : vInfo) { string sKey, sVal ; SplitFirst( sInfo, "=", sKey, sVal) ; metaDataGrp->AddMetaData( sInfoNamespace, sKey, sVal, "xs:string", 0) ; } m_model->AddBuildItem( meshObject.get(), m_wrapper->GetIdentityTransform()) ; return true ; } //---------------------------------------------------------------------------- bool Export3MF::ScanGroup( const IGdbIterator& iIter) { // creo un iteratore PtrOwner pIter( CreateGdbIterator( iIter.GetGDB())) ; if ( IsNull( pIter)) return false ; // scandisco il gruppo bool bOk = true ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { if ( ! ExportObject( *pIter)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool Export3MF::GetColor( Color& pCol, const IGeomDB * pGDB, const int& nId) { if ( nId == GDB_ID_NULL) return false ; if ( ! pGDB->GetMaterial( nId, pCol)) // se fallisce cerco il colore del parent return GetColor( pCol, pGDB, pGDB->GetParentId( nId)) ; return true ; } //---------------------------------------------------------------------------- Lib3MF_uint32 Export3MF::ColorHandler3MF( const Color* pCol) { PColorGroup pColorGrp = m_model->GetColorGroupByID( 1) ; // converto il colore nel formato usato da 3MF Lib3MF_uint8 nAlpha = ( int)( pCol->GetIntAlpha() * 2.55 + 0.5) ; sColor cCol3mf = m_wrapper->RGBAToColor( pCol->GetIntRed(), pCol->GetIntGreen(), pCol->GetIntBlue(), nAlpha) ; // verifico se il colore è già presente nel colorgroup UINTVECTOR vColorIdx ; pColorGrp->GetAllPropertyIDs( vColorIdx) ; for ( Lib3MF_uint32 i : vColorIdx) { sColor cColTmp = pColorGrp->GetColor( i) ; if ( cColTmp.m_Red == cCol3mf.m_Red && cColTmp.m_Green == cCol3mf.m_Green && cColTmp.m_Blue == cCol3mf.m_Blue && cColTmp.m_Alpha == cCol3mf.m_Alpha) return i ; } // se non fosse presente, lo aggiungo return pColorGrp->AddColor( cCol3mf) ; }