Files
EgtGeomKernel/GdbGroup.cpp
T
Dario Sassi 650540e573 EgtGeomKernel :
- semplificata e ottimizzata creazione di superficie trimesh box standard
- miglioramenti sintattici vari.
2023-12-29 12:55:24 +01:00

495 lines
14 KiB
C++

//----------------------------------------------------------------------------
// 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 ;
}