From fd2396fb1b537659905fd51a635ad7cb60eba98e Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 20 Feb 2020 08:59:39 +0000 Subject: [PATCH] EgtGeomKernel 2.2b3 : - correzioni per triangoli che scompaiono in booleane di trimesh. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes IntersLineTria.cpp | 3 + SurfTriMeshBooleans.cpp | 205 ++++++++++++++++++++++++++++++++-------- 3 files changed, 171 insertions(+), 37 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 8b77bab04cf6f3819567df9c3a9ce09f52f0cd7c..5b6efb7170b11f91786478fdf45c8d15fa345895 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&Qw&A-_cnHh~ID{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-W11TR delta 94 zcmdlNy)SyhFE&P_&A-_cnHh~HD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-Vf-5U diff --git a/IntersLineTria.cpp b/IntersLineTria.cpp index 01647f2..7365212 100644 --- a/IntersLineTria.cpp +++ b/IntersLineTria.cpp @@ -164,6 +164,9 @@ IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, co swap( dUmin, dUmax) ; swap( ptInt, ptInt2) ; } + // Per garantire l'appartenenza dei punti alla linea li ricalcolo + ptInt = ptL + dUmin * vtL ; + ptInt2 = ptL + dUmax * vtL ; // Se linea infinita if ( ! bFinite) { return ILTT_SEGM_ON_EDGE ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 9213769..9fc03b7 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -745,7 +745,8 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA PNTVECTOR Loop1, Loop2 ; bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ; bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ; - if ( ! ( bChangedStart && bSplitted)) + if ( ! ( bChangedStart && bSplitted) || + ( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2))) continue ; bLoopSplitted = true ; Chain cvCounterChain ; @@ -1083,8 +1084,61 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT BOOLVECTOR vbInOut ; vbInOut.push_back( true) ; // Divido il loop usando le catene - if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) - continue ; + if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) { + if ( int( cvBoundClosedLoopVec.size()) == 1 && int( cvOpenChain.size()) == 2) { + Point3d ptLink0St = cvOpenChain[0][0].ptSt ; + Point3d ptLink0En = cvOpenChain[0].back().ptEn ; + Point3d ptLink1St = cvOpenChain.back()[0].ptSt ; + Point3d ptLink1En = cvOpenChain.back().back().ptEn ; + double dDist01 = sqrt( ( ptLink0En - ptLink1St) * ( ptLink0En - ptLink1St)) ; + double dDist10 = sqrt( ( ptLink1En - ptLink0St) * ( ptLink1En - ptLink0St)) ; + if ( dDist01 < 2 * EPS_SMALL) { + IntSegment LinkingSeg ; + LinkingSeg.ptSt = ptLink0En ; + LinkingSeg.ptEn = ptLink1St ; + LinkingSeg.vtOuter = cvOpenChain[0].back().vtOuter ; + LinkingSeg.bDegenerate = false ; + cvOpenChain[0].emplace_back( LinkingSeg) ; + for ( int nLinkI = 0 ; nLinkI < int( cvOpenChain.back().size()) ; ++ nLinkI) { + cvOpenChain[0].emplace_back( cvOpenChain.back()[nLinkI]) ; + } + cvOpenChain.resize( 1) ; + int nComplDeg = vnDegVec[0] * vnDegVec[1] ; + vnDegVec[0] = nComplDeg ; + vnDegVec.resize( 1) ; + } + else if ( dDist10 < 2 * EPS_SMALL) { + IntSegment LinkingSeg ; + LinkingSeg.ptSt = cvOpenChain.back().back().ptEn ; + LinkingSeg.ptEn = cvOpenChain[0].back().ptSt ; + LinkingSeg.vtOuter = cvOpenChain.back().back().vtOuter ; + LinkingSeg.bDegenerate = false ; + cvOpenChain.back().emplace_back( LinkingSeg) ; + for ( int nLinkI = 0 ; nLinkI < int( cvOpenChain[0].size()) ; ++ nLinkI) { + cvOpenChain.back().emplace_back( cvOpenChain[0][nLinkI]) ; + } + cvOpenChain.erase( cvOpenChain.begin()) ; + int nComplDeg = vnDegVec[0] * vnDegVec[1] ; + vnDegVec[0] = nComplDeg ; + vnDegVec.resize( 1) ; + } + else { + Surf.m_vTria[it->first].nTempPart = 0 ; + continue ; + } + vbInOut.resize( 1) ; + vbInOut[0] = true ; + if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) { + Surf.m_vTria[it->first].nTempPart = 0 ; + continue ; + } + } + else { + Surf.m_vTria[it->first].nTempPart = 0 ; + /*Surf.m_vTria[it->first].nTempPart *= 10 ;*/ + continue ; + } + } // Rimuovo il triangolo corrente Surf.RemoveTriangle( it->first) ; // Trasformo i loop compositi in loop polyline @@ -1203,8 +1257,16 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT vInnerLoop.emplace_back( nCLI) ; } } - - if ( vInnerLoop.size() == 0) { + // Elimino loop interni non validi + bool bDouble = true ; + for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) { + if ( int( cvClosedChain[vInnerLoop[nInnLoop]].size()) > 2) { + bDouble = false ; + break ; + } + } + + if ( vInnerLoop.size() == 0 || bDouble) { // Eseguo triangolazione PNTVECTOR vPt ; INTVECTOR vTr ; @@ -1297,33 +1359,101 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT //---------------------------------------------------------------------------- bool -SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) -{ - for ( auto it = Ambiguos.begin() ; it != Ambiguos.end() ; ++ it) { - Triangle3d trTria ; - Surf.GetTriangle( it->first, trTria) ; - trTria.Validate() ; - Point3d ptBar = ( trTria.GetP( 0) + trTria.GetP( 1) + trTria.GetP( 2)) / 3 ; - double dMinDist = DBL_MAX ; - int nTriaIndex = - 1 ; - for ( int nOthSurfT = 0 ; nOthSurfT < int( it->second.size()) ; ++ nOthSurfT) { - Triangle3d trOthSurfTria = it->second[nOthSurfT] ; - double dDot = ( ptBar - trOthSurfTria.GetP( 0)) * trOthSurfTria.GetN() ; - if ( abs( dDot) > EPS_SMALL) { - double dDist ; - if ( DistPointTriangle( ptBar, trOthSurfTria).GetDist( dDist) && dDist < dMinDist) { - nTriaIndex = nOthSurfT ; - dMinDist = dDist ; +FindTriaIncidence( const Triangle3d& trTria, const TRIA3DVECTOR& vOthTriaVec, INTMATRIX& vAdjSegToCurTria) +{ + int nNumFoundContact = 0 ; + vAdjSegToCurTria.resize( 3) ; + for ( int nEdge = 0 ; nEdge < 3 ; ++ nEdge) { + for ( int nOther = 0 ; nOther < int( vOthTriaVec.size()) ; ++ nOther) { + Triangle3d trOthTria = vOthTriaVec[nOther] ; + Point3d ptSt = trTria.GetP( nEdge) ; + Point3d ptEn = trTria.GetP( ( nEdge + 1) % 3) ; + CurveLine cvEdgeLine ; + cvEdgeLine.Set( ptSt, ptEn) ; + for ( int nOthEdge = 0 ; nOthEdge < 3 ; ++ nOthEdge) { + Point3d ptOthSt = trOthTria.GetP( nOthEdge) ; + Point3d ptOthEn = trOthTria.GetP( ( nOthEdge + 1) % 3) ; + CurveLine cvOthEdgeLine ; + cvOthEdgeLine.Set( ptOthSt, ptOthEn) ; + DistPointLine DistCalculatorCurOth( 0.5 * ( ptSt + ptEn), cvOthEdgeLine, false) ; + double dSqDistCurOth ; + DistCalculatorCurOth.GetSqDist( dSqDistCurOth) ; + DistPointLine DistCalculatorOthCur( 0.5 * ( ptOthSt + ptOthEn), cvEdgeLine, false) ; + double dSqDistOthCur ; + DistCalculatorOthCur.GetSqDist( dSqDistOthCur) ; + if ( dSqDistCurOth < EPS_SMALL * EPS_SMALL && dSqDistOthCur < EPS_SMALL * EPS_SMALL) { + vAdjSegToCurTria[nEdge].emplace_back( nOther) ; + ++ nNumFoundContact ; } } } - if ( nTriaIndex != -1) { - Triangle3d trOthSurfTria = it->second[nTriaIndex] ; - trOthSurfTria.Validate() ; - double dDot = ( ptBar - trOthSurfTria.GetP( 0)) * trOthSurfTria.GetN() ; - Surf.m_vTria[it->first].nTempPart = ( dDot < 0 ? 1 : -1) ; + } + if (nNumFoundContact != int(vOthTriaVec.size())) + int dudu = 0 ; + return ( nNumFoundContact == int( vOthTriaVec.size())) ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) +{ + 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. + if ( Surf.m_vTria[it->first].nTempPart != 0) + continue ; + // Recupero il triangolo corrente + Triangle3d trTria ; + Surf.GetTriangle( it->first, trTria) ; + trTria.Validate() ; + // Vettore dei triangoli i cui edge incidono su quelli del triangolo corrente + TRIA3DVECTOR& vOthTriaVec = it->second ; + // Vettore degli indici dei segmenti del triangolo adiacenti agli altri triangoli + INTMATRIX vAdjSegToCurTria ; + if ( ! FindTriaIncidence( trTria, vOthTriaVec, vAdjSegToCurTria)) + return false ; + // Classifico il triangolo in base ai triangoli che incidono sui suoi edge + int nTriaClassificationByEdges[3] = { 0, 0, 0 } ; + for ( int nEdge = 0 ; nEdge < 3 ; ++ nEdge) { + if ( int( vAdjSegToCurTria[nEdge].size()) == 0) + continue ; + // Calcolo la normale media ai triangoli che incidono sull'edge corrente + Vector3d vtAvVec ; + for ( int nTr = 0 ; nTr < int( vAdjSegToCurTria[nEdge].size()) ; ++ nTr) { + vtAvVec += vOthTriaVec[vAdjSegToCurTria[nEdge][nTr]].GetN() ; + } + // Calcolo il vettore ortogonale all'edge corrente che punta al baricentro del triangolo corrente + Point3d ptBar = ( trTria.GetP(0) + trTria.GetP(1) + trTria.GetP(2)) / 3. ; + Vector3d vtBarVec = ptBar - trTria.GetP( nEdge) ; + Vector3d vtEdgeDir = trTria.GetP( ( nEdge + 1) % 3) - trTria.GetP( nEdge) ; + vtEdgeDir.Normalize() ; + vtBarVec -= ( vtBarVec * vtEdgeDir) * vtEdgeDir ; + // Se entrambi i vettori sono definiti classifico il triangolo in modo opportuno + if ( vtBarVec.Normalize( 0.01 * EPS_SMALL) && vtAvVec.Normalize( 0.01 * EPS_SMALL)) { + if ( vtBarVec * vtAvVec < - EPS_ZERO) { + nTriaClassificationByEdges[nEdge] = 1 ; + } + else if ( vtBarVec * vtAvVec > EPS_ZERO) { + nTriaClassificationByEdges[nEdge] = -1 ; + } + } } - } + // Verifico che le classificazioni siano coerenti + for ( int i = 0 ; i < 3 ; ++ i) { + if ( nTriaClassificationByEdges[i] == 0) + continue ; + Surf.m_vTria[it->first].nTempPart = nTriaClassificationByEdges[i] ; + int j ; + for ( j = i + 1 ; j < 3 ; ++ j) { + if ( nTriaClassificationByEdges[j] != 0 && nTriaClassificationByEdges[i] != nTriaClassificationByEdges[j]) { + Surf.m_vTria[it->first].nTempPart = 0 ; + break ; + } + } + if ( j < 3) + break ; + } + } return true ; } @@ -2080,15 +2210,16 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf, } ///////////////////////// DEBUG ///////////////////////////////////////////////////////////////////////////////////////////////// -//if ( ( AreSamePointApprox(trTriaA.GetP(0), Point3d(0.6312, 42.0801, 100)) && -// AreSamePointApprox(trTriaA.GetP(1), Point3d(0.3554, 44.0491, 100)) && -// AreSamePointApprox(trTriaA.GetP(2), Point3d(0.6312, 42.0801, 0))) || -// ( AreSamePointApprox(trTriaA.GetP(2), Point3d(0.6312, 42.0801, 100)) && -// AreSamePointApprox(trTriaA.GetP(0), Point3d(0.3554, 44.0491, 100)) && -// AreSamePointApprox(trTriaA.GetP(1), Point3d(0.6312, 42.0801, 0))) || -// ( AreSamePointApprox(trTriaA.GetP(1), Point3d(0.6312, 42.0801, 100)) && -// AreSamePointApprox(trTriaA.GetP(2), Point3d(0.3554, 44.0491, 100)) && -// AreSamePointApprox(trTriaA.GetP(0), Point3d(0.6312, 42.0801, 0)))) { +//if ( nTriaNumB == 76 && +// ( AreSamePointApprox(trTriaA.GetP(0), Point3d( 920.5333, 0.0000, 190.5)) && +// AreSamePointApprox(trTriaA.GetP(1), Point3d( 1150.6666, 0.0000, 190.5)) && +// AreSamePointApprox(trTriaA.GetP(2), Point3d( 920.5333, 245.89, 190.5))) || +// ( AreSamePointApprox(trTriaA.GetP(2), Point3d( 920.5333, 0.0000, 190.5)) && +// AreSamePointApprox(trTriaA.GetP(0), Point3d( 1150.6666, 0.0000, 190.5)) && +// AreSamePointApprox(trTriaA.GetP(1), Point3d( 920.5333, 245.89, 190.5))) || +// ( AreSamePointApprox(trTriaA.GetP(1), Point3d( 920.5333, 0.0000, 190.5)) && +// AreSamePointApprox(trTriaA.GetP(2), Point3d( 1150.6666, 0.0000, 190.5)) && +// AreSamePointApprox(trTriaA.GetP(0), Point3d( 920.5333, 245.89, 190.5)))) { // int a = 0 ; //} //