diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 6280b38..9669d67 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 539befd..7853643 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -411,7 +411,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool RemoveTripleTriangles( void) ; bool ScanForTripleTriangles( bool& bModified) ; bool FlipTriangles( int nTA, int nTB) ; - bool SimplifyFacets( double dMaxEdgeLen) ; + bool SimplifyFacets( double dMaxEdgeLen, bool bForced = false) ; bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ; bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ; bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 3313f44..bdda833 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -251,7 +251,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT if ( int( it->second.size()) == 0) continue ; - // Se il triangolo � stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori. + // 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 itS = Ambiguos.find( it->first) ; @@ -499,7 +499,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT // 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 - // chiusi di cui � formato il perimetro. + // chiusi di cui è formato il perimetro. PNTVECTOR cvFirstLoop ; cvFirstLoop.emplace_back( trTria.GetP( 0)) ; cvFirstLoop.emplace_back( trTria.GetP( 1)) ; @@ -579,7 +579,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT // Assegno ai loop trovati i rispettivi interni // Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello. // Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un - // loop � figlio del nodo corrispondente al loop che lo contiene. + // loop è figlio del nodo corrispondente al loop che lo contiene. INTVECTOR vInnerLoop ; for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) { for ( int nPtNum = 0 ; nPtNum < int( cvClosedChain[nCLI].size()) ; ++ nPtNum) { @@ -1004,7 +1004,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su { for ( auto it = Ambiguos.begin() ; it != Ambiguos.end() ; ++ it) { // Se il triangolo ha l'indice diverso da zero vuol dire che oltre a un - // contatto edge-edge ha avuto dei contatti che lo hanno gi� classificato. + // contatto edge-edge ha avuto dei contatti che lo hanno già classificato. if ( Surf.m_vTria[it->first].nTempPart != 0) continue ; // Recupero il triangolo corrente @@ -1080,7 +1080,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su if ( j < 3) break ; } - // Se la classificazione � coerente segno gli edge di contatto come invalicabili + // Se la classificazione è coerente segno gli edge di contatto come invalicabili Surf.m_vTria[it->first].nETempFlag[0] = int( vAdjSegToCurTria[0].size()) > 0 ? 1 : 0 ; Surf.m_vTria[it->first].nETempFlag[1] = int( vAdjSegToCurTria[1].size()) > 0 ? 1 : 0 ; Surf.m_vTria[it->first].nETempFlag[2] = int( vAdjSegToCurTria[2].size()) > 0 ? 1 : 0 ; @@ -1106,7 +1106,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) // Ciclo sui triangoli delle mesh int nTriaNumA = GetTriangleSize() ; int nTriaNumB = SurfB.GetTriangleSize() ; - // Setto il triangolo come n� fuori n� dentro + // Setto il triangolo come né fuori né dentro for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { m_vTria[nTA].nTempPart = 0 ; m_vTria[nTA].nETempFlag[0] = 0 ; @@ -1122,7 +1122,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) // Resetto e ricalcolo la HashGrid della superficie B SurfB.ResetHashGrids3d() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { - // Se il triangolo A non � valido, continuo + // Se il triangolo A non è valido, continuo Triangle3d trTriaA ; if ( ! GetTriangle( nTA, trTriaA) || ! trTriaA.Validate( true)) continue ; @@ -1133,7 +1133,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ; for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) { - // Se il triangolo B non � valido, continuo + // Se il triangolo B non è valido, continuo Triangle3d trTriaB ; if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true)) continue ; @@ -1209,7 +1209,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) } } if ( nSegMaxDist >= 0) { - // Cerco qual'� il segmento di contatto per dichiararlo come invalicabile + // Cerco qual'è il segmento di contatto per dichiararlo come invalicabile int nVA ; for ( nVA = 0 ; nVA < 3 ; ++ nVA) { if ( abs( ( trTriaA.GetP( nVA) - trTriaB.GetP( 0)) * trTriaB.GetN()) < EPS_SMALL && @@ -1233,7 +1233,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) } } if ( nSegMaxDist >= 0) { - // Cerco qual'� il segmento di contatto per dichiararlo come invalicabile + // Cerco qual'è il segmento di contatto per dichiararlo come invalicabile int nVB ; for ( nVB = 0 ; nVB < 3 ; ++ nVB) { if ( abs( ( trTriaB.GetP( nVB) - trTriaA.GetP(0)) * trTriaA.GetN()) < EPS_SMALL && @@ -1246,8 +1246,8 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) } } // Intersezione edge-edge: salvo indice e vettore triangoli - // Uso i triangoli perch�, se un triangolo fosse cancellato, non potrei accedervi poi usando l'indice. - // Salvando i triangoli risolvo il problema perch� ai fini dello studio di questi contatti, triangolo + // Uso i triangoli perchè, se un triangolo fosse cancellato, non potrei accedervi poi usando l'indice. + // Salvando i triangoli risolvo il problema perchè ai fini dello studio di questi contatti, triangolo // e sua ritriangolazione portano al medesimo risultato. else if ( bIntOnEndgeA && bIntOnEndgeB) { auto itA = AmbiguosA.find( nTA) ; @@ -1277,7 +1277,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) RetriangulationForBooleanOperation( LineMapA, AmbiguosA, *this, bModif) ; RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ; - // Se i triangoli delle superfici non si intersecano, una delle due � totalmente interna o esterna all'altra. + // Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra. bool bRetriangulated = true ; if ( ! bModif && ( int( AmbiguosA.size()) == 0 || int( AmbiguosB.size()) == 0)) { bRetriangulated = false ; @@ -1289,7 +1289,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) int nTriaNum = - 1 ; double dMinDist = DBL_MAX ; for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - // Se il triangolo B non � valido, continuo + // Se il triangolo B non è valido, continuo Triangle3d trTriaB ; if ( ! SurfB.GetTriangle( nTB, trTriaB) || ! trTriaB.Validate( true)) continue ; @@ -1322,7 +1322,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) int nTriaNum = - 1 ; double dMinDist = DBL_MAX ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { - // Se il triangolo A non � valido, continuo + // Se il triangolo A non è valido, continuo Triangle3d trTriaA ; if ( ! ( GetTriangle( nTA, trTriaA) && trTriaA.Validate( true))) continue ; @@ -1354,7 +1354,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) } } - // Se c'� stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori. + // 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) { AmbiguosTriangleManager( AmbiguosA, *this) ; @@ -1371,7 +1371,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) // Resetto e ricalcolo la HashGrid della superficie B SurfB.ResetHashGrids3d() ; for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) { - // Se il triangolo A non � valido, continuo + // Se il triangolo A non è valido, continuo Triangle3d trTriaA ; if ( ! GetTriangle( nTA, trTriaA) || ! trTriaA.Validate( true)) continue ; @@ -1382,7 +1382,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ; for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) { - // Se il triangolo B non � valido, continuo + // Se il triangolo B non è valido, continuo Triangle3d trTriaB ; if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true)) continue ; @@ -1411,7 +1411,7 @@ bool SurfTriMesh::IdentifyParts( void) const { for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) { - // salto triangoli cancellati o gi� assegnati + // salto triangoli cancellati o già assegnati if ( m_vTria[i].nIdVert[0] == SVT_DEL || abs( m_vTria[i].nTempPart) != 1) continue ; @@ -1443,18 +1443,17 @@ SurfTriMesh::IdentifyParts( void) const bool SurfTriMesh::RemoveTJunctions(void) { - //PerformanceCounter Counter ; - // Vettore di indici dei vertici sui lati del triangolo corrente - INTMATRIX vvIndexMatrix( m_vTria.size()) ; - // Ciclo sui triangoli della superficie + unordered_map< int, INTVECTOR> TriaMap ; + + // Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro 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 + // Se il triangolo non è valido, passo al successivo Triangle3d trTria ; if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) continue ; + // Vettore degli altri vertici sul contorno del triangolo + INTVECTOR vVertOtl ; // Box del triangolo BBox3d b3Tria ; trTria.GetLocalBBox( b3Tria) ; @@ -1462,12 +1461,12 @@ SurfTriMesh::RemoveTJunctions(void) 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]) ; - // Se in questo lato il triangolo � adiacente a un altro, lo salto. + // aggiungo al vettore il vertice iniziale del lato + vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ; + // Se in questo lato il triangolo è adiacente a un altro, lo salto. if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL) continue ; - int nPrevSize = int( vIndexRow.size()) ; + int nPrevSize = int( vVertOtl.size()) ; // recupero la geometria del lato Point3d ptSegSt = trTria.GetP( nSeg) ; Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ; @@ -1478,7 +1477,7 @@ SurfTriMesh::RemoveTJunctions(void) vtSeg /= dSegLen ; // Ciclo sui triangoli vicini for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) { - // Salto il triangolo se � quello di riferimento + // Salto il triangolo se è quello di riferimento if ( vNearTria[nI] == nT) continue ; // Cerco i vertici che stanno sul lato del triangolo @@ -1488,50 +1487,66 @@ SurfTriMesh::RemoveTJunctions(void) continue ; 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]) ; - } + if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H) + vVertOtl.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) ; + auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2) + { Point3d ptV1, ptV2 ; + GetVertex( nV1, ptV1) ; + GetVertex( nV2, ptV2) ; + return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ; } ; - sort( vIndexRow.begin() + nPrevSize, vIndexRow.end(), SortVerteces) ; + sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ; + } + // Se ci sono più di 3 vertici + if ( vVertOtl.size() > 3) { + // Elimino i vertici ripetuti + vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ; + // Se ci sono ancora più di 3 vertici, inserisco nel Map + if ( vVertOtl.size() > 3) + TriaMap.emplace( nT, vVertOtl) ; } } - - //double dTime1 = Counter.Stop() ; Counter.Start() ; - - for ( int nT = 0 ; nT < int( vvIndexMatrix.size()) ; ++ nT) { - if ( vvIndexMatrix[nT].size() > 3) { - for ( auto itI = vvIndexMatrix[nT].begin() ; itI != vvIndexMatrix[nT].end() ; ) { - auto itJ = itI ; - ++ itJ ; - for ( ; itJ != vvIndexMatrix[nT].end() && *itI == *itJ ; ++ itJ) { - ; - } - auto itN = itI ; - ++ itN ; - itI = vvIndexMatrix[nT].erase( itN, itJ) ; + + // Ciclo sui triangoli da sistemare + for ( auto itT = TriaMap.begin() ; itT != TriaMap.end() ; ++ itT) { + // Indice del triangolo + int nT = itT->first ; + // Vettore degli altri vertici sul perimetro + const INTVECTOR& vVertOtl = itT->second ; + // Se il triangolo non è valido, passo al successivo + Triangle3d trTria ; + if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) + continue ; + // Rimuovo il triangolo + int nTFlag = m_vTria[nT].nTFlag ; + RemoveTriangle( nT) ; + // Se ci sono 4 vertici, inserisco due triangoli + if ( vVertOtl.size() == 4) { + // se 1-2-3 è triangolo (e quindi 0-1-3) + int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ; + if ( AddTriangle( nNew1Id, nTFlag) >= 0) { + int nNew2Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[3]} ; + AddTriangle( nNew2Id, nTFlag) ; } - // Se il triangolo non � valido, passo al successivo - Triangle3d trTria ; - if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) - continue ; - - int nTFlag = m_vTria[nT].nTFlag ; - RemoveTriangle( nT) ; - + // altrimenti 0-1-2 e 2-3-0 + else { + int nNew3Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[2]} ; + AddTriangle( nNew3Id, nTFlag) ; + int nNew4Id[3] = { vVertOtl[2], vVertOtl[3], vVertOtl[0]} ; + AddTriangle( nNew4Id, nTFlag) ; + } + } + // altrimenti inserisco un ventaglio di triangoli dal centro ai vertici + else { Point3d ptTriaCen = trTria.GetCentroid() ; int nCenIndex = AddVertex( ptTriaCen) ; - int nVertNum = int( vvIndexMatrix[nT].size()) ; + int nVertNum = int( vVertOtl.size()) ; for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) { int nEnV = ( nStV + 1) % nVertNum ; - int nNewId[3] = { nCenIndex, vvIndexMatrix[nT][nStV], vvIndexMatrix[nT][nEnV] } ; + int nNewId[3] = { nCenIndex, vVertOtl[nStV], vVertOtl[nEnV]} ; AddTriangle( nNewId, nTFlag) ; } } @@ -1621,7 +1636,7 @@ SurfTriMesh::ScanForTripleTriangles( bool& bModified) bool bCirc ; INTVECTOR vTriaIndex ; int nTriaNum = GetAllTriaAroundVertex( nV, vTriaIndex, bCirc) ; - // Se il vertice � condiviso da tre triangoli tutti adiacenti fra loro a due a due + // Se il vertice è condiviso da tre triangoli tutti adiacenti fra loro a due a due if ( nTriaNum == 3 && bCirc) { // Valuto parallelismo fra le normali int nParallel = 0 ; @@ -1634,7 +1649,7 @@ SurfTriMesh::ScanForTripleTriangles( bool& bModified) } // Se sono tutte parallele fra loro unisco i tre triangoli in uno if ( nParallel == 3) { - // Cerco gli altri triangoli adiacenti a quelli che sostituir� con il triangolo grande. + // Cerco gli altri triangoli adiacenti a quelli che sostituirò con il triangolo grande. // Cerco anche quali lati dei tre triangoli che saranno eliminati sono adiacenti a quelli esterni INTVECTOR vVertAndAdjTria ; for ( int nTria = 0 ; nTria < 3 ; ++ nTria) { @@ -1646,7 +1661,7 @@ SurfTriMesh::ScanForTripleTriangles( bool& bModified) } } } - // Cerco fra questi altri triangoli esterni sono adiacenti ai triangoli che eliminer� + // Cerco fra questi altri triangoli esterni sono adiacenti ai triangoli che eliminerò int nAdjTriaContactEdge[3] ; for ( int nAdjTria = 1 ; nAdjTria < 6 ; nAdjTria += 2) { for ( int nAdjEdge = 0 ; nAdjEdge < 3 ; ++ nAdjEdge) { @@ -1709,19 +1724,19 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB) if ( m_vTria[nTB].nIdAdjac[nEdgeB] == nTA) break ; } - // Se uno � adiacente all'altro ma non viceversa, c'� un errore + // Se uno è adiacente all'altro ma non viceversa, c'è un errore if ( ( nEdgeA == 3 && nEdgeB < 3) || ( nEdgeA < 3 && nEdgeB == 3)) return false ; // Se non sono adiacenti, ho finito else if ( nEdgeA == 3 && nEdgeB == 3) return true ; - // Se non trovo i vertici del triangolo A, c'� un errorre + // Se non trovo i vertici del triangolo A, c'è un errorre Point3d ptSegSt, ptSegEn, ptVertA ; if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) || ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) || ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA)) return false ; - // Se non trovo i vertici del triangolo B, c'� un errorre + // Se non trovo i vertici del triangolo B, c'è un errorre Point3d ptVertB ; if ( ! GetVertex( m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3], ptVertB)) return false ; @@ -1749,15 +1764,19 @@ bool SurfTriMesh::Add( const ISurfTriMesh& Other) { m_OGrMgr.Clear() ; + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + IntersectTriMeshTriangle( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; + int nTriaNumA = GetTriangleSize() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == - 2) @@ -1776,12 +1795,21 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) AddTriangle( nNewVert, m_nMaxTFlag) ; } } + bool bOk = ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTripleTriangles() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTJunctions() ; + + //bOk && RemoveTripleTriangles() ; + //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + + bOk = bOk && RemoveTJunctions() ; bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; + + // cerco di semplificare le facce + if ( ! SimplifyFacets( 5000.0, true)) + LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Add") + return bOk ; } @@ -1790,15 +1818,19 @@ bool SurfTriMesh::Intersect( const ISurfTriMesh& Other) { m_OGrMgr.Clear() ; + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + IntersectTriMeshTriangle( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; + int nTriaNumA = GetTriangleSize() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2) @@ -1817,12 +1849,20 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) AddTriangle( nNewVert, m_nMaxTFlag) ; } } + bool bOk = ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTripleTriangles() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTJunctions() ; + + //bOk && RemoveTripleTriangles() ; + //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + + bOk = bOk && RemoveTJunctions() ; bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; + + if ( ! SimplifyFacets( 5000.0, true)) + LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Intersect") + return bOk ; } @@ -1831,15 +1871,19 @@ bool SurfTriMesh::Subtract( const ISurfTriMesh& Other) { m_OGrMgr.Clear() ; + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + Frame3d frScalingRef; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + IntersectTriMeshTriangle( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; + int nTriaNumA = GetTriangleSize() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == 2) @@ -1859,12 +1903,20 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) AddTriangle( nNewVert, m_nMaxTFlag) ; } } + bool bOk = ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTripleTriangles() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTJunctions() ; + + //bOk && RemoveTripleTriangles() ; + //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + + bOk = bOk && RemoveTJunctions() ; bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; + + if ( ! SimplifyFacets( 5000.0, true)) + LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Intersect") + return bOk ; } @@ -1880,12 +1932,15 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf, return false ; if ( m_vVert.empty() || m_vTria.empty()) return true ; + SurfTriMesh SurfC ; SurfC.CopyFrom( &ClassifierSurf) ; + Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfC.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + IntersectTriMeshTriangle( SurfC) ; IdentifyParts() ; Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; @@ -1912,6 +1967,7 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf, break ; } } + return true ; } diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index c467009..4c48646 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -46,6 +46,7 @@ SurfTriMesh::UpdateFaceting( void) { // reset faceting m_bFaceted = false ; + m_vFacet.clear() ; for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) m_vTria[i].nIdFacet = SVT_NULL ; diff --git a/SurfTriMeshUtilities.cpp b/SurfTriMeshUtilities.cpp index ee7f2cc..039d5f4 100644 --- a/SurfTriMeshUtilities.cpp +++ b/SurfTriMeshUtilities.cpp @@ -163,7 +163,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif) //---------------------------------------------------------------------------- bool -SurfTriMesh::SimplifyFacets( double dMaxEdgeLen) +SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced) { // La trimesh deve essere valida if ( ! IsValid()) @@ -184,7 +184,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen) GetFacetLoops( nF, LoopVec) ; // Ciclo sui loop della faccia - bool bToRetriangulate = false ; + bool bToRetriangulate = bForced ; for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL) { // Lista dei punti del loop @@ -202,7 +202,24 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen) bToRetriangulate = true ; } - // Se da ritriangolare, + // Se non richiesta ritriangolazione dai bordi, verifico se ci sono vertici di triangoli interni + if ( false && ! bToRetriangulate) { + // numero dei triangoli nella faccia + INTVECTOR vFacetTria ; + GetAllTriaInFacet( nF, vFacetTria) ; + int nTriaCnt = int( vFacetTria.size()) ; + // numero dei lati di contorno della faccia + int nSideCnt = 0 ; + for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL) + nSideCnt += LoopVec[nL].GetLineNbr() ; + // numero dei buchi della faccia + int nHoleCnt = int( LoopVec.size()) - 1 ; + // dalla formula di Eulero adattata al caso ( nTriaCnt = nSideCnt + 2 * ( nHoleCnt -1)) + if ( nTriaCnt != nSideCnt + 2 * ( nHoleCnt - 1)) + bToRetriangulate = true ; + } + + // Se da ritriangolare if ( bToRetriangulate) { // Eseguo la ritriangolazione della faccia PNTVECTOR vPt ; @@ -217,28 +234,30 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen) } // Ciclo sulle facce da ritriangolare per eliminare i triangoli (nel contempo salvo flag colore) + INTVECTOR vDelTria ; unordered_map< int, int> ColorMap ; for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) { // Recupero i triangoli della faccia INTVECTOR vFacetTria ; GetAllTriaInFacet( itF->first, vFacetTria) ; + vDelTria.insert( vDelTria.end(), vFacetTria.begin(), vFacetTria.end()) ; // Salvo il colore della faccia da flag di un suo triangolo ColorMap.emplace( itF->first, m_vTria[m_vFacet[itF->first]].nTFlag) ; - // Cancello i triangoli della faccia. - for ( int nT : vFacetTria) - RemoveTriangle( nT) ; } + // Cancello i triangoli + for ( int nT : vDelTria) + RemoveTriangle( nT) ; // Applico le nuove triangolazioni delle facce - for ( auto itFac = FacetMap.begin() ; itFac != FacetMap.end() ; ++ itFac) { - const PNTVECTOR& vPt = itFac->second.first ; - const INTVECTOR& vTr = itFac->second.second ; + for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) { + const PNTVECTOR& vPt = itF->second.first ; + const INTVECTOR& vTr = itF->second.second ; // Inserisco i nuovi triangoli for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { int nNewId[3] = { AddVertex( vPt[vTr[n]]), AddVertex( vPt[vTr[n + 1]]), AddVertex( vPt[vTr[n + 2]])} ; - auto itCol = ColorMap.find( itFac->first) ; + auto itCol = ColorMap.find( itF->first) ; int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ; int nNewTriaId = AddTriangle( nNewId, nTFlag) ; }