EgtGeomKernel 1.6b8 :
- velocizzata chiusura DB con molte entità selezionate - aggiunta intersezione linea superficie TM (versione semplice) - migliorata intersezione linea-triangolo - aggiunto calcolo area di superfici TM - aggiunto calcolo volume di superfici TM chiuse - aggiunta gestione facce piane di superficie TM - aggiunto calcolo punti notevoli di facce di superfici TM.
This commit is contained in:
+313
-75
@@ -1,5 +1,5 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2014
|
||||
// EgalTech 2014-2015
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMesh.cpp Data : 15.05.14 Versione : 1.5e5
|
||||
// Contenuto : Implementazione della classe Superfici TriMesh.
|
||||
@@ -33,7 +33,7 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ;
|
||||
//----------------------------------------------------------------------------
|
||||
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_bClosed( false), m_nTempProp()
|
||||
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false), m_nTimeStamp(), m_nTempProp()
|
||||
{
|
||||
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
|
||||
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
|
||||
@@ -46,7 +46,7 @@ SurfTriMesh::~SurfTriMesh( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Init( int nNumVert, int nNumTria)
|
||||
SurfTriMesh::Init( int nNumVert, int nNumTria, int nNumFacet)
|
||||
{
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -57,6 +57,8 @@ SurfTriMesh::Init( int nNumVert, int nNumTria)
|
||||
try {
|
||||
m_vVert.reserve( nNumVert) ;
|
||||
m_vTria.reserve( nNumTria) ;
|
||||
if ( nNumFacet > 0)
|
||||
m_vFacet.reserve( nNumFacet) ;
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
@@ -169,11 +171,115 @@ SurfTriMesh::SetTriangle( int nInd, const StmTria& tT)
|
||||
m_vTria[i] = tEmpty ;
|
||||
}
|
||||
}
|
||||
// inserisco il vertice
|
||||
// inserisco il triangolo
|
||||
m_vTria[nInd] = tT ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetArea( double& dArea) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// inizio con area nulla
|
||||
dArea = 0 ;
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// sommo l'area di tutti i triangoli
|
||||
Triangle3d Tria ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
dArea += Tria.GetArea() ;
|
||||
nId = GetNextTriangle( nId, Tria) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetVolume( double& dVolume) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &dVolume == nullptr)
|
||||
return false ;
|
||||
// inizio con volume nullo
|
||||
dVolume = 0 ;
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// la superficie deve essere chiusa
|
||||
if ( ! IsClosed())
|
||||
return true ;
|
||||
// sommo il volume con segno di tutte le piramidi dall'origine ad ogni faccia
|
||||
Triangle3d Tria ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
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::GetCentroid( Point3d& ptCen) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &ptCen == nullptr)
|
||||
return false ;
|
||||
// inizio con centro nell'origine
|
||||
ptCen = ORIG ;
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// se la superficie è chiusa, calcolo il centroide del solido
|
||||
if ( IsClosed()) {
|
||||
// applico le formule di R. Nurnberg Imperial College London ad ogni faccia
|
||||
Triangle3d Tria ;
|
||||
double dVolume = 0 ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
Vector3d vtA = ( Tria.GetP( 1) - Tria.GetP( 0)) ^ ( Tria.GetP( 2) - Tria.GetP( 0)) ;
|
||||
dVolume += ( Tria.GetP( 0) - ORIG) * vtA ;
|
||||
ptCen.x += vtA.x * (( Tria.GetP( 0).x + Tria.GetP( 1).x) * ( Tria.GetP( 0).x + Tria.GetP( 1).x) +
|
||||
( Tria.GetP( 1).x + Tria.GetP( 2).x) * ( Tria.GetP( 1).x + Tria.GetP( 2).x) +
|
||||
( Tria.GetP( 2).x + Tria.GetP( 0).x) * ( Tria.GetP( 2).x + Tria.GetP( 0).x)) ;
|
||||
ptCen.y += vtA.y * (( Tria.GetP( 0).y + Tria.GetP( 1).y) * ( Tria.GetP( 0).y + Tria.GetP( 1).y) +
|
||||
( Tria.GetP( 1).y + Tria.GetP( 2).y) * ( Tria.GetP( 1).y + Tria.GetP( 2).y) +
|
||||
( Tria.GetP( 2).y + Tria.GetP( 0).y) * ( Tria.GetP( 2).y + Tria.GetP( 0).y)) ;
|
||||
ptCen.z += vtA.z * (( Tria.GetP( 0).z + Tria.GetP( 1).z) * ( Tria.GetP( 0).z + Tria.GetP( 1).z) +
|
||||
( Tria.GetP( 1).z + Tria.GetP( 2).z) * ( Tria.GetP( 1).z + Tria.GetP( 2).z) +
|
||||
( Tria.GetP( 2).z + Tria.GetP( 0).z) * ( Tria.GetP( 2).z + Tria.GetP( 0).z)) ;
|
||||
nId = GetNextTriangle( nId, Tria) ;
|
||||
}
|
||||
dVolume /= 6 ;
|
||||
if ( fabs( dVolume) < EPS_SMALL * EPS_SMALL * EPS_SMALL)
|
||||
return false ;
|
||||
ptCen /= ( 24 * 2 * dVolume) ;
|
||||
}
|
||||
// altrimenti calcolo il centroide della superficie
|
||||
else {
|
||||
Triangle3d Tria ;
|
||||
double dArea = 0 ;
|
||||
int nId = GetFirstTriangle( Tria) ;
|
||||
while ( nId != SVT_NULL) {
|
||||
double dTriaArea = Tria.GetArea() ;
|
||||
dArea += dTriaArea ;
|
||||
ptCen += Tria.GetCentroid() * dTriaArea ;
|
||||
nId = GetNextTriangle( nId, Tria) ;
|
||||
}
|
||||
if ( fabs( dArea) < EPS_SMALL * EPS_SMALL)
|
||||
return false ;
|
||||
ptCen /= dArea ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetVertexNum( void) const
|
||||
@@ -414,8 +520,14 @@ SurfTriMesh::GetTriangleBoundaryEdges( int nId, TriFlags3d& TFlags) const
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
// indice triangolo adiacente al lato
|
||||
int nT = m_vTria[nId].nIdAdjac[i] ;
|
||||
// se non c'è triangolo adiacente o se forma un angolo oltre il limite, il lato è un contorno
|
||||
TFlags.bFlag[i] = ( nT == SVT_NULL || m_vTria[nId].vtN * m_vTria[nT].vtN < m_dCosBndAng) ;
|
||||
// se già definite le facce, verifico indice faccia
|
||||
if ( m_bFaceted) {
|
||||
TFlags.bFlag[i] = ( nT == SVT_NULL || m_vTria[nId].nIdFacet != m_vTria[nT].nIdFacet) ;
|
||||
}
|
||||
// altrimenti verifico con le normali
|
||||
else
|
||||
// se non c'è triangolo adiacente o se forma un angolo oltre il limite, il lato è un contorno
|
||||
TFlags.bFlag[i] = ( nT == SVT_NULL || m_vTria[nId].vtN * m_vTria[nT].vtN < m_dCosBndAng) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -523,12 +635,16 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
|
||||
return false ;
|
||||
m_vVert = stmSrc.m_vVert ;
|
||||
m_vTria = stmSrc.m_vTria ;
|
||||
m_bOriented = stmSrc.m_bOriented ;
|
||||
m_bClosed = stmSrc.m_bClosed ;
|
||||
m_dLinTol = stmSrc.m_dLinTol ;
|
||||
m_dSmoothAng = stmSrc.m_dSmoothAng ;
|
||||
m_dCosSmAng = stmSrc.m_dCosSmAng ;
|
||||
m_nStatus = stmSrc.m_nStatus ;
|
||||
m_nTimeStamp = stmSrc.m_nTimeStamp ;
|
||||
m_nTempProp = stmSrc.m_nTempProp ;
|
||||
m_bFaceted = stmSrc.m_bFaceted ;
|
||||
m_vFacet = stmSrc.m_vFacet ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -551,14 +667,29 @@ SurfTriMesh::GetTitle( void) const
|
||||
bool
|
||||
SurfTriMesh::Dump( string& sOut, const char* szNewLine) const
|
||||
{
|
||||
// se superficie aperta o chiusa
|
||||
sOut += ( m_bClosed ? "Closed" : "Open") + string( szNewLine) ;
|
||||
// area
|
||||
double dArea ;
|
||||
GetArea( dArea) ;
|
||||
sOut += "Area=" + ToString( dArea,1) + szNewLine ;
|
||||
// altri dati per superficie chiusa
|
||||
if ( m_bClosed) {
|
||||
double dVolume ;
|
||||
GetVolume( dVolume) ;
|
||||
sOut += "Closed Volume=" + ToString( dVolume,1) + szNewLine ;
|
||||
}
|
||||
// se segnalo eventuale incongruenza di orientamento
|
||||
if ( ! m_bOriented)
|
||||
sOut += string( "Inconsistent Orientation") + szNewLine ;
|
||||
// numero di vertici
|
||||
sOut += "Vert : Nbr=" + ToString( GetVertexNum()) +
|
||||
" Size=" + ToString( GetVertexSize()) + szNewLine ;
|
||||
// numero di triangoli
|
||||
sOut += "Tria : Nbr=" + ToString( GetTriangleNum()) +
|
||||
" Size=" + ToString( GetTriangleSize()) + szNewLine ;
|
||||
// numero facce, se calcolate
|
||||
if ( m_bFaceted)
|
||||
sOut += "Facet : Nbr=" + ToString( GetFacetNum()) +
|
||||
" Size=" + ToString( GetFacetSize()) + szNewLine ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -580,6 +711,9 @@ SurfTriMesh::Save( NgeWriter& ngeOut) const
|
||||
// angolo limite per mediare le normali
|
||||
if ( ! ngeOut.WriteDouble( m_dSmoothAng, ";", true))
|
||||
return false ;
|
||||
// flag orientata
|
||||
if ( ! ngeOut.WriteBool( m_bOriented, ";"))
|
||||
return false ;
|
||||
// flag aperta/chiusa
|
||||
if ( ! ngeOut.WriteBool( m_bClosed, ";"))
|
||||
return false ;
|
||||
@@ -587,7 +721,10 @@ SurfTriMesh::Save( NgeWriter& ngeOut) const
|
||||
if ( ! ngeOut.WriteInt( GetVertexSize(), ";"))
|
||||
return false ;
|
||||
// numero di triangoli
|
||||
if ( ! ngeOut.WriteInt( GetTriangleSize(), ";", true))
|
||||
if ( ! ngeOut.WriteInt( GetTriangleSize(), ";"))
|
||||
return false ;
|
||||
// numero di facce
|
||||
if ( ! ngeOut.WriteInt( GetFacetSize(), ";", true))
|
||||
return false ;
|
||||
// ciclo sui vertici
|
||||
for ( int i = 0 ; i < int( m_vVert.size()) ; ++ i) {
|
||||
@@ -607,10 +744,19 @@ SurfTriMesh::Save( NgeWriter& ngeOut) const
|
||||
! ngeOut.WriteInt( m_vTria[i].nIdAdjac[1], ",") ||
|
||||
! ngeOut.WriteInt( m_vTria[i].nIdAdjac[2], ";") ||
|
||||
! ngeOut.WriteVector( m_vTria[i].vtN, ";") ||
|
||||
! ngeOut.WriteInt( m_vTria[i].nIdFacet, ";") ||
|
||||
! ngeOut.WriteInt( m_vTria[i].nTFlag, ";") ||
|
||||
! ngeOut.WriteInt( m_vTria[i].nEFlag, ";", true))
|
||||
return false ;
|
||||
}
|
||||
// ciclo sulle facce
|
||||
int nNumFacet = int( m_vFacet.size()) ;
|
||||
for ( int i = 0 ; i < nNumFacet ; ++ i) {
|
||||
bool bEndL = ( ( i + 1) % 10 == 0) || i == ( nNumFacet - 1) ;
|
||||
if ( ! ngeOut.WriteInt( i, ",") ||
|
||||
! ngeOut.WriteInt( m_vFacet[i], ";", bEndL))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -630,26 +776,46 @@ SurfTriMesh::Load( NgeReader& ngeIn)
|
||||
double dSmoothAng ;
|
||||
if ( ! ngeIn.ReadDouble( dSmoothAng, ";", true))
|
||||
return false ;
|
||||
// leggo la prossima linea ( 3 parametri : flag chiuso num vertici e num tria)
|
||||
// recupero il flag
|
||||
bool bClosed ;
|
||||
if ( ! ngeIn.ReadBool( bClosed, ";"))
|
||||
return false ;
|
||||
// recupero il numero di vertici
|
||||
int nNumVert ;
|
||||
if ( ! ngeIn.ReadInt( nNumVert, ";"))
|
||||
return false ;
|
||||
// recupero il numero di triangoli
|
||||
int nNumTria ;
|
||||
if ( ! ngeIn.ReadInt( nNumTria, ";", true))
|
||||
return false ;
|
||||
// preparo la superficie
|
||||
if ( ! Init( nNumVert, nNumTria))
|
||||
return false ;
|
||||
m_bClosed = bClosed ;
|
||||
m_dLinTol = dLinTol ;
|
||||
m_dSmoothAng = dSmoothAng ;
|
||||
m_dCosSmAng = cos( dSmoothAng * DEGTORAD) ;
|
||||
// leggo la prossima linea
|
||||
// prima di versione 1010 3 parametri : flag di chiusa, num vertici, num tria
|
||||
// da versione 1010 leggo flag di orientata
|
||||
bool bOriented ;
|
||||
bool bClosed ;
|
||||
int nNumVert ;
|
||||
int nNumTria ;
|
||||
int nNumFacet ;
|
||||
if ( ngeIn.GetFileVersion() < NGE_VER_1010) {
|
||||
bOriented = false ;
|
||||
if ( ! ngeIn.ReadBool( bClosed, ";"))
|
||||
return false ;
|
||||
if ( ! ngeIn.ReadInt( nNumVert, ";"))
|
||||
return false ;
|
||||
if ( ! ngeIn.ReadInt( nNumTria, ";", true))
|
||||
return false ;
|
||||
nNumFacet = 0 ;
|
||||
}
|
||||
// da versione 1010 5 parametri : flag di orientata, flag di chiusa, num vertici, num tria, num facet
|
||||
else {
|
||||
if ( ! ngeIn.ReadBool( bOriented, ";"))
|
||||
return false ;
|
||||
if ( ! ngeIn.ReadBool( bClosed, ";"))
|
||||
return false ;
|
||||
if ( ! ngeIn.ReadInt( nNumVert, ";"))
|
||||
return false ;
|
||||
if ( ! ngeIn.ReadInt( nNumTria, ";"))
|
||||
return false ;
|
||||
if ( ! ngeIn.ReadInt( nNumFacet, ";", true))
|
||||
return false ;
|
||||
}
|
||||
// preparo la superficie
|
||||
if ( ! Init( nNumVert, nNumTria, nNumFacet))
|
||||
return false ;
|
||||
m_bOriented = bOriented ;
|
||||
m_bClosed = bClosed ;
|
||||
m_bFaceted = ( nNumFacet > 0) ;
|
||||
// lettura dei vertici
|
||||
int nInd ;
|
||||
StmVert vV ;
|
||||
@@ -666,7 +832,7 @@ SurfTriMesh::Load( NgeReader& ngeIn)
|
||||
// lettura dei triangoli
|
||||
StmTria tT ;
|
||||
for ( int i = 0 ; i < nNumTria ; ++ i) {
|
||||
// leggo la prossima linea ( 6 parametri : Indice, IdVertici, IdAdiacenze, Normale, TFlag, EFlag)
|
||||
// leggo la prossima linea ( 6 o 7 parametri : Indice, IdVertici, IdAdiacenze, Normale, [Facet,] TFlag, EFlag)
|
||||
// la interpreto e imposto il vertice
|
||||
if ( ! ngeIn.ReadInt( nInd, ";") ||
|
||||
! ngeIn.ReadInt( tT.nIdVert[0], ",") ||
|
||||
@@ -676,11 +842,21 @@ SurfTriMesh::Load( NgeReader& ngeIn)
|
||||
! ngeIn.ReadInt( tT.nIdAdjac[1], ",") ||
|
||||
! ngeIn.ReadInt( tT.nIdAdjac[2], ";") ||
|
||||
! ngeIn.ReadVector( tT.vtN, ";") ||
|
||||
( ngeIn.GetFileVersion() >= NGE_VER_1010 && ! ngeIn.ReadInt( tT.nIdFacet, ";")) ||
|
||||
! ngeIn.ReadInt( tT.nTFlag, ";") ||
|
||||
! ngeIn.ReadInt( tT.nEFlag, ";", true) ||
|
||||
! SetTriangle( nInd, tT))
|
||||
return false ;
|
||||
}
|
||||
// lettura delle facce
|
||||
int nT ;
|
||||
for ( int i = 0 ; i < nNumFacet ; ++ i) {
|
||||
bool bEndL = ( ( i + 1) % 10 == 0) || i == ( nNumFacet - 1) ;
|
||||
if ( ! ngeIn.ReadInt( nInd, ",") ||
|
||||
! ngeIn.ReadInt( nT, ";", bEndL) ||
|
||||
! SetFacet( nInd, nT))
|
||||
return false ;
|
||||
}
|
||||
// eseguo validazione
|
||||
return Validate() ;
|
||||
}
|
||||
@@ -720,6 +896,15 @@ SurfTriMesh::Validate( void)
|
||||
}
|
||||
}
|
||||
|
||||
// Verifico che i triangoli riferiti dalle facce esistano
|
||||
for ( int i = 0 ; i < GetFacetSize() && m_nStatus == OK && m_bFaceted ; ++ i) {
|
||||
// verifico validità triangolo riferito
|
||||
if ( m_vFacet[i] <= SVT_NULL ||
|
||||
m_vFacet[i] >= GetTriangleSize() ||
|
||||
m_vTria[ m_vFacet[i]].nIdVert[0] == SVT_DEL)
|
||||
m_bFaceted = false ;
|
||||
}
|
||||
|
||||
return ( m_nStatus == OK) ;
|
||||
}
|
||||
|
||||
@@ -839,57 +1024,113 @@ SurfTriMesh::AdjustAdjacencies( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustOrientations( int nLev, bool& bSomeWrong)
|
||||
SurfTriMesh::AdjustOrientations( void)
|
||||
{
|
||||
// inizializzo parametro di ritorno
|
||||
bSomeWrong = false ;
|
||||
// ciclo sui triangoli
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// flags
|
||||
int nNull = 0 ;
|
||||
int nWrong = 0 ;
|
||||
// ciclo sui lati del triangolo
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
// se non c'è adiacenza
|
||||
if ( m_vTria[i].nIdAdjac[j] == SVT_NULL)
|
||||
++ nNull ;
|
||||
// la verifico
|
||||
else {
|
||||
// indice altro triangolo
|
||||
int nT = m_vTria[i].nIdAdjac[j] ;
|
||||
// indice altro half-hedge
|
||||
int nE = 0 ;
|
||||
if ( m_vTria[nT].nIdAdjac[1] == i)
|
||||
nE = 1 ;
|
||||
else if ( m_vTria[nT].nIdAdjac[2] == i)
|
||||
nE = 2 ;
|
||||
// verifico corrispondenza vertici ( i due inizi devono essere diversi)
|
||||
if ( m_vTria[i].nIdVert[j] == m_vTria[nT].nIdVert[nE])
|
||||
++ nWrong ;
|
||||
}
|
||||
}
|
||||
// aggiorno stato
|
||||
if ( nWrong > 0)
|
||||
bSomeWrong = true ;
|
||||
// se almeno uno errato e gli altri nulli, inverto il triangolo
|
||||
if ( nWrong >= nLev && ( nWrong + nNull) == 3)
|
||||
InvertTriangle( i) ;
|
||||
// se non ci sono almeno 2 triangoli è inutile fare test
|
||||
if ( m_vTria.size() < 2) {
|
||||
m_bOriented = true ;
|
||||
return true ;
|
||||
}
|
||||
// incremento time stamp di due step (serve un marcatore intermedio)
|
||||
m_nTimeStamp += 2 ;
|
||||
// ciclo sui triangoli
|
||||
TRINTDEQUE S3iQ ;
|
||||
bool bOk = true ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// se triangolo non cancellato e senza time stamp
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
abs( m_vTria[i].nTemp) != m_nTimeStamp) {
|
||||
S3iQ.emplace_back( i, SVT_NULL, 0) ;
|
||||
while ( ! S3iQ.empty()) {
|
||||
if ( ! AdjustTriaOrientation( S3iQ))
|
||||
bOk = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// salvo il risultato
|
||||
m_bOriented = bOk ;
|
||||
// in caso di errore ripristino l'orientamento originale
|
||||
if ( ! m_bOriented){
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
if ( - m_vTria[i].nTemp == m_nTimeStamp)
|
||||
InvertTriangle( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::TestClosure( void)
|
||||
SurfTriMesh::AdjustTriaOrientation( TRINTDEQUE& S3iQ)
|
||||
{
|
||||
// recupero e tolgo i dati dalla testa della coda
|
||||
int nT = S3iQ.front().nI1 ;
|
||||
int nRefT = S3iQ.front().nI2 ;
|
||||
int nRefE = S3iQ.front().nI3 ;
|
||||
S3iQ.pop_front() ;
|
||||
// assegno time stamp al triangolo
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// se c'è triangolo di riferimento, devo verificare se da invertire
|
||||
if ( nRefT != SVT_NULL) {
|
||||
// cerco indice half-edge in comune
|
||||
int nE = 0 ;
|
||||
if ( m_vTria[nT].nIdAdjac[1] == nRefT)
|
||||
nE = 1 ;
|
||||
else if ( m_vTria[nT].nIdAdjac[2] == nRefT)
|
||||
nE = 2 ;
|
||||
// verifico corrispondenza vertici ( i due inizi devono essere diversi)
|
||||
if ( m_vTria[nT].nIdVert[nE] == m_vTria[nRefT].nIdVert[nRefE]) {
|
||||
m_vTria[nT].nTemp = - m_vTria[nT].nTemp ;
|
||||
InvertTriangle( nT) ;
|
||||
}
|
||||
}
|
||||
// verifico i triangoli adiacenti
|
||||
bool bOk = true ;
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
// se non c'è adiacenza o va sul triangolo di provenienza
|
||||
if ( nAdjT == SVT_NULL || nAdjT == nRefT)
|
||||
;
|
||||
// la verifico
|
||||
else {
|
||||
// se triangolo adiacente senza timestamp finale e intermedio
|
||||
if ( abs( m_vTria[nAdjT].nTemp) != m_nTimeStamp &&
|
||||
m_vTria[nAdjT].nTemp != ( m_nTimeStamp - 1)) {
|
||||
m_vTria[nAdjT].nTemp = m_nTimeStamp - 1 ;
|
||||
S3iQ.emplace_back( nAdjT, nT, j) ;
|
||||
}
|
||||
// altrimenti verifico che l'orientamento sia congruente
|
||||
else {
|
||||
// indice altro half-hedge
|
||||
int nE = 0 ;
|
||||
if ( m_vTria[nAdjT].nIdAdjac[1] == nT)
|
||||
nE = 1 ;
|
||||
else if ( m_vTria[nAdjT].nIdAdjac[2] == nT)
|
||||
nE = 2 ;
|
||||
// verifico corrispondenza vertici ( i due inizi devono essere diversi)
|
||||
if ( m_vTria[nT].nIdVert[j] == m_vTria[nAdjT].nIdVert[nE])
|
||||
bOk = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::TestSealing( void)
|
||||
{
|
||||
// ciclo sui triangoli
|
||||
bool bClosed = true ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
if ( m_vTria[i].nIdAdjac[0] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[2] == SVT_NULL)
|
||||
bClosed = false ;
|
||||
// se triangolo non cancellato
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL) {
|
||||
// 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 ;
|
||||
}
|
||||
}
|
||||
// aggiorno la chiusura della superficie
|
||||
m_bClosed = bClosed ;
|
||||
@@ -900,6 +1141,8 @@ SurfTriMesh::TestClosure( void)
|
||||
bool
|
||||
SurfTriMesh::AdjustTopology( void)
|
||||
{
|
||||
// dichiaro sfaccettatura da ricalcolare
|
||||
ResetFaceting() ;
|
||||
// verifica indici
|
||||
if ( ! Validate())
|
||||
return false ;
|
||||
@@ -907,15 +1150,10 @@ SurfTriMesh::AdjustTopology( void)
|
||||
if ( ! AdjustAdjacencies())
|
||||
return false ;
|
||||
// verifica continuità orientazione
|
||||
int nLev = 3 ;
|
||||
bool bSomeWrong ;
|
||||
do {
|
||||
if ( ! AdjustOrientations( nLev, bSomeWrong))
|
||||
return false ;
|
||||
-- nLev ;
|
||||
} while ( bSomeWrong && nLev > 0) ;
|
||||
if ( ! AdjustOrientations())
|
||||
return false ;
|
||||
// verifica chiusura
|
||||
if ( ! TestClosure())
|
||||
if ( ! TestSealing())
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
|
||||
Reference in New Issue
Block a user