From ffad8c6dd266f7a58f98f4dbbe49704cffd35c85 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 18 Nov 2019 09:17:05 +0000 Subject: [PATCH] EgtGeomKernel 2.1k4 : - correzioni alle operazioni booleane tra superfici trimesh. --- EgtGeomKernel.rc | Bin 11718 -> 11718 bytes SurfTriMesh.h | 28 +- SurfTriMeshBooleans.cpp | 777 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 772 insertions(+), 33 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 2ba6af378ff1c04fb3755045bff4da70c2a616e8..69065106d884c71139331fa3bc1fde0e00c0310f 100644 GIT binary patch delta 110 zcmX>WeJpyzA2vpl&G-4vGfl1&(wY2&Q;pGNvZAo=W*@FeEMOU1X1ItOWeJpyzA2vqg&G-4vGfl1&(wY2&Q;pGhvZAo=W*@FeEMOU1X1ItO diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 91530e0..3a6825a 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -19,6 +19,7 @@ #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkHashGrids3d.h" #include +#include //---------------------------------------------------------------------------- // Classe Vertice @@ -83,6 +84,24 @@ typedef std::vector Chain ; typedef std::vector CHAINVECTOR ; //---------------------------------------------------------------------------- +// Struttura per la ricerca delle T-Junction +struct TEdgeId { + int nTriaId ; + int nEdge ; +} ; +// Overloading dell'operatore < per TEdgeSet +inline bool operator<( const TEdgeId& TEdgeA, const TEdgeId& TEdgeB) { + if ( TEdgeA.nTriaId != TEdgeB.nTriaId) + return ( TEdgeA.nTriaId < TEdgeB.nTriaId) ; + return ( TEdgeA.nEdge < TEdgeB.nEdge) ; +} +// Loop con T-Junction +typedef std::vector TJuncLoop ; +// Vettore di loop con T-Junction +typedef std::vector TJuncLoopVec ; +// Set di TEdgeId +typedef std::set TJEdgeSet ; + //---------------------------------------------------------------------------- class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW { @@ -271,10 +290,15 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ; void ResetHashGrids3d( void) const ; bool VerifyHashGrids3d( void) const ; - bool VerifyConnection( void) const ; - bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, std::vector& cvBoundClosedLoopVec, std::vector& vbInOut) ; + bool VerifyConnection( void) const ; + bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, std::vector& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ; bool IntersectTriMeshTriangle( SurfTriMesh& Other) ; bool IdentifyParts( void) const ; + bool RemoveTJunction( void) ; + bool MarchAlongFacetLoopForTJunc( int nT, int nV, int nTimeStamp, TJuncLoop& TJLoop) const ; + bool MarchOneFacetTriaForTJunc( int& nT, int& nV, int nTimeStamp, TJuncLoop& TJLoop, bool& bEnd) const ; + bool GetForwardAdjTriaSharingVertex( int& nTria, int& nVertInTria) const ; + bool GetBackwardAdjTriaSharingVertex( int& nTria, int& nVertInTria) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index b3224e1..aadfb28 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -28,7 +28,6 @@ #include "/EgtDev/Include/EGkGeoCollection.h" #include "/EgtDev/Include/EGkPolygon3d.h" #include -#include 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 cvBoundClosedLoopVec ; cvBoundClosedLoopVec.emplace_back(cvFirstLoop); - vector 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& cvBoundClosedLoopVec, vector& vbInOut) +SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, vector& 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 LineMapA ; - unordered_map LineMapB ; + std::unordered_map LineMapA ; + std::unordered_map LineMapB ; + // Unordered map dei triangoli ambigui (intersezione edge-edge) + std::unordered_map > AmbiguosA ; + std::unordered_map > 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 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 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 cvBoundClosedLoopVec ; cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ; - vector 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 cvBoundClosedLoopVec ; cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ; - vector 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> 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 TriaIndexSet ;// devi usare stack +// TriaIndexSet.emplace( nT) ; +// while ( ! TriaIndexSet.empty()) { +// +// } +// } +// } +// return true ; +//}