f54f1f8969
- aggiunta importazione formato OFF (Object File Format).
372 lines
12 KiB
C++
372 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/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/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<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) {
|
|
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<IGdbIterator> 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)
|
|
{
|
|
// 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)) {
|
|
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 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 ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Export3MF::TestFilter( int nLev, int nMode, int nStat, bool bGroup)
|
|
{
|
|
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 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<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 : 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<IGdbIterator> 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) ;
|
|
}
|