diff --git a/SurfTriMesh.h b/SurfTriMesh.h index cdb651f..8cafbc1 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -94,30 +94,11 @@ typedef std::unordered_map< int, Chain> CHAINMAP ; typedef std::unordered_map< int, TRIA3DVECTOR> TRIA3DVECTORMAP ; //---------------------------------------------------------------------------- -// Struttura per la ricerca delle T-Junction -struct TEdgeId { - int nTriaId ; - int nEdge ; -} ; -// Overloading dell'operatore < per TEdgeSet -inline bool operator<( const TEdgeId& TEdgeA, const TEdgeId& TEdgeB) { - if ( TEdgeA.nTriaId != TEdgeB.nTriaId) - return ( TEdgeA.nTriaId < TEdgeB.nTriaId) ; - return ( TEdgeA.nEdge < TEdgeB.nEdge) ; -} -// Loop con T-Junction -typedef std::vector TJuncLoop ; -// Vettore di loop con T-Junction -typedef std::vector TJuncLoopVec ; -// Set di TEdgeId -typedef std::set TJEdgeSet ; - -// Definizione strutture intersezione linea-faccia -//---------------------------------------------------------------------------- +// Struttura intersezione linea-faccia struct LineFacetClass { Point3d ptSt, ptEn ; int nTypeA, nTypeB ; - LineFacetClass() { + LineFacetClass( void) { nTypeA = 0 ; nTypeB = 0 ; } @@ -134,25 +115,24 @@ typedef std::vector LineFacetClassVector ; enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_IN = 2, FPI_OUT = 3, FPI_ON = 4 } ; //---------------------------------------------------------------------------- -// Definizione strutture e contenitori -// Contatti interno-interno +// Strutture e contenitori contatti interno-interno struct IntersInnSeg { Point3d ptSt ; Point3d ptEn ; Vector3d vtOuter ; - IntersInnSeg(void) { + IntersInnSeg( void) { ; } - IntersInnSeg(const Point3d& ptS, const Point3d& ptE) { - ptSt = ptS; - ptEn = ptE; + IntersInnSeg( const Point3d& ptS, const Point3d& ptE) { + ptSt = ptS ; + ptEn = ptE ; } - IntersInnSeg(const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) { - ptSt = ptS; - ptEn = ptE; - vtOuter = vtO; + IntersInnSeg( const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) { + ptSt = ptS ; + ptEn = ptE ; + vtOuter = vtO ; } -}; +} ; typedef std::vector IntersInnChain ; typedef std::vector INNCHAINVECTOR ; typedef std::unordered_map INTERSCHAINMAP ; @@ -164,7 +144,7 @@ struct IntersEdge { IntersEdge( const Point3d& ptS, const Point3d& ptE, const INTVECTOR& vOFI) { ptSt = ptS; ptEn = ptE; - vOthFacetIndex = vOFI; + vOthFacetIndex = vOFI ; } } ; typedef std::vector IntersEdgeVec ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 057ef8a..c26b6ff 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -1439,122 +1439,6 @@ SurfTriMesh::IdentifyParts( void) const return true ; } -//---------------------------------------------------------------------------- -bool -SurfTriMesh::RemoveTJunctions(void) -{ - // Vettore di indici dei vertici sui lati del triangolo corrente - unordered_map< int, INTVECTOR> TriaMap ; - - // Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro - for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) { - // Se il triangolo non è valido, passo al successivo - Triangle3d trTria ; - if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) - continue ; - // Vettore degli altri vertici sul contorno del triangolo - INTVECTOR vVertOtl ; - // Box del triangolo - BBox3d b3Tria ; - trTria.GetLocalBBox( b3Tria) ; - INTVECTOR vNearTria ; - GetAllTriaOverlapBox( b3Tria, vNearTria) ; - // Ciclo sui lati del triangolo - for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) { - // aggiungo al vettore il vertice iniziale del lato - vVertOtl.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( vVertOtl.size()) ; - // recupero la geometria del lato - Point3d ptSegSt = trTria.GetP( nSeg) ; - Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ; - Vector3d vtSeg = ptSegEn - ptSegSt ; - double dSegLen = vtSeg.Len() ; - if ( dSegLen < EPS_SMALL) - continue ; - vtSeg /= dSegLen ; - // Ciclo sui triangoli vicini - for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) { - // Salto il triangolo se è quello di riferimento - if ( vNearTria[nI] == nT) - continue ; - // Cerco i vertici che stanno sul lato del triangolo - for ( int nVert = 0 ; nVert < 3 ; ++ nVert) { - Point3d 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) - vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ; - } - } - // Riordino i vertici sul segmento - auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2) - { Point3d ptV1, ptV2 ; - GetVertex( nV1, ptV1) ; - GetVertex( nV2, ptV2) ; - return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ; - } ; - sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ; - } - // Se ci sono più di 3 vertici - if ( vVertOtl.size() > 3) { - // Elimino i vertici ripetuti - vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ; - // Se ci sono ancora più di 3 vertici, inserisco nel Map - if ( vVertOtl.size() > 3) - TriaMap.emplace( nT, vVertOtl) ; - } - } - - // Ciclo sui triangoli da sistemare - for ( auto itT = TriaMap.begin() ; itT != TriaMap.end() ; ++ itT) { - // Indice del triangolo - int nT = itT->first ; - // Vettore degli altri vertici sul perimetro - const INTVECTOR& vVertOtl = itT->second ; - // Se il triangolo non è valido, passo al successivo - Triangle3d trTria ; - if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) - continue ; - // Rimuovo il triangolo - int nTFlag = m_vTria[nT].nTFlag ; - RemoveTriangle( nT) ; - // Se ci sono 4 vertici, inserisco due triangoli - if ( vVertOtl.size() == 4) { - // se 1-2-3 è triangolo (e quindi 0-1-3) - int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ; - if ( AddTriangle( nNew1Id, nTFlag) >= 0) { - int nNew2Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[3]} ; - AddTriangle( nNew2Id, nTFlag) ; - } - // altrimenti 0-1-2 e 2-3-0 - else { - int nNew3Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[2]} ; - AddTriangle( nNew3Id, nTFlag) ; - int nNew4Id[3] = { vVertOtl[2], vVertOtl[3], vVertOtl[0]} ; - AddTriangle( nNew4Id, nTFlag) ; - } - } - // altrimenti inserisco un ventaglio di triangoli dal centro ai vertici - else { - Point3d ptTriaCen = trTria.GetCentroid() ; - int nCenIndex = AddVertex( ptTriaCen) ; - int nVertNum = int( vVertOtl.size()) ; - for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) { - int nEnV = ( nStV + 1) % nVertNum ; - int nNewId[3] = { nCenIndex, vVertOtl[nStV], vVertOtl[nEnV]} ; - AddTriangle( nNewId, nTFlag) ; - } - } - } - - return true ; -} - //---------------------------------------------------------------------------- bool SurfTriMesh::RemoveCaps(void) diff --git a/SurfTriMeshUtilities.cpp b/SurfTriMeshUtilities.cpp index b56af72..2aeb542 100644 --- a/SurfTriMeshUtilities.cpp +++ b/SurfTriMeshUtilities.cpp @@ -19,6 +19,141 @@ using namespace std ; +//---------------------------------------------------------------------------- +bool +SurfTriMesh::RemoveTJunctions(void) +{ + // Vettore di indici dei vertici sui lati del triangolo corrente + unordered_map< int, INTVECTOR> TriaMap ; + + // Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro + for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) { + // Se il triangolo non è valido, passo al successivo + Triangle3d trTria ; + if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) + continue ; + // Vettore degli altri vertici sul contorno del triangolo + INTVECTOR vVertOtl ; + // Box del triangolo + BBox3d b3Tria ; + trTria.GetLocalBBox( b3Tria) ; + INTVECTOR vNearTria ; + GetAllTriaOverlapBox( b3Tria, vNearTria) ; + // Ciclo sui lati del triangolo + for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) { + // aggiungo al vettore il vertice iniziale del lato + vVertOtl.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( vVertOtl.size()) ; + // recupero la geometria del lato + Point3d ptSegSt = trTria.GetP( nSeg) ; + Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ; + Vector3d vtSeg = ptSegEn - ptSegSt ; + double dSegLen = vtSeg.Len() ; + if ( dSegLen < EPS_SMALL) + continue ; + vtSeg /= dSegLen ; + // Ciclo sui triangoli vicini + for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) { + // Salto il triangolo se è quello di riferimento + if ( vNearTria[nI] == nT) + continue ; + // Cerco i vertici che stanno sul lato del triangolo + for ( int nVert = 0 ; nVert < 3 ; ++ nVert) { + Point3d 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) + vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ; + } + } + // Riordino i vertici sul segmento + auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2) + { Point3d ptV1, ptV2 ; + GetVertex( nV1, ptV1) ; + GetVertex( nV2, ptV2) ; + return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ; + } ; + sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ; + } + // Se ci sono più di 3 vertici + if ( vVertOtl.size() > 3) { + // Elimino i vertici ripetuti + vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ; + // Se ci sono ancora più di 3 vertici, inserisco nel Map + if ( vVertOtl.size() > 3) + TriaMap.emplace( nT, vVertOtl) ; + } + } + + // Ciclo sui triangoli da sistemare + for ( auto itT = TriaMap.begin() ; itT != TriaMap.end() ; ++ itT) { + // Indice del triangolo + int nT = itT->first ; + // Vettore degli altri vertici sul perimetro + const INTVECTOR& vVertOtl = itT->second ; + // Se il triangolo non è valido, passo al successivo + Triangle3d trTria ; + if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) + continue ; + // Salvo eventuale indice di faccetta + int nFacet = m_vTria[nT].nIdFacet ; + if ( nFacet > int( m_vFacet.size()) || m_vFacet[nFacet] != nT) + nFacet = SVT_NULL ; + // Rimuovo il triangolo + int nTFlag = m_vTria[nT].nTFlag ; + RemoveTriangle( nT) ; + // Aggiungo i nuovi triangoli + int nLastNewTria = SVT_NULL ; + // Se ci sono 4 vertici, inserisco due triangoli + if ( vVertOtl.size() == 4) { + // se 1-2-3 è triangolo (e quindi 0-1-3) + int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ; + int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ; + if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) { + nLastNewTria = nNew1Tria ; + int nNew2Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[3]} ; + int nNew2Tria = AddTriangle( nNew2Id, nTFlag) ; + if ( nNew2Tria != SVT_NULL && nNew2Tria != SVT_DEL) + nLastNewTria = nNew2Tria ; + } + // altrimenti 0-1-2 e 2-3-0 + else { + int nNew3Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[2]} ; + int nNew3Tria = AddTriangle( nNew3Id, nTFlag) ; + if ( nNew3Tria != SVT_NULL && nNew3Tria != SVT_DEL) + nLastNewTria = nNew3Tria ; + int nNew4Id[3] = { vVertOtl[2], vVertOtl[3], vVertOtl[0]} ; + int nNew4Tria = AddTriangle( nNew4Id, nTFlag) ; + if ( nNew4Tria != SVT_NULL && nNew4Tria != SVT_DEL) + nLastNewTria = nNew4Tria ; + } + } + // altrimenti inserisco un ventaglio di triangoli dal centro ai vertici + else { + Point3d ptTriaCen = trTria.GetCentroid() ; + int nCenIndex = AddVertex( ptTriaCen) ; + int nVertNum = int( vVertOtl.size()) ; + for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) { + int nEnV = ( nStV + 1) % nVertNum ; + int nNewId[3] = { nCenIndex, vVertOtl[nStV], vVertOtl[nEnV]} ; + int nNewTria = AddTriangle( nNewId, nTFlag) ; + if ( nNewTria != SVT_NULL && nNewTria != SVT_DEL) + nLastNewTria = nNewTria ; + } + } + // Eventuale aggiustamento per indice di faccetta + if ( nFacet != SVT_NULL && nLastNewTria != SVT_NULL) + m_vFacet[nFacet] = nLastNewTria ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool IsVertex( PNTULIST& PointList, PNTULIST::const_iterator itCurr)