//---------------------------------------------------------------------------- // EgalTech 2018-2018 //---------------------------------------------------------------------------- // File : IntersSurfTmSurfTm.cpp Data : 27.08.18 Versione : 1.9h3 // Contenuto : Implementazione della intersezione tra due superfici trimesh. // // // // Modifiche : 27.08.18 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "HashGrids3d.h" #include "DistPointLine.h" #include "IntersLineTria.h" #include "DllMain.h" #include "/EgtDev/Include/EGkIntersSurfTmSurfTm.h" #include "/EgtDev/Include/EGkIntersTriaTria.h" #include "/EgtDev/Include/EGkPointGrid3d.h" #include "/EgtDev/Include/EGkDistPointTria.h" #include "/EgtDev/Include/EgnStringUtils.h" #include using namespace std ; //---------------------------------------------------------------------------- // Intersezione di due superficie TriMesh //---------------------------------------------------------------------------- bool IntersSurfTmSurfTm( const ISurfTriMesh& Stm1, const ISurfTriMesh& Stm2, PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria) { // verifico superfici if ( &Stm1 == nullptr || ! Stm1.IsValid() || &Stm2 == nullptr || ! Stm2.IsValid()) return false ; // verifico parametri di ritorno if ( &vPnt == nullptr || &vBpt == nullptr || &vTria == nullptr) return false ; vPnt.clear() ; vBpt.clear() ; vTria.clear() ; // per ricerca veloce di punti ripetuti PointGrid3d PtGrid ; PtGrid.Init( 100) ; // per ricerca veloce di linee ripetute HashGrids3d LnGrid ; LnGrid.SetActivationGrid( true) ; // per ricerca veloce di triangoli ripetuti HashGrids3d TrGrid ; TrGrid.SetActivationGrid( true) ; // creo HashGrids3d per superficie con maggior numero di elementi int nTriaNbr1 = Stm1.GetTriangleCount() ; int nTriaNbr2 = Stm2.GetTriangleCount() ; bool bHash1 = ( nTriaNbr1 > nTriaNbr2) ; HashGrids3d HHGrids ; const int LIM_SRFNBRSQUARED = 4095 ; HHGrids.SetActivationGrid( long long( nTriaNbr1) * long long(nTriaNbr2) > LIM_SRFNBRSQUARED) ; Triangle3d Tria ; int nT = ( bHash1 ? Stm1.GetFirstTriangle( Tria) : Stm2.GetFirstTriangle( Tria)) ; while ( nT != SVT_NULL) { BBox3d boxT ; Tria.GetLocalBBox( boxT) ; if ( ! HHGrids.Add( nT, boxT)) return false ; nT = ( bHash1 ? Stm1.GetNextTriangle( nT, Tria) : Stm2.GetNextTriangle( nT, Tria)) ; } if ( ! HHGrids.Update()) return false ; // cerco i triangoli che si intersecano Triangle3d TriaA ; int nTA = ( bHash1 ? Stm2.GetFirstTriangle( TriaA) : Stm1.GetFirstTriangle( TriaA)) ; while ( nTA != SVT_NULL) { BBox3d boxA ; TriaA.GetLocalBBox( boxA) ; INTVECTOR vnIds ; if ( HHGrids.Find( boxA, vnIds)) { for ( int h = 0 ; h < int( vnIds.size()) ; ++ h) { int nB = vnIds[h] ; Triangle3d TriaB ; if ( bHash1 ? Stm1.GetTriangle( nB, TriaB) : Stm2.GetTriangle( nB, TriaB)) { // intersezione tra i triangoli Point3d ptInt, ptInt2 ; PNTVECTOR vPnt ; int nRes = IntersTriaTria( TriaA, TriaB, ptInt, ptInt2, vPnt) ; // se punto if ( nRes == ITTT_VERT || nRes == ITTT_PNT) { // verifico se punto già inserito int nId ; if ( ! PtGrid.Find( ptInt, 10 * EPS_SMALL, nId)) { vPnt.emplace_back( ptInt) ; PtGrid.InsertPoint( ptInt, int( vPnt.size()) - 1) ; } } // se altrimenti segmento else if ( nRes == ITTT_EDGE || nRes == ITTT_YES) { // se abbastanza lungo if ( ! AreSamePointApprox( ptInt, ptInt2)) { // verifico se già inserito bool bFound = false ; BBox3d b3Line( ptInt, ptInt2) ; INTVECTOR vnIds ; if ( LnGrid.Find( b3Line, vnIds)) { for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) { int nA = vnIds[i] ; const Point3d& ptOth = vBpt[nA].first ; const Point3d& ptOth2 = vBpt[nA].second ; if ( ( AreSamePointEpsilon( ptInt, ptOth, 10 * EPS_SMALL) && AreSamePointEpsilon( ptInt2, ptOth2, 10 * EPS_SMALL)) || ( AreSamePointEpsilon( ptInt, ptOth2, 10 * EPS_SMALL) && AreSamePointEpsilon( ptInt2, ptOth, 10 * EPS_SMALL))) { bFound = true ; break ; } } } // se non inserito, procedo if ( ! bFound) { vBpt.emplace_back( ptInt, ptInt2) ; LnGrid.Add( int( vBpt.size()) - 1, b3Line) ; LnGrid.Update() ; } } } // se altrimenti sovrapposizione else if ( nRes == ITTT_OVERLAPS) { //// verifico se triangolo già inserito // bool bFound = false ; // BBox3d b3Tria( Tria.GetP( 0), Tria.GetP( 1)) ; // b3Tria.Add( Tria.GetP( 2)) ; // INTVECTOR vnIds ; // if ( TrGrid.Find( b3Tria, vnIds)) { // for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) { // int nA = vnIds[i] ; // const Triangle3d& trOth = vTria[nA] ; // array< bool, 3> bOth = { false, false, false} ; // for ( int j = 0 ; j < 3 ; ++ j) { // for ( int k = 0 ; k < 3 ; ++ k) { // if ( ! bOth[k]) // bOth[k] = AreSamePointEpsilon( Tria.GetP( j), trOth.GetP( k), 10 * EPS_SMALL) ; // } // } // if ( bOth[0] && bOth[1] && bOth[2]) { // bFound = true ; // break ; // } // } // } //// se non inserito, procedo // if ( ! bFound) { // vTria.emplace_back( Tria) ; // TrGrid.Add( int( vTria.size()) - 1, b3Tria) ; // TrGrid.Update() ; // } } } } } // passo al prossimo triangolo nTA = ( bHash1 ? Stm2.GetNextTriangle( nTA, TriaA) : Stm1.GetNextTriangle( nTA, TriaA)) ; } // rimuovo i punti che stanno sui segmenti for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) { bool bFound = false ; BBox3d b3Pnt( vPnt[i]) ; b3Pnt.Expand( 10 * EPS_SMALL) ; INTVECTOR vnIds ; if ( LnGrid.Find( b3Pnt, vnIds)) { for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) { int nA = vnIds[j] ; double dSqDist ; if ( DistPointLine( vPnt[i], vBpt[nA].first, vBpt[nA].second).GetSqDist( dSqDist) && dSqDist < 100 * SQ_EPS_SMALL) { bFound = true ; break ; } } } if ( bFound) vPnt.erase( vPnt.begin() + i) ; } // rimuovo i punti che stanno sui triangoli for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) { bool bFound = false ; BBox3d b3Pnt( vPnt[i]) ; b3Pnt.Expand( 10 * EPS_SMALL) ; INTVECTOR vnIds ; if ( TrGrid.Find( b3Pnt, vnIds)) { for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) { int nA = vnIds[j] ; const Triangle3d& trOth = vTria[nA] ; double dSqDist ; if ( DistPointTriangle( vPnt[i], trOth).GetSqDist( dSqDist) && dSqDist < 100 * SQ_EPS_SMALL) { bFound = true ; break ; } } } if ( bFound) vPnt.erase( vPnt.begin() + i) ; } // rimuovo i segmenti che stanno sui triangoli for ( int i = int( vBpt.size()) - 1 ; i >= 0 ; -- i) { bool bFound = false ; Point3d ptStart = vBpt[i].first ; Point3d ptEnd = vBpt[i].second ; BBox3d b3Line( ptStart, ptEnd) ; INTVECTOR vnIds ; if ( TrGrid.Find( b3Line, vnIds)) { for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) { int nA = vnIds[j] ; const Triangle3d& trOth = vTria[nA] ; Point3d ptInt, ptInt2 ; if ( IntersLineTria( ptStart, ptEnd, trOth, ptInt, ptInt2) == ILTT_SEGM_ON_EDGE) { bFound = true ; break ; } } } if ( bFound) vBpt.erase( vBpt.begin() + i) ; } return true ; }