diff --git a/DistPointSurfTm.cpp b/DistPointSurfTm.cpp index 6ba054d..db2df80 100644 --- a/DistPointSurfTm.cpp +++ b/DistPointSurfTm.cpp @@ -15,6 +15,7 @@ #include "SurfTriMesh.h" #include "/EgtDev/Include/EGkDistPointTria.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Include/EGkIntersLineTria.h" using namespace std ; @@ -93,6 +94,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) { // Inizializzo distanza non calcolata m_dDist = - 1. ; + // Controllo se la superficie è chiusa + m_bIsSurfClosed = tmSurf.IsClosed() ; // Lavoro con l'oggetto superficie trimesh di base const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; @@ -121,6 +124,9 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // Finché non si verifica la condizione di terminazione ingrandisco il box. pStm->ResetTempInts() ; bool bContinue = true ; + + // creazione del vettore dei triangoli più vicini a ptP + vector> vTria ; // while ( bContinue) { // Calcolo il box differenza con il precedente per non esplorare parti già considerate BOXVECTOR vBox ; @@ -134,8 +140,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) continue ; // ricerca sui triangoli nel box bCollide = true ; - INTVECTOR vnIds ; - if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { + INTVECTOR vnIds ; + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { // Ciclo sui triangoli del sotto-box corrente for ( auto nT : vnIds) { int nTriaTemp ; @@ -144,18 +150,24 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) pStm->SetTempInt( nT, 1) ; DistPointTriangle distPT( ptP, trCurTria) ; double dCurSqDist ; - // Se la distanza del triangolo è valida e minore di quella attuale aggiorno - if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) { - dMinSqDist = dCurSqDist ; - nMinDistTriaIndex = nT ; - distPT.GetMinDistPoint( ptMinDistPoint) ; + // Se la distanza del triangolo è valida e minore di quella attuale aggiorno + if ( distPT.GetSqDist( dCurSqDist)) { + if ( abs( dCurSqDist - dMinSqDist) < EPS_SMALL) // se distanze uguali... + vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo + else if ( dCurSqDist < dMinSqDist) { // se minore... + vTria.clear() ; // pulisco il vettore + dMinSqDist = dCurSqDist ; + nMinDistTriaIndex = nT ; + distPT.GetMinDistPoint( ptMinDistPoint) ; + vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo + } } } } } } // Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box - if ( ! bCollide || dMinSqDist < EPS_SMALL * EPS_SMALL) + if ( ! bCollide || dMinSqDist < SQ_EPS_SMALL) bContinue = false ; else { boxPPrev = boxP ; @@ -163,15 +175,70 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) } } - if ( nMinDistTriaIndex != SVT_NULL) { - m_dDist = sqrt( max( dMinSqDist, 0.)) ; + // se non ho trovato nessun triangolo, esco + if ( nMinDistTriaIndex == SVT_NULL) + return ; + + // salvo la distanza minima + m_dDist = sqrt( max( dMinSqDist, 0.)) ; + // salvo il punto a distanza minima + m_ptMinDistPoint = ptMinDistPoint ; + // se il punto è sulla TriMesh... + if ( m_dDist < EPS_SMALL) { m_nMinDistTriaIndex = nMinDistTriaIndex ; - m_ptMinDistPoint = ptMinDistPoint ; - Triangle3d trMinDistTria ; - pStm->GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; - trMinDistTria.Validate() ; - m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && pStm->IsClosed() ; + m_bIsInside = false ; + return ; } + // se ho un solo triangolo, allora deduco le informazioni da lui + else if ( int( vTria.size()) == 1) { + m_nMinDistTriaIndex = vTria.back().first ; + m_bIsInside = ( ( ptP - m_ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ; + return ; + } + + // controllo se tutti i triangoli a minima distanza forniscono la stessa informazione + // ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito ) + bool bInside = false ; + bool bOutside = false ; + for ( int i = 0 ; i < int( vTria.size()) ; ++ i) { // scorro i triangoli a minima distanza + if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL) + bInside = true ; + else + bOutside = true ; + } + + // inizializzo le variabili membro + m_nMinDistTriaIndex = nMinDistTriaIndex ; + m_bIsInside = false ; + + // se le informazioni non sono coerenti, allora : + // 1) calcolo i centroidi dei triangoli in questione + // 2) ottengo il punto medio di questi centroidi + // 3) controllo quale triangolo interseca il segmento che parte da ptP e arriva a tale punto + // 4) userò questo triangolo per classificare ptP + if ( bOutside == bInside) { + // calcolo il baricentro complessivo + Point3d ptBar_tot ; + for ( auto& Tria : vTria) + ptBar_tot += Tria.second.GetCentroid() ; + ptBar_tot /= int( vTria.size()) ; + // per ogni triangolo, cerco quello che interseca il segmento + for ( auto& Tria : vTria) { + Point3d ptInters1, ptInters2 ; + int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ; + if ( nType == ILTT_IN) { // se intersezione ho finito + DistPointTriangle( ptP, Tria.second).GetMinDistPoint( m_ptMinDistPoint) ; + m_bIsInside = ( ( ptP - m_ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ; + m_nMinDistTriaIndex = Tria.first ; + break ; + } + } + } + else // se informazioni coerenti + m_bIsInside = bInside ; + + return ; + } //---------------------------------------------------------------------------- diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 11241e0..aea48eb 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -24,6 +24,7 @@ #include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointTria.h" +#include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkIntersLineTria.h" #include "/EgtDev/Include/EGkIntersLineBox.h" #include "/EgtDev/Include/EGkIntersPlanePlane.h" @@ -1326,168 +1327,25 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) bool bRetriangulated = true ; if ( ! bModif && ( int( AmbiguosA.size()) == 0 || int( AmbiguosB.size()) == 0)) { bRetriangulated = false ; - int nVertNum = 0 ; - Point3d ptFirstV ; - int nCurVert = GetFirstVertex( ptFirstV) ; + // devo assegnare a tutti i triangoli della superficie la medesima proprietà ( definita da nInOutNum) + // ( -1 -> esterno | 0 -> indefinito | +1 -> interno ) + // devo farlo sia per la SurfA( *this) che per la SurfB int nInOutNum = 0 ; - while ( nInOutNum == 0 && nCurVert != SVT_NULL) { - INTVECTOR vnTriaNum ; - double dMinDist = DBL_MAX ; - for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - // Se il triangolo B non è valido, continuo - Triangle3d trTriaB ; - if ( ! SurfB.GetTriangle( nTB, trTriaB) || ! trTriaB.Validate( true)) - continue ; - double 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 ( ! vnTriaNum.empty()) { - Triangle3d trTriaB ; - 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) ; - ++ nVertNum ; - } + for ( int v = 0 ; v < int( m_vVert.size()) && nInOutNum == 0 ; ++ v) { + double dDist = 0. ; + DistPointSurfTm distCalculator( m_vVert[v].ptP, SurfB) ; + if ( distCalculator.GetDist( dDist) && dDist > EPS_SMALL) + nInOutNum = ( distCalculator.IsPointOnLeftSide() ? 1 : -1) ; } - for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) m_vTria[nTA].nTempPart = nInOutNum ; - nVertNum = 0 ; - nCurVert = SurfB.GetFirstVertex( ptFirstV) ; nInOutNum = 0 ; - while ( nInOutNum == 0 && nCurVert != SVT_NULL) { - INTVECTOR vnTriaNum ; - double dMinDist = DBL_MAX ; - for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { - // Se il triangolo A non è valido, continuo - Triangle3d trTriaA ; - if ( ! ( GetTriangle( nTA, trTriaA) && trTriaA.Validate( true))) - continue ; - DistPointTriangle DistCalculator( ptFirstV, trTriaA) ; - double dDist ; - DistCalculator.GetDist( 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 ( ! vnTriaNum.empty()) { - Triangle3d trTriaA ; - 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 ; - } - } - } - // 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) { - nCurVert = SurfB.GetNextVertex( nVertNum, ptFirstV) ; - ++ nVertNum ; - } + for ( int v = 0 ; v < int( SurfB.m_vVert.size()) && nInOutNum == 0 ; ++ v) { + double dDist = 0. ; + DistPointSurfTm distCalculator( SurfB.m_vVert[v].ptP, *this) ; + if ( distCalculator.GetDist( dDist) && dDist > EPS_SMALL) + nInOutNum = ( distCalculator.IsPointOnLeftSide() ? 1 : -1) ; } for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) SurfB.m_vTria[nTB].nTempPart = nInOutNum ; @@ -1583,66 +1441,102 @@ SurfTriMesh::IdentifyParts( void) const bool SurfTriMesh::Add( const ISurfTriMesh& Other) { - // Le superfici devono essere valide + + // le superfici devono essere valide if ( ! IsValid() || ! Other.IsValid()) return false ; - // Se la seconda è vuota non devo fare alcunchè + // se la seconda è vuota non devo fare alcunchè if ( Other.IsEmpty()) return true ; m_OGrMgr.Clear() ; - // Se la prima è vuota, copio la seconda nella prima + // se la prima è vuota, copio la seconda nella prima if ( IsEmpty()) { CopyFrom( &Other) ; return true ; } + // clono la superficie B SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; + // creazione del frame per scalare A e B Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + // scalo A e B Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) + SurfTriMesh SurfB_cl ; + SurfB_cl.CopyFrom( &SurfB) ; + + // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) + SurfTriMesh SurfA_cl ; + SurfA_cl.CopyFrom( this) ; + + // ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo IntersectTriMeshTriangle( SurfB) ; + + // assegno un medesimo indice ai triangoli che non interferiscono con altri IdentifyParts() ; SurfB.IdentifyParts() ; + // rimozione dei triangoli di A con proprietà 1 e -2 ( e gestione dei triangoli ambigui, 0) int nTriaNumA = GetTriangleSize() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == - 2) RemoveTriangle( nTA) ; + // se triangolo ambiguo + if ( m_vTria[nTA].nTempPart == 0) { + Triangle3d TriaA ; + GetTriangle( nTA, TriaA) ; + // rimuovo il triangolo se interno a surfB ( basta controllare un solo vertice(?) ) + DistPointSurfTm distCalculator( TriaA.GetP( 0), SurfB_cl) ; + if ( distCalculator.IsPointOnLeftSide()) + RemoveTriangle( nTA) ; + } } + + // aggiunta di tutti i triangoli di B con proprietà -1 ( e gestione dei triangoli ambigui, 0) int nPrevMaxTFlag = m_nMaxTFlag ; int nTriaNumB = SurfB.GetTriangleSize() ; for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - if ( SurfB.m_vTria[nTB].nTempPart == - 1) { - int nNewVert[3] ; - for ( int nV = 0 ; nV < 3 ; ++ nV) { - nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ; + bool bAdd = ( SurfB.m_vTria[nTB].nTempPart == - 1) ; + if ( ! bAdd) { + // se ambiguo + if ( SurfB.m_vTria[nTB].nTempPart == 0) { + // aggiungo se il triangolo è a surfA ( basta controllare un solo vertice(?) ) + DistPointSurfTm distCalculator( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[0]].ptP, SurfA_cl) ; + bAdd = ! distCalculator.IsPointOnLeftSide() ; } + } + if ( bAdd) { + int nNewVert[3] ; + for ( int nV = 0 ; nV < 3 ; ++ nV) + nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ; if ( nPrevMaxTFlag == m_nMaxTFlag) ++ m_nMaxTFlag ; AddTriangle( nNewVert, m_nMaxTFlag) ; } } + // sistemazioni varie bool bOk = ( AdjustVertices() && DoCompacting()) ; - bool bModified = false ; bOk = bOk && RemoveDoubleTriangles( bModified) ; if ( bModified) bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk = bOk && RemoveTJunctions( bModified) ; if ( bModified) bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + // scalo alla dimensioni originali Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; + // semplifico eventuale geometria delle facce if ( ! SimplifyFacets()) LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Add") @@ -1653,6 +1547,7 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) bool SurfTriMesh::Intersect( const ISurfTriMesh& Other) { + // Le superfici devono essere valide if ( ! IsValid() || ! Other.IsValid()) return false ; @@ -1681,6 +1576,14 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) + SurfTriMesh SurfB_cl ; + SurfB_cl.CopyFrom( &SurfB) ; + + // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) + SurfTriMesh SurfA_cl ; + SurfA_cl.CopyFrom( this) ; + // ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo IntersectTriMeshTriangle( SurfB) ; @@ -1688,22 +1591,36 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) IdentifyParts() ; SurfB.IdentifyParts() ; - // rimozione dei triangoli di A con proprietà -1 e -2 + // rimozione dei triangoli di A con proprietà -1 e -2 (e gestione dei triangoli ambigui, 0) int nTriaNumA = GetTriangleSize() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2) RemoveTriangle( nTA) ; + // se triangolo ambiguo + else if ( m_vTria[nTA].nTempPart == 0) { + Triangle3d TriaA ; + GetTriangle( nTA, TriaA) ; + // rimuovo il triangolo se fuori a surfB ( basta controllare un solo vertice(?) ) + DistPointSurfTm distCalculator( TriaA.GetP( 0), SurfB_cl) ; + if ( ! distCalculator.IsPointOnLeftSide()) + RemoveTriangle( nTA) ; + } } - // aggiunta dei triangoli di B con proprietà +1 + // aggiunta dei triangoli di B con proprietà +1 ( e gestione dei triangoli ambigui, 0) int nPrevMaxTFlag = m_nMaxTFlag ; int nTriaNumB = SurfB.GetTriangleSize() ; for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - if ( SurfB.m_vTria[nTB].nTempPart == 1) { + bool bAdd = ( SurfB.m_vTria[nTB].nTempPart == 1) ; + if ( ! bAdd && SurfB.m_vTria[nTB].nTempPart == 0) { + // aggiungo se il triangolo è interno a surfA ( basta controllare un solo vertice(?) ) + DistPointSurfTm distCalculator( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[0]].ptP, SurfA_cl) ; + bAdd = distCalculator.IsPointOnLeftSide() ; + } + if ( bAdd) { int nNewVert[3] ; for ( int nV = 0 ; nV < 3 ; ++ nV) nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ; - if ( nPrevMaxTFlag == m_nMaxTFlag) ++ m_nMaxTFlag ; AddTriangle( nNewVert, m_nMaxTFlag) ; @@ -1720,33 +1637,6 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) if ( bModified) bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - // rimuovo tutte le parti esterne all'intersezione - int nParts = GetPartCount() ; - if ( nParts > 1) { - for ( int i = 0 ; i < nParts ; ++ i) { - // recupero i triangoli della stessa Part - INTVECTOR vTriaPart ; - for ( int j = 0 ; j < int( m_vTria.size()) ; ++ j) - if ( m_vTria[j].nPart == i) - vTriaPart.push_back( j) ; - // controllo se il loro box interferisce con il box della superficie B - bool bErasePart = true ; - for ( int j = 0 ; j < int( vTriaPart.size()) && bErasePart ; ++ j) { - // Se il triangolo A non è valido, continuo - Triangle3d Tria ; - if ( ! GetTriangle( j, Tria) || ! Tria.Validate( true)) - continue ; - // Box del triangolo A - BBox3d b3dTriaA ; Tria.GetLocalBBox( b3dTriaA) ; - // Recupero i triangoli di B che interferiscono col box del triangolo di A - INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ; - bErasePart = int( vNearTria.size() == 0) ; - } - if ( bErasePart) - RemovePart( i) ; - } - } - // scalo alle dimensioni originali Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; @@ -1760,42 +1650,77 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) bool SurfTriMesh::Subtract( const ISurfTriMesh& Other) { - // Le superfici devono essere valide + + // le superfici devono essere valide if ( ! IsValid() || ! Other.IsValid()) return false ; - // Se una delle due è vuota non devo fare alcunchè + // se una delle due è vuota non devo fare alcunchè if ( IsEmpty() || Other.IsEmpty()) return true ; + // pulisco grafica m_OGrMgr.Clear() ; + // clono superficie B SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; - Frame3d frScalingRef; + // creazione del frame per scalare A e B + Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + // scalo A e B Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) + SurfTriMesh SurfB_cl ; + SurfB_cl.CopyFrom( &SurfB) ; + + // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) + SurfTriMesh SurfA_cl ; + SurfA_cl.CopyFrom( this) ; + + // ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo IntersectTriMeshTriangle( SurfB) ; + // assegno un medesimo indice ai triangoli che non interferiscono con altri IdentifyParts() ; SurfB.IdentifyParts() ; + // rimozione dei triangoli di A con proprietà 1 e 2 ( e gestione triangoli ambigui, 0) int nTriaNumA = GetTriangleSize() ; for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == 2) RemoveTriangle( nTA) ; + // se triangolo ambiguo... + if ( m_vTria[nTA].nTempPart == 0) { + Triangle3d TriaA ; + GetTriangle( nTA, TriaA) ; + // rimuovo il triangolo se interno a SurfB ( basta controllare un solo vertice(?) ) + DistPointSurfTm distCalculator( TriaA.GetP( 0), SurfB_cl) ; + if ( distCalculator.IsPointOnLeftSide()) + RemoveTriangle( nTA) ; + } } + + // aggiunta dei triangoli di B con proprietà +1 ( e gestione triangoli ambigui, 0) int nPrevMaxTFlag = m_nMaxTFlag ; int nTriaNumB = SurfB.GetTriangleSize() ; for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - if ( SurfB.m_vTria[nTB].nTempPart == 1) { - int nNewVert[3] ; - for ( int nV = 0 ; nV < 3 ; ++ nV) { - nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ; + bool bAdd = SurfB.m_vTria[nTB].nTempPart == 1 ; + if ( ! bAdd) { + // se ambiguo + if ( SurfB.m_vTria[nTB].nTempPart == 0) { + // aggiungo il triangolo se interno alla SurfA ( basta controllare un solo vertice(?) ) + DistPointSurfTm distCalculator( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[0]].ptP, SurfA_cl) ; + bAdd = distCalculator.IsPointOnLeftSide() ; } + } + if ( bAdd) { + int nNewVert[3] ; + for ( int nV = 0 ; nV < 3 ; ++ nV) + nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ; swap( nNewVert[1], nNewVert[2]) ; if ( nPrevMaxTFlag == m_nMaxTFlag) ++ m_nMaxTFlag ; @@ -1803,22 +1728,23 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) } } + // sistemazioni varie bool bOk = ( AdjustVertices() && DoCompacting()) ; - bool bModified = false ; bOk = bOk && RemoveDoubleTriangles( bModified) ; if ( bModified) bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk = bOk && RemoveTJunctions( bModified) ; if ( bModified) bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + // scalo alle dimensioni originali Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; + // semplifico le facce if ( ! SimplifyFacets()) LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Subtract") - + return bOk ; }