aa80fb63af
- in import ed export 3MF gestione della gerarchia dei gruppi - migliorie e correzioni varie.
370 lines
12 KiB
C++
370 lines
12 KiB
C++
//----------------------------------------------------------------------------
|
|
// 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<IExport3MF*> ( 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<IGdbIterator> 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<sLib3MFPosition> 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<sLib3MFTriangle> 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<IGdbIterator> 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) ;
|
|
}
|