diff --git a/CDeClosedSurfTmClosedSurfTm.cpp b/CDeClosedSurfTmClosedSurfTm.cpp index a877e19..8d1cfd1 100644 --- a/CDeClosedSurfTmClosedSurfTm.cpp +++ b/CDeClosedSurfTmClosedSurfTm.cpp @@ -67,8 +67,8 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf INTVECTOR vNearTria ; pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ; // Settare tutti i triangoli come già processati. - // Al termine della chiamata i TFlags dei triangoli valgono 0. - pSrfB->ResetTempInt() ; + // Al termine della chiamata i TempInt dei triangoli valgono 0. + pSrfB->ResetTempInts() ; // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. for ( int nTB : vNearTria) { // Recupero il triangolo corrente della superficie B. @@ -85,7 +85,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf // Se il triangolo adiacente al triangolo corrente su questo edge // non è stato processato, processo il vertice e l'edge. int nAdjTriaTempFlag ; - if ( ! ( pSrfB->GetTriangleTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) + if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) continue ; // Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito. if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA)) diff --git a/DistPointSurfTm.cpp b/DistPointSurfTm.cpp index 31ef065..44b340f 100644 --- a/DistPointSurfTm.cpp +++ b/DistPointSurfTm.cpp @@ -12,6 +12,7 @@ //---------------------------------------------------------------------------- #include "stdafx.h" +#include "SurfTriMesh.h" #include "/EgtDev/Include/EGkDistPointTria.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" @@ -24,7 +25,7 @@ using namespace std ; // I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto // nel box B; uno di questi si verifica se il box A è vuoto. // Nel vettore vBoxDiff vengono restituiti i box la cui unione costituisce la differenza fra A e B. -bool +static bool BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff) { // Svuoto il risultato @@ -93,30 +94,33 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // Inizializzo distanza non calcolata m_dDist = - 1. ; + // Lavoro con l'oggetto superficie trimesh di base + const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; + if ( pStm == nullptr) + return ; + // Recupero e verifico il box locale della superficie - BBox3d b3Stm = tmSurf.GetAllTriaBox() ; + BBox3d b3Stm = pStm->GetAllTriaBox() ; if ( b3Stm.IsEmpty()) return ; - // Determino i triangoli vicini e fra di essi cerco quello di minima distanza. - // Considero un box centrato nel punto P; finché all'interno del box non trovo un set di triangoli - // fra cui quello a distanza minima dal punto P ha distanza minore del minimo semi-lato del box, - // continuo a ingrandire il box. La condizione di terminazione garantisce di trovare il tiangolo di - // distanza minima della trimesh intera. + // Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // Termino quando non trovo più triangoli che possano soddisfare la richiesta. Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; - double dDeltaLen = max( min( min( ptMax.x - ptMin.x, ptMax.y - ptMin.y), ptMax.z - ptMin.z) / 40., 10.) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; - // Considero anche il box precedente per poter analizzare solo lo spazio differenza tra i due + // Considero anche il box precedente per poter analizzare solo il volume differenza tra i due BBox3d boxPPrev( ptP) ; BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; // Variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima double dMinSqDist = DBL_MAX ; int nMinDistTriaIndex = SVT_NULL ; Point3d ptMinDistPoint ; - bool bContinue = true ; // Finché non si verifica la condizione di terminazione ingrandisco il box. + pStm->ResetTempInts() ; + bool bContinue = true ; while ( bContinue) { // Calcolo il box differenza con il precedente per non esplorare parti già considerate BOXVECTOR vBox ; @@ -131,18 +135,21 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // ricerca sui triangoli nel box bCollide = true ; INTVECTOR vnIds ; - if ( tmSurf.GetAllTriaOverlapBox( b3Int, vnIds)) { + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { // Ciclo sui triangoli del sotto-box corrente for ( auto nT : vnIds) { + int nTriaTemp ; Triangle3d trCurTria ; - tmSurf.GetTriangle( nT, trCurTria) ; - 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) ; + if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, trCurTria)) { + 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) ; + } } } } @@ -161,9 +168,9 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) m_nMinDistTriaIndex = nMinDistTriaIndex ; m_ptMinDistPoint = ptMinDistPoint ; Triangle3d trMinDistTria ; - tmSurf.GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; + pStm->GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; trMinDistTria.Validate() ; - m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && tmSurf.IsClosed() ; + m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && pStm->IsClosed() ; } } @@ -202,3 +209,80 @@ DistPointSurfTm::GetMinDistTriaIndex( int& nMinDistIndex) nMinDistIndex = m_nMinDistTriaIndex ; return true ; } + +//---------------------------------------------------------------------------- +int +GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf) +{ + // Lavoro con l'oggetto superficie trimesh di base + const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; + if ( pStm == nullptr) + return SVT_NULL ; + + // Recupero e verifico il box locale della superficie + BBox3d b3Stm = pStm->GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return SVT_NULL ; + + // Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // Termino quando non trovo più triangoli che possano soddisfare la richiesta. + Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; + double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; + double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; + double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; + // Considero anche il box precedente per poter analizzare solo il volume differenza tra i due + BBox3d boxPPrev( ptP) ; + BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; + // Variabili distanza minima + int nVert = SVT_NULL ; + double dMinSqDist = DBL_MAX ; + // Finché non si verifica la condizione di terminazione ingrandisco il box. + pStm->ResetTempInts() ; + bool bContinue = true ; + while ( bContinue) { + // Calcolo il box differenza con il precedente per non esplorare parti già considerate + BOXVECTOR vBox ; + BoundingBoxDifference( boxP, boxPPrev, vBox) ; + // Ciclo sui box differenza + bool bCollide = false ; + for ( const auto& b3Box : vBox) { + // interseco il box con quello della superficie e ne verifico la distanza minima dal punto + BBox3d b3Int ; + if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.SqDistFromPoint( ptP) > dMinSqDist) + continue ; + // ricerca sui triangoli nel box + bCollide = true ; + INTVECTOR vnIds ; + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { + // Ciclo sui triangoli del sotto-box corrente + for ( auto nT : vnIds) { + int nTriaTemp ; + int nIdVert[3] ; + if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, nIdVert)) { + pStm->SetTempInt( nT, 1) ; + for ( int i = 0 ; i < 3 ; ++ i) { + Point3d ptVert ; + if ( ! pStm->GetVertex( nIdVert[i], ptVert)) + continue ; + double dCurrSqDist = SqDist( ptP, ptVert) ; + if ( dCurrSqDist < dMinSqDist) { + dMinSqDist = dCurrSqDist ; + nVert = nIdVert[i] ; + } + } + } + } + } + } + // Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box + if ( ! bCollide || dMinSqDist < EPS_SMALL * EPS_SMALL) + bContinue = false ; + else { + boxPPrev = boxP ; + boxP.Expand( dDeltaLen) ; + } + } + + return nVert ; +} diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index b932cbf..4a5aa34 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/GeomDB.cpp b/GeomDB.cpp index 4dcb7d4..994c236 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -453,7 +453,7 @@ GeomDB::Save( const INTVECTOR& vId, const string& sFileOut, int nFlag) const return false ; // ciclo sugli oggetti da esportare - unordered_set usSavedId ; + INTUNORDSET usSavedId ; for ( const auto nId : vId) { // se già salvato, passo oltre diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index ae834c0..5f11d01 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -121,6 +121,27 @@ SurfTriMesh::AddVertex( const Point3d& ptVert) return int( m_vVert.size() - 1) ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::MoveVertex( int nInd, const Point3d& ptNewVert) +{ + // verifico validità indice + if ( nInd < 0 || nInd >= int( m_vVert.size())) + return false ; + // verifico non sia già cancellato + if ( m_vVert[nInd].nIdTria == SVT_DEL) + return false ; + // sposto il vertice + m_vVert[nInd].ptP = ptNewVert ; + // imposto ricalcolo + m_nStatus = TO_VERIFY ; + m_nParts = - 1 ; + m_OGrMgr.Reset() ; + ResetHashGrids3d() ; + // per aggiornare completamente la superficie chiamare DoCompacting + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::SetVertex( int nInd, const StmVert& vV) @@ -758,23 +779,23 @@ SurfTriMesh::GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const //---------------------------------------------------------------------------- bool -SurfTriMesh::GetTriangleFlag( int nId, int& nFlag) const +SurfTriMesh::GetTFlag( int nTriaId, int& nTFlag) const { // verifico esistenza del triangolo - if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nTriaId < 0 || nTriaId >= GetTriangleSize() || m_vTria[nTriaId].nIdVert[0] == SVT_DEL) return false ; - nFlag = m_vTria[nId].nTFlag ; + nTFlag = m_vTria[nTriaId].nTFlag ; return true ; } //---------------------------------------------------------------------------- bool -SurfTriMesh::GetTriangleTempInt( int nId, int& nTempInt) const +SurfTriMesh::GetTempInt( int nTriaId, int& nTempInt) const { // verifico esistenza del triangolo - if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nTriaId < 0 || nTriaId >= GetTriangleSize() || m_vTria[nTriaId].nIdVert[0] == SVT_DEL) return false ; - nTempInt = m_vTria[nId].nTemp ; + nTempInt = m_vTria[nTriaId].nTemp ; return true ; } @@ -2950,14 +2971,13 @@ SurfTriMesh::DoCompacting( double dTol) // sistemo gli indici dei vertici nei triangoli for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) { - // recupero gli indici dei vertici del triangolo - int vOId[3] ; - vOId[0] = m_vTria[nId].nIdVert[0] ; - vOId[1] = m_vTria[nId].nIdVert[1] ; - vOId[2] = m_vTria[nId].nIdVert[2] ; // salto i triangoli cancellati - if ( vOId[0] == SVT_DEL) + if ( m_vTria[nId].nIdVert[0] == SVT_DEL) continue ; + // recupero gli indici dei vertici del triangolo + int vOId[3]{ m_vTria[nId].nIdVert[0], + m_vTria[nId].nIdVert[1], + m_vTria[nId].nIdVert[2]} ; // verifico la validità degli indici if ( vOId[0] < 0 || vOId[0] >= nVIdSize || vOId[1] < 0 || vOId[1] >= nVIdSize || @@ -2967,11 +2987,12 @@ SurfTriMesh::DoCompacting( double dTol) m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ; m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ; m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ; - // se due vertici coincidono, cancello il triangolo + // se due vertici coincidono o la normale non è calcolabile, cancello il triangolo if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] || m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] || - m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) - RemoveTriangle( nId) ; + m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] || + ! CalcTriangleNormal( nId)) + RemoveTriangle( nId) ; } // compatto il vettore dei vertici @@ -3662,7 +3683,7 @@ SurfTriMesh::ResetTFlags( void) //---------------------------------------------------------------------------- bool -SurfTriMesh::ResetTempInt( void) const +SurfTriMesh::ResetTempInts( void) const { for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) m_vTria[i].nTemp = 0 ; diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 0ae775c..6ae2946 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2022 +// EgalTech 2014-2023 //---------------------------------------------------------------------------- -// File : SurfTriMesh.h Data : 10.10.22 Versione : 2.4i4 +// File : SurfTriMesh.h Data : 07.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe Superficie TriMesh. // // @@ -216,6 +216,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; m_OGrMgr.Reset() ; } int AddVertex( const Point3d& ptVert) override ; + bool MoveVertex( int nInd, const Point3d& ptNewVert) override ; int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ; bool RemoveTriangle( int nId) override ; bool AdjustTopology( void) override ; @@ -266,6 +267,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW { return int( m_vFacet.size()) ; } int GetFacetFromTria( int nT) const override ; bool GetAllTriaInFacet( int nF, INTVECTOR& vT) const override ; + bool GetAllVertInFacet( int nF, INTVECTOR& vVert) const override ; bool GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const override ; bool GetFacetAdjacencies( int nF, INTMATRIX& vAdj) const override ; bool GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const override ; @@ -315,9 +317,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool ExistsTriangle( int nT) const { return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; } bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ; - bool GetTriangleFlag( int nId, int& nFlag) const ; - bool GetTriangleTempInt( int nId, int& nTempInt) const ; - bool ResetTempInt( void) const ; + bool GetTFlag( int nId, int& nFlag) const ; + bool GetTempInt( int nId, int& nTempInt) const ; + bool ResetTempInts( void) const ; bool SetTFlag( int nId, int nTFlag) ; bool SetTempInt( int nId, int nTempInt) const ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index 0188cc4..ce55f56 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -254,6 +254,30 @@ SurfTriMesh::VerifyAdjacTriaFacet( INTVECTOR& vT) const return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetAllVertInFacet( int nF, INTVECTOR& vVert) const +{ + // recupero tutti i triangoli della faccia + INTVECTOR vTria ; + if ( ! GetAllTriaInFacet( nF, vTria)) + return false ; + // ne ricavo i vertici + vVert.clear() ; + INTUNORDSET usTempVert ; + for ( int nT : vTria) { + for ( int i = 0 ; i < 3 ; ++ i) { + int nV = m_vTria[nT].nIdVert[i] ; + if ( usTempVert.find( nV) == usTempVert.end()) { + usTempVert.insert( nV) ; + vVert.push_back( nV) ; + } + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const