From 009328b31bfcfaf1c2b1b6aaab8a97dad0fc93f3 Mon Sep 17 00:00:00 2001 From: LorenzoM Date: Tue, 7 Dec 2021 09:43:59 +0100 Subject: [PATCH] Migliorie operazioni booleane e intersezione triangoli --- IntersTriaTria.cpp | 31 +++++++++- SurfTriMeshBooleans.cpp | 129 +++++++++++++++++++++++++++++++--------- 2 files changed, 129 insertions(+), 31 deletions(-) diff --git a/IntersTriaTria.cpp b/IntersTriaTria.cpp index 03cf31e..177ebf3 100644 --- a/IntersTriaTria.cpp +++ b/IntersTriaTria.cpp @@ -83,8 +83,35 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p // se i triangoli sono complanari if ( nResPP == IPPT_OVERLAPS || ((( nVertPos1 == 0 && nVertNeg1 == 0) || ( nVertPos2 == 0 && nVertNeg2 == 0)) && - ( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL)) - return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ; + ( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL)) { + bool bCounter = false ; + Triangle3d trMyTria2 = trTria2 ; + if ( trTria1.GetN() * trTria2.GetN() < 0) { + Point3d ptV0 = trMyTria2.GetP( 0) ; + trMyTria2.SetP( 0, trMyTria2.GetP( 1)) ; + trMyTria2.SetP( 1, ptV0) ; + trMyTria2.Validate() ; + bCounter = true ; + } + bool bAreSameTria = ( ( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 0)) && + AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 1)) && + AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 2))) || + ( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 1)) && + AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 2)) && + AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 0))) || + ( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 2)) && + AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 0)) && + AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 1)))) && + ( AreSameVectorExact( trTria1.GetN(), trMyTria2.GetN())) ; + if ( bAreSameTria) { + vTria.emplace_back( trTria1) ; + return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ; + } + if ( ITTT_OVERLAPS == IntersCoplanarTriaTria( trTria1, trMyTria2, vTria)) { + return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ; + } + return ITTT_NO ; + } // limito la linea di intersezione con il primo triangolo Point3d ptSt1, ptEn1 ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 2b199d5..ac5cc01 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -27,6 +27,7 @@ #include "/EgtDev/Include/EGkIntersLineTria.h" #include "/EgtDev/Include/EGkIntersLineBox.h" #include "/EgtDev/Include/EGkIntersPlanePlane.h" +#include "/EgtDev/Include/EGkIntersPlaneTria.h" #include "/EgtDev/Include/EGkIntersTriaTria.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkChainCurves.h" @@ -125,7 +126,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA nCvSecond = nLine ; } } - + if ( nCvFirst != nCvSecond && nCvSecond != - 1) { // li ordino in senso crescente if ( nCvFirst > nCvSecond) @@ -444,6 +445,57 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } } + // Gestione tagli piccoli + if ( int( cvOpenChain.size()) == 1 && int( cvOpenChain[0].size()) == 1 && int( cvClosedChain.size()) == 0) { + if ( AreSamePointEpsilon( cvOpenChain[0][0].ptSt, cvOpenChain[0][0].ptEn, EPS_SMALL)) { + Plane3d plPlane ; + plPlane.Set( cvOpenChain[0][0].ptSt, cvOpenChain[0][0].vtOuter) ; + Point3d ptIntSt, ptIntEn ; + int nPlaneTriaInt = IntersPlaneTria( plPlane, trTria, ptIntEn, ptIntSt) ; + if ( nPlaneTriaInt == IPTT_YES) { + int nOldTriaCol = Surf.m_vTria[it->first].nTFlag ; + Surf.RemoveTriangle( it->first) ; + int nDist[3] ; + for ( int nV = 0 ; nV < 3 ; ++ nV) { + double dD = - DistPointPlane( trTria.GetP( nV), plPlane) ; + nDist[nV] = ( abs( dD) < EPS_SMALL ? 0 : ( dD > 0 ? 1 : - 1)) ; + } + int nAloneVert = ( nDist[0] == nDist[1] ? 2 : ( nDist[0] == nDist[2] ? 1 : 0)) ; + if ( nDist[nAloneVert] == - 1) { + swap( ptIntSt, ptIntEn) ; + } + int nNewAloneId[3] = { Surf.AddVertex( trTria.GetP( nAloneVert)), Surf.AddVertex( ptIntSt), Surf.AddVertex( ptIntEn) } ; + int nNewAloneTriaNum = Surf.AddTriangle( nNewAloneId, nOldTriaCol) ; + if ( IsValidSvt( nNewAloneTriaNum)) { + Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ; + Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ; + Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ; + Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ; + bModif = true ; + } + int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ; + int nNewCoupleTriaNum1 = Surf.AddTriangle( nNewCoupleId1, nOldTriaCol) ; + if ( IsValidSvt( nNewCoupleTriaNum1)) { + Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ; + Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ; + Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ; + Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ; + bModif = true ; + } + int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ; + int nNewCoupleTriaNum2 = Surf.AddTriangle( nNewCoupleId2, nOldTriaCol) ; + if ( IsValidSvt( nNewCoupleTriaNum2)) { + Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ; + Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ; + Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ; + Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ; + bModif = true ; + } + continue ; + } + } + } + // 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 @@ -1339,9 +1391,12 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) Point3d ptTempA, ptTempB ; int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ; if ( nIntTypeAB == ITTT_OVERLAPS) { - bool bInvertB = trTriaA.GetN() * trTriaB.GetN() < 0. ; - m_vTria[nTA].nTempPart = ( bInvertB ? -2 : 2) ; - SurfB.m_vTria[vNearTria[nTB]].nTempPart = ( bInvertB ? - 2 : 2) ; + m_vTria[nTA].nTempPart = 2 ; + SurfB.m_vTria[vNearTria[nTB]].nTempPart = 2 ; + } + else if ( nIntTypeAB == ITTT_COUNTER_OVERLAPS) { + m_vTria[nTA].nTempPart = - 2 ; + SurfB.m_vTria[vNearTria[nTB]].nTempPart = - 2 ; } } } @@ -1409,6 +1464,9 @@ SurfTriMesh::RemoveTJunctions(void) 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. + if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL) + continue ; int nPrevSize = int( vIndexRow.size()) ; // recupero la geometria del lato Point3d ptSegSt = trTria.GetP( nSeg) ; @@ -1426,10 +1484,11 @@ SurfTriMesh::RemoveTJunctions(void) // 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) ; + if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert)) + 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) { + if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < /*10 * BOOLEAN_SCALE **/ SQ_EPS_TRIA_H) { vIndexRow.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ; } } @@ -1446,34 +1505,38 @@ SurfTriMesh::RemoveTJunctions(void) } //double dTime1 = Counter.Stop() ; Counter.Start() ; - + for ( int nT = 0 ; nT < int( vvIndexMatrix.size()) ; ++ nT) { if ( vvIndexMatrix[nT].size() > 3) { - PolyLine Polygon ; - for ( int nV = 0 ; nV < int( vvIndexMatrix[nT].size()) ; ++ nV) { - Point3d ptPt; - GetVertex( vvIndexMatrix[nT][nV], ptPt) ; - Polygon.AddUPoint( 0., ptPt) ; - } - Polygon.Close() ; - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( Polygon, vPt, vTr)) { - // Rimuovo il triangolo originale e salvo il suo flag - int nTFlag = m_vTria[nT].nTFlag ; - RemoveTriangle( nT) ; - // Inserisco i nuovi triangoli che lo sostituiscono e asegno loro lo stesso flag - 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, nTFlag) ; + 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) ; + } + // 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) ; + + Point3d ptTriaCen = trTria.GetCentroid() ; + int nCenIndex = AddVertex( ptTriaCen) ; + int nVertNum = int( vvIndexMatrix[nT].size()) ; + for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) { + int nEnV = ( nStV + 1) % nVertNum ; + int nNewId[3] = { nCenIndex, vvIndexMatrix[nT][nStV], vvIndexMatrix[nT][nEnV] } ; + AddTriangle( nNewId, nTFlag) ; } } } - + return true ; } @@ -3662,10 +3725,18 @@ SurfTriMesh::IntersectTriMeshFacets( SurfTriMesh& Other) IsPointInsideTriangle( ptIntTriaCentroid, trTriaB, TriangleType::EXACT) ; } // Se l'intersezeione è corretta e i triangoli sono sovrapposti aggiorno gli indici. - if ( nIntTypeAB == ITTT_OVERLAPS && bSuccesfullInters) { + /*if ( nIntTypeAB == ITTT_OVERLAPS && bSuccesfullInters) { bool bInvertB = trTriaA.GetN() * trTriaB.GetN() < 0. ; m_vTria[nTA].nTempPart = ( bInvertB ? -2 : 2) ; SurfB.m_vTria[vNearTria[nTB]].nTempPart = ( bInvertB ? - 2 : 2) ; + }*/ + if ( nIntTypeAB == ITTT_OVERLAPS && bSuccesfullInters) { + m_vTria[nTA].nTempPart = 2 ; + SurfB.m_vTria[vNearTria[nTB]].nTempPart = 2 ; + } + else if ( nIntTypeAB == ITTT_COUNTER_OVERLAPS && bSuccesfullInters) { + m_vTria[nTA].nTempPart = - 2 ; + SurfB.m_vTria[vNearTria[nTB]].nTempPart = - 2 ; } } }