EgtGeomKernel 2.6f4 :
- miglioramenti alla gestione di shell e part nelle superfici Trimesh.
This commit is contained in:
+381
-228
@@ -33,8 +33,8 @@
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <new>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -46,7 +46,7 @@ SurfTriMesh::SurfTriMesh( void)
|
||||
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
|
||||
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bShowEdges( false), m_bOriented( false), m_bClosed( false),
|
||||
m_bFaceted( false), m_bFacEdged( false), m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0,0},
|
||||
m_nMaxTFlag( 0), m_nParts( -1), m_nShells( -1), m_pHGrd3d( nullptr)
|
||||
m_nMaxTFlag( 0), m_nShells( -1), m_pHGrd3d( nullptr)
|
||||
{
|
||||
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
|
||||
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
|
||||
@@ -85,8 +85,8 @@ SurfTriMesh::Init( int nNumVert, int nNumTria, int nNumFacet)
|
||||
m_nStatus = OK ;
|
||||
m_bClosed = false ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_nParts = -1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -117,8 +117,8 @@ SurfTriMesh::Clear( void)
|
||||
m_dTempParam[0] = 0 ;
|
||||
m_dTempParam[1] = 0 ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_nParts = -1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ SurfTriMesh::AddVertex( const Point3d& ptVert, double dU, double dV)
|
||||
{
|
||||
// imposto ricalcolo
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
// inserisco il vertice
|
||||
@@ -160,8 +160,8 @@ SurfTriMesh::MoveVertex( int nInd, const Point3d& ptNewVert)
|
||||
m_vVert[nInd].ptP = ptNewVert ;
|
||||
// imposto ricalcolo
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = - 1 ;
|
||||
m_vPart.clear() ;
|
||||
m_bFaceted = false ;
|
||||
m_bFacEdged = false ;
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -230,8 +230,8 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
|
||||
return SVT_DEL ;
|
||||
// imposto ricalcolo
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
// inserisco il triangolo
|
||||
@@ -322,8 +322,8 @@ SurfTriMesh::RemoveTriangle( int nId)
|
||||
m_bFaceted = false ;
|
||||
m_bFacEdged = false ;
|
||||
// invalido calcolo connettività
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -912,8 +912,6 @@ SurfTriMesh::CloneTriangle( int nT) const
|
||||
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
pSurfTM->m_nShells = 1 ;
|
||||
|
||||
// Copio il triangolo
|
||||
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[nT].nIdVert[0]].ptP),
|
||||
@@ -1311,8 +1309,8 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
|
||||
m_nTempProp[0] = stmSrc.m_nTempProp[0] ;
|
||||
m_nTempProp[1] = stmSrc.m_nTempProp[1] ;
|
||||
m_nMaxTFlag = stmSrc.m_nMaxTFlag ;
|
||||
m_nParts = stmSrc.m_nParts ;
|
||||
m_nShells = stmSrc.m_nShells ;
|
||||
m_vPart = stmSrc.m_vPart ;
|
||||
m_dTempParam[0] = stmSrc.m_dTempParam[0] ;
|
||||
m_dTempParam[1] = stmSrc.m_dTempParam[1] ;
|
||||
return true ;
|
||||
@@ -1350,12 +1348,10 @@ SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
// segnalo eventuale incongruenza di orientamento
|
||||
if ( ! m_bOriented)
|
||||
sOut += string( "Inconsistent Orientation") + szNewLine ;
|
||||
// segnalo numero di parti
|
||||
// segnalo numero di parti e di gusci
|
||||
int nParts = GetPartCount() ;
|
||||
sOut += string( "Parts=") + ToString( nParts) + szNewLine ;
|
||||
// segnalo numero di gusci
|
||||
int nShells = GetShellCount() ;
|
||||
sOut += string( "Shells=") + ToString( nShells) + szNewLine ;
|
||||
sOut += string( "Parts=") + ToString( nParts) + string( " Shells=") + ToString( nShells) + szNewLine ;
|
||||
// numero di vertici
|
||||
sOut += "Vert : Nbr=" + ToString( GetVertexCount()) +
|
||||
" Size=" + ToString( GetVertexSize()) + szNewLine ;
|
||||
@@ -1465,8 +1461,8 @@ SurfTriMesh::Load( NgeReader& ngeIn)
|
||||
// imposto ricalcolo della grafica, della connessione e di hashgrids3d
|
||||
m_OGrMgr.Clear() ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_nParts = -1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
ResetHashGrids3d() ;
|
||||
// leggo la prossima linea ( 2 parametri : dLinTol e dSmoothAng)
|
||||
// tolleranza lineare di costruzione
|
||||
@@ -1626,8 +1622,8 @@ SurfTriMesh::Validate( bool bCorrect)
|
||||
}
|
||||
|
||||
// invalido calcolo connessione
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
m_vPart.clear() ;
|
||||
|
||||
return ( m_nStatus == OK) ;
|
||||
}
|
||||
@@ -1902,8 +1898,8 @@ SurfTriMesh::AdjustTopology( void)
|
||||
m_bFaceted = false ;
|
||||
m_bFacEdged = false ;
|
||||
// invalido calcolo connessione
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = - 1 ;
|
||||
m_vPart.clear() ;
|
||||
// verifica indici
|
||||
if ( ! Validate( true))
|
||||
return false ;
|
||||
@@ -3572,7 +3568,10 @@ SurfTriMesh::Invert( void)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
// imposto ricalcolo numero delle parti (le shell non cambiano)
|
||||
m_vPart.clear() ;
|
||||
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
@@ -3645,14 +3644,187 @@ SurfTriMesh::GetAllTriaBox( void) const
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetPartCount( void) const
|
||||
bool
|
||||
SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
if ( m_nParts == - 1 && ! VerifyConnection())
|
||||
return 0 ;
|
||||
return m_nParts ;
|
||||
return false ;
|
||||
|
||||
// se non sono già note le shell
|
||||
if ( m_nShells == -1) {
|
||||
// reset connessione
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nShell = SVT_NULL ;
|
||||
// ciclo sui triangoli per determinare le shells
|
||||
m_nShells = 0 ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nShell != SVT_NULL)
|
||||
continue ;
|
||||
// assegno indice di shell connessa al triangolo
|
||||
m_vTria[i].nShell = m_nShells ;
|
||||
++ m_nShells ;
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( i) ;
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
const auto iIt = stTria.begin() ;
|
||||
int nT = *iIt ;
|
||||
stTria.erase( iIt) ;
|
||||
// aggiorno i triangoli adiacenti
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nShell == SVT_NULL) {
|
||||
m_vTria[nAdjT].nShell = m_vTria[nT].nShell ;
|
||||
stTria.insert( nAdjT) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset delle parti
|
||||
m_vPart.clear() ;
|
||||
|
||||
// se richiesta solo la determinazione delle shell, esco
|
||||
if ( ! bShellsAndParts)
|
||||
return true ;
|
||||
|
||||
// Se superficie vuota, allora non ho parti
|
||||
if ( m_nShells == 0)
|
||||
return true ;
|
||||
|
||||
// Se ho solo una shell, allora ho una sola parte
|
||||
if ( m_nShells == 1) {
|
||||
m_vPart.emplace_back( m_bClosed, INTVECTOR{ 0}) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Ho più shell devo controllare la loro posizione relativa
|
||||
struct SHELLINFO {
|
||||
SHELLINFO( int nI, double dVol, const BBox3d& b3B, ISurfTriMesh* pStm)
|
||||
: nInd( nI), dVolume( dVol), b3Box( b3B), pStmShell( pStm) {}
|
||||
int nInd ;
|
||||
double dVolume ;
|
||||
BBox3d b3Box ;
|
||||
PtrOwner<ISurfTriMesh> pStmShell ;
|
||||
} ;
|
||||
vector<SHELLINFO> vOuterShells ;
|
||||
vector<SHELLINFO> vInnerShells ;
|
||||
INTVECTOR vOpenShells ;
|
||||
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
|
||||
// se la shell è chiusa
|
||||
if ( IsShellClosed( nSh)) {
|
||||
// creo una superficie clonata dalla shell
|
||||
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
|
||||
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
||||
return false ;
|
||||
// ne calcolo il volume (con segno)
|
||||
double dVol = 0. ;
|
||||
pStmShell->GetVolume( dVol) ;
|
||||
// ne calcolo il bounding box
|
||||
BBox3d b3Box ;
|
||||
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
|
||||
// la inserisco nel vettore opportuno
|
||||
if ( dVol > 0)
|
||||
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||
else
|
||||
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||
}
|
||||
// altrimenti aperta
|
||||
else {
|
||||
// la inserisco nel vettore delle shell aperte
|
||||
vOpenShells.push_back( nSh) ;
|
||||
}
|
||||
}
|
||||
|
||||
// ordino il vettore delle shell esterne in senso crescente di volume (crescenti anche in valore assoluto)
|
||||
sort( vOuterShells.begin(), vOuterShells.end(),
|
||||
[]( const SHELLINFO& a, const SHELLINFO& b) {
|
||||
return ( a.dVolume < b.dVolume) ;
|
||||
}) ;
|
||||
// ordino il vettore delle shell interne in senso crescente di volume (decrescenti in valore assoluto)
|
||||
sort( vInnerShells.begin(), vInnerShells.end(),
|
||||
[]( const SHELLINFO& a, const SHELLINFO& b) {
|
||||
return ( a.dVolume < b.dVolume) ;
|
||||
}) ;
|
||||
|
||||
// classifico le shell esterne
|
||||
for ( int i = 0 ; i < int( vOuterShells.size()) ; ++ i) {
|
||||
// inserisco nel vettore delle parti
|
||||
m_vPart.emplace_back( true, INTVECTOR{ vOuterShells[i].nInd}) ;
|
||||
// cerco eventuali interne che vi appartengono
|
||||
CISURFTMPVECTOR vStmTest{ vOuterShells[i].pStmShell} ;
|
||||
for ( int j = 0 ; j < int( vInnerShells.size()) ; ++ j) {
|
||||
// se libera e il box è incluso, verifico se realmente interna
|
||||
if ( vInnerShells[j].nInd >= 0 && vOuterShells[i].b3Box.Encloses( vInnerShells[j].b3Box)) {
|
||||
Point3d ptCheck ;
|
||||
vInnerShells[j].pStmShell->GetFirstVertex( ptCheck) ;
|
||||
bool bIsInside = true ;
|
||||
for ( const auto& pStmTest : vStmTest) {
|
||||
BBox3d b3Test = pStmTest->GetAllTriaBox() ;
|
||||
if ( b3Test.Overlaps( vInnerShells[j].b3Box)) {
|
||||
DistPointSurfTm distCalculator( ptCheck, *pStmTest) ;
|
||||
if ( ! distCalculator.IsPointInside()) {
|
||||
bIsInside = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bIsInside) {
|
||||
m_vPart.back().vShell.push_back( vInnerShells[j].nInd) ;
|
||||
vInnerShells[j].nInd = -1 ;
|
||||
vStmTest.push_back( vInnerShells[j].pStmShell) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// classifico le shell interne rimaste libere
|
||||
bool bNewInner = true ;
|
||||
CISURFTMPVECTOR vStmTest ;
|
||||
for ( int i = 0 ; i < int( vInnerShells.size()) ; ++ i) {
|
||||
if ( vInnerShells[i].nInd >= 0) {
|
||||
// se non è nuova interna verifico sia interna alle altre correnti
|
||||
if ( ! bNewInner) {
|
||||
bool bIsInside = true ;
|
||||
Point3d ptCheck ;
|
||||
vInnerShells[i].pStmShell->GetFirstVertex( ptCheck) ;
|
||||
// se il box interferisce con altri, verifico se realmente interna
|
||||
for ( const auto& pStmTest : vStmTest) {
|
||||
BBox3d b3Test = pStmTest->GetAllTriaBox() ;
|
||||
if ( b3Test.Overlaps( vInnerShells[i].b3Box)) {
|
||||
DistPointSurfTm distCalculator( ptCheck, *pStmTest) ;
|
||||
if ( ! distCalculator.IsPointInside()) {
|
||||
bIsInside = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bIsInside)
|
||||
m_vPart.back().vShell.push_back( vInnerShells[i].nInd) ;
|
||||
else
|
||||
bNewInner = true ;
|
||||
}
|
||||
// se nuova interna
|
||||
if ( bNewInner) {
|
||||
bNewInner = false ;
|
||||
m_vPart.emplace_back( true, INTVECTOR{ -1, vInnerShells[i].nInd}) ;
|
||||
vStmTest.clear() ;
|
||||
}
|
||||
vInnerShells[i].nInd = -1 ;
|
||||
vStmTest.push_back( vInnerShells[i].pStmShell) ;
|
||||
}
|
||||
}
|
||||
|
||||
// aggiungo all'elenco delle parti le shell aperte
|
||||
for ( int i = 0 ; i < int( vOpenShells.size()) ; ++ i) {
|
||||
m_vPart.emplace_back( false, INTVECTOR{ vOpenShells[i]}) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -3661,209 +3833,67 @@ SurfTriMesh::GetShellCount( void) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
if ( m_nShells == - 1 && ! VerifyConnection())
|
||||
if ( m_nShells == -1 && ! VerifyConnection())
|
||||
return 0 ;
|
||||
return m_nShells ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::VerifyConnection( void) const
|
||||
SurfTriMesh::GetShellArea( int nShell, double& dArea) const
|
||||
{
|
||||
// Controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// Imposto area nulla
|
||||
dArea = 0 ;
|
||||
// Verifiche sull'oggetto
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// reset connessione
|
||||
for ( auto& Tria : m_vTria) {
|
||||
Tria.nPart = SVT_NULL ;
|
||||
Tria.nShell = SVT_NULL ;
|
||||
if ( m_nShells == -1 && ! VerifyConnection())
|
||||
return false ;
|
||||
// Se la componente non esiste, errore
|
||||
if ( nShell < 0 || nShell >= m_nShells)
|
||||
return false ;
|
||||
// sommo l'area di tutti i triangoli della shell
|
||||
Triangle3d Tria ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
if ( m_vTria[nId].nShell == nShell)
|
||||
dArea += Tria.GetArea() ;
|
||||
nId = GetNextTriangle( nId, Tria) ;
|
||||
}
|
||||
|
||||
// ciclo sui triangoli per determinare le shells
|
||||
m_nShells = 0 ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nShell != SVT_NULL)
|
||||
continue ;
|
||||
// assegno indice di parte connessa al triangolo
|
||||
m_vTria[i].nShell = m_nShells ;
|
||||
++ m_nShells ;
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( i) ;
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
const auto iIt = stTria.begin() ;
|
||||
int nT = *iIt ;
|
||||
stTria.erase( iIt) ;
|
||||
// aggiorno i triangoli adiacenti
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nShell == SVT_NULL) {
|
||||
m_vTria[nAdjT].nShell = m_vTria[nT].nShell ;
|
||||
stTria.insert( nAdjT) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// identifico le parti
|
||||
m_nParts = 0 ;
|
||||
if ( m_nShells == 1) { // se ho solo una shell allora ho una sola parte
|
||||
m_nParts = 1 ;
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nPart = Tria.nShell ;
|
||||
}
|
||||
else { // se ho più shells devo controllare la loro posizione
|
||||
// salvo solo le Shells chiuse e per ognuna di esse il loro volume e l'indice della shell
|
||||
// < stmShell, ( nShellInd, dVol) >
|
||||
// NB. I Volumi sono sempre finiti, il segno del volume mi dice solo se sto considerando
|
||||
// la parte interna o esterna della superficie
|
||||
typedef pair<PtrOwner<ISurfTriMesh>, pair<int, double>> SHELLINFO ;
|
||||
vector<SHELLINFO> vClosedShells ;
|
||||
vClosedShells.reserve( m_nShells) ;
|
||||
INTVECTOR vOpenShells ; // vettore di indici di Shell aperte
|
||||
for ( int s = 0 ; s < GetShellCount() ; ++ s) {
|
||||
// recupero la Shell
|
||||
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( s)) ;
|
||||
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
||||
return false ;
|
||||
double dVol = 0. ;
|
||||
// se chiusa calcolo il suo volume con segno
|
||||
if ( pStmShell->IsClosed()) {
|
||||
pStmShell->GetVolume( dVol) ;
|
||||
vClosedShells.emplace_back( make_pair( Release( pStmShell), make_pair( s, dVol))) ;
|
||||
}
|
||||
// se aperta, non rientra nella classficazione ( sarà coincidente ad una Part)
|
||||
else
|
||||
vOpenShells.push_back( s) ;
|
||||
}
|
||||
|
||||
// ordino il vettore in senso decrescente per volume, in valore assoluto
|
||||
// NB. tutte le shell con volume negativo sono state invertite !
|
||||
sort( vClosedShells.begin(), vClosedShells.end(),
|
||||
[]( const SHELLINFO& a, const SHELLINFO& b) {
|
||||
return abs( a.second.second) > abs( b.second.second) ;
|
||||
}) ;
|
||||
|
||||
// se la superficie in prima posizione è negativa, allora le inverto tutte; il numero di
|
||||
// Parts non cambia nel conto
|
||||
if ( ! vClosedShells.empty() && vClosedShells.front().second.second < - EPS_SMALL)
|
||||
for ( auto& Shell : vClosedShells)
|
||||
Shell.first->Invert() ;
|
||||
|
||||
// creo una matrice di interi ; ogni riga corrisponde ad una Parte, dove in posizione 0 c'è
|
||||
// la shell esterna e nelle successive le rispettiva shells interne
|
||||
INTMATRIX vnShellIndMat ;
|
||||
|
||||
bool bFirstShell ; // flag per indicare se la shell corrente è esterna
|
||||
int nIndExtShell = -1 ; // indice del vettore di shell chiuse della shell esterna
|
||||
INTVECTOR vIndIntShells ; // vettore di indici di shell chiuse interne alla shell esterna corrente
|
||||
do {
|
||||
bFirstShell = true ;
|
||||
for ( int i = 0 ; i < int( vClosedShells.size()) ; ++ i) {
|
||||
// recupero l'indice della shell e verifico che sia valido
|
||||
int j = vClosedShells[i].second.first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstShell) {
|
||||
vnShellIndMat.push_back({ j}) ;
|
||||
vClosedShells[i].second.first = -1 ;
|
||||
bFirstShell = false ;
|
||||
nIndExtShell = i ;
|
||||
vIndIntShells.clear() ;
|
||||
}
|
||||
// altrimento verifico se la shell è interna o no
|
||||
else {
|
||||
// la shell è interna se è sia interna alla shell esterna corrente ( della riga di
|
||||
// vnShellIndMat ) e allo stesso tempo esterna a tutte le shell già inserite nella riga
|
||||
// attuale.
|
||||
Point3d ptCheck ;
|
||||
vClosedShells[i].first->GetFirstVertex( ptCheck) ;
|
||||
|
||||
// 1) verifica rispetto alla shell esterna
|
||||
DistPointSurfTm distCalculator( ptCheck, *vClosedShells[nIndExtShell].first) ;
|
||||
if ( ! distCalculator.IsPointInside())
|
||||
continue ;
|
||||
|
||||
// 2) verifica rispetto a tutte la shell già trovate interne
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vIndIntShells.size()) ; ++ k) {
|
||||
DistPointSurfTm distCalculator( ptCheck, *vClosedShells[vIndIntShells[k]].first) ;
|
||||
// NB. tutte le shell hanno volume negativo !
|
||||
if ( ! distCalculator.IsPointInside()) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnShellIndMat.back().push_back( j) ;
|
||||
vClosedShells[i].second.first = - 1 ;
|
||||
vIndIntShells.push_back( i) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstShell) ;
|
||||
|
||||
// scorro le righe della matrice e assegno la Part ( ovvero la riga )
|
||||
int nPart = 0 ;
|
||||
for ( nPart = 0 ; nPart < int( vnShellIndMat.size()) ; ++ nPart) {
|
||||
++ m_nParts ;
|
||||
for ( int j = 0 ; j < int( vnShellIndMat[nPart].size()) ; ++ j) {
|
||||
for ( auto& Tria : m_vTria) {
|
||||
if ( Tria.nShell == j)
|
||||
Tria.nPart = nPart ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// per tutte le superfici aperte, assegno loro una Parte
|
||||
for ( int i = 0 ; i < int( vOpenShells.size()) ; ++ i) {
|
||||
++ m_nParts ;
|
||||
for ( auto& Tria : m_vTria) {
|
||||
if ( Tria.nShell == i)
|
||||
Tria.nPart = i + ( nPart ++ ) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemovePart( int nPart)
|
||||
bool
|
||||
SurfTriMesh::IsShellClosed( int nShell) const
|
||||
{
|
||||
// Verifiche sull'oggetto
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// Il numero delle componenti deve essere maggiore di zero o calcolabile
|
||||
if ( m_nParts == -1 && ! VerifyConnection())
|
||||
if ( m_nShells == -1 && ! VerifyConnection( false))
|
||||
return false ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( m_nParts <= 0 || nPart < 0 || nPart >= m_nParts)
|
||||
if ( nShell < 0 || nShell >= m_nShells)
|
||||
return false ;
|
||||
|
||||
int nPartsOld = m_nParts ;
|
||||
// Rimuovo i triangoli della componente nPart
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
if ( m_vTria[i].nPart == nPart)
|
||||
RemoveTriangle( i) ;
|
||||
// ciclo sui triangoli della shell
|
||||
bool bClosed = true ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// se triangolo non cancellato e della shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||
// verifico le adiacenze
|
||||
if ( m_vTria[i].nIdAdjac[0] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
|
||||
bClosed = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiorno il numero di componenti
|
||||
m_nParts = nPartsOld - 1 ;
|
||||
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
return true ;
|
||||
// restituisco il risultato
|
||||
return bClosed ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -3878,18 +3908,18 @@ SurfTriMesh::RemoveShell( int nShell)
|
||||
return false ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( m_nShells <= 0 || nShell < 0 || nShell >= m_nShells)
|
||||
if ( nShell < 0 || nShell >= m_nShells)
|
||||
return false ;
|
||||
|
||||
int nShellsOld = m_nShells ;
|
||||
// Rimuovo i triangoli della componente nPart
|
||||
int nOldShells = m_nShells ;
|
||||
// Rimuovo i triangoli della componente nShell
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
if ( m_vTria[i].nShell == nShell)
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
|
||||
// Aggiorno il numero di componenti
|
||||
m_nShells = nShellsOld - 1 ;
|
||||
// Aggiorno il numero di shell
|
||||
m_nShells = nOldShells - 1 ;
|
||||
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -3899,18 +3929,18 @@ SurfTriMesh::RemoveShell( int nShell)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::ClonePart( int nPart) const
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneShell( int nShell) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// Il numero delle componenti deve essere maggiore di zero o calcolabile
|
||||
if ( m_nParts == -1 && ! VerifyConnection())
|
||||
if ( m_nShells == -1 && ! VerifyConnection())
|
||||
return nullptr ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( m_nParts <= 0 || nPart < 0 || nPart >= m_nParts)
|
||||
if ( nShell < 0 || nShell >= m_nShells)
|
||||
return nullptr ;
|
||||
|
||||
// Creo nuovo oggetto SurfTriMesh
|
||||
@@ -3924,12 +3954,10 @@ SurfTriMesh::ClonePart( int nPart) const
|
||||
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
pSurfTM->m_nShells = 1 ;
|
||||
|
||||
// Copio i triangoli
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nPart == nPart) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[0]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[1]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[2]].ptP)} ;
|
||||
@@ -3946,18 +3974,143 @@ SurfTriMesh::ClonePart( int nPart) const
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneShell( int nShell) const
|
||||
int
|
||||
SurfTriMesh::GetPartCount( void) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
if ( m_vPart.empty() && ! VerifyConnection())
|
||||
return 0 ;
|
||||
return int( m_vPart.size()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartArea( int nPart, double& dArea) const
|
||||
{
|
||||
// Controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// Imposto area nulla
|
||||
dArea = 0 ;
|
||||
// Verifiche sull'oggetto
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
if ( m_vPart.empty() && ! VerifyConnection())
|
||||
return false ;
|
||||
// Se la componente non esiste, errore
|
||||
if ( nPart < 0 || nPart >= int( m_vPart.size()))
|
||||
return false ;
|
||||
// sommo l'area di tutti i triangoli della parte
|
||||
Triangle3d Tria ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
const auto& vShell = m_vPart[nPart].vShell ;
|
||||
if ( find( vShell.begin(), vShell.end(), m_vTria[nId].nShell) != vShell.end())
|
||||
dArea += Tria.GetArea() ;
|
||||
nId = GetNextTriangle( nId, Tria) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::IsPartClosed( int nPart) const
|
||||
{
|
||||
// Verifiche sull'oggetto
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
if ( m_vPart.empty() && ! VerifyConnection())
|
||||
return false ;
|
||||
// Se la componente non esiste, errore
|
||||
if ( nPart < 0 || nPart >= int( m_vPart.size()))
|
||||
return false ;
|
||||
return m_vPart[nPart].bClosed ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartVolume( int nPart, double& dVolume) const
|
||||
{
|
||||
// Controllo parametro di ritorno
|
||||
if ( &dVolume == nullptr)
|
||||
return false ;
|
||||
// Imposto volume nullo
|
||||
dVolume = 0 ;
|
||||
// Verifiche sull'oggetto
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
if ( m_vPart.empty() && ! VerifyConnection())
|
||||
return false ;
|
||||
// Se la componente non esiste, errore
|
||||
if ( nPart < 0 || nPart >= int( m_vPart.size()))
|
||||
return false ;
|
||||
// la parte deve essere chiusa
|
||||
if ( ! m_vPart[nPart].bClosed)
|
||||
return true ;
|
||||
// sommo il volume con segno di tutte le piramidi della parte dall'origine ad ogni faccia
|
||||
Triangle3d Tria ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
const auto& vShell = m_vPart[nPart].vShell ;
|
||||
if ( find( vShell.begin(), vShell.end(), m_vTria[nId].nShell) != vShell.end()) {
|
||||
Vector3d vtA = ( Tria.GetP( 1) - Tria.GetP( 0)) ^ ( Tria.GetP( 2) - Tria.GetP( 0)) ;
|
||||
dVolume += ( Tria.GetP( 0) - ORIG) * vtA ;
|
||||
}
|
||||
nId = GetNextTriangle( nId, Tria) ;
|
||||
}
|
||||
dVolume /= 6 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemovePart( int nPart)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// Il numero delle componenti deve essere maggiore di zero o calcolabile
|
||||
if ( m_vPart.empty() && ! VerifyConnection())
|
||||
return false ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( nPart < 0 || nPart >= int( m_vPart.size()))
|
||||
return false ;
|
||||
|
||||
int nOldShells = m_nShells ;
|
||||
// Rimuovo i triangoli della componente nPart (ovvero delle sue shell)
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
const auto& vShell = m_vPart[nPart].vShell ;
|
||||
if ( find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiorno il numero di componenti
|
||||
m_nShells = nOldShells - m_vPart[nPart].GetShellCount() ;
|
||||
m_vPart.erase( m_vPart.begin() + nPart) ;
|
||||
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::ClonePart( int nPart) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// Il numero delle componenti deve essere maggiore di zero o calcolabile
|
||||
if ( m_nShells == -1 && ! VerifyConnection())
|
||||
// Il numero delle parti deve essere maggiore di zero o calcolabile
|
||||
if ( m_vPart.empty() && ! VerifyConnection())
|
||||
return nullptr ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( m_nShells <= 0 || nShell < 0 || nShell >= m_nShells)
|
||||
// Se la parte non esiste, errore
|
||||
if ( nPart < 0 || nPart >= int( m_vPart.size()))
|
||||
return nullptr ;
|
||||
|
||||
// Creo nuovo oggetto SurfTriMesh
|
||||
@@ -3971,12 +4124,12 @@ SurfTriMesh::CloneShell( int nShell) const
|
||||
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
pSurfTM->m_nShells = 1 ;
|
||||
|
||||
// Copio i triangoli
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||
const auto& vShell = m_vPart[nPart].vShell ;
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[0]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[1]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[2]].ptP)} ;
|
||||
|
||||
Reference in New Issue
Block a user