6c14e51ef6
- aggiunte funzioni per circonferenze e archi tangenti.
535 lines
20 KiB
C++
535 lines
20 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2015
|
|
//----------------------------------------------------------------------------
|
|
// File : SurfTriMeshFaceting.cpp Data : 25.02.15 Versione : 1.6b
|
|
// Contenuto : Implementazione della classe Superfici TriMesh.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 26.03.14 DS Creazione modulo.
|
|
// 15.05.14 DS Corr. errore CreateByTwoCurves che dava loop infinito.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "SurfTriMesh.h"
|
|
#include "GeoConst.h"
|
|
#include "PolygonPlane.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::ResetFaceting( void)
|
|
{
|
|
m_bFaceted = false ;
|
|
m_vFacet.clear() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::VerifyFaceting( void) const
|
|
{
|
|
if ( m_bFaceted)
|
|
return true ;
|
|
return (const_cast<SurfTriMesh*>(this))->UpdateFaceting() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::UpdateFaceting( void)
|
|
{
|
|
// reset faceting
|
|
m_bFaceted = false ;
|
|
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i)
|
|
m_vTria[i].nIdFacet = SVT_NULL ;
|
|
|
|
// ricostruisco le sfaccettature
|
|
int nFacet = 0 ;
|
|
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
|
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
|
m_vTria[i].nIdFacet == SVT_NULL) {
|
|
// assegno indice di faccia al triangolo
|
|
m_vTria[i].nIdFacet = nFacet ;
|
|
m_vFacet.push_back( i) ;
|
|
++ nFacet ;
|
|
// piano del triangolo
|
|
Plane3d plPlane ;
|
|
if ( ! SetPlane( m_vVert[m_vTria[i].nIdVert[0]].ptP, m_vTria[i].vtN, plPlane))
|
|
return false ;
|
|
// aggiorno i triangoli adiacenti
|
|
for ( int j = 0 ; j < 3 ; ++ j) {
|
|
int nAdjT = m_vTria[i].nIdAdjac[j] ;
|
|
if ( nAdjT != SVT_NULL &&
|
|
m_vTria[nAdjT].nIdFacet == SVT_NULL) {
|
|
if ( ! UpdateTriaFaceting( i, m_vTria[i].nIdFacet, plPlane, nAdjT))
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// calcolo facce piane riuscito
|
|
m_bFaceted = true ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT)
|
|
{
|
|
// verifica scostamento della normale da quella del piano
|
|
if ( plPlane.vtN * m_vTria[nT].vtN < m_dCosBndAng)
|
|
return true ;
|
|
// verifica scostamento del vertice opposto al lato in comune dal piano
|
|
int nV = SVT_NULL ;
|
|
for ( int i = 0 ; i < 3 ; ++i) {
|
|
if ( m_vTria[nT].nIdAdjac[i] == nRefT) {
|
|
nV = Prev( i) ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( nV == SVT_NULL)
|
|
return false ;
|
|
if ( ! PointInPlaneApprox( m_vVert[m_vTria[nT].nIdVert[nV]].ptP, plPlane))
|
|
return true ;
|
|
// il triangolo fa parte della faccia
|
|
m_vTria[nT].nIdFacet = nFacet ;
|
|
// 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].nIdFacet == SVT_NULL) {
|
|
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
|
|
return false ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetFacetNum( void) const
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return 0 ;
|
|
// verifico stato sfaccettatura
|
|
if ( ! VerifyFaceting())
|
|
return 0 ;
|
|
// restituisco il numero
|
|
return int( m_vFacet.size()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::SetFacet( int nInd, int nT)
|
|
{
|
|
// recupero la dimensione originale
|
|
int nPrevSize = int( m_vFacet.size()) ;
|
|
// determino la dimensione necessaria
|
|
int nNewSize = max( nInd + 1, nPrevSize) ;
|
|
// se necessaria dimensione maggiore
|
|
if ( nNewSize > nPrevSize) {
|
|
// espando vettore
|
|
try { m_vFacet.resize( nNewSize) ; }
|
|
catch (...) { return false ; }
|
|
// inizializzo a cancellate le eventuali facce intermedie
|
|
if ( ( nNewSize - nPrevSize) > 1) {
|
|
for ( int i = nPrevSize ; i < nNewSize ; ++ i)
|
|
m_vFacet[i] = SVT_DEL ;
|
|
}
|
|
}
|
|
// inserisco la faccia
|
|
m_vFacet[nInd] = nT ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SurfTriMesh::GetFacetFromTria( int nT) const
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return SVT_NULL ;
|
|
// verifico stato sfaccettatura
|
|
if ( ! VerifyFaceting())
|
|
return SVT_NULL ;
|
|
// l'indice del triangolo deve essere nei limiti
|
|
if ( nT < 0 || nT >= int( m_vTria.size()) || m_vTria[nT].nIdVert[0] == SVT_DEL)
|
|
return SVT_NULL ;
|
|
// restituisco l'indice di faccia
|
|
return m_vTria[nT].nIdFacet ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetAllTriaInFacet( int nF, INTVECTOR& vT) const
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico stato sfaccettatura
|
|
if ( ! VerifyFaceting())
|
|
return false ;
|
|
// l'indice della faccia deve essere nei limiti
|
|
if ( nF < 0 || nF >= int( m_vFacet.size()))
|
|
return false ;
|
|
// recupero l'indice del primo triangolo della faccia
|
|
int nT = m_vFacet[nF] ;
|
|
// incremento time stamp
|
|
++ m_nTimeStamp ;
|
|
// recupero i triangoli della faccia
|
|
vT.clear() ;
|
|
vT.reserve( 10) ;
|
|
vT.push_back( nT) ;
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
return VerifyAdjacTriaFacet( nT, vT) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const
|
|
{
|
|
// verifico i triangoli adiacenti
|
|
for ( int j = 0 ; j < 3 ; ++ j) {
|
|
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
|
if ( nAdjT != SVT_NULL &&
|
|
m_vTria[nAdjT].nTemp != m_nTimeStamp &&
|
|
m_vTria[nAdjT].nIdFacet == m_vTria[nT].nIdFacet) {
|
|
vT.push_back( nAdjT) ;
|
|
m_vTria[nAdjT].nTemp = m_nTimeStamp ;
|
|
if ( ! VerifyAdjacTriaFacet( nAdjT, vT))
|
|
return false ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const
|
|
{
|
|
// recupero l'elenco dei triangoli della faccia
|
|
INTVECTOR vTria ;
|
|
if ( ! GetAllTriaInFacet( nF, vTria))
|
|
return false ;
|
|
// ciclo sui triangoli e sui loro lati di bordo
|
|
bool bFound = false ;
|
|
double dMinSqDist = INFINITO * INFINITO ;
|
|
for ( int i = 0 ; i < int( vTria.size()) ; ++i) {
|
|
int nT = vTria[i] ;
|
|
for ( int j = 0 ; j < 3 ; ++ j) {
|
|
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
|
if ( nAdjT == SVT_NULL ||
|
|
m_vTria[nAdjT].nIdFacet != nF) {
|
|
Point3d ptTest = m_vVert[m_vTria[nT].nIdVert[j]].ptP ;
|
|
double dSqDist = SqDist( ptTest, ptNear) ;
|
|
if ( dSqDist < dMinSqDist) {
|
|
// salvo i dati del punto
|
|
dMinSqDist = dSqDist ;
|
|
ptEnd = ptTest ;
|
|
bFound = true ;
|
|
// recupero la normale della faccia (non quella mediata del vertice)
|
|
vtN = m_vTria[nT].vtN ;
|
|
//Vector3d vtN1, vtN2 ;
|
|
//if ( ! GetTriangleSmoothNormal( nT, j, vtN))
|
|
// vtN = m_vTria[nT].vtN ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bFound ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetFacetNearestMidPoint( int nF, const Point3d& ptNear, Point3d& ptMid, Vector3d& vtN) const
|
|
{
|
|
// recupero l'elenco dei triangoli della faccia
|
|
INTVECTOR vTria ;
|
|
if ( ! GetAllTriaInFacet( nF, vTria))
|
|
return false ;
|
|
// ciclo sui triangoli e sui loro lati di bordo
|
|
bool bFound = false ;
|
|
double dMinSqDist = INFINITO * INFINITO ;
|
|
for ( int i = 0 ; i < int( vTria.size()) ; ++i) {
|
|
int nT = vTria[i] ;
|
|
for ( int j = 0 ; j < 3 ; ++ j) {
|
|
int k = Next( j) ;
|
|
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
|
if ( nAdjT == SVT_NULL ||
|
|
m_vTria[nAdjT].nIdFacet != nF) {
|
|
Point3d ptTest = Media( m_vVert[m_vTria[nT].nIdVert[j]].ptP,
|
|
m_vVert[m_vTria[nT].nIdVert[k]].ptP, 0.5) ;
|
|
double dSqDist = SqDist( ptTest, ptNear) ;
|
|
if ( dSqDist < dMinSqDist) {
|
|
// salvo i dati del punto
|
|
dMinSqDist = dSqDist ;
|
|
ptMid = ptTest ;
|
|
bFound = true ;
|
|
// recupero la normale della faccia (non quella mediata del vertice)
|
|
vtN = m_vTria[nT].vtN ;
|
|
//Vector3d vtN1, vtN2 ;
|
|
//if ( GetTriangleSmoothNormal( nT, j, vtN1) &&
|
|
// GetTriangleSmoothNormal( nT, k, vtN2)) {
|
|
// vtN = Media( vtN1, vtN2, 0.5) ;
|
|
// vtN.Normalize() ;
|
|
//}
|
|
//else
|
|
// vtN = m_vTria[nT].vtN ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bFound ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
|
{
|
|
// recupero l'elenco dei triangoli della faccia
|
|
INTVECTOR vTria ;
|
|
if ( ! GetAllTriaInFacet( nF, vTria))
|
|
return false ;
|
|
// incremento time stamp
|
|
++ m_nTimeStamp ;
|
|
// ciclo sui triangoli
|
|
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) {
|
|
int nT = vTria[i] ;
|
|
// se triangolo non ancora visitato
|
|
if ( m_vTria[nT].nTemp != m_nTimeStamp) {
|
|
// determino i triangoli adiacenti
|
|
int nAdjT[3] ;
|
|
for ( int j = 0 ; j < 3 ; ++ j)
|
|
nAdjT[j] = m_vTria[nT].nIdAdjac[j] ;
|
|
// se tutti e tre i lati sono di contorno
|
|
if ( ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF) &&
|
|
( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF) &&
|
|
( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF)) {
|
|
// ho trovato un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
}
|
|
// se i due lati 0 e 1 sono di contorno
|
|
else if ( ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF) &&
|
|
( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF)) {
|
|
// ho trovato l'inizio di un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
// cammino lungo il loop fino a chiuderlo
|
|
if ( ! MarchAlongLoop( nF, nT, 2, m_nTimeStamp, vPL.back()))
|
|
return false ;
|
|
}
|
|
// se i due lati 1 e 2 sono di contorno
|
|
else if ( ( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF) &&
|
|
( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF)) {
|
|
// ho trovato l'inizio di un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
// cammino lungo il loop fino a chiuderlo
|
|
if ( ! MarchAlongLoop( nF, nT, 0, m_nTimeStamp, vPL.back()))
|
|
return false ;
|
|
}
|
|
// se i due lati 2 e 0 sono di contorno
|
|
else if ( ( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF) &&
|
|
( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF)) {
|
|
// ho trovato l'inizio di un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
// cammino lungo il loop fino a chiuderlo
|
|
if ( ! MarchAlongLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
|
|
return false ;
|
|
}
|
|
// se il lato 0 è di contorno
|
|
else if ( nAdjT[0] == SVT_NULL || m_vTria[nAdjT[0]].nIdFacet != nF) {
|
|
// ho trovato l'inizio di un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
// cammino lungo il loop fino a chiuderlo
|
|
if ( ! MarchAlongLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
|
|
return false ;
|
|
}
|
|
// se il lato 1 è di contorno
|
|
else if ( nAdjT[1] == SVT_NULL || m_vTria[nAdjT[1]].nIdFacet != nF) {
|
|
// ho trovato l'inizio di un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
// cammino lungo il loop fino a chiuderlo
|
|
if ( ! MarchAlongLoop( nF, nT, 2, m_nTimeStamp, vPL.back()))
|
|
return false ;
|
|
}
|
|
// se il lato 2 è di contorno
|
|
else if ( nAdjT[2] == SVT_NULL || m_vTria[nAdjT[2]].nIdFacet != nF) {
|
|
// ho trovato l'inizio di un loop
|
|
vPL.emplace_back() ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
|
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
// cammino lungo il loop fino a chiuderlo
|
|
if ( ! MarchAlongLoop( nF, nT, 0, m_nTimeStamp, vPL.back()))
|
|
return false ;
|
|
}
|
|
// altrimenti non c'è contorno
|
|
else {
|
|
// marco il triangolo come verificato
|
|
m_vTria[nT].nTemp = m_nTimeStamp ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// normale di riferimento della faccia
|
|
Vector3d vtN = m_vTria[vTria[0]].vtN ;
|
|
// in prima posizione ci deve essere il loop esterno
|
|
bool bOutFirst = false ;
|
|
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
|
Plane3d plPlane ;
|
|
double dArea ;
|
|
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
|
return false ;
|
|
// se loop esterno
|
|
if ( vtN * plPlane.vtN > 0) {
|
|
// se non c'è ancora loop esterno in prima posizione
|
|
if ( ! bOutFirst) {
|
|
// lo sposto in prima posizione
|
|
if ( i != 0)
|
|
swap( vPL[0], vPL[i]) ;
|
|
bOutFirst = true ;
|
|
}
|
|
// altrimenti errore
|
|
else
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return bOutFirst ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::MarchAlongLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& PL) const
|
|
{
|
|
// mi muovo lungo il loop, un triangolo alla volta
|
|
bool bEnd = false ;
|
|
while ( ! bEnd) {
|
|
if ( ! MarchOneTria( nF, nT, nV, nTimeStamp, PL, bEnd))
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::MarchOneTria( int nF, int& nT, int& nV, int nTimeStamp,
|
|
PolyLine& PL, bool& bEnd) const
|
|
{
|
|
// verifico esistenza triangolo adiacente, sul lato dopo il vertice
|
|
if ( m_vTria[nT].nIdAdjac[nV] == SVT_NULL)
|
|
return false ;
|
|
int nAdjT = m_vTria[nT].nIdAdjac[nV] ;
|
|
// verifico appartenga alla stessa faccia
|
|
if ( m_vTria[nAdjT].nIdFacet != nF)
|
|
return false ;
|
|
// recupero il suo lato di adiacenza
|
|
int nAdjS = SVT_NULL ;
|
|
for ( int i = 0 ; i < 3 ; ++ i) {
|
|
if ( m_vTria[nAdjT].nIdAdjac[i] == nT) {
|
|
nAdjS = i ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( nAdjS == SVT_NULL)
|
|
return false ;
|
|
// vertice di fine adiacenza e indice del successivo lato
|
|
int nAdjV = Next( nAdjS) ;
|
|
// verifico se il lato successivo è un bordo
|
|
int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
|
|
if ( nNextT == SVT_NULL || m_vTria[nNextT].nIdFacet != nF) {
|
|
// se già recuperato
|
|
if ( m_vTria[nAdjT].nTemp == nTimeStamp) {
|
|
bEnd = true ;
|
|
return true ;
|
|
}
|
|
// dichiaro triangolo analizzato
|
|
m_vTria[nAdjT].nTemp = nTimeStamp ;
|
|
// aggiungo il lato al loop
|
|
nAdjV = Next( nAdjV) ;
|
|
PL.AddUPoint( nAdjT, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ;
|
|
// verifico anche il successivo
|
|
nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
|
|
if ( nNextT == SVT_NULL || m_vTria[nNextT].nIdFacet != nF) {
|
|
// aggiungo il lato al loop
|
|
nAdjV = Next( nAdjV) ;
|
|
PL.AddUPoint( nAdjT, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ;
|
|
}
|
|
}
|
|
// devo passare al triangolo adiacente
|
|
nT = nAdjT ;
|
|
nV = nAdjV ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
|
|
{
|
|
// recupero i loop della faccia
|
|
POLYLINEVECTOR vPL ;
|
|
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
|
|
return false ;
|
|
// calcolo il centro del loop esterno (è il primo)
|
|
PolygonPlane PolyPlane ;
|
|
Point3d ptP ;
|
|
for ( bool bFound = vPL[0].GetFirstPoint( ptP) ; bFound ; bFound = vPL[0].GetNextPoint( ptP))
|
|
PolyPlane.AddPoint( ptP) ;
|
|
if ( ! PolyPlane.GetCentroid( ptCen))
|
|
return false ;
|
|
// recupero la normale di un triangolo della faccetta
|
|
vtN = m_vTria[m_vFacet[nF]].vtN ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GetFacetNormal( int nF, Vector3d& vtN) const
|
|
{
|
|
// la superficie deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico stato sfaccettatura
|
|
if ( ! VerifyFaceting())
|
|
return false ;
|
|
// l'indice della faccia deve essere nei limiti
|
|
if ( nF < 0 || nF >= int( m_vFacet.size()))
|
|
return false ;
|
|
// recupero la normale di un triangolo della faccetta
|
|
vtN = m_vTria[m_vFacet[nF]].vtN ;
|
|
return true ;
|
|
} |