//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : GdbGroup.cpp Data : 28.11.13 Versione : 1.4a2 // Contenuto : Implementazione della classe GdbGroup. // // // // Modifiche : 28.11.13 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "GdbGroup.h" #include "GeomDB.h" #include "IdManager.h" #include "NgeWriter.h" #include "NgeReader.h" #include "/EgtDev/Include/EGkGdbFunct.h" #include "/EgtDev/Include/EGnStringUtils.h" using namespace std ; //---------------------------------------------------------------------------- GdbGroup::GdbGroup( void) : m_nObjCount( 0), m_pFirstObj( nullptr), m_pLastObj( nullptr) { } //---------------------------------------------------------------------------- GdbGroup::~GdbGroup( void) { // elimino i figli Clear() ; // se ha un sorgente int nSou ; if ( ! GetInfo( GDB_SI_SOURCE, nSou)) return ; GdbObj* pGdbObj ; if ( m_pGDB == nullptr || ( pGdbObj = m_pGDB->GetGdbObj( nSou)) == nullptr) return ; // nel sorgente aggiorno lista dei riferimenti INTVECTOR vnList ; pGdbObj->GetInfo( GDB_SI_LIST, vnList) ; const auto iFind = find( vnList.begin(), vnList.end(), m_nId) ; if ( iFind != vnList.end()) vnList.erase( iFind) ; if ( vnList.empty()) pGdbObj->RemoveInfo( GDB_SI_LIST) ; else pGdbObj->SetInfo( GDB_SI_LIST, vnList) ; // nel sorgente aggiorno base int nRef ; pGdbObj->GetInfo( GDB_SI_BASE, nRef) ; if ( nRef == m_nId) pGdbObj->RemoveInfo( GDB_SI_BASE) ; } //---------------------------------------------------------------------------- bool GdbGroup::Clear( void) { // disalloco gli oggetti (dal fondo) GdbObj* pObj ; pObj = GetLastObj() ; while ( pObj != nullptr) { // lo rimuovo dalla lista pObj->Remove() ; // lo disalloco delete pObj ; // passo al nuovo ultimo pObj = GetLastObj() ; } return true ; } //---------------------------------------------------------------------------- GdbGroup* GdbGroup::Clone( int nId) const { // verifico validità riferimento a DB geometrico if ( m_pGDB == nullptr) return nullptr ; // alloco gruppo Gdb GdbGroup* pGdbGroup = new(nothrow) GdbGroup ; if ( pGdbGroup == nullptr) return nullptr ; // copio dati oggetto Gdb pGdbGroup->GdbObj::CopyFrom( this) ; // assegno nuovo Id pGdbGroup->m_nId = nId ; m_pGDB->m_IdManager.UpdateMaxId( nId) ; // aggiorno eventuale UserObj if ( pGdbGroup->m_pUserObj != nullptr) pGdbGroup->m_pUserObj->SetOwner( nId, m_pGDB) ; // assegno il riferimento al DB geometrico pGdbGroup->SetGeomDB( m_pGDB) ; // copio dati gruppo pGdbGroup->m_frF = m_frF ; // clono gli oggetti figli const GdbObj* pObj = GetFirstObj() ; while ( pObj != nullptr) { // eseguo copia GdbObj* pNewObj = pObj->Clone( m_pGDB->m_IdManager.GetNewId()) ; if ( pNewObj == nullptr) { delete pGdbGroup ; return nullptr ; } // lo inserisco nella lista dei figli if ( ! pNewObj->AddTail( pGdbGroup)) { delete pNewObj ; delete pGdbGroup ; return nullptr ; } // lo inserisco nella mappa degli Id if ( ! m_pGDB->m_IdManager.AddObj( pNewObj->m_nId, pNewObj)) { delete pGdbGroup ; return nullptr ; } // passo al prossimo oggetto pObj = pObj->GetNext() ; } return pGdbGroup ; } //---------------------------------------------------------------------------- bool GdbGroup::Save( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const { return ( SaveEmpty( nBaseId, ngeOut, pSavedIds) && SaveChildren( nBaseId, ngeOut, pSavedIds)) ; } //---------------------------------------------------------------------------- bool GdbGroup::SaveEmpty( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const { // eventuale verifica di già salvato if ( pSavedIds != nullptr && ! pSavedIds->insert( m_nId).second) return true ; // tipo entità e identificativi if ( ! ngeOut.WriteKey( NGE_A_GRP)) return false ; if ( ! ngeOut.WriteInt( m_nId - nBaseId, "@")) return false ; if ( ! ngeOut.WriteInt( max( GetParentId() - nBaseId, GDB_ID_ROOT), nullptr, true)) return false ; // attributi if ( ! GdbObj::SaveAttribs( ngeOut)) return false ; // TextureData if ( ! GdbObj::SaveTextureData( ngeOut)) return false ; // UserObj if ( ! GdbObj::SaveUserObj( nBaseId, ngeOut)) return false ; // dati geometrici if ( ! ngeOut.WriteKey( NGE_G)) return false ; // puntatore alla prima copia (per ora NULL) if ( ! ngeOut.WriteInt( GDB_ID_NULL, nullptr, true)) return false ; // frame if ( ! ngeOut.WriteFrame( m_frF, ";", true)) return false ; return true ; } //---------------------------------------------------------------------------- bool GdbGroup::SaveChildren( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const { // ciclo sui figli const GdbObj* pGdbObj = GetFirstObj() ; while ( pGdbObj != nullptr) { // recupero il livello dell'oggetto int nLevel = GDB_LV_USER ; pGdbObj->GetLevel( nLevel) ; // se non temporaneo, lo salvo if ( nLevel != GDB_LV_TEMP) { if ( ! pGdbObj->Save( nBaseId, ngeOut, pSavedIds)) return false ; } pGdbObj = pGdbObj->GetNext() ; } return true ; } //---------------------------------------------------------------------------- bool GdbGroup::Load( int nNgeId, NgeReader& ngeIn, int nBaseGdbId, int& nParentId) { // leggo la prossima linea if ( ! ngeIn.ReadInt( m_nId, "@")) return false ; if ( ! ngeIn.ReadInt( nParentId, nullptr, true)) return false ; // leggo la prossima linea int nKey ; if ( ! ngeIn.ReadKey( nKey)) return false ; // eventuali attributi if ( nKey == NGE_A) { if ( ! GdbObj::LoadAttribs( ngeIn)) return false ; // leggo la prossima linea if ( ! ngeIn.ReadKey( nKey)) return false ; } // eventuale TextureData if ( nKey == NGE_T) { if ( ! GdbObj::LoadTextureData( ngeIn)) return false ; // leggo la prossima linea if ( ! ngeIn.ReadKey( nKey)) return false ; } // eventuale UserObj if ( nKey == NGE_U) { if ( ! GdbObj::LoadUserObj( ngeIn, nBaseGdbId)) return false ; // leggo la prossima linea if ( ! ngeIn.ReadKey( nKey)) return false ; } // verifico inizio dati geometrici if ( nKey != NGE_G) return false ; // leggo il puntatore alla prima copia int nCopyId ; if ( ! ngeIn.ReadInt( nCopyId, nullptr, true)) return false ; // leggo i dati del riferimento return ngeIn.ReadFrame( m_frF, ";", true) ; } //---------------------------------------------------------------------------- bool GdbGroup::GetLocalBBox( BBox3d& b3Loc, int nFlag, int nLev) const { b3Loc.Reset() ; // se richiesto controllo visibilità oggetto if ( ( nFlag & BBF_ONLY_VISIBLE) != 0) { // recupero lo stato dell'oggetto int nStat = GDB_ST_ON ; if ( nLev == 0) // questa funzione già tiene conto del modo GetCalcStatus( nStat) ; else { // devo aggiustare lo stato con il modo GetStatus( nStat) ; int nMode = GDB_MD_STD ; GetMode( nMode) ; nStat = ::AdjustStatusWithMode( nStat, nMode) ; } // se non visibile if ( nStat == GDB_ST_OFF) return true ; } // ciclo sui figli const GdbObj* pGdbObj = GetFirstObj() ; while ( pGdbObj != nullptr) { BBox3d b3B ; // voglio il box come appare nel frame del gruppo, quindi passo frame identità if ( pGdbObj->GetBBox( GLOB_FRM, b3B, nFlag, ( nLev + 1))) b3Loc.Add( b3B) ; pGdbObj = pGdbObj->GetNext() ; } return true ; } //---------------------------------------------------------------------------- bool GdbGroup::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag, int nLev) const { b3Ref.Reset() ; // se richiesto controllo visibilità oggetto if ( ( nFlag & BBF_ONLY_VISIBLE) != 0) { // recupero lo stato dell'oggetto int nStat = GDB_ST_ON ; if ( nLev == 0) // questa funzione già tiene conto del modo GetCalcStatus( nStat) ; else { // devo aggiustare lo stato con il modo GetStatus( nStat) ; int nMode = GDB_MD_STD ; GetMode( nMode) ; nStat = ::AdjustStatusWithMode( nStat, nMode) ; } // se non visibile if ( nStat == GDB_ST_OFF) return true ; } // ciclo sui figli Frame3d frCurr = m_frF * frRef ; const GdbObj* pGdbObj = GetFirstObj() ; while ( pGdbObj != nullptr) { BBox3d b3B ; if ( pGdbObj->GetBBox( frCurr, b3B, nFlag, ( nLev + 1))) b3Ref.Add( b3B) ; pGdbObj = pGdbObj->GetNext() ; } return true ; } //---------------------------------------------------------------------------- bool GdbGroup::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { // parziale scalatura del riferimento (non può essere completa) Frame3d frTrasf = m_frF ; m_frF.PseudoScale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; // porto gli oggetti nel nuovo riferimento, senza modificarne la geometria in globale frTrasf.ToLoc( m_frF) ; for ( GdbObj* pGdbObj = GetFirstObj() ; pGdbObj != nullptr ; pGdbObj = pGdbObj->GetNext()) { pGdbObj->ToGlob( frTrasf) ; } // porto il riferimento di scalatura nel nuovo riferimento del gruppo Frame3d frRefLoc = frRef ; frRefLoc.ToLoc( m_frF) ; // ciclo sugli oggetti bool bOk = true ; for ( GdbObj* pGdbObj = GetFirstObj() ; pGdbObj != nullptr ; pGdbObj = pGdbObj->GetNext()) { if ( ! pGdbObj->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool GdbGroup::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { // parziale mirror del riferimento (non può essere completa) Frame3d frTrasf = m_frF ; m_frF.PseudoMirror( ptOn, vtNorm) ; // porto i nodi nel nuovo riferimento, senza modificarne la geometria in globale frTrasf.ToLoc( m_frF) ; for ( GdbObj* pGdbObj = GetFirstObj() ; pGdbObj != nullptr ; pGdbObj = pGdbObj->GetNext()) { pGdbObj->ToGlob( frTrasf) ; } // porto i dati del piano di mirror nel riferimento del gruppo Point3d ptOnLoc = ptOn ; ptOnLoc.ToLoc( m_frF) ; Vector3d vtNormLoc = vtNorm ; vtNormLoc.ToLoc( m_frF) ; // ciclo sugli oggetti bool bOk = true ; for ( GdbObj* pGdbObj = GetFirstObj() ; pGdbObj != nullptr ; pGdbObj = pGdbObj->GetNext()) { if ( ! pGdbObj->Mirror( ptOnLoc, vtNormLoc)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool GdbGroup::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) { // parziale scorrimento del riferimento (non può essere completa) Frame3d frTrasf = m_frF ; m_frF.PseudoShear( ptOn, vtNorm, vtDir, dCoeff) ; // porto gli oggetti nel nuovo riferimento, senza modificarne la geometria in globale frTrasf.ToLoc( m_frF) ; for ( GdbObj* pGdbObj = GetFirstObj() ; pGdbObj != nullptr ; pGdbObj = pGdbObj->GetNext()) { pGdbObj->ToGlob( frTrasf) ; } // porto i dati di scorrimento nel riferimento del gruppo Point3d ptOnLoc = ptOn ; ptOnLoc.ToLoc( m_frF) ; Vector3d vtNormLoc = vtNorm ; vtNormLoc.ToLoc( m_frF) ; Vector3d vtDirLoc = vtDir ; vtDirLoc.ToLoc( m_frF) ; // ciclo sugli oggetti bool bOk = true ; for ( GdbObj* pGdbObj = GetFirstObj() ; pGdbObj != nullptr ; pGdbObj = pGdbObj->GetNext()) { if ( ! pGdbObj->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool GdbGroup::OnSetMaterial( void) { // ciclo sugli oggetti bool bOk = true ; GdbObj* pGdbObj = GetFirstObj() ; while ( pGdbObj != nullptr) { // se non ci sono attributi o ci si deve riferire al padre int nMat ; if ( ! pGdbObj->GetMaterial( nMat) || nMat == GDB_MT_PARENT) { if ( ! pGdbObj->OnSetMaterial()) bOk = false ; } // passo al prossimo pGdbObj = pGdbObj->GetNext() ; } return bOk ; } //---------------------------------------------------------------------------- bool GdbGroup::GetGlobFrame( Frame3d& frGlob) const { // assegno il proprio frame frGlob = m_frF ; // mentre ci sono padri const GdbGroup* pParent ; pParent = GetParent() ; while ( pParent != nullptr) { // porto il riferimento corrente sopra il padre frGlob.ToGlob( pParent->GetFrame()) ; // passo al successivo pParent = pParent->GetParent() ; } return true ; } //---------------------------------------------------------------------------- int GdbGroup::GetMinId( void) const { // assegno come minimo il suo stesso Id int nMinId = m_nId ; // ciclo sugli oggetti const GdbObj* pGdbObj = GetFirstObj() ; while ( pGdbObj != nullptr) { // se oggetto geometrico if ( pGdbObj->GetGdbType() == GDB_TY_GEO) nMinId = min( nMinId, pGdbObj->m_nId) ; // altrimenti gruppo else if ( pGdbObj->GetGdbType() == GDB_TY_GROUP) { const GdbGroup* pGdbGroup = ::GetGdbGroup( pGdbObj) ; nMinId = min( nMinId, pGdbGroup->GetMinId()) ; } // passo al prossimo pGdbObj = pGdbObj->GetNext() ; } return nMinId ; }