f54f1f8969
- aggiunta importazione formato OFF (Object File Format).
266 lines
8.7 KiB
C++
266 lines
8.7 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2014-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : ExportStl.cpp Data : 07.08.14 Versione : 1.5h2
|
|
// Contenuto : Implementazione della classe per l'esportazione in formato STL.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 07.08.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "ExportStl.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"
|
|
#include <fstream>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
IExportStl*
|
|
CreateExportStl( void)
|
|
{
|
|
// verifico la chiave e le opzioni
|
|
if ( ! VerifyKey( KEYOPT_EEX_EXPBASE))
|
|
return nullptr ;
|
|
// creo l'oggetto
|
|
return static_cast<IExportStl*> ( new(nothrow) ExportStl) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportStl::SetOptions( int nFilter)
|
|
{
|
|
m_nFilter = nFilter ;
|
|
CalcGroupFilter() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportStl::Export( IGeomDB* pGDB, int nId, const string& sFile)
|
|
{
|
|
// verifico il DB geometrico
|
|
if ( pGDB == nullptr) {
|
|
LOG_ERROR( GetEExLogger(), "ExportStl : Error on GeomDB")
|
|
return false ;
|
|
}
|
|
|
|
// verifico l'Id dell'oggetto da esportare
|
|
if ( ! pGDB->ExistsObj( nId)) {
|
|
LOG_ERROR( GetEExLogger(), "ExportStl : Error on Id")
|
|
return false ;
|
|
}
|
|
|
|
// apro il file di testo in scrittura
|
|
m_Writer.Close() ;
|
|
if ( ! m_Writer.Init( sFile)) {
|
|
LOG_ERROR( GetEExLogger(), "ExportStl : Error on open file")
|
|
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
|
|
bool bOk = ExportObject( *pIter) ;
|
|
|
|
// chiudo il file
|
|
if ( ! m_Writer.Close())
|
|
bOk = false ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportStl::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 ( nType) {
|
|
case GDB_TY_GEO :
|
|
{
|
|
// recupero l'oggetto geometrico
|
|
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
|
|
if ( pGeoObj == nullptr)
|
|
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()) ;
|
|
// emetto l'oggetto
|
|
switch ( pGeoObj->GetType()) {
|
|
case SRF_TRIMESH :
|
|
if ( ! ExportSTM( sName, pGeoObj, frFrame))
|
|
return false ;
|
|
break ;
|
|
case SRF_FLATRGN :
|
|
if ( ! ExportSFR( sName, pGeoObj, frFrame))
|
|
return false ;
|
|
break ;
|
|
default :
|
|
break ;
|
|
}
|
|
}
|
|
return true ;
|
|
case GDB_TY_GROUP :
|
|
// esploro il gruppo
|
|
return ScanGroup( iIter) ;
|
|
default :
|
|
return false ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportStl::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
|
|
ExportStl::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
|
|
ExportStl::ExportSFR( const string& sName, const IGeoObj* pGeoObj, const Frame3d& frFrame)
|
|
{
|
|
// 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) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportStl::ExportSTM( const string& sName, const IGeoObj* pGeoObj, const Frame3d& frFrame)
|
|
{
|
|
// verifico oggetto
|
|
const ISurfTriMesh* pSTM = GetSurfTriMesh( pGeoObj) ;
|
|
if ( pSTM == nullptr)
|
|
return false ;
|
|
|
|
// inizio oggetto
|
|
bool bOk = m_Writer.OutText( "solid " + sName) ;
|
|
|
|
// ciclo sui triangoli della trimesh
|
|
Triangle3d Tria ;
|
|
int nId = pSTM->GetFirstTriangle( Tria) ;
|
|
while ( nId != SVT_NULL) {
|
|
// lo porto in coordinate globali
|
|
Tria.ToGlob( frFrame) ;
|
|
// emetto il triangolo
|
|
bOk = bOk && m_Writer.OutText( " facet normal " + ToString( Tria.GetN().x) +
|
|
" " + ToString( Tria.GetN().y) +
|
|
" " + ToString( Tria.GetN().z)) ;
|
|
m_Writer.OutText( " outer loop") ;
|
|
for ( int i = 0 ; i < 3 ; ++ i) {
|
|
bOk = bOk && m_Writer.OutText( " vertex " + ToString( Tria.GetP( i).x) +
|
|
" " + ToString( Tria.GetP( i).y) +
|
|
" " + ToString( Tria.GetP( i).z)) ;
|
|
}
|
|
bOk = bOk && m_Writer.OutText( " endloop") ;
|
|
bOk = bOk && m_Writer.OutText( " endfacet") ;
|
|
// passo al successivo
|
|
nId = pSTM->GetNextTriangle( nId, Tria) ;
|
|
}
|
|
|
|
// termino oggetto
|
|
bOk = bOk && m_Writer.OutText( "endsolid") ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportStl::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 ;
|
|
}
|