985729fd47
- modifiche a TriMesh.
894 lines
27 KiB
C++
894 lines
27 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : SurfTriMesh.cpp Data : 26.03.14 Versione : 1.5c9
|
|
// Contenuto : Implementazione della classe Superfici TriMesh.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 26.03.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "DllMain.h"
|
|
#include "SurfTriMesh.h"
|
|
#include "GeoConst.h"
|
|
#include "DistPointLine.h"
|
|
#include "GeoObjFactory.h"
|
|
#include "PolynomialPoint3d.h"
|
|
#include "\EgtDev\Include\EGkCurveArc.h"
|
|
#include "\EgtDev\Include\ENkPolynomial.h"
|
|
#include "\EgtDev\Include\EGkStringUtils3d.h"
|
|
#include <new>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
GEOOBJ_REGISTER( SRF_TRIMESH, "S_TRM", SurfTriMesh) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfTriMesh::SurfTriMesh( void)
|
|
: m_nStatus( TO_VERIFY), m_bClosed( false)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfTriMesh::~SurfTriMesh( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Init( int nNumVert, int nNumTria)
|
|
{
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// verifico validità parametri
|
|
if ( nNumVert < 3 || nNumTria < 1)
|
|
return false ;
|
|
// prealloco la memoria
|
|
try {
|
|
m_vVert.reserve( nNumVert) ;
|
|
m_vTria.reserve( nNumTria) ;
|
|
}
|
|
catch (...) {
|
|
return false ;
|
|
}
|
|
// completo inizializzazione
|
|
m_nStatus = OK ;
|
|
m_bClosed = false ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::AddVertex( const Point3d& ptVert)
|
|
{
|
|
// imposto ricalcolo
|
|
m_nStatus = TO_VERIFY ;
|
|
m_OGrMgr.Reset() ;
|
|
// inserisco il vertice
|
|
try { m_vVert.push_back( StmVert( ptVert)) ;}
|
|
catch(...) { return - 1 ;}
|
|
// ne determino l'indice
|
|
return int( m_vVert.size() - 1) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::SetVertex( int nInd, const StmVert& vV)
|
|
{
|
|
// imposto ricalcolo
|
|
m_nStatus = TO_VERIFY ;
|
|
m_OGrMgr.Reset() ;
|
|
// recupero la dimensione originale
|
|
int nPrevSize = int( m_vVert.size()) ;
|
|
// determino la dimensione necessaria
|
|
int nNewSize = max( nInd + 1, nPrevSize) ;
|
|
// se necessaria dimensione maggiore
|
|
if ( nNewSize > nPrevSize) {
|
|
// espando vettore
|
|
try { m_vVert.resize( nNewSize) ; }
|
|
catch (...) { return false ; }
|
|
// inizializzo a cancellati gli eventuali vertici intermedi
|
|
StmVert vEmpty( Point3d(), VT_DEL, 0) ;
|
|
for ( int i = nPrevSize ; i < nNewSize ; ++ i)
|
|
m_vVert[i] = vEmpty ;
|
|
}
|
|
// inserisco il vertice
|
|
m_vVert[nInd] = vV ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::AddTriangle( const int nIdVert[3])
|
|
{
|
|
// imposto ricalcolo
|
|
m_nStatus = TO_VERIFY ;
|
|
m_OGrMgr.Reset() ;
|
|
// inserisco il triangolo
|
|
m_vTria.push_back( StmTria( nIdVert)) ;
|
|
// ne determino l'indice
|
|
return int( m_vTria.size() - 1) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::SetTriangle( int nInd, const StmTria& tT)
|
|
{
|
|
// imposto ricalcolo
|
|
m_nStatus = TO_VERIFY ;
|
|
m_OGrMgr.Reset() ;
|
|
// recupero la dimensione originale
|
|
int nPrevSize = int( m_vTria.size()) ;
|
|
// determino la dimensione necessaria
|
|
int nNewSize = max( nInd + 1, nPrevSize) ;
|
|
// se necessaria dimensione maggiore
|
|
if ( nNewSize > nPrevSize) {
|
|
// espando vettore
|
|
try { m_vTria.resize( nNewSize) ; }
|
|
catch (...) { return false ; }
|
|
// inizializzo a cancellati gli eventuali triangoli intermedi
|
|
StmTria tEmpty ;
|
|
tEmpty.nIdVert[0] = VT_DEL ;
|
|
for ( int i = nPrevSize ; i < nNewSize ; ++ i)
|
|
m_vTria[i] = tEmpty ;
|
|
}
|
|
// inserisco il vertice
|
|
m_vTria[nInd] = tT ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetFirstVertex( Point3d& ptP) const
|
|
{
|
|
return GetNextVertex( -1, ptP) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const
|
|
{
|
|
// cerco il primo successivo valido
|
|
do {
|
|
nId ++ ;
|
|
} while ( nId < GetVertexNum() && m_vVert[nId].nIdTria == VT_DEL) ;
|
|
// se oltrepassata fine
|
|
if ( nId >= GetVertexNum())
|
|
return -1 ;
|
|
// recupero i dati
|
|
ptP = m_vVert[nId].ptP ;
|
|
// ritorno indice triangolo corrente
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetFirstTriangle( Triangle3d& Tria) const
|
|
{
|
|
return GetNextTriangle( -1, Tria) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetNextTriangle( int nId, Triangle3d& Tria) const
|
|
{
|
|
// cerco il primo successivo valido
|
|
do {
|
|
nId ++ ;
|
|
} while ( nId < GetTriangleNum() && m_vTria[nId].nIdVert[0] == VT_DEL) ;
|
|
// se oltrepassata fine
|
|
if ( nId >= GetTriangleNum())
|
|
return -1 ;
|
|
// recupero i dati
|
|
Tria.Set( m_vVert[m_vTria[nId].nIdVert[0]].ptP,
|
|
m_vVert[m_vTria[nId].nIdVert[1]].ptP,
|
|
m_vVert[m_vTria[nId].nIdVert[2]].ptP,
|
|
m_vTria[nId].vtN) ;
|
|
// ritorno indice triangolo corrente
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SurfTriMesh*
|
|
SurfTriMesh::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
SurfTriMesh* pStm = new(nothrow) SurfTriMesh ;
|
|
if ( pStm != nullptr) {
|
|
if ( ! pStm->Copy( *this)) {
|
|
delete pStm ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
|
|
return pStm ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Copy( const IGeoObj* pGObjSrc)
|
|
{
|
|
const SurfTriMesh* pStm = dynamic_cast<const SurfTriMesh*>( pGObjSrc) ;
|
|
if ( pStm == nullptr)
|
|
return false ;
|
|
return Copy( *pStm) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Copy( const SurfTriMesh& stmSrc)
|
|
{
|
|
if ( &stmSrc == this)
|
|
return true ;
|
|
if ( ! Init( stmSrc.GetVertexNum(), stmSrc.GetTriangleNum()))
|
|
return false ;
|
|
m_vVert = stmSrc.m_vVert ;
|
|
m_vTria = stmSrc.m_vTria ;
|
|
m_bClosed = stmSrc.m_bClosed ;
|
|
m_nStatus = stmSrc.m_nStatus ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
SurfTriMesh::GetTitle( void) const
|
|
{
|
|
static const string sTitle = "TriMesh" ;
|
|
return sTitle ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Dump( string& sOut, const char* szNewLine) const
|
|
{
|
|
// se superficie aperta o chiusa
|
|
sOut += ( m_bClosed ? "Closed" : "Open") ;
|
|
// numero di vertici
|
|
sOut += " NbrVert=" + ToString( GetVertexNum()) ;
|
|
// numero di triangoli
|
|
sOut += " NbrTria=" + ToString( GetTriangleNum()) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
SurfTriMesh::GetKey( void) const
|
|
{
|
|
return GEOOBJ_GETKEY( SurfTriMesh) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Save( ostream& osOut) const
|
|
{
|
|
// flag aperta/chiusa
|
|
osOut << ToString( m_bClosed) << ";" ;
|
|
// numero di vertici
|
|
osOut << ToString( GetVertexNum()) << ";" ;
|
|
// numero di triangoli
|
|
osOut << ToString( GetTriangleNum()) << ";" << endl ;
|
|
// ciclo sui vertici
|
|
for ( int i = 0 ; i < int( m_vVert.size()) ; ++ i) {
|
|
osOut << ToString( i) << ";" ;
|
|
osOut << ToString( m_vVert[i].ptP) << ";" ;
|
|
osOut << ToString( m_vVert[i].nIdTria) << ";" ;
|
|
osOut << ToString( m_vVert[i].nFlag) << ";" << endl ;
|
|
}
|
|
// ciclo sui triangoli
|
|
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
|
osOut << ToString( i) << ";" ;
|
|
osOut << ToString( m_vTria[i].nIdVert[0]) << "," ;
|
|
osOut << ToString( m_vTria[i].nIdVert[1]) << "," ;
|
|
osOut << ToString( m_vTria[i].nIdVert[2]) << ";" ;
|
|
osOut << ToString( m_vTria[i].nIdAdjac[0]) << "," ;
|
|
osOut << ToString( m_vTria[i].nIdAdjac[1]) << "," ;
|
|
osOut << ToString( m_vTria[i].nIdAdjac[2]) << ";" ;
|
|
osOut << ToString( m_vTria[i].vtN) << ";" ;
|
|
osOut << ToString( m_vTria[i].nTFlag) << ";" ;
|
|
osOut << ToString( m_vTria[i].nEFlag) << ";" << endl ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Load( Scanner& TheScanner)
|
|
{
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// leggo la prossima linea
|
|
string sLine ;
|
|
if ( ! TheScanner.GetLine( sLine))
|
|
return false ;
|
|
// la divido in parametri
|
|
STRVECTOR vsParams ;
|
|
Tokenize( sLine, ";", vsParams) ;
|
|
// 3 parametri : flag chiuso num vertici e num tria
|
|
if ( vsParams.size() != 3)
|
|
return false ;
|
|
// recupero il flag
|
|
bool bClosed ;
|
|
if ( ! FromString( vsParams[0], bClosed))
|
|
return false ;
|
|
// recupero il numero di vertici
|
|
int nNumVert ;
|
|
if ( ! FromString( vsParams[1], nNumVert))
|
|
return false ;
|
|
// recupero il numero di triangoli
|
|
int nNumTria ;
|
|
if ( ! FromString( vsParams[2], nNumTria))
|
|
return false ;
|
|
// inizializzo la superficie TriMesh
|
|
if ( ! Init( nNumVert, nNumTria))
|
|
return false ;
|
|
m_bClosed = bClosed ;
|
|
// lettura dei vertici
|
|
int nInd ;
|
|
StmVert vV ;
|
|
for ( int i = 0 ; i < nNumVert ; ++ i) {
|
|
// leggo la prossima linea
|
|
if ( ! TheScanner.GetLine( sLine))
|
|
return false ;
|
|
// la divido in parametri
|
|
Tokenize( sLine, ";", vsParams) ;
|
|
// 4 parametri : Indice, Punto, IdTria, Flag
|
|
if ( vsParams.size() != 4)
|
|
return false ;
|
|
// la interpreto e imposto il vertice
|
|
if ( ! FromString( vsParams[0], nInd) ||
|
|
! FromString( vsParams[1], vV.ptP) ||
|
|
! FromString( vsParams[2], vV.nIdTria) ||
|
|
! FromString( vsParams[3], vV.nFlag) ||
|
|
! SetVertex( nInd, vV))
|
|
return false ;
|
|
}
|
|
// lettura dei triangoli
|
|
StmTria tT ;
|
|
for ( int i = 0 ; i < nNumTria ; ++ i) {
|
|
// leggo la prossima linea
|
|
if ( ! TheScanner.GetLine( sLine))
|
|
return false ;
|
|
// la divido in parametri
|
|
Tokenize( sLine, ";", vsParams) ;
|
|
// 6 parametri : Indice, Punto, IdTria, Flag
|
|
if ( vsParams.size() != 6)
|
|
return false ;
|
|
// la interpreto e imposto il vertice
|
|
if ( ! FromString( vsParams[0], nInd) ||
|
|
! FromString( vsParams[1], tT.nIdVert) ||
|
|
! FromString( vsParams[2], tT.nIdAdjac) ||
|
|
! FromString( vsParams[3], tT.vtN) ||
|
|
! FromString( vsParams[4], tT.nTFlag) ||
|
|
! FromString( vsParams[5], tT.nEFlag) ||
|
|
! SetTriangle( nInd, tT))
|
|
return false ;
|
|
}
|
|
// eseguo validazione
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Validate( void)
|
|
{
|
|
if ( m_nStatus == OK)
|
|
return true ;
|
|
|
|
// Verifico che i vertici riferiti dai triangoli esistano
|
|
m_nStatus = OK ;
|
|
for ( int i = 0 ; i < GetTriangleNum() && m_nStatus == OK ; ++ i) {
|
|
// se triangolo non cancellato
|
|
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
|
|
for ( int j = 0 ; j < 3 && m_nStatus == OK ; ++ j) {
|
|
if ( m_vTria[i].nIdVert[j] >= GetVertexNum() ||
|
|
m_vVert[ m_vTria[i].nIdVert[j]].nIdTria == VT_DEL)
|
|
m_nStatus = ERR ;
|
|
}
|
|
// calcolo eventuali normale mancante
|
|
if ( m_vTria[i].vtN.IsSmall())
|
|
CalcTriangleNormal( i) ;
|
|
}
|
|
}
|
|
|
|
// Verifico che i triangoli riferiti dai vertici esistano
|
|
for ( int i = 0 ; i < GetVertexNum() && m_nStatus == OK ; ++ i) {
|
|
// se vertice non cancellato e con riferimento assegnato
|
|
if ( m_vVert[i].nIdTria != VT_DEL && m_vVert[i].nIdTria != VT_NULL) {
|
|
if ( m_vVert[i].nIdTria >= GetTriangleNum() ||
|
|
m_vTria[ m_vVert[i].nIdTria].nIdVert[0] == VT_DEL)
|
|
m_nStatus = ERR ;
|
|
}
|
|
}
|
|
|
|
return ( m_nStatus == OK) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::FindVertexInTria( int nV, int nT, int& nK)
|
|
{
|
|
nK = - 1 ;
|
|
for ( int k = 0 ; k < 3 ; k ++) {
|
|
if ( nV == m_vTria[nT].nIdVert[k]) {
|
|
nK = k ;
|
|
break ;
|
|
}
|
|
}
|
|
return ( nK != -1) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT)
|
|
{
|
|
const int MAX_VT_SIZE = 512 ;
|
|
|
|
// pulisco il vettore risultato
|
|
vT.clear() ;
|
|
|
|
// recupero il triangolo puntato dal vertice
|
|
int nT = m_vVert[nV].nIdTria ;
|
|
if ( nT == VT_NULL)
|
|
return 0 ;
|
|
vT.push_back( nT) ;
|
|
|
|
// cerco i triangoli adiacenti con lo stesso vertice in CCW
|
|
int k ;
|
|
int nTa = nT ;
|
|
do {
|
|
if ( FindVertexInTria( nV, nTa, k))
|
|
nTa = m_vTria[nTa].nIdAdjac[Prev(k)] ;
|
|
else
|
|
nTa = VT_NULL ;
|
|
// per evitare cicli infiniti dovuti a triangoli invertiti
|
|
if ( vT.size() >= 2 && nTa == vT[vT.size()-2])
|
|
break ;
|
|
// se valido
|
|
if ( nTa != nT && nTa != VT_NULL)
|
|
vT.push_back( nTa) ;
|
|
} while ( nTa != nT && nTa != VT_NULL && vT.size() < MAX_VT_SIZE / 2) ;
|
|
|
|
// se sono ritornato al triangolo di partenza ho fatto un giro e concluso la ricerca
|
|
if ( nTa == nT)
|
|
return int( vT.size()) ;
|
|
|
|
// altrimenti, devo cercare i triangoli adiacenti con lo stesso vertice in CW
|
|
nTa = nT ;
|
|
do {
|
|
if ( FindVertexInTria( nV, nTa, k))
|
|
nTa = m_vTria[nTa].nIdAdjac[k] ;
|
|
else
|
|
nTa = VT_NULL ;
|
|
// per evitare cicli infiniti dovuti a triangoli invertiti
|
|
if ( vT.size() >= 2 && nTa == vT[vT.size()-2])
|
|
break ;
|
|
// se valido
|
|
if ( nTa != nT && nTa != VT_NULL)
|
|
vT.insert( vT.begin(), nTa) ;
|
|
} while ( nTa != nT && nTa != VT_NULL && vT.size() < MAX_VT_SIZE) ;
|
|
|
|
return int( vT.size()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::AdjustAdjacencies( void)
|
|
{
|
|
// sistemo i puntatori dai vertici ai triangoli
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
|
|
// se triangolo non cancellato
|
|
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
|
|
for ( int j = 0 ; j < 3 ; ++ j) {
|
|
if ( m_vVert[ m_vTria[i].nIdVert[j]].nIdTria == VT_NULL)
|
|
m_vVert[ m_vTria[i].nIdVert[j]].nIdTria = i ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// sistemo i puntatori tra triangoli
|
|
bool bModif ;
|
|
do {
|
|
bModif = false ;
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
|
|
// se triangolo non cancellato
|
|
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
|
|
for ( int j = 0 ; j < 3 ; ++ j) {
|
|
// se adiacenza non risolta
|
|
if ( m_vTria[i].nIdAdjac[j] == VT_NULL) {
|
|
// vertici all'estremo dello half-edge di indice j
|
|
int nVi = m_vTria[i].nIdVert[j] ;
|
|
int nVf = m_vTria[i].nIdVert[Next(j)] ;
|
|
// indice altro vertice in altro triangolo
|
|
int k ;
|
|
int nN ;
|
|
INTVECTOR vT ;
|
|
// triangoli con il vertice all'inizio dello half-edge
|
|
nN = GetAllTriaAroundVertex( nVi, vT) ;
|
|
for ( int l = 0 ; l < nN ; ++ l) {
|
|
int nTi = vT[l] ;
|
|
if ( nTi != i) {
|
|
// se altro vertice in comune, aggiusto le adiacenze dei due triangoli
|
|
if ( FindVertexInTria( nVf, nTi, k)) {
|
|
m_vTria[i].nIdAdjac[j] = nTi ;
|
|
// se half-hedge con orientazione opposta (come dovrebbe essere)
|
|
// il successivo di k deve coincidere con j
|
|
if ( m_vTria[nTi].nIdVert[Next(k)] == m_vTria[i].nIdVert[j])
|
|
m_vTria[nTi].nIdAdjac[k] = i ;
|
|
else
|
|
m_vTria[nTi].nIdAdjac[Prev(k)] = i ;
|
|
bModif = true ;
|
|
continue ;
|
|
}
|
|
}
|
|
}
|
|
// triangoli con il vertice alla fine dello half-edge
|
|
nN = GetAllTriaAroundVertex( nVf, vT) ;
|
|
for ( int l = 0 ; l < nN ; ++ l) {
|
|
int nTf = vT[l] ;
|
|
if ( nTf != i) {
|
|
// se altro vertice in comune, aggiusto le adiacenze dei due triangoli
|
|
if ( FindVertexInTria( nVi, nTf, k)) {
|
|
m_vTria[i].nIdAdjac[j] = nTf ;
|
|
// se half-hedge con orientazione opposta (come dovrebbe essere)
|
|
// il precedente di k deve coincidere con il successivo j
|
|
if ( m_vTria[nTf].nIdVert[Prev(k)] == m_vTria[i].nIdVert[Next(j)])
|
|
m_vTria[nTf].nIdAdjac[Prev(k)] = i ;
|
|
else
|
|
m_vTria[nTf].nIdAdjac[k] = i ;
|
|
bModif = true ;
|
|
continue ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while ( bModif) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::AdjustOrientations( int nLev, bool& bSomeWrong)
|
|
{
|
|
// inizializzo parametro di ritorno
|
|
bSomeWrong = false ;
|
|
// ciclo sui triangoli
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ 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] == VT_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) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::TestClosure( void)
|
|
{
|
|
// ciclo sui triangoli
|
|
bool bClosed = true ;
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
|
|
if ( m_vTria[i].nIdAdjac[0] == VT_NULL ||
|
|
m_vTria[i].nIdAdjac[1] == VT_NULL ||
|
|
m_vTria[i].nIdAdjac[2] == VT_NULL)
|
|
bClosed = false ;
|
|
}
|
|
// aggiorno la chiusura della superficie
|
|
m_bClosed = bClosed ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::AdjustTopology( void)
|
|
{
|
|
// verifica indici
|
|
if ( ! Validate())
|
|
return false ;
|
|
// verifica adiacenze
|
|
if ( ! AdjustAdjacencies())
|
|
return false ;
|
|
// verifica continuità orientazione
|
|
int nLev = 3 ;
|
|
bool bSomeWrong ;
|
|
do {
|
|
if ( ! AdjustOrientations( nLev, bSomeWrong))
|
|
return false ;
|
|
-- nLev ;
|
|
} while ( bSomeWrong && nLev > 0) ;
|
|
// verifica chiusura
|
|
if ( ! TestClosure())
|
|
return false ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// assegno il box in locale
|
|
b3Loc.Reset() ;
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
|
|
if ( m_vVert[i].nIdTria != VT_DEL)
|
|
b3Loc.Add( m_vVert[i].ptP) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
// assegno il box nel riferimento
|
|
b3Ref.Reset() ;
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
|
|
if ( m_vVert[i].nIdTria != VT_DEL) {
|
|
Point3d ptTemp = m_vVert[i].ptP ;
|
|
ptTemp.ToGlob( frRef) ;
|
|
b3Ref.Add( ptTemp) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Translate( const Vector3d& vtMove)
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// traslo i vertici
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
|
|
if ( m_vVert[i].nIdTria != VT_DEL)
|
|
m_vVert[i].ptP.Translate( vtMove) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// verifico validità dell'asse di rotazione
|
|
if ( vtAx.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// ruoto i vertici
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
|
|
if ( m_vVert[i].nIdTria != VT_DEL)
|
|
m_vVert[i].ptP.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
}
|
|
|
|
// ruoto le normali delle facce
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
|
|
if ( m_vTria[i].nIdVert[0] != VT_DEL)
|
|
m_vTria[i].vtN.Rotate( vtAx, dCosAng, dSinAng) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// verifico non sia nulla
|
|
if ( fabs( dCoeffX) < EPS_ZERO && fabs( dCoeffY) < EPS_ZERO && fabs( dCoeffZ) < EPS_ZERO)
|
|
return false ;
|
|
|
|
// determino se contiene anche un mirror (numero dispari di coefficienti negativi)
|
|
bool bMirror = ( dCoeffX < 0) ;
|
|
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
|
|
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// scalo i vertici
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
|
|
if ( m_vVert[i].nIdTria != VT_DEL)
|
|
m_vVert[i].ptP.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
|
}
|
|
|
|
// aggiorno le facce
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
|
|
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
|
|
// se c'è mirror, devo invertire la faccia
|
|
if ( bMirror && ! InvertTriangle( i))
|
|
return false ;
|
|
// aggiorno la normale
|
|
if ( ! CalcTriangleNormal( i))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::InvertTriangle( int nT)
|
|
{
|
|
// controllo validità triangolo
|
|
if ( m_vTria[nT].nIdVert[0] == VT_DEL)
|
|
return false ;
|
|
// scambio di due vertici
|
|
swap( m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]) ;
|
|
// scambio delle conseguenti due adiacenze
|
|
swap( m_vTria[nT].nIdAdjac[0], m_vTria[nT].nIdAdjac[2]) ;
|
|
// inversione della normale
|
|
m_vTria[nT].vtN *= - 1 ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::CalcTriangleNormal( int nT)
|
|
{
|
|
// controllo validità triangolo
|
|
if ( m_vTria[nT].nIdVert[0] == VT_DEL)
|
|
return false ;
|
|
// controllo validità vertici riferiti dal triangolo
|
|
if ( m_vTria[nT].nIdVert[0] >= GetVertexNum() ||
|
|
m_vVert[m_vTria[nT].nIdVert[0]].nIdTria == VT_DEL ||
|
|
m_vTria[nT].nIdVert[1] >= GetVertexNum() ||
|
|
m_vVert[m_vTria[nT].nIdVert[1]].nIdTria == VT_DEL ||
|
|
m_vTria[nT].nIdVert[2] >= GetVertexNum() ||
|
|
m_vVert[m_vTria[nT].nIdVert[2]].nIdTria == VT_DEL)
|
|
return false ;
|
|
// calcolo vettori come due lati consecutivi del triangolo
|
|
Vector3d vtV1 = m_vVert[m_vTria[nT].nIdVert[1]].ptP - m_vVert[m_vTria[nT].nIdVert[0]].ptP ;
|
|
Vector3d vtV2 = m_vVert[m_vTria[nT].nIdVert[2]].ptP - m_vVert[m_vTria[nT].nIdVert[1]].ptP ;
|
|
Vector3d vtN = vtV1 ^ vtV2 ;
|
|
// normale da prodotto vettoriale
|
|
if ( ! vtN.Normalize())
|
|
return false ;
|
|
m_vTria[nT].vtN = vtN ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// verifico validità del piano di specchiatura
|
|
if ( vtNorm.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// specchio i vertici
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i)
|
|
m_vVert[i].ptP.Mirror( ptOn, vtNorm) ;
|
|
|
|
// inverto le facce
|
|
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
|
|
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
|
|
// inverto la faccia
|
|
if ( ! InvertTriangle( i))
|
|
return false ;
|
|
// aggiorno la normale
|
|
if ( ! CalcTriangleNormal( i))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::ToGlob( const Frame3d& frRef)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// trasformo i vertici
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i)
|
|
m_vVert[i].ptP.ToGlob( frRef) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::ToLoc( const Frame3d& frRef)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// trasformo i vertici
|
|
for ( int i = 0 ; i < GetVertexNum() ; ++ i)
|
|
m_vVert[i].ptP.ToLoc( frRef) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|