From 59f5c16c3b006fa1e91abe2a5df4f7db297b246b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 19 Dec 2023 10:19:03 +0100 Subject: [PATCH] EgtGeomKernel : - correzione alle intersezioni tra trimesh. --- SurfTriMeshBooleans.cpp | 135 ++++++++++++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 20 deletions(-) diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index c3dfa8e..1704a4d 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -1272,6 +1272,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ; // Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra. + // non mi basta fare un controllo sulle bbox perché non so come sono orientate le superfici e che potrebbero anche non essere chiuse bool bRetriangulated = true ; if ( ! bModif && ( int( AmbiguosA.size()) == 0 || int( AmbiguosB.size()) == 0)) { bRetriangulated = false ; @@ -1280,7 +1281,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) int nCurVert = GetFirstVertex( ptFirstV) ; int nInOutNum = 0 ; while ( nInOutNum == 0 && nCurVert != SVT_NULL) { - int nTriaNum = - 1 ; + INTVECTOR vnTriaNum ; double dMinDist = DBL_MAX ; for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { // Se il triangolo B non è valido, continuo @@ -1288,18 +1289,66 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) if ( ! SurfB.GetTriangle( nTB, trTriaB) || ! trTriaB.Validate( true)) continue ; double dDist ; - if ( DistPointTriangle( ptFirstV, trTriaB).GetDist( dDist) && dDist < dMinDist) { - nTriaNum = nTB ; - dMinDist = dDist ; + // potrei trovare più triangolo equidistanti, li salvo tutti + if ( DistPointTriangle( ptFirstV, trTriaB).GetDist( dDist)) { + if ( abs(dDist - dMinDist) < EPS_SMALL) + vnTriaNum.push_back( nTB) ; + else if ( dDist < dMinDist){ + vnTriaNum.clear() ; + vnTriaNum.push_back( nTB) ; + dMinDist = dDist ; + } } } - if ( nTriaNum >= 0) { + if ( ! vnTriaNum.empty()) { Triangle3d trTriaB ; - SurfB.GetTriangle( nTriaNum, trTriaB) ; - if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) - nInOutNum = 1 ; - else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) - nInOutNum = - 1 ; + bool bSame = true ; + // controllo se rispetto a questi triangoli il punto risulta sempre fuori o sempre dentro + for ( int nTriaNum : vnTriaNum) { + SurfB.GetTriangle( nTriaNum, trTriaB) ; + if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) { + if ( nInOutNum == 0) + nInOutNum = 1 ; + else if (nInOutNum == -1) { + bSame = false ; + break ; + } + } + else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) { + if ( nInOutNum == 0) + nInOutNum = -1 ; + else if (nInOutNum == 1) { + bSame = false ; + break ; + } + } + } + // se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino + // e ricalcolo l'informazione che mi dà la sua normale + if ( ! bSame ) { + Point3d ptBar_tot ; + for (int nTriaNum : vnTriaNum) { + SurfB.GetTriangle( nTriaNum, trTriaB) ; + ptBar_tot += trTriaB.GetCentroid(); + } + ptBar_tot /= (int)vnTriaNum.size() ; + for (int nTriaNum : vnTriaNum) { + SurfB.GetTriangle( nTriaNum, trTriaB) ; + Point3d ptInters1, ptInters2 ; + int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ; + if (nInters == ILTT_NO) + continue ; + else if ( nInters == ILTT_IN ) { + if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) + nInOutNum = 1 ; + else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) + nInOutNum = -1 ; + break ; + } + else + nInOutNum = 0 ; + } + } } if ( nInOutNum == 0) { nCurVert = GetNextVertex( nVertNum, ptFirstV) ; @@ -1313,7 +1362,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) nCurVert = SurfB.GetFirstVertex( ptFirstV) ; nInOutNum = 0 ; while ( nInOutNum == 0 && nCurVert != SVT_NULL) { - int nTriaNum = - 1 ; + INTVECTOR vnTriaNum ; double dMinDist = DBL_MAX ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { // Se il triangolo A non è valido, continuo @@ -1323,19 +1372,65 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) DistPointTriangle DistCalculator( ptFirstV, trTriaA) ; double dDist ; DistCalculator.GetDist( dDist) ; - if ( dDist < dMinDist) { - nTriaNum = nTA ; - dMinDist = dDist ; + // potrei trovare più triangolo equidistanti, li salvo tutti + if ( DistPointTriangle( ptFirstV, trTriaA).GetDist( dDist)) { + if ( abs(dDist - dMinDist) < EPS_SMALL) + vnTriaNum.push_back( nTA) ; + else if ( dDist < dMinDist){ + vnTriaNum.clear() ; + vnTriaNum.push_back( nTA) ; + dMinDist = dDist ; + } } } - if ( nTriaNum >= 0) { + if ( ! vnTriaNum.empty()) { Triangle3d trTriaA ; - GetTriangle( nTriaNum, trTriaA) ; - if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL) { - nInOutNum = 1 ; + bool bSame = true ; + // controllo se rispetto a questi triangoli il punto risulta sempre fuori o sempre dentro + for ( int nTriaNum : vnTriaNum) { + GetTriangle( nTriaNum, trTriaA) ; + if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) { + if ( nInOutNum == 0) + nInOutNum = 1 ; + else if (nInOutNum == -1) { + bSame = false ; + break ; + } + } + else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) { + if ( nInOutNum == 0) + nInOutNum = -1 ; + else if (nInOutNum == 1) { + bSame = false ; + break ; + } + } } - else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) { - nInOutNum = - 1 ; + // se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino + // e ricalcolo l'informazione che mi dà la sua normale + if ( ! bSame ) { + Point3d ptBar_tot ; + for (int nTriaNum : vnTriaNum) { + GetTriangle( nTriaNum, trTriaA) ; + ptBar_tot += trTriaA.GetCentroid(); + } + ptBar_tot /= (int)vnTriaNum.size() ; + for (int nTriaNum : vnTriaNum) { + GetTriangle( nTriaNum, trTriaA) ; + Point3d ptInters1, ptInters2 ; + int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ; + if (nInters == ILTT_NO) + continue ; + else if ( nInters == ILTT_IN ) { + if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) + nInOutNum = 1 ; + else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) + nInOutNum = -1 ; + break ; + } + else + nInOutNum = 0 ; + } } } if ( nInOutNum == 0) {