From 19e2b480b2bad07d0dfe7c55bb7b1156f659652c Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 2 Jan 2020 19:38:35 +0000 Subject: [PATCH] EgtGeoKernel : - piccole migliorie a Booleane di SurfTriMesh. --- SurfTriMesh.h | 2 +- SurfTriMeshBooleans.cpp | 149 +++++++++++++++++++++------------------- Triangulate.h | 4 +- 3 files changed, 80 insertions(+), 75 deletions(-) diff --git a/SurfTriMesh.h b/SurfTriMesh.h index f10aa18..7fe4573 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -302,7 +302,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ; bool IntersectTriMeshTriangle( SurfTriMesh& Other) ; bool IdentifyParts( void) const ; - bool RemoveTJunction3( void) ; + bool RemoveTJunctions( void) ; bool RemoveCaps( void) ; bool RemoveTripleTriangles( void) ; bool ScanForTripleTriangles( bool& bModified) ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 3a99c80..c546dec 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -1654,72 +1654,71 @@ SurfTriMesh::IdentifyParts( void) const //---------------------------------------------------------------------------- bool -SurfTriMesh::RemoveTJunction3(void) +SurfTriMesh::RemoveTJunctions(void) { - // Resetto e ricalcolo la HashGrid. - ResetHashGrids3d(); - VerifyHashGrids3d(); - // Vettore di indici dei vertici sui lati del triangolo corrente - vector vvIndexMatrix ; - for ( int nT = 0; nT < int( m_vTria.size()) ; ++ nT) { - // Se il triangolo non è valido, continuo. - Triangle3d trTria; - if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) - continue; - vvIndexMatrix.emplace_back() ; - // Box del triangolo - BBox3d b3dTria ; - trTria.GetLocalBBox( b3dTria) ; - INTVECTOR vNearTria ; - GetAllTriaOverlapBox( b3dTria, vNearTria) ; - // Ciclo sui lati del triangolo - for ( int nSeg = 0; nSeg < 3; ++nSeg) { - vvIndexMatrix.back().emplace_back( m_vTria[nT].nIdVert[nSeg]) ; - int nPrevSize = int( vvIndexMatrix.back().size()) ; - Point3d ptSegSt = trTria.GetP(nSeg); - Point3d ptSegEn = trTria.GetP((nSeg + 1) % 3); - Vector3d vtSeg = ptSegEn - ptSegSt; - double dSegLen = vtSeg.Len(); - if (dSegLen < EPS_SMALL) - continue; - vtSeg /= dSegLen; - // Ciclo sui triangoli vicini - for ( int nNT = 0 ; nNT < int( vNearTria.size()) ; ++ nNT) { - // Ciclo sui vertici del triangolo vicino corrente - for ( int nVert = 0; nVert < 3; ++ nVert) { - Point3d ptVert0, ptVert1, ptVert2; - GetVertex(m_vTria[vNearTria[nNT]].nIdVert[nVert], ptVert0); - GetVertex(m_vTria[vNearTria[nNT]].nIdVert[(nVert + 1) % 3], ptVert1); - GetVertex(m_vTria[vNearTria[nNT]].nIdVert[(nVert + 2) % 3], ptVert2); - double dProj0 = (ptVert0 - ptSegSt) * vtSeg; - double dOrt0 = ((ptVert0 - ptSegSt) - dProj0 * vtSeg).SqLen(); - if ( dProj0 > EPS_SMALL && dProj0 < dSegLen - EPS_SMALL && - dOrt0 < SQ_EPS_TRIA_H) { - vvIndexMatrix.back().emplace_back(m_vTria[vNearTria[nNT]].nIdVert[nVert]); - } - } - } - int nCurSize = int(vvIndexMatrix.back().size()); - // Vanno riordinati gli indici - for ( int nV = nPrevSize ; nV < nCurSize ; ++ nV) { - for ( int nVV = nV + 1 ; nVV < nCurSize ; ++ nVV) { - Point3d ptPV, ptPVV ; - GetVertex( vvIndexMatrix.back()[nV], ptPV) ; - GetVertex( vvIndexMatrix.back()[nVV], ptPVV) ; - if (( ptPV - ptSegSt) * vtSeg > (ptPVV - ptSegSt) * vtSeg) { - swap(vvIndexMatrix.back()[nV], vvIndexMatrix.back()[nVV]) ; - } - } - } + //PerformanceCounter Counter ; + // Vettore di indici dei vertici sui lati del triangolo corrente + INTMATRIX vvIndexMatrix( m_vTria.size()) ; + // Ciclo sui triangoli della superficie + for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) { + // Riga di matrice per il triangolo + INTVECTOR& vIndexRow = vvIndexMatrix[nT] ; + // Se il triangolo non è valido, passo al successivo + Triangle3d trTria ; + if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) + continue ; + // Box del triangolo + BBox3d b3Tria ; + trTria.GetLocalBBox( b3Tria) ; + INTVECTOR vNearTria ; + GetAllTriaOverlapBox( b3Tria, vNearTria) ; + // Ciclo sui lati del triangolo + for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) { + // aggiungo alla riga della matrice il vertice iniziale del lato + vIndexRow.emplace_back( m_vTria[nT].nIdVert[nSeg]) ; + int nPrevSize = int( vIndexRow.size()) ; + // recupero la geometria del lato + Point3d ptSegSt = trTria.GetP( nSeg) ; + Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ; + Vector3d vtSeg = ptSegEn - ptSegSt ; + double dSegLen = vtSeg.Len() ; + if ( dSegLen < EPS_SMALL) + continue ; + vtSeg /= dSegLen ; + // Ciclo sui triangoli vicini + for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) { + // Salto il triangolo se è quello di riferimento + if ( vNearTria[nI] == nT) + continue ; + // Cerco i vertici che stanno sul lato del triangolo + for ( int nVert = 0 ; nVert < 3 ; ++ nVert) { + Point3d ptVert ; + GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert) ; + double dProj = ( ptVert - ptSegSt) * vtSeg ; + double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ; + if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H) { + vIndexRow.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ; + } + } + } + // Riordino i vertici sul segmento + auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV, const int nVV) + { Point3d ptPV, ptPVV ; + GetVertex( nV, ptPV) ; + GetVertex( nVV, ptPVV) ; + return ( ( ptPV - ptSegSt) * vtSeg < ( ptPVV - ptSegSt) * vtSeg) ; + } ; + sort( vIndexRow.begin() + nPrevSize, vIndexRow.end(), SortVerteces) ; } } + //double dTime1 = Counter.Stop() ; Counter.Start() ; + for ( int nT = 0 ; nT < int( vvIndexMatrix.size()) ; ++ nT) { - if ( int( vvIndexMatrix[nT].size()) > 3) { - RemoveTriangle( nT) ; + if ( vvIndexMatrix[nT].size() > 3) { PolyLine Polygon ; - for ( int nV = 0 ; nV < int(vvIndexMatrix[nT].size()) ; ++ nV) { + for ( int nV = 0 ; nV < int( vvIndexMatrix[nT].size()) ; ++ nV) { Point3d ptPt; GetVertex( vvIndexMatrix[nT][nV], ptPt) ; Polygon.AddUPoint( 0., ptPt) ; @@ -1728,7 +1727,9 @@ SurfTriMesh::RemoveTJunction3(void) PNTVECTOR vPt ; INTVECTOR vTr ; if ( Triangulate().Make( Polygon, vPt, vTr)) { - // Inserisco i nuovi triangoli + // Rimuovo il triangolo originale + RemoveTriangle( nT) ; + // Inserisco i nuovi triangoli che lo sostituiscono 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]]), @@ -1737,11 +1738,15 @@ SurfTriMesh::RemoveTJunction3(void) AddTriangle( nNewId) ; } } - else - int perepe = 0 ; } } + //double dTime2 = Counter.Stop() ; Counter.Start() ; + + //string sOut = "T1=" + ToString( dTime1, 1) + + // " T2=" + ToString( dTime2, 1) ; + //LOG_INFO( GetEGkLogger(), sOut.c_str()) ; + return true ; } @@ -1805,9 +1810,9 @@ SurfTriMesh::RemoveCaps(void) bool SurfTriMesh::RemoveTripleTriangles() { - bool bContinue = true ; int nCounter = 1 ; - const int N_STOP = 10 ; + const int N_STOP = 100 ; + bool bContinue = true ; while ( bContinue && nCounter <= N_STOP) { ScanForTripleTriangles( bContinue) ; } @@ -1855,8 +1860,8 @@ SurfTriMesh::ScanForTripleTriangles( bool& bModified) int nAdjTriaContactEdge[3] ; for ( int nAdjTria = 1 ; nAdjTria < 6 ; nAdjTria += 2) { for ( int nAdjEdge = 0 ; nAdjEdge < 3 ; ++ nAdjEdge) { - if ( vVertAndAdjTria[nAdjTria] >= 0 && m_vTria[vVertAndAdjTria[nAdjTria]].nIdAdjac[nAdjEdge] == vTriaIndex[( nAdjTria - 1) / int( 2)]) - nAdjTriaContactEdge[(nAdjTria - 1) / int( 2)] = nAdjEdge ; + if ( vVertAndAdjTria[nAdjTria] >= 0 && m_vTria[vVertAndAdjTria[nAdjTria]].nIdAdjac[nAdjEdge] == vTriaIndex[( nAdjTria - 1) / 2]) + nAdjTriaContactEdge[(nAdjTria - 1) / 2] = nAdjEdge ; } } // Elimino i triangoli @@ -1865,7 +1870,7 @@ SurfTriMesh::ScanForTripleTriangles( bool& bModified) } // Aggiungo il novo triangolo int nNewVert[3] = { vVertAndAdjTria[0], vVertAndAdjTria[2], vVertAndAdjTria[4] } ; - int nNewTriaId = AddTriangle(nNewVert) ; + int nNewTriaId = AddTriangle( nNewVert) ; if ( nNewTriaId != SVT_NULL) { // Sistemo le adiacenze m_vTria[nNewTriaId].nIdAdjac[0] = vVertAndAdjTria[1] ; @@ -1967,9 +1972,9 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) if ( ! AdjustVertices() || ! DoCompacting()) return false ; RemoveTripleTriangles() ; - if ( ! AdjustVertices() || ! DoCompacting()) + if ( ! AdjustVertices() || ! DoCompacting()) return false ; - RemoveTJunction3() ; + RemoveTJunctions() ; return ( AdjustVertices() && DoCompacting()) ; } @@ -2000,9 +2005,9 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) if ( ! AdjustVertices() || ! DoCompacting()) return false ; RemoveTripleTriangles() ; - if ( ! AdjustVertices() || ! DoCompacting()) + if ( ! AdjustVertices() || ! DoCompacting()) return false ; - RemoveTJunction3() ; + RemoveTJunctions() ; return ( AdjustVertices() && DoCompacting()) ; } @@ -2036,7 +2041,7 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) RemoveTripleTriangles() ; if ( ! AdjustVertices() || ! DoCompacting()) return false ; - RemoveTJunction3() ; + RemoveTJunctions() ; return ( AdjustVertices() && DoCompacting()) ; } diff --git a/Triangulate.h b/Triangulate.h index 3e9eed3..6fe4a83 100644 --- a/Triangulate.h +++ b/Triangulate.h @@ -36,8 +36,8 @@ class Triangulate double TwoArea( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ; bool AreSamePoint( const Point3d& ptA, const Point3d& ptB, double dToler = EPS_SMALL) ; bool SameDirection( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ; - bool Collinear( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = EPS_SMALL) ; - bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = EPS_SMALL) ; + bool Collinear( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = 0.1 * EPS_SMALL) ; + bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = 0.1 * EPS_SMALL) ; bool TestIntersection( const Point3d& ptA1, const Point3d& ptA2, const Point3d& ptB1, const Point3d& ptB2) ; bool TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ; bool SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd) ;