Files
EgtExchange/Import3MF.cpp
T
SaraP aa80fb63af EgtExchange 2.6l3 :
- in import ed export 3MF gestione della gerarchia dei gruppi
- migliorie e correzioni varie.
2024-12-16 10:52:28 +01:00

413 lines
15 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : Import3MF.h Data : 29.01.21 Versione : 2.3b1
// Contenuto : Dichiarazione della classe Import3MF.
//
//
//
// Modifiche : 21.01.21 SP Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Import3MF.h"
#include "DllMain.h"
#include "/EgtDev/Include/EExDllMain.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
using namespace std ;
using namespace Lib3MF ;
//----------------------------------------------------------------------------
IImport3MF*
CreateImport3MF( void)
{
// verifico la chiave e le opzioni
if ( ! VerifyKey( KEYOPT_EEX_INPBASE))
return nullptr ;
// creo l'oggetto
return static_cast<IImport3MF*> ( new( nothrow) Import3MF) ;
}
//----------------------------------------------------------------------------
bool
Import3MF::Import( const string& sFile, IGeomDB* pGDB, int nIdGroup, int nFlag)
{
LOG_INFO( GetEExLogger(), ( "Import3MF : " + sFile).c_str()) ;
// verifico il DB geometrico
if ( pGDB == nullptr) {
LOG_ERROR( GetEExLogger(), " Import3MF : Error on GeomDB") ;
return false ;
}
m_pGDB = pGDB ;
// verifico l'Id di gruppo
if ( ! m_pGDB->ExistsObj( nIdGroup)) {
LOG_ERROR( GetEExLogger(), " Import3MF : Error on IdGroup") ;
return false ;
}
m_nIdGroup = nIdGroup ;
// imposto le opzioni di importazione
m_nFlag = nFlag ;
try {
if ( ! DoImport( sFile))
return false ;
}
catch ( ELib3MFException &exception) {
LOG_ERROR( GetEExLogger(), exception.what()) ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Import3MF::DoImport( const string& sFile)
{
// libreria 3MF
m_wrapper = CWrapper::loadLibrary() ;
if ( m_wrapper == nullptr) {
LOG_ERROR( GetEExLogger(), " Import3MF : Error on lib3mf Wrapper") ;
return false ;
}
// creazione del 3MF model
m_model = m_wrapper->CreateModel() ;
if ( m_model == nullptr) {
LOG_ERROR( GetEExLogger(), " Import3MF : Error on lib3mf Model") ;
return false ;
}
// lettura file
PReader reader = m_model->QueryReader( "3mf") ;
reader->ReadFromFile( sFile) ;
for ( Lib3MF_uint32 nWarning = 0 ; nWarning < reader->GetWarningCount() ; nWarning ++) {
Lib3MF_uint32 nErrorCode ;
string sWarningMsg = reader->GetWarning( nWarning, nErrorCode) ;
string sErrorMsg = " Reading 3MF file encountered warning # " + to_string( nErrorCode) + " : " + sWarningMsg ;
LOG_ERROR( GetEExLogger(), sErrorMsg.c_str()) ;
}
switch ( m_model->GetUnit()) {
case eModelUnit::MicroMeter :
m_dScaleFactor = 0.001 ;
break ;
case eModelUnit::MilliMeter :
m_dScaleFactor = 1.0 ;
break ;
case eModelUnit::CentiMeter :
m_dScaleFactor = 10.0 ;
break ;
case eModelUnit::Inch :
m_dScaleFactor = 25.4 ;
break ;
case eModelUnit::Foot :
m_dScaleFactor = 304.8 ;
break ;
case eModelUnit::Meter :
m_dScaleFactor = 1000.0 ;
break ;
default:
m_dScaleFactor = 1.0 ;
}
// analisi metadata
PMetaDataGroup metaDataGrp = m_model->GetMetaDataGroup() ;
Lib3MF_uint32 nMetaDataCount = metaDataGrp->GetMetaDataCount() ;
for ( Lib3MF_uint32 i = 0 ; i < nMetaDataCount ; i ++) {
PMetaData metaData = metaDataGrp->GetMetaData( i) ;
string sName = metaData->GetName() ;
string sValue = metaData->GetValue() ;
if ( ! sName.empty() && ! sValue.empty())
m_pGDB->SetInfo( m_nIdGroup, sName, sValue) ;
}
// scorro gli items nel build node
PBuildItemIterator pBuildItemsIter = m_model->GetBuildItems() ;
while ( pBuildItemsIter->MoveNext()) {
PBuildItem pItem = pBuildItemsIter->GetCurrent() ;
// ignoro i suoi attributes e i suoi metadata
// recupero la sua trasformazione
sTransform sTransf = pItem->GetObjectTransform() ;
// lettura oggetto associato
if ( ! ReadObject( pItem->GetObjectResource(), sTransf, m_nIdGroup))
return false ;
}
return true ;
}
//-------------------------------------------------------------------------------------------------
bool
Import3MF::ReadObject( const PObject pObj, const sTransform& Transform, int nParentId)
{
if ( pObj == nullptr)
return false ;
// attributes
INFOVECTOR vInfo ;
string sName = pObj->GetName() ;
string sProp = pObj->GetPartNumber() ;
if ( ! sProp.empty())
vInfo.emplace_back( "PartNumber", sProp) ;
bool bUUID = false ;
sProp = pObj->GetUUID( bUUID) ;
if ( bUUID)
vInfo.emplace_back( "UUID", sProp) ;
switch ( pObj->GetType()) {
case eObjectType::Model :
vInfo.emplace_back( "Type", "Model") ;
break ;
case eObjectType::Support :
vInfo.emplace_back( "Type", "Support") ;
break ;
case eObjectType::SolidSupport :
vInfo.emplace_back( "Type", "SolidSupport") ;
break ;
default :
break ;
}
// metadata
PMetaDataGroup pMetaDataGrp = pObj->GetMetaDataGroup() ;
for ( Lib3MF_uint32 i = 0 ; i < pMetaDataGrp->GetMetaDataCount() ; i ++) {
PMetaData metaData = pMetaDataGrp->GetMetaData( i) ;
string sMetaDataName = metaData->GetName() ;
string sMetaDataValue = metaData->GetValue() ;
if ( ! sMetaDataName.empty() && ! sMetaDataValue.empty())
vInfo.emplace_back( sMetaDataName, sMetaDataValue) ;
}
if ( pObj->IsMeshObject())
return ReadMesh( pObj->GetResourceID(), sName, vInfo, Transform, nParentId) ;
else if ( pObj->IsComponentsObject())
return ReadComponent( pObj->GetResourceID(), sName, vInfo, Transform, nParentId) ;
return false ;
}
//----------------------------------------------------------------------------------------------------------------
bool
Import3MF::ReadMesh( Lib3MF_uint32 nId, const string& sName, const INFOVECTOR& vInfo, const sTransform& Transform, int nParentId)
{
// Recupero puntatore alla mesh 3MF
PMeshObject pMesh = m_model->GetMeshObjectByID( nId) ;
if ( pMesh == nullptr)
return false ;
// Creo e inizializzo trimesh
PtrOwner<ISurfTriMesh> pStm( CreateSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->Init( pMesh->GetVertexCount(), pMesh->GetTriangleCount())) {
LOG_ERROR( GetEExLogger(), " Error reading 3MF mesh : ISurfTriMesh Create error") ;
return false ;
}
pStm->SetLinearTolerance( 10 * EPS_SMALL) ;
// Ciclo sui vertici della mesh 3MF
for ( Lib3MF_uint32 i = 0 ; i < pMesh->GetVertexCount() ; i ++) {
// recupero le coordinate del vertice
sPosition pVertex = pMesh->GetVertex( i) ;
// applico la trasformazione
double x = 0.0, y = 0.0, z = 0.0 ;
for ( int k = 0 ; k < 3 ; k ++) {
x += pVertex.m_Coordinates[k] * Transform.m_Fields[k][0] ;
y += pVertex.m_Coordinates[k] * Transform.m_Fields[k][1] ;
z += pVertex.m_Coordinates[k] * Transform.m_Fields[k][2] ;
}
x += Transform.m_Fields[3][0] ;
y += Transform.m_Fields[3][1] ;
z += Transform.m_Fields[3][2] ;
// inserisco il vertice nella trimesh
if ( pStm->AddVertex( Point3d( x, y, z) * m_dScaleFactor) == SVT_NULL) {
LOG_ERROR( GetEExLogger(), " Error reading 3MF mesh : ISurfTriMesh AddVertex error") ;
return false ;
}
}
// Ciclo sui triangoli della mesh 3MF
for ( Lib3MF_uint32 i = 0 ; i < pMesh->GetTriangleCount() ; i ++) {
// recupero gli indici dei vertici del triangolo
sTriangle tTrg = pMesh->GetTriangle( i) ;
int nIdV[3] = { int( tTrg.m_Indices[0]), int( tTrg.m_Indices[1]), int( tTrg.m_Indices[2])} ;
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) {
if ( pStm->AddTriangle( nIdV) == SVT_NULL) {
LOG_ERROR( GetEExLogger(), " Error reading 3MF mesh : ISurfTriMesh AddTriangle error") ;
return false ;
}
}
}
// Aggiustamenti finali
if ( ! pStm->DoCompacting()) {
LOG_ERROR( GetEExLogger(), " Error reading 3MF mesh : ISurfTriMesh DoCompacting error") ;
return false ;
}
// Inserimento nel DB geometrico
int nGeoId = m_pGDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pStm)) ;
if ( nGeoId == GDB_ID_NULL) {
LOG_ERROR( GetEExLogger(), " Error reading 3MF mesh : error adding GeoObject") ;
return false ;
}
// colore
Lib3MF_uint32 pid, pindex ;
if ( pMesh->GetObjectLevelProperty( pid, pindex)) {
Color cCol ;
if ( FindColor( pid, pindex, cCol))
m_pGDB->SetMaterial( nGeoId, cCol) ;
}
// attributes
if ( ! sName.empty())
m_pGDB->SetName( nGeoId, sName) ;
for ( int i = 0 ; i < int( vInfo.size()) ; i++)
m_pGDB->SetInfo( nGeoId, vInfo[i].first, vInfo[i].second) ;
return true ;
}
//-----------------------------------------------------------------------------------
bool
Import3MF::ReadComponent( Lib3MF_uint32 nId, const string& sName, const INFOVECTOR& vInfo, const sTransform& Transform, int nParentId)
{
// se va conservata la gerarchia ogni componente corrisponde ad un layer, altrimenti gli elementi della componente vengono
// inseriti direttamente in m_nIdGroup e i suoi attributes vengono ignorati
PComponentsObject pComponents = m_model->GetComponentsObjectByID( nId) ;
if ( pComponents == nullptr)
return false ;
int nLayerId = nParentId ;
// se importo gerarchia creo il layer corrispondente alla componente
if ( ( m_nFlag & EI3FLAG_KEEP_GROUPS) != 0) {
nLayerId = m_pGDB->AddGroup( GDB_ID_NULL, nParentId, GLOB_FRM) ;
// assegno nome e info
if ( ! sName.empty())
m_pGDB->SetName( nLayerId, sName) ;
for ( int i = 0 ; i < int( vInfo.size()) ; i++)
m_pGDB->SetInfo( nLayerId, vInfo[i].first, vInfo[i].second) ;
}
// scorro tutti i suoi oggetti
for ( Lib3MF_uint32 nC = 0 ; nC < pComponents->GetComponentCount() ; nC++) {
PComponent pComponent = pComponents->GetComponent( nC) ;
// combino le trasformazioni
sTransform TransfComp = pComponent->GetTransform() ;
sTransform TransfRes ;
// inizializzo TransfRes a zero
for ( Lib3MF_uint32 i = 0 ; i < 4 ; i++)
fill( TransfRes.m_Fields[i], TransfRes.m_Fields[i] + 3, ( Lib3MF_single) 0.0) ;
for ( Lib3MF_uint32 i = 0 ; i < 4 ; i ++)
for ( Lib3MF_uint32 j = 0 ; j < 3 ; j++)
for ( Lib3MF_uint32 k = 0 ; k < 3 ; k ++)
TransfRes.m_Fields[i][j] += TransfComp.m_Fields[i][k] * Transform.m_Fields[k][j] ; // prodotto fra matrici
for ( Lib3MF_uint32 j = 0 ; j < 3 ; j ++)
TransfRes.m_Fields[3][j] += Transform.m_Fields[3][j] ;
if ( ! ReadObject( pComponent->GetObjectResource(), TransfRes, nLayerId))
return false ;
}
return true ;
}
//------------------------------------------------------------------------------------
bool
Import3MF::FindColor( Lib3MF_uint32 pid, Lib3MF_uint32 pindex, Color& cCol) const
{
sColor sCol ;
switch ( m_model->GetPropertyTypeByID( pid)) {
case ePropertyType::BaseMaterial :
{
PBaseMaterialGroup pBaseMatGrp = m_model->GetBaseMaterialGroupByID( pid) ;
sCol = pBaseMatGrp->GetDisplayColor( pindex) ;
break ;
}
case ePropertyType::Colors :
{
PColorGroup pColorGrp = m_model->GetColorGroupByID( pid) ;
sCol = pColorGrp->GetColor( pindex) ;
break ;
}
case ePropertyType::Multi :
{
PMultiPropertyGroup pMultiPropGrp = m_model->GetMultiPropertyGroupByID( pid) ;
// multiproperty corrispondente a pindex
UINTVECTOR pindices ;
pMultiPropGrp->GetMultiProperty( pindex, pindices) ;
// analizzo i layers alla ricerca di una proprietà che definisca un colore
Lib3MF_uint32 nLayers = pMultiPropGrp->GetLayerCount() ;
for ( Lib3MF_uint32 i = 0 ; i < nLayers ; i ++) {
sMultiPropertyLayer layer = pMultiPropGrp->GetLayer( i) ;
Lib3MF_uint32 pidLayer = layer.m_ResourceID ;
// appena trovo una propietà che definisce un colore mi fermo
if ( m_model->GetPropertyTypeByID( pidLayer) == ePropertyType::BaseMaterial ||
m_model->GetPropertyTypeByID( pidLayer) == ePropertyType::Colors)
return FindColor( pidLayer, pindices[i], cCol) ;
}
return false ;
}
case ePropertyType::Composite :
{
PCompositeMaterials pCompoMat = m_model->GetCompositeMaterialsByID( pid) ;
// BaseMaterialGroup corrispondente
PBaseMaterialGroup pBaseMatGrp = pCompoMat->GetBaseMaterialGroup() ;
vector<sCompositeConstituent> vComposite ;
pCompoMat->GetComposite( pindex, vComposite) ;
// check sui valori in vComposite
double dMixSum = 0.0 ;
for( int i = 0 ; i < int( vComposite.size()) ; i ++)
dMixSum += vComposite[i].m_MixingRatio ;
// se fossero tutti zero, considero proporzioni uguali per ogni colore
if ( abs( dMixSum) < EPS_SMALL) {
dMixSum = vComposite.size() ;
for ( int i = 0 ; i < int( vComposite.size()) ; i++)
vComposite[i].m_MixingRatio = 1 ;
}
double dRed = 0.0, dGreen = 0.0, dBlue = 0.0, dAlpha = 0.0 ; // colore finale
Lib3MF_uint8 nRedTmp, nGreenTmp, nBlueTmp, nAlphaTmp ; // colore del BaseMaterial
// per ogni elemento di composite aggiungo il suo colore con l'opportuno coefficiente
for ( int i = 0 ; i < int( vComposite.size()) ; i++) {
sCol = pBaseMatGrp->GetDisplayColor( vComposite[i].m_PropertyID) ;
m_wrapper->ColorToRGBA( sCol, nRedTmp, nGreenTmp, nBlueTmp, nAlphaTmp) ;
double dMixingRatio = vComposite[i].m_MixingRatio / dMixSum ;
dRed += nRedTmp * dMixingRatio ;
dGreen += nGreenTmp * dMixingRatio ;
dBlue += nBlueTmp * dMixingRatio ;
dAlpha += nAlphaTmp * dMixingRatio ;
}
dAlpha = dAlpha * 100.0 / 255.0 ;
cCol.Set( int( dRed + 0.5), int( dGreen + 0.5), int( dBlue + 0.5), int( dAlpha + 0.5)) ;
return true ;
}
default :
return false ;
}
// converto il colore
Lib3MF_uint8 nRed, nGreen, nBlue, nAlpha ;
m_wrapper->ColorToRGBA( sCol, nRed, nGreen, nBlue, nAlpha) ;
nAlpha = Lib3MF_uint8( nAlpha * 100.0 / 255.0 + 0.5) ;
cCol.Set( nRed, nGreen, nBlue, nAlpha) ;
return true ;
}