//---------------------------------------------------------------------------- // 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/EGkSurfFlatRegion.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkGdbIterator.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 ; CalcGroupFilter() ; 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 == nullptr) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on lib3mf Wrapper") return false ; } // creo model per 3MF m_model = m_wrapper->CreateModel() ; if ( m_model == nullptr) { 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) ; // 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, PComponentsObject pParent, bool bSaveGrpAsComponent) { // 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) ; int nType = iIter.GetGdbType() ; // se il filtro lo abilita if ( TestFilter( nLev, nMode, nStat, nType == GDB_TY_GROUP)) { // se è un oggetto geometrico diverso da una superficie esco int nGeoType = iIter.GetGeoType() ; if ( nGeoType != GEO_NONE && nGeoType != SRF_TRIMESH && nGeoType != SRF_FLATRGN) return true ; // recupero nome string sName ; iIter.GetName( sName) ; // recupero info STRVECTOR vsInfo ; iIter.GetAllInfo( vsInfo) ; // esporto switch ( nType) { case GDB_TY_GEO : { // recupero l'oggetto geometrico const IGeoObj* pGeoObj = iIter.GetGeoObj() ; if ( pGeoObj == nullptr) return false ; // recupero il riferimento globale dell'oggetto Frame3d frFrame ; if ( ! iIter.GetGlobFrame( frFrame)) return false ; // recupero il colore Color cCol ; iIter.GetCalcMaterial( cCol) ; // emetto l'oggetto switch ( nGeoType) { case SRF_TRIMESH : return ExportSTM( pGeoObj, frFrame, sName, vsInfo, cCol, pParent) ; case SRF_FLATRGN : return ExportSFR( pGeoObj, frFrame, sName, vsInfo, cCol, pParent) ; default : return false ; } } case GDB_TY_GROUP : return ExportGroup( iIter, sName, vsInfo, pParent, bSaveGrpAsComponent) ; default : return false ; } } return true ; } //---------------------------------------------------------------------------- bool Export3MF::TestFilter( int nLev, int nMode, int nStat, bool bGroup) const { int nFilter = bGroup ? m_nGroupFilter : m_nFilter ; if ( ( nLev == GDB_LV_USER && ( nFilter & EEXFLT_LEVUSER) == 0) || ( nLev == GDB_LV_SYSTEM && ( nFilter & EEXFLT_LEVSYSTEM) == 0) || ( nLev == GDB_LV_TEMP && ( nFilter & EEXFLT_LEVTEMP) == 0)) return false ; if ( ( nMode == GDB_MD_STD && ( nFilter & EEXFLT_MODESTD) == 0) || ( nMode == GDB_MD_LOCKED && ( nFilter & EEXFLT_MODELOCKED) == 0) || ( nMode == GDB_MD_HIDDEN && ( nFilter & EEXFLT_MODEHIDDEN) == 0)) return false ; if ( ( nStat == GDB_ST_OFF && ( nFilter & EEXFLT_STAOFF) == 0) || ( nStat == GDB_ST_ON && ( nFilter & EEXFLT_STAON) == 0) || ( nStat == GDB_ST_SEL && ( nFilter & EEXFLT_STASEL) == 0)) return false ; return true ; } //---------------------------------------------------------------------------- bool Export3MF::CalcGroupFilter( void) { m_nGroupFilter = 0 ; // Status if ( ( m_nFilter & EEXFLT_STASEL) != 0) m_nGroupFilter += EEXFLT_STASEL + EEXFLT_STAOFF + EEXFLT_STAON ; else if ( ( m_nFilter & EEXFLT_STAOFF) != 0) m_nGroupFilter += EEXFLT_STAOFF + EEXFLT_STAON ; else m_nGroupFilter += EEXFLT_STAON ; // Mode if ( ( m_nFilter & EEXFLT_MODELOCKED) != 0) m_nGroupFilter += EEXFLT_MODELOCKED + EEXFLT_MODEHIDDEN + EEXFLT_MODESTD ; else if ( ( m_nFilter & EEXFLT_MODEHIDDEN) != 0) m_nGroupFilter += EEXFLT_MODEHIDDEN + EEXFLT_MODESTD ; else m_nGroupFilter += EEXFLT_MODESTD ; // Level if ( ( m_nFilter & EEXFLT_LEVSYSTEM) != 0) m_nGroupFilter += EEXFLT_LEVSYSTEM + EEXFLT_LEVTEMP + EEXFLT_LEVUSER ; else if ( ( m_nFilter & EEXFLT_LEVTEMP) != 0) m_nGroupFilter += EEXFLT_LEVTEMP + EEXFLT_LEVUSER ; else m_nGroupFilter += EEXFLT_LEVUSER ; return true ; } //---------------------------------------------------------------------------- bool Export3MF::ExportSFR( const IGeoObj* pGeoObj, const Frame3d& frFrame, const string& sName, const STRVECTOR& vInfo, const Color& cCol, PComponentsObject pParent) { // verifico oggetto const ISurfFlatRegion* pSFR = GetSurfFlatRegion( pGeoObj) ; if ( pSFR == nullptr) return false ; // ricavo la trimesh equivalente const ISurfTriMesh* pStm = pSFR->GetAuxSurf() ; return ExportSTM( pStm, frFrame, sName, vInfo, cCol, pParent) ; } //---------------------------------------------------------------------------- bool Export3MF::ExportSTM( const IGeoObj* pGeoObj, const Frame3d& frFrame, const string& sName, const STRVECTOR& vInfo, const Color& cCol, PComponentsObject pParent) { // 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 : empty surface ignored") ; return true ; } // creo mesh 3MF PMeshObject meshObject = m_model->AddMeshObject() ; if ( meshObject == nullptr) { LOG_ERROR( GetEExLogger(), "Export3MF : Error on lib3mf Mesh Object") return false ; } meshObject->SetGeometry( vVertices, vTriangles) ; // assegno il nome if ( ! sName.empty()) meshObject->SetName( sName) ; // 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) ; } // assegno il colore Lib3MF_uint32 nColId = ColorHandler3MF( cCol) ; meshObject->SetObjectLevelProperty( 1, nColId) ; // aggiungo al modello if ( pParent == nullptr) m_model->AddBuildItem( meshObject.get(), m_wrapper->GetIdentityTransform()) ; else pParent->AddComponent( meshObject.get(), m_wrapper->GetIdentityTransform()) ; return true ; } //---------------------------------------------------------------------------- bool Export3MF::ExportGroup( const IGdbIterator& iIter, const string& sName, const STRVECTOR& vsInfo, PComponentsObject pParent, bool bSaveAsComponent) { PComponentsObject pComponent = pParent ; // se il layer va salvato come componente, la creo if ( bSaveAsComponent) { pComponent = m_model->AddComponentsObject() ; if ( ! sName.empty()) pComponent->SetName( sName) ; } // salvo le info sulla componente ( se il gruppo viene esportato come tale) o sul modello PMetaDataGroup metaDataGrp ; if ( bSaveAsComponent) metaDataGrp = pComponent->GetMetaDataGroup() ; else metaDataGrp = m_model->GetMetaDataGroup() ; for ( const string& sInfo : vsInfo) { string sKey, sVal ; SplitFirst( sInfo, "=", sKey, sVal) ; metaDataGrp->AddMetaData( sInfoNamespace, sKey, sVal, "xs:string", 0) ; } // scandisco il gruppo per inserire i suoi oggetti PtrOwner pIter( CreateGdbIterator( iIter.GetGDB())) ; if ( IsNull( pIter)) return false ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { if ( ! ExportObject( *pIter, pComponent, true)) return false ; } // se il gruppo va salvato come componente, lo aggiungo al modello if ( bSaveAsComponent && pComponent->GetComponentCount() > 0) { if ( pParent == nullptr) m_model->AddBuildItem( pComponent.get(), m_wrapper->GetIdentityTransform()) ; else pParent->AddComponent( pComponent.get(), m_wrapper->GetIdentityTransform()) ; } return true ; } //---------------------------------------------------------------------------- Lib3MF_uint32 Export3MF::ColorHandler3MF( const Color& cCol) { PColorGroup pColorGrp = m_model->GetColorGroupByID( 1) ; // converto il colore nel formato usato da 3MF Lib3MF_uint8 nAlpha = ( int)( cCol.GetIntAlpha() * 2.55 + 0.5) ; sColor cCol3mf = m_wrapper->RGBAToColor( cCol.GetIntRed(), cCol.GetIntGreen(), cCol.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) ; }