EgtGeomKernel 2.1k4 :

- correzioni alle operazioni booleane tra superfici trimesh.
This commit is contained in:
Dario Sassi
2019-11-18 09:17:05 +00:00
parent 970b901895
commit ffad8c6dd2
3 changed files with 772 additions and 33 deletions
+746 -31
View File
@@ -28,7 +28,6 @@
#include "/EgtDev/Include/EGkGeoCollection.h"
#include "/EgtDev/Include/EGkPolygon3d.h"
#include <algorithm>
#include <set>
using namespace std ;
@@ -64,7 +63,7 @@ IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3
if ( FromSpecialToNormal( nIntTypeB) == ITTT_PNT || FromSpecialToNormal( nIntTypeB) == ITTT_VERT)
nIntB = 1 ;
else if ( FromSpecialToNormal( nIntTypeB) == ITTT_YES || FromSpecialToNormal( nIntTypeB) == ITTT_EDGE) {
nIntB = 2 ;
nIntB = 2 ;
}
// Unisco le due intersezioni
int nIntTot = nIntA + nIntB ;
@@ -544,7 +543,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
vector<PNTVECTOR> cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back(cvFirstLoop);
vector<bool> vbInOut ;
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop di partenza in sotto-loop
while ( cvOpenChain.size() > 0) {
@@ -742,10 +741,12 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
//----------------------------------------------------------------------------
bool
SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, vector<PNTVECTOR>& cvBoundClosedLoopVec, vector<bool>& vbInOut)
SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, vector<PNTVECTOR>& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut)
{
// Divido il loop di partenza in sotto-loop
while ( cvOpenChain.size() > 0) {
// Divido il loop di partenza in sotto-loop
int nIterationCount = 0 ;
while ( cvOpenChain.size() > 0) {
bool bLoopSplitted = false ;
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
if ( vnDegVec[nLastOpenLoopN] == 1) {
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
@@ -757,7 +758,8 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, vecto
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted))
continue ;
continue ;
bLoopSplitted = true ;
Chain cvCounterChain ;
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
IntSegment CurSeg ;
@@ -892,11 +894,32 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, vecto
bool bC21 = ( ( ptM21 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC21 ;
}
}
bLoopSplitted = true ;
}
}
}
if ( ! bLoopSplitted) {
int nCurDeg = vnDegVec[nLastOpenLoopN] ;
vnDegVec.emplace( vnDegVec.begin(), nCurDeg) ;
Chain CurChain ;
for ( int nCrChSeg = 0 ; nCrChSeg < int( cvOpenChain[nLastOpenLoopN].size()) ; ++ nCrChSeg) {
IntSegment CurChainSeg ;
CurChainSeg.ptSt = cvOpenChain[nLastOpenLoopN][nCrChSeg].ptSt ;
CurChainSeg.ptEn = cvOpenChain[nLastOpenLoopN][nCrChSeg].ptEn ;
CurChainSeg.vtOuter = cvOpenChain[nLastOpenLoopN][nCrChSeg].vtOuter ;
CurChainSeg.bDegenerate = cvOpenChain[nLastOpenLoopN][nCrChSeg].bDegenerate ;
CurChain.emplace_back( CurChainSeg) ;
}
cvOpenChain.emplace( cvOpenChain.begin(), CurChain) ;
++ nLastOpenLoopN ;
++ nIterationCount ;
}
else
nIterationCount = 0 ;
vnDegVec.resize( nLastOpenLoopN) ;
cvOpenChain.resize( nLastOpenLoopN) ;
if ( nIterationCount > int( cvOpenChain.size()) + 2)
return false ;
}
return true ;
}
@@ -911,8 +934,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( m_nStatus != OK || ! SurfB.IsValid())
return false ;
// Unordered map dei segmenti di intersezione
unordered_map <int, Chain> LineMapA ;
unordered_map <int, Chain> LineMapB ;
std::unordered_map <int, Chain> LineMapA ;
std::unordered_map <int, Chain> LineMapB ;
// Unordered map dei triangoli ambigui (intersezione edge-edge)
std::unordered_map <int, std::vector <Triangle3d>> AmbiguosA ;
std::unordered_map <int, std::vector <Triangle3d>> AmbiguosB ;
// Ciclo sui triangoli delle mesh
int nTriaNumA = GetTriangleSize() ;
int nTriaNumB = SurfB.GetTriangleSize() ;
@@ -925,7 +951,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Se il triangolo A non è valido, continuo
Triangle3d trTriaA ;
if ( ! ( GetTriangle( nTA, trTriaA) && trTriaA.Validate( true)))
continue ;
continue ;
// Box del triangolo A
BBox3d b3dTriaA ;
trTriaA.GetLocalBBox( b3dTriaA) ;
@@ -934,7 +960,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Se il triangolo B non è valido, continuo
Triangle3d trTriaB ;
if ( ! ( SurfB.GetTriangle( nTB, trTriaB) && trTriaB.Validate( true)))
continue ;
continue ;
// Box del triangolo B
BBox3d b3dTriaB ;
trTriaB.GetLocalBBox( b3dTriaB) ;
@@ -999,7 +1025,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
else
bIntOnEndgeB = true ;
// Intersezione edge-interno
if ( bIntOnEndgeA && ! bIntOnEndgeB) {
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
@@ -1014,6 +1040,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
m_vTria[nTA].nTempPart = ( ( trTriaA.GetP( nSegMaxDist) - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL ? 1 : - 1) ;
}
}
// Intersezione interno-edge
else if ( ! bIntOnEndgeA && bIntOnEndgeB) {
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
@@ -1028,6 +1055,27 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
SurfB.m_vTria[nTB].nTempPart = ( ( trTriaB.GetP( nSegMaxDist) - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL ? 1 : - 1) ;
}
}
// Intersezione edge-edge
else if ( bIntOnEndgeA && bIntOnEndgeB) {
auto itA = AmbiguosA.find( nTA) ;
if ( itA == AmbiguosA.end()) {
std::vector <Triangle3d> vVecTriaB ;
vVecTriaB.emplace_back( trTriaB) ;
AmbiguosA.emplace( nTA, vVecTriaB) ;
}
else {
itA->second.emplace_back( trTriaB) ;
}
auto itB = AmbiguosB.find( nTB) ;
if ( itB == AmbiguosB.end()) {
std::vector <Triangle3d> vVecTriaA ;
vVecTriaA.emplace_back( trTriaA) ;
AmbiguosB.emplace( nTB, vVecTriaA) ;
}
else {
itB->second.emplace_back( trTriaA) ;
}
}
}
else {
;
@@ -1035,7 +1083,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
}
// Ritriangolarizzo i triangoli della superficie A
for ( auto it = LineMapA.begin() ; it != LineMapA.end() ; ++ it) {
for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) {
@@ -1052,6 +1100,14 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
if ( int( it->second.size()) == 0)
continue ;
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
else {
auto itA = AmbiguosA.find( it->first) ;
if ( itA != AmbiguosA.end()) {
AmbiguosA.erase( itA) ;
}
}
// Recupero il triangolo
Triangle3d trTriaA ;
@@ -1150,8 +1206,33 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else
vnDegVec.emplace_back( 1) ;
}
}
}
for ( int nCh1 = 0 ; nCh1 < int( cvOpenChain.size()) - 1 ; ++ nCh1) {
for ( int nCh2 = nCh1 + 1 ; nCh2 < int( cvOpenChain.size()) ; ++ nCh2) {
int nChainSize1 = int( cvOpenChain[nCh1].size()) ;
int nChainSize2 = int( cvOpenChain[nCh2].size()) ;
int nSameSeg = 0 ;
for ( int nSeg1 = 0 ; nSeg1 < nChainSize1 ; ++ nSeg1) {
for ( int nSeg2 = 0 ; nSeg2 < nChainSize2 ; ++ nSeg2) {
if ( AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt) &&
AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn) &&
AreSameVectorExact( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter)) {
++ nSameSeg ;
}
}
}
if ( nChainSize1 == nSameSeg) {
cvOpenChain.erase( cvOpenChain.begin() + nCh1) ;
vnDegVec.erase( vnDegVec.begin() + nCh1) ;
-- nCh1 ;
}
else if ( nChainSize2 == nSameSeg) {
cvOpenChain.erase( cvOpenChain.begin() + nCh2) ;
vnDegVec.erase( vnDegVec.begin() + nCh2) ;
-- nCh2 ;
}
}
}
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
@@ -1160,14 +1241,14 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
cvFirstLoop.emplace_back( trTriaA.GetP( 0)) ;
cvFirstLoop.emplace_back( trTriaA.GetP( 1)) ;
cvFirstLoop.emplace_back( trTriaA.GetP( 2)) ;
vector<PNTVECTOR> cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
vector<bool> vbInOut ;
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop usando le catene
DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ;
// Divido il loop usando le catene
bool bDecomposed = DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ;
// Rimuovo il triangolo corrente
RemoveTriangle( it->first) ;
// Trasformo i loop compositi in loop polyline
@@ -1412,8 +1493,17 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
}
if ( int( it->second.size()) == 0)
continue ;
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
else {
auto itB = AmbiguosB.find( it->first) ;
if ( itB != AmbiguosB.end()) {
AmbiguosB.erase( itB) ;
}
}
// Recupero il triangolo
Triangle3d trTriaB ;
@@ -1513,6 +1603,31 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
vnDegVec.emplace_back( 1) ;
}
}
for ( int nCh1 = 0 ; nCh1 < int( cvOpenChain.size()) - 1 ; ++ nCh1) {
for ( int nCh2 = nCh1 + 1 ; nCh2 < int( cvOpenChain.size()) ; ++ nCh2) {
int nChainSize1 = int( cvOpenChain[nCh1].size()) ;
int nChainSize2 = int( cvOpenChain[nCh2].size()) ;
int nSameSeg = 0 ;
for ( int nSeg1 = 0 ; nSeg1 < nChainSize1 ; ++ nSeg1) {
for ( int nSeg2 = 0 ; nSeg2 < nChainSize2 ; ++ nSeg2) {
if ( AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt) &&
AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn) &&
AreSameVectorExact( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter)) {
++ nSameSeg ;
}
}
}
if ( nChainSize1 == nSameSeg) {
cvOpenChain.erase( cvOpenChain.begin() + nCh1) ;
vnDegVec.erase( vnDegVec.begin() + nCh1) ;
}
else if ( nChainSize2 == nSameSeg) {
cvOpenChain.erase( cvOpenChain.begin() + nCh2) ;
vnDegVec.erase( vnDegVec.begin() + nCh2) ;
}
}
}
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
@@ -1525,10 +1640,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
vector<PNTVECTOR> cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
vector<bool> vbInOut ;
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop usando le catene
DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ;
bool bDecomposed = DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ;
// Rimuovo il triangolo corrente
SurfB.RemoveTriangle( it->first) ;
// Trasformo i loop compositi in loop polyline
@@ -1761,9 +1876,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
vInnerLoop.resize( 0) ;
}
}
// Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra.
bool bRetriangulated = true ;
if ( ! bModif) {
bRetriangulated = false ;
int nVertNum = 0 ;
Point3d ptFirstV ;
int nCurVert = GetFirstVertex( ptFirstV) ;
@@ -1843,12 +1960,67 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
SurfB.m_vTria[nTB].nTempPart = nInOutNum ;
}
}
// Se c'è stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori.
// Studio i triangoli ambigui.
if ( bRetriangulated) {
for ( auto it = AmbiguosA.begin() ; it != AmbiguosA.end() ; ++ it) {
Triangle3d trTriaA ;
GetTriangle( it->first, trTriaA) ;
trTriaA.Validate() ;
Point3d ptBarA = ( trTriaA.GetP( 0) + trTriaA.GetP( 1) + trTriaA.GetP( 2)) / 3 ;
double dMinDist = DBL_MAX ;
int nTriaIndex = - 1 ;
for ( int nTB = 0 ; nTB < int( it->second.size()) ; ++ nTB) {
Triangle3d trTriaB = it->second[nTB] ;
double dDot = ( ptBarA - trTriaB.GetP( 0)) * trTriaB.GetN() ;
if ( abs( dDot) > EPS_SMALL) {
DistPointTriangle DistCalc( ptBarA, trTriaB) ;
double dDist ;
DistCalc.GetDist( dDist) ;
if ( dDist < dMinDist) {
nTriaIndex = nTB ;
dMinDist = dDist ;
}
}
}
if ( nTriaIndex != - 1) {
Triangle3d trTriaB = it->second[nTriaIndex] ;
trTriaB.Validate() ;
double dDot = ( ptBarA - trTriaB.GetP( 0)) * trTriaB.GetN() ;
m_vTria[it->first].nTempPart = ( dDot < 0 ? 1 : - 1) ;
}
}
for ( auto it = AmbiguosB.begin() ; it != AmbiguosB.end() ; ++ it) {
Triangle3d trTriaB ;
SurfB.GetTriangle( it->first, trTriaB) ;
Point3d ptBarB = ( trTriaB.GetP( 0) + trTriaB.GetP( 1) + trTriaB.GetP( 2)) / 3 ;
double dMinDist = DBL_MAX ;
int nTriaIndex = - 1 ;
for ( int nTA = 0 ; nTA < int( it->second.size()) ; ++ nTA) {
Triangle3d trTriaA = it->second[nTA] ;
double dDot = ( ptBarB - trTriaA.GetP( 0)) * trTriaA.GetN() ;
if ( abs(dDot) > EPS_SMALL) {
DistPointTriangle DistCalc( ptBarB, trTriaA);
double dDist ;
DistCalc.GetDist( dDist) ;
if ( dDist < dMinDist) {
nTriaIndex = nTA ;
dMinDist = dDist ;
}
}
}
if ( nTriaIndex != - 1) {
Triangle3d trTriaA = it->second[nTriaIndex] ;
double dDot = ( ptBarB - trTriaA.GetP( 0)) * trTriaA.GetN() ;
SurfB.m_vTria[it->first].nTempPart = ( dDot < 0 ? 1 : -1) ;
}
}
}
bool bContinue = true ;
// Se avvenuta modifica, aggiorno tutto
if ( bModif)
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
// Triangoli sovrapposti
if ( bContinue) {
int nTriaNumA = GetTriangleSize() ;
@@ -1879,8 +2051,6 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ;
if ( nIntTypeAB == ITTTS_OVERLAPS) {
bool bInvertB = trTriaA.GetN() * trTriaB.GetN() < 0. ;
//m_vTria[nTA].nTempPart = ( m_vTria[nTA].nTempPart == 1 ? ( bInvertB ? -2 : 2) : m_vTria[nTA].nTempPart) ;
//SurfB.m_vTria[nTB].nTempPart = ( SurfB.m_vTria[nTB].nTempPart == 1 ? ( bInvertB ? - 2 : 2) : SurfB.m_vTria[nTB].nTempPart) ;
m_vTria[nTA].nTempPart = ( bInvertB ? -2 : 2) ;
SurfB.m_vTria[nTB].nTempPart = ( bInvertB ? - 2 : 2) ;
}
@@ -1923,6 +2093,464 @@ SurfTriMesh::IdentifyParts( void) const
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemoveTJunction( void)
{
// Verifico lo stato
if ( m_nStatus != OK)
return false ;
// Aggiorno timestamp dei triangoli
++ m_nTimeStamp ;
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
// Incremento time stamp
++ m_nTimeStamp ;
// Vettore di loop di T-Junction
TJuncLoopVec TJLVec ;
// Ciclo sui triangoli
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
// Se triangolo valido e non ancora visitato
if ( m_vTria[nT].nIdVert[0] != SVT_DEL && 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] ;
// Tre lati di contorno
if ( nAdjT[0] == SVT_NULL && nAdjT[1] == SVT_NULL && nAdjT[2] == SVT_NULL) {
m_vTria[nT].nTemp = m_nTimeStamp ;
}
// Lati 0 e 1 di contorno
else if ( nAdjT[0] == SVT_NULL && nAdjT[1] == SVT_NULL) {
// Ho trovato l'inizio di un loop
TJLVec.emplace_back() ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 0 ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 1 ;
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// Cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongFacetLoopForTJunc( nT, 2, m_nTimeStamp, TJLVec.back()))
return false ;
}
// Lati 1 e 2 di contorno
else if ( nAdjT[1] == SVT_NULL && nAdjT[2] == SVT_NULL) {
// Ho trovato l'inizio di un loop
TJLVec.emplace_back() ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 1 ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 2 ;
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// Cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongFacetLoopForTJunc( nT, 0, m_nTimeStamp, TJLVec.back()))
return false ;
}
// Lati 2 e 0 di contorno
else if ( nAdjT[2] == SVT_NULL && nAdjT[0] == SVT_NULL) {
// Ho trovato l'inizio di un loop
TJLVec.emplace_back() ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 2 ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 0 ;
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// Cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongFacetLoopForTJunc( nT, 1, m_nTimeStamp, TJLVec.back()))
return false ;
}
//Lato 0 di contorno
else if ( nAdjT[0] == SVT_NULL) {
// Ho trovato l'inizio di un loop
TJLVec.emplace_back() ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 0 ;
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// Cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongFacetLoopForTJunc( nT, 1, m_nTimeStamp, TJLVec.back()))
return false ;
}
// Lato 1 di contorno
else if ( nAdjT[1] == SVT_NULL) {
// Ho trovato l'inizio di un loop
TJLVec.emplace_back() ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 1 ;
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// Cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongFacetLoopForTJunc( nT, 2, m_nTimeStamp, TJLVec.back()))
return false ;
}
// Lato 2 di contorno
else if ( nAdjT[2] == SVT_NULL) {
// Ho trovato l'inizio di un loop
TJLVec.emplace_back() ;
TJLVec.back().emplace_back() ;
TJLVec.back().back().nTriaId = nT ;
TJLVec.back().back().nEdge = 2 ;
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// Cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongFacetLoopForTJunc( nT, 0, m_nTimeStamp, TJLVec.back()))
return false ;
}
// Altrimenti non c'è contorno
else {
// Marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
}
}
}
std::vector<std::vector<TJEdgeSet>> vvIndexesSet ;
// Cerco delle T-Junction nei loop trovati
for ( int nL = 0 ; nL < int( TJLVec.size()) ; ++ nL) {
// Ciclo suigli edges per raggrupparli
for ( int nPos1 = 0 ; nPos1 < int( TJLVec[nL].size()) ; ++ nPos1) {
bool bNew = true ;
for ( int nPos2 = 0 ; nPos2 < int( TJLVec[nL].size()) ; ++ nPos2) {
if ( nPos1 == nPos2)
continue ;
// Punti estremi dei due edge correnti
Point3d ptS1, ptE1, ptS2, ptE2 ;
GetVertex( m_vTria[TJLVec[nL][nPos1].nTriaId].nIdVert[TJLVec[nL][nPos1].nEdge], ptS1) ;
GetVertex( m_vTria[TJLVec[nL][nPos1].nTriaId].nIdVert[( TJLVec[nL][nPos1].nEdge + 1) % 3], ptE1) ;
GetVertex( m_vTria[TJLVec[nL][nPos2].nTriaId].nIdVert[TJLVec[nL][nPos2].nEdge], ptS2) ;
GetVertex( m_vTria[TJLVec[nL][nPos2].nTriaId].nIdVert[( TJLVec[nL][nPos2].nEdge + 1) % 3], ptE2) ;
Vector3d vtV = ptE1 - ptS1 ;
double dLen = vtV.Len() ;
vtV.Normalize() ;
double dProjSt = ( ptS2 - ptS1) * vtV ;
double dProjEn = ( ptE2 - ptS1) * vtV ;
double dOrtSt = ( ( ptS2 - ptS1) - dProjSt * vtV).Len() ;
double dOrtEn = ( ( ptE2 - ptS1) - dProjEn * vtV).Len() ;
// Edge di posizione 2 forma una T-Junction su edge di posizione 1
if ( ( dProjSt > EPS_SMALL && dProjSt < dLen - EPS_SMALL && dOrtSt < EPS_SMALL) ||
( dProjEn > EPS_SMALL && dProjEn < dLen - EPS_SMALL && dOrtEn < EPS_SMALL)) {
// Edge di pos 1 non aveva ancora T-Junction con edge di pos 2
if ( bNew) {
// Aggiungo il vettore di tutti i gruppi di edge che formano T-Junction con endge di pos 1,
// aggiungo il gruppo con la normale di edge di pos 2 e aggiungo edge di pos due a tale gruppo.
vvIndexesSet.emplace_back() ;
vvIndexesSet[vvIndexesSet.size() - 1].emplace_back() ;
vvIndexesSet[vvIndexesSet.size() - 1][vvIndexesSet[vvIndexesSet.size() - 1].size() - 1].emplace( TJLVec[nL][nPos2]) ;
bNew = false ;
}
// Edge di pos 1 aveva già T-Junction con edge di pos 2
else {
// Cerco nei triangoli degli edge di pos 2 già trovati alcuni con la normale uguale al nuovo trovato
int nNorm ;
for ( nNorm = 0 ; nNorm < int( vvIndexesSet[vvIndexesSet.size() - 1].size()) ; ++ nNorm) {
auto TEdgePtr = vvIndexesSet[vvIndexesSet.size() - 1][nNorm].begin() ;
if ( AreSameVectorExact( m_vTria[TEdgePtr->nTriaId].vtN, m_vTria[TJLVec[nL][nPos2].nTriaId].vtN)) {
break ;
}
}
// Se non ho trovato tali triangoli aggiungo un nuovo gruppo
if ( nNorm == int( vvIndexesSet[vvIndexesSet.size() - 1].size())) {
vvIndexesSet[vvIndexesSet.size() - 1].emplace_back() ;
}
// Aggiungo il nuovo edge al suo gruppo
vvIndexesSet[vvIndexesSet.size() - 1][nNorm].emplace( TJLVec[nL][nPos2]) ;
}
// Fra i triangoli adiacenti al triangolo con l'edge di pos 2
// ne cerco altri con un vertice nella T-Junction
for ( int m = 0 ; m < 3 ; ++ m) {
// Triangolo adiacente e suo indice
int nAdjTriaIndex = m_vTria[TJLVec[nL][nPos2].nTriaId].nIdAdjac[m] ;
Triangle3d trAdjTria ;
if ( GetTriangle( nAdjTriaIndex, trAdjTria)) {
// Ciclo sugli edge del triangolo adiacente
for ( int nVrt = 0 ; nVrt < 3 ; ++ nVrt) {
double dAdjProjVrt = ( trAdjTria.GetP( nVrt) - ptS1) * vtV ;
double dAdjOrtVrt = ( ( trAdjTria.GetP( nVrt) - ptS1) - dAdjProjVrt * vtV).Len() ;
double dAdjProjNxt1 = ( trAdjTria.GetP( ( nVrt + 1) % 3) - ptS1) * vtV ;
double dAdjOrtNxt1 = ( ( trAdjTria.GetP( ( nVrt + 1) % 3) - ptS1) - dAdjProjNxt1 * vtV).Len() ;
double dAdjProjNxt2 = ( trAdjTria.GetP( ( nVrt + 2) % 3) - ptS1) * vtV ;
double dAdjOrtNxt2 = ( ( trAdjTria.GetP( ( nVrt + 2) % 3) - ptS1) - dAdjProjNxt2 * vtV).Len() ;
// Triangolo adiacente forma una T-Junction con l'edge di pos 1
if ( dAdjProjVrt > EPS_SMALL && dAdjProjVrt < dLen - EPS_SMALL && dAdjOrtVrt < EPS_SMALL &&
dAdjOrtNxt1 > EPS_SMALL && dAdjOrtNxt2 > EPS_SMALL) {
// Lo aggiungo nel gruppo con i triangoli aventi la sua normale.
// Se tale gruppo non esiste, lo aggiungo preventivamente
int nNorm ;
for ( nNorm = 0 ; nNorm < int( vvIndexesSet[vvIndexesSet.size() - 1].size()) ; ++ nNorm) {
auto TEdgePtr = vvIndexesSet[vvIndexesSet.size() - 1][nNorm].begin() ;
if ( AreSameVectorExact( m_vTria[TEdgePtr->nTriaId].vtN, m_vTria[nAdjTriaIndex].vtN)) {
break ;
}
}
if ( nNorm == int( vvIndexesSet[vvIndexesSet.size() - 1].size())) {
vvIndexesSet[vvIndexesSet.size() - 1].emplace_back() ;
}
// Cerco adiacenti dell'adiacente
TEdgeId TJAdjTria ;
TJAdjTria.nTriaId = nAdjTriaIndex ;
TJAdjTria.nEdge = nVrt ;
vvIndexesSet[vvIndexesSet.size() - 1][nNorm].emplace( TJAdjTria) ;
TEdgeId TJTurnTria ;
TJTurnTria.nTriaId = TJAdjTria.nTriaId ;
TJTurnTria.nEdge = TJAdjTria.nEdge ;
while ( GetForwardAdjTriaSharingVertex( TJTurnTria.nTriaId, TJTurnTria.nEdge) &&
TJTurnTria.nTriaId != TJAdjTria.nTriaId) {
if ( AreSameVectorExact( m_vTria[TJTurnTria.nTriaId].vtN, m_vTria[TJAdjTria.nTriaId].vtN)) {
vvIndexesSet[vvIndexesSet.size() - 1][nNorm].emplace( TJTurnTria) ;
}
}
TJTurnTria.nTriaId = TJAdjTria.nTriaId ;
TJTurnTria.nEdge = TJAdjTria.nEdge ;
while ( GetBackwardAdjTriaSharingVertex( TJTurnTria.nTriaId, TJTurnTria.nEdge) &&
TJTurnTria.nTriaId != TJAdjTria.nTriaId) {
if ( AreSameVectorExact( m_vTria[TJTurnTria.nTriaId].vtN, m_vTria[TJAdjTria.nTriaId].vtN)) {
vvIndexesSet[vvIndexesSet.size() - 1][nNorm].emplace( TJTurnTria) ;
}
}
}
}
}
}
}
}
}
}
// Fra Loop diversi cerco se un medesimo gruppo appartiene a più edge dello stesso loop
// o edge di loop diversi. In entrambi i casi fondo i gruppi.
for ( int nL1 = 0 ; nL1 < int( vvIndexesSet.size()) ; ++ nL1) {
for ( int nL2 = nL1 + 1 ; nL2 < int( vvIndexesSet.size()) ; ++ nL2) {
for ( int nN1 = 0 ; nN1 < int( vvIndexesSet[nL1].size()) ; ++ nN1) {
for ( int nN2 = 0 ; nN2 < int( vvIndexesSet[nL2].size()) ; ++ nN2) {
bool bFoundCouple = false ;
for ( auto it1 = vvIndexesSet[nL1][nN1].begin() ; it1 != vvIndexesSet[nL1][nN1].end() ; ++ it1) {
for ( auto it2 = vvIndexesSet[nL2][nN2].begin() ; it2 != vvIndexesSet[nL2][nN2].end() ; ++ it2) {
if ( it1->nTriaId == it2->nTriaId) {
bFoundCouple = true ;
break ;
}
}
if ( bFoundCouple)
break ;
}
if ( bFoundCouple) {
if ( vvIndexesSet[nL1][nN1].size() < vvIndexesSet[nL2][nN2].size()) {
for ( auto it1 = vvIndexesSet[nL1][nN1].begin() ; it1 != vvIndexesSet[nL1][nN1].end() ; ++ it1) {
vvIndexesSet[nL2][nN2].emplace( *it1) ;
}
vvIndexesSet[nL1][nN1].clear() ;
}
else {
for ( auto it2 = vvIndexesSet[nL2][nN2].begin() ; it2 != vvIndexesSet[nL2][nN2].end(); ++ it2) {
vvIndexesSet[nL1][nN1].emplace( *it2) ;
}
vvIndexesSet[nL2][nN2].clear() ;
}
}
}
}
}
}
// Retriangolarizzo i poligoni
for ( int nP = 0 ; nP < int( vvIndexesSet.size()) ; ++ nP) {
for ( int nPP = 0 ; nPP < int( vvIndexesSet[nP].size()) ; ++ nPP) {
auto it = vvIndexesSet[nP][nPP].begin() ;
if ( it == vvIndexesSet[nP][nPP].end())
continue ;
Point3d ptP0, ptP1, ptP2 ;
GetVertex( m_vTria[it->nTriaId].nIdVert[0], ptP0) ;
GetVertex( m_vTria[it->nTriaId].nIdVert[1], ptP1) ;
GetVertex( m_vTria[it->nTriaId].nIdVert[2], ptP2) ;
CurveLine cvLine0 ;
cvLine0.Set( ptP0, ptP1) ;
CurveLine cvLine1 ;
cvLine1.Set( ptP1, ptP2) ;
CurveLine cvLine2 ;
cvLine2.Set( ptP2, ptP0) ;
CurveComposite cvLoop ;
cvLoop.AddCurve( cvLine0) ;
cvLoop.AddCurve( cvLine1) ;
cvLoop.AddCurve( cvLine2) ;
SurfFlatRegion Facet ;
Facet.AddExtLoop( cvLoop) ;
RemoveTriangle( it->nTriaId) ;
++ it ;
for ( ; it != vvIndexesSet[nP][nPP].end() ; ) {
Point3d ptAddP0, ptAddP1, ptAddP2;
if ( ! ( GetVertex( m_vTria[it->nTriaId].nIdVert[0], ptAddP0) &&
GetVertex( m_vTria[it->nTriaId].nIdVert[1], ptAddP1) &&
GetVertex( m_vTria[it->nTriaId].nIdVert[2], ptAddP2))) {
++ it ;
continue ;
}
CurveLine cvAddLine0 ;
cvAddLine0.Set( ptAddP0, ptAddP1) ;
CurveLine cvAddLine1 ;
cvAddLine1.Set( ptAddP1, ptAddP2) ;
CurveLine cvAddLine2 ;
cvAddLine2.Set( ptAddP2, ptAddP0) ;
CurveComposite cvAddLoop ;
cvAddLoop.AddCurve( cvAddLine0) ;
cvAddLoop.AddCurve( cvAddLine1) ;
cvAddLoop.AddCurve( cvAddLine2) ;
SurfFlatRegion AddFacet ;
AddFacet.AddExtLoop( cvAddLoop) ;
Facet.Add( AddFacet) ;
RemoveTriangle( it->nTriaId) ;
++it ;
}
int nChunkNum = Facet.GetChunkCount() ;
for ( int nChunk = 0 ; nChunk < nChunkNum ; ++ nChunk) {
ICurve* pOutline = Facet.GetLoop( nChunk, 0) ;
PolyLine PolyOutline ;
pOutline->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, PolyOutline) ;
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( PolyOutline, vPt, vTr)) {
// Inserisco i nuovi triangoli
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] };
int nNewId[3] = { AddVertex( vPt[nNewTriaVertId[0]]),
AddVertex( vPt[nNewTriaVertId[1]]),
AddVertex( vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::MarchAlongFacetLoopForTJunc( int nT, int nV, int nTimeStamp, TJuncLoop& TJLoop) const
{
// Mi muovo lungo il loop, un triangolo alla volta
bool bEnd = false ;
while ( ! bEnd) {
if ( ! MarchOneFacetTriaForTJunc( nT, nV, nTimeStamp, TJLoop, bEnd))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::MarchOneFacetTriaForTJunc( int& nT, int& nV, int nTimeStamp, TJuncLoop& TJLoop, bool& bEnd) const
{
// Verifico esistenza triangolo adiacente, sul lato dopo il vertice
if ( m_vTria[nT].nIdAdjac[nV] == SVT_NULL)
return false ;
// Indice del triangolo adiacente
int nAdjT = m_vTria[nT].nIdAdjac[nV] ;
// 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) {
// 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
TJLoop.emplace_back() ;
TJLoop.back().nTriaId = nAdjT ;
TJLoop.back().nEdge = nAdjV ;
// Verifico anche il successivo
nAdjV = Next( nAdjV) ;
nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
if ( nNextT == SVT_NULL) {
// Aggiungo il lato al loop
TJLoop.emplace_back() ;
TJLoop.back().nTriaId = nAdjT ;
TJLoop.back().nEdge = nAdjV ;
nAdjV = Next(nAdjV);
}
}
// Devo passare al triangolo adiacente
nT = nAdjT ;
nV = nAdjV ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetForwardAdjTriaSharingVertex( int& nTria, int& nVertInTria) const
{
// Verifico validità della posizione del vertice nel triangolo
if ( nVertInTria < 0 || nVertInTria > 2)
return false ;
int nVert = m_vTria[nTria].nIdVert[nVertInTria] ;
// Verifico esistenza del vertice
if ( nVert < 0 || nVert >= GetVertexSize() || m_vVert[nVert].nIdTria == SVT_DEL)
return false ;
// Verifico esistenza del triangolo
if ( nTria < 0 || nTria >= GetTriangleSize() || m_vTria[nTria].nIdVert[0] == SVT_DEL)
return false ;
// Trovo triangolo adiacente che condivide il vertice
nTria = m_vTria[nTria].nIdAdjac[nVertInTria] ;
if ( nTria < 0 || nTria >= GetTriangleSize())
return false ;
// Trovo posizione del vertice nel triangolo adiacente
nVertInTria = - 1 ;
for ( int n = 0 ; n < 3 ; ++ n) {
if ( m_vTria[nTria].nIdVert[n] == nVert)
nVertInTria = n ;
}
return ( nVertInTria != - 1) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetBackwardAdjTriaSharingVertex( int& nTria, int& nVertInTria) const
{
// Verifico validità della posizione del vertice nel triangolo
if ( nVertInTria < 0 || nVertInTria > 2)
return false ;
int nVert = m_vTria[nTria].nIdVert[nVertInTria] ;
// Verifico esistenza del vertice
if ( nVert < 0 || nVert >= GetVertexSize() || m_vVert[nVert].nIdTria == SVT_DEL)
return false ;
// Verifico esistenza del triangolo
if ( nTria < 0 || nTria >= GetTriangleSize() || m_vTria[nTria].nIdVert[0] == SVT_DEL)
return false ;
// Trovo triangolo adiacente che condivide il vertice
nTria = m_vTria[nTria].nIdAdjac[( nVertInTria + 2) % 3] ;
if ( nTria < 0 || nTria >= GetTriangleSize())
return false ;
// Trovo posizione del vertice nel triangolo adiacente
nVertInTria = -1 ;
for ( int n = 0 ; n < 3 ; ++ n) {
if ( m_vTria[nTria].nIdVert[n] == nVert)
nVertInTria = n ;
}
return ( nVertInTria != - 1) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Add( const ISurfTriMesh& Other)
@@ -1947,7 +2575,11 @@ SurfTriMesh::Add( const ISurfTriMesh& Other)
AddTriangle( nNewVert) ;
}
}
bool bContinue = ( AdjustVertices() && DoCompacting()) ;
if ( bContinue)
RemoveTJunction() ;
else
return false ;
return ( AdjustVertices() && DoCompacting()) ;
}
@@ -1975,7 +2607,11 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
AddTriangle( nNewVert) ;
}
}
bool bContinue = ( AdjustVertices() && DoCompacting()) ;
if ( bContinue)
RemoveTJunction() ;
else
return false ;
return ( AdjustVertices() && DoCompacting()) ;
}
@@ -1989,7 +2625,7 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other)
IdentifyParts() ;
SurfB.IdentifyParts() ;
int nTriaNumA = GetTriangleSize() ;
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == 2)
RemoveTriangle( nTA) ;
}
@@ -2004,6 +2640,85 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other)
AddTriangle( nNewVert) ;
}
}
bool bContinue = ( AdjustVertices() && DoCompacting()) ;
if ( bContinue)
RemoveTJunction() ;
else
return false ;
return ( AdjustVertices() && DoCompacting()) ;
}
///////////////////////// DEBUG /////////////////////////////////////////////////////////////////////////////////////////////////
//if ( ( AreSamePointApprox(trTriaA.GetP(0), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(20, 40, 30))) ||
// ( AreSamePointApprox(trTriaA.GetP(2), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(20, 40, 30))) ||
// ( AreSamePointApprox(trTriaA.GetP(1), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(20, 40, 30)))) {
// int a = 0 ;
//}
//
//if ( ( AreSamePointApprox(trTriaB.GetP(0), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(20, 40, 30))) ||
// ( AreSamePointApprox(trTriaB.GetP(2), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(20, 40, 30))) ||
// ( AreSamePointApprox(trTriaB.GetP(1), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(20, 40, 30)))) {
// int b = 0 ;
//}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//if ((AreSamePointApprox(trTriaA.GetP(0), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaA.GetP(2), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaA.GetP(1), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(20, 40, 30)))) {
//
// if ((AreSamePointApprox(trTriaB.GetP(0), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaB.GetP(2), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaB.GetP(1), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(20, 40, 30)))) {
// int b = 0;
// }
//}
///////////////////////////////////////////////////////////////////////////////////////////////////
//bool
//FacesRetriangulation()
//{
// // Mi assicuro che la trimesh sia ok
// // Assicurarsi che la trimesh sia ok ......
// // Pongo tutti i triangoli come non visitati
// for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
// m_vTria[nT].nTemp = 0 ;
// }
// // Ciclo sui triangoli
// for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
// // Se triangolo non visitato
// if ( m_vTria[nT].nTemp == 0) {
// m_vTria[nT].nTemp = 1 ;
// std::unordered_set<int> TriaIndexSet ;// devi usare stack
// TriaIndexSet.emplace( nT) ;
// while ( ! TriaIndexSet.empty()) {
//
// }
// }
// }
// return true ;
//}