From bd1efafbc0bae5e3e73a7886a22b57a4c9d18a08 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 12 Sep 2019 07:43:35 +0000 Subject: [PATCH] EgtGeomKernel 2.1i1 : - migliorie a ChainCurves - aggiunta GetFeatureChaines a VolZmap. --- ChainCurves.cpp | 214 ++++++++++++++++++++++++++++++++++++-------- CurveComposite.cpp | 12 +-- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes GdbExecutor.cpp | 32 ++++++- GdbExecutor.h | 1 + VolZmap.h | 1 + VolZmapGraphics.cpp | 182 +++++++++++++++++++++++++++++++++++++ 7 files changed, 398 insertions(+), 44 deletions(-) diff --git a/ChainCurves.cpp b/ChainCurves.cpp index c629838..18c8f66 100644 --- a/ChainCurves.cpp +++ b/ChainCurves.cpp @@ -32,6 +32,10 @@ ChainCurves::Init( bool bAllowInvert, double dToler, int nCrvNbrHint) m_vCrvData.reserve( nCrvNbrHint) ; const double DIM_CELL = 10.0 ; m_PointGrid.Init( 2 * nCrvNbrHint, DIM_CELL) ; + m_bFromNear = false ; + m_vForkData.clear() ; + m_bIsFork = false ; + m_vFork.clear() ; return true ; } @@ -61,6 +65,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT { // pulisco il risultato vIds.clear() ; + m_bFromNear = true ; m_bIsFork = false ; m_vFork.clear() ; @@ -68,28 +73,56 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT int nStart ; INTVECTOR vStart ; if ( ! m_PointGrid.FindNearest( ptStart, vStart) || - ! ChooseStart( ptStart, vStart, nStart)) + ! ChooseStart( ptStart, vStart, nStart)) { + m_bFromNear = false ; return false ; + } // recupero indice e verso int nId = abs( nStart) - 1 ; bool bEquiv = true ; // tolgo dal grid RemoveEntityFromGrid( nId) ; + // se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione + bool bSkip = false ; + if ( bHaltOnFork) { + auto iIter = GetForkPoint( m_vCrvData[nId].ptEnd) ; + if ( iIter != m_vForkData.end()) { + m_bIsFork = true ; + m_vFork.insert( m_vFork.end(), iIter->vnFork.begin(), iIter->vnFork.end()) ; + bSkip = true ; + } + } + // concateno dopo la fine dell'entità di partenza INTVECTOR vIdsAfter ; - bool bClosed ; - if ( ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd, - m_vCrvData[nId].ptStart, bHaltOnFork, vIdsAfter, bClosed)) + bool bClosed = false ; + if ( ! bSkip && ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd, + m_vCrvData[nId].ptStart, bHaltOnFork, vIdsAfter, bClosed)) { + m_bFromNear = false ; return false ; + } + + // se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione + bool bRevSkip = false ; + if ( bHaltOnFork) { + auto iIter = GetForkPoint( m_vCrvData[nId].ptStart) ; + if ( iIter != m_vForkData.end()) { + m_bIsFork = true ; + m_vFork.insert( m_vFork.end(), iIter->vnFork.begin(), iIter->vnFork.end()) ; + bRevSkip = true ; + } + } // se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza INTVECTOR vIdsBefore ; if ( ! bClosed) { bool bRevClosed ; - if ( ! GetReverseChainFromPoint( m_vCrvData[nId].ptStart, m_vCrvData[nId].vtStart, - m_vCrvData[nId].ptEnd, bHaltOnFork, vIdsBefore, bRevClosed)) + if ( ! bRevSkip && ! GetReverseChainFromPoint( m_vCrvData[nId].ptStart, m_vCrvData[nId].vtStart, + m_vCrvData[nId].ptEnd, bHaltOnFork, vIdsBefore, bRevClosed)) { + m_bFromNear = false ; return false ; + } // inverto l'ordine reverse( vIdsBefore.begin(), vIdsBefore.end()) ; } @@ -100,6 +133,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT AddToChain( nId, bEquiv, vIds) ; vIds.insert( vIds.end(), vIdsAfter.begin(), vIdsAfter.end()) ; + m_bFromNear = false ; return true ; } @@ -112,8 +146,10 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart, // pulisco il risultato vIds.clear() ; bStopped = false ; - m_bIsFork = false ; - m_vFork.clear() ; + if ( ! m_bFromNear) { + m_bIsFork = false ; + m_vFork.clear() ; + } // concateno in senso normale Point3d ptCurr = ptStart ; @@ -121,7 +157,7 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart, int nNext ; INTVECTOR vNext ; while ( m_PointGrid.Find( ptCurr, m_dToler, vNext) && - ChooseNext( vtCurr, vNext, bHaltOnFork, nNext)) { + ChooseNext( ptCurr, vtCurr, vNext, bHaltOnFork, nNext)) { // recupero indice e verso int nId = abs( nNext) - 1 ; bool bEquiv = ( nNext > 0) ; @@ -137,6 +173,15 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart, bStopped = true ; break ; } + // se devo fermarmi su biforcazione, verifico se sono su vecchia biforcazione + if ( bHaltOnFork) { + auto iIter = GetForkPoint( ptCurr) ; + if ( iIter != m_vForkData.end()) { + m_bIsFork = true ; + m_vFork.insert( m_vFork.end(), iIter->vnFork.begin(), iIter->vnFork.end()) ; + break ; + } + } } return true ; @@ -151,8 +196,10 @@ ChainCurves::GetReverseChainFromPoint( const Point3d& ptStart, const Vector3d& v // pulisco il risultato vIds.clear() ; bStopped = false ; - m_bIsFork = false ; - m_vFork.clear() ; + if ( ! m_bFromNear) { + m_bIsFork = false ; + m_vFork.clear() ; + } // concateno in senso invertito Point3d ptCurr = ptStart ; @@ -160,7 +207,7 @@ ChainCurves::GetReverseChainFromPoint( const Point3d& ptStart, const Vector3d& v int nPrev ; INTVECTOR vPrev ; while ( m_PointGrid.Find( ptCurr, m_dToler, vPrev) && - ChoosePrev( vtCurr, vPrev, bHaltOnFork, nPrev)) { + ChoosePrev( ptCurr, vtCurr, vPrev, bHaltOnFork, nPrev)) { // recupero indice e verso int nId = abs( nPrev) - 1 ; bool bEquiv = ( nPrev < 0) ; @@ -176,6 +223,15 @@ ChainCurves::GetReverseChainFromPoint( const Point3d& ptStart, const Vector3d& v bStopped = true ; break ; } + // se devo fermarmi su biforcazione, verifico se sono su vecchia biforcazione + if ( bHaltOnFork) { + auto iIter = GetForkPoint( ptCurr) ; + if ( iIter != m_vForkData.end()) { + m_bIsFork = true ; + m_vFork.insert( m_vFork.end(), iIter->vnFork.begin(), iIter->vnFork.end()) ; + break ; + } + } } return true ; @@ -244,23 +300,56 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& //---------------------------------------------------------------------------- bool -ChainCurves::ChooseNext( const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext) +ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext) { - // cerco la direzione più vicina - int nI = - 1 ; - int nF = 0 ; - double dProScaMax = - 1.1 ; - for ( int i = 0 ; i < int( vNext.size()) ; ++ i) { + INTVECTOR vMyNext = vNext ; + // scarto quelle entità che sono più vicine all'altro estremo del più vicino + int nM = -1 ; + Point3d ptRef ; + double dSqMinDist = m_dToler * m_dToler ; + for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) { // recupero indice e verso - int nId = abs( vNext[i]) - 1 ; - bool bEquiv = ( vNext[i] > 0) ; + int nId = abs( vMyNext[i]) - 1 ; + bool bEquiv = ( vMyNext[i] > 0) ; + // determino minima distanza + double dSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ; + if ( dSqDist < dSqMinDist) { + ptRef = ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart) ; + dSqMinDist = dSqDist ; + nM = i ; + } + } + for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) { + // salto l'entità più vicina + if ( i == nM) + continue ; + // recupero indice e verso + int nId = abs( vMyNext[i]) - 1 ; + bool bEquiv = ( vMyNext[i] > 0) ; + // verifico se più vicino al più vicino + double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ; + double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ; + if ( dRefSqDist < dCurrSqDist) + vMyNext[i] = 0 ; + } + // cerco la direzione più vicina + int nI = -1 ; + int nF = 0 ; + INTVECTOR vFork ; + double dProScaMax = - 1.1 ; + for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) { + // salto gli scartati + if ( vMyNext[i] == 0) + continue ; + // recupero indice e verso + int nId = abs( vMyNext[i]) - 1 ; + bool bEquiv = ( vMyNext[i] > 0) ; + // incremento contatore indice entità tra cui scegliere + ++ nF ; + vFork.push_back( vMyNext[i]) ; // se vietata inversione, salto se controverso if ( ! m_bAllowInvert && ! bEquiv) continue ; - // incremento contatore indice entità tra cui scegliere - ++ nF ; - if ( bHaltOnFork) - m_vFork.push_back( vNext[i]) ; // determino scarto angolare Vector3d vtDir = ( bEquiv ? m_vCrvData[nId].vtStart : - m_vCrvData[nId].vtEnd) ; double dProSca = vtCurr * vtDir ; @@ -276,37 +365,76 @@ ChainCurves::ChooseNext( const Vector3d& vtCurr, const INTVECTOR& vNext, bool bH return false ; } + // se biforcazione, aggiungo il punto nel vettore relativo + if ( nF > 1) { + if ( GetForkPoint( ptCurr) == m_vForkData.end()) + m_vForkData.emplace_back( ptCurr, vFork) ; + } + // se richiesto arresto su biforcazione e trovata biforcazione if ( bHaltOnFork && nF > 1) { m_bIsFork = true ; + m_vFork.insert( m_vFork.end(), vFork.begin(), vFork.end()) ; return false ; } // altrimenti assegno il migliore - nNext = vNext[nI] ; - m_bIsFork = false ; + nNext = vMyNext[nI] ; return true ; } //---------------------------------------------------------------------------- bool -ChainCurves::ChoosePrev( const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev) +ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev) { + INTVECTOR vMyPrev = vPrev ; + // scarto quelle entità che sono più vicine all'altro estremo del più vicino + int nM = -1 ; + Point3d ptRef ; + double dSqMinDist = m_dToler * m_dToler ; + for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) { + // recupero indice e verso + int nId = abs( vMyPrev[i]) - 1 ; + bool bEquiv = ( vMyPrev[i] < 0) ; + // determino minima distanza + double dSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ; + if ( dSqDist < dSqMinDist) { + ptRef = ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd) ; + dSqMinDist = dSqDist ; + nM = i ; + } + } + for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) { + // salto l'entità più vicina + if ( i == nM) + continue ; + // recupero indice e verso + int nId = abs( vMyPrev[i]) - 1 ; + bool bEquiv = ( vMyPrev[i] < 0) ; + // verifico se più vicino al più vicino + double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ; + double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ; + if ( dRefSqDist < dCurrSqDist) + vMyPrev[i] = 0 ; + } // cerco la direzione più vicina int nI = - 1 ; int nF = 0 ; double dProScaMax = - 1.1 ; - for ( int i = 0 ; i < int( vPrev.size()) ; ++ i) { + INTVECTOR vFork ; + for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) { + // salto gli scartati + if ( vMyPrev[i] == 0) + continue ; // recupero indice e verso - int nId = abs( vPrev[i]) - 1 ; - bool bEquiv = ( vPrev[i] < 0) ; + int nId = abs( vMyPrev[i]) - 1 ; + bool bEquiv = ( vMyPrev[i] < 0) ; + // incremento contatore indice entità tra cui scegliere + ++ nF ; + vFork.push_back( vMyPrev[i]) ; // se vietata inversione, salto se controverso if ( ! m_bAllowInvert && ! bEquiv) continue ; - // incremento contatore indice entità tra cui scegliere - ++ nF ; - if ( bHaltOnFork) - m_vFork.push_back( vPrev[i]) ; // determino scarto angolare Vector3d vtDir = ( bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart) ; double dProSca = vtCurr * vtDir ; @@ -322,15 +450,21 @@ ChainCurves::ChoosePrev( const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bH return false ; } + // se biforcazione, aggiungo il punto nel vettore relativo + if ( nF > 1) { + if ( GetForkPoint( ptCurr) == m_vForkData.end()) + m_vForkData.emplace_back( ptCurr, vFork) ; + } + // se richiesto arresto su biforcazione e trovata biforcazione if ( bHaltOnFork && nF > 1) { m_bIsFork = true ; + m_vFork.insert( m_vFork.end(), vFork.begin(), vFork.end()) ; return false ; } // altrimenti assegno il migliore - nPrev = vPrev[nI] ; - m_bIsFork = false ; + nPrev = vMyPrev[nI] ; return true ; } @@ -352,3 +486,11 @@ ChainCurves::GetForkIds( INTVECTOR& vForkIds) } return true ; } + +//---------------------------------------------------------------------------- +ChainCurves::FDV_CONST_ITER +ChainCurves::GetForkPoint( const Point3d& ptP) +{ + return ( find_if( m_vForkData.begin(), m_vForkData.end(), + [&]( const ForkData& frkData) { return AreSamePointEpsilon( frkData.ptFork, ptP, m_dToler) ; })) ; +} diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 32b2e8d..566a12b 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -188,8 +188,8 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT pCrv->SetThickness( 0) ; // recupero i punti iniziali e finali della curva - Point3d ptStart, ptEnd ; - if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetEndPoint( ptEnd)) + Point3d ptCrvStart, ptCrvEnd ; + if ( ! pCrv->GetStartPoint( ptCrvStart) || ! pCrv->GetEndPoint( ptCrvEnd)) return false ; // se non è la prima @@ -199,9 +199,9 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT // verifico sia in continuità con il finale attuale Point3d ptEnd ; GetEndPoint( ptEnd) ; - if ( ! AreSamePointApprox( ptStart, ptEnd)) { + if ( ! AreSamePointApprox( ptCrvStart, ptEnd)) { // se in tolleranza, modifico l'inizio dell'entità - if ( SqDist( ptStart, ptEnd) < ( dLinTol * dLinTol)) { + if ( SqDist( ptCrvStart, ptEnd) < ( dLinTol * dLinTol)) { if ( ! pCrv->ModifyStart( ptEnd)) return false ; } @@ -214,9 +214,9 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT // verifico sia in continuità con l'iniziale attuale Point3d ptStart ; GetStartPoint( ptStart) ; - if ( ! AreSamePointApprox( ptEnd, ptStart)) { + if ( ! AreSamePointApprox( ptCrvEnd, ptStart)) { // se in tolleranza, modifico la fine dell'entità - if ( SqDist( ptEnd, ptStart) < ( dLinTol * dLinTol)) { + if ( SqDist( ptCrvEnd, ptStart) < ( dLinTol * dLinTol)) { if ( ! pCrv->ModifyEnd( ptStart)) return false ; } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 2a9dfb432f164eff3f1e099de5e5070965a54f3f..c3567723526f5e88052e848515ef80a8a1d951c0 100644 GIT binary patch delta 110 zcmdlNy)SyhH#SDg&FAHmnVB;g3@0mc>u&bq>R|zkU1plRN-zgW+>LQ_kFXmvPRR~w Ps3eMM9*mo_ltZ`xv~nRZ delta 110 zcmdlNy)SyhH#SC#&FAHmnVB;f3@0mc>u&bq>R|zkU1plRN-zgW+>LQ_kFXmvPRR~w Ps3eMM9*mo_ltZ`xvWy`p diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index fddac5b..ed92303 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -2711,6 +2711,9 @@ GdbExecutor::ExecuteVolZmap( const string& sCmd2, const STRVECTOR& vsParams) else if ( sCmd2 == "COMP") { return ExecuteVolZmapCompact( vsParams) ; } + else if ( sCmd2 == "CHAIN") { + return ExecuteVolZmapChain( vsParams) ; + } return false ; } /* @@ -3055,10 +3058,10 @@ GdbExecutor::ExecuteVolZmapCut( const STRVECTOR& vsParams) bool GdbExecutor::ExecuteVolZmapCompact( const STRVECTOR& vsParams) { - // Parametri : ZmapId + // Parametri : ZmapId if ( vsParams.size() != 1) return false ; - // Recupero Zmap + // Recupero Zmap int nZmapId = GetIdParam( vsParams[0]) ; VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ; if ( pZmap == nullptr) @@ -3067,6 +3070,31 @@ GdbExecutor::ExecuteVolZmapCompact( const STRVECTOR& vsParams) return true ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::ExecuteVolZmapChain(const STRVECTOR& vsParams) +{ + // Parametri : ZmapId, ParentId + if ( vsParams.size() != 2) + return false ; + // Recupero Zmap + int nZmapId = GetIdParam( vsParams[0]) ; + VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ; + if ( pZmap == nullptr) + return false; + // recupero il riferimento in cui è immerso lo Zmap + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + ICURVEPOVECTOR vpLoop ; + pZmap->GetFeatureChaines( vpLoop) ; + bool bOk = true ; + for ( int n = 0 ; n < int( vpLoop.size()) && bOk ; ++ n) { + bOk = bOk && AddGeoObj( "$NN", vsParams[1], Release( vpLoop[n])) ; + } + return bOk ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteIntersection( const std::string& sCmd2, const STRVECTOR& vsParams) diff --git a/GdbExecutor.h b/GdbExecutor.h index 65f3073..c688d06 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -129,6 +129,7 @@ class GdbExecutor : public IGdbExecutor //bool VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams) ; bool ExecuteVolZmapCut( const STRVECTOR& vsParams) ; bool ExecuteVolZmapCompact( const STRVECTOR& vsParams) ; + bool ExecuteVolZmapChain( const STRVECTOR& vsParams) ; bool ExecuteIntersection( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool LineDiscInters( const STRVECTOR& vsParams) ; bool RayDiscInters( const STRVECTOR& vsParams) ; diff --git a/VolZmap.h b/VolZmap.h index 52a4991..c410039 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -93,6 +93,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool GetDepth( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bExact) const override ; bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const override ; bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const override ; + bool GetFeatureChaines( ICURVEPOVECTOR& vpCurve) const ; bool AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist) const override ; bool AvoidSphere( const Point3d& ptCenter, double dRad, double dSafeDist) const override ; bool AvoidCylinder( const Frame3d& frCyl, double dH, double dR, double dSafeDist) const override ; diff --git a/VolZmapGraphics.cpp b/VolZmapGraphics.cpp index cc1d006..121876a 100644 --- a/VolZmapGraphics.cpp +++ b/VolZmapGraphics.cpp @@ -20,6 +20,7 @@ #include "PolygonPlane.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EGkChainCurves.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Extern/Eigen/Core" #include "/EgtDev/Extern/Eigen/SVD" @@ -4453,3 +4454,184 @@ VolZmap::Remove( FlatVoxelContainer& VoxCont, int nI, int nJ, int nK) const return false ; return ( VoxCont.erase( nN) > 0) ; } + +//---------------------------------------------------------------------------- +bool +VolZmap::GetFeatureChaines( ICURVEPOVECTOR& vpCurve) const +{ + // Garantisco grafica aggiornata + UpdateTripleMapGraphics() ; + + // Vettore delle curve di feature + vector vLine ; + + // Ciclo sui triangoli feature all'interno dei blocchi + for ( int nBlock = 0 ; nBlock < m_nNumBlock ; ++ nBlock) { + // Numero di voxel in cui si presentano sharp feature + int nVoxelNum = int( m_BlockSharpTria[nBlock].size()) ; + // Ciclo sui voxel con sharp feature + for ( int n1 = 0 ; n1 < nVoxelNum ; ++ n1) { + const SharpTriaStruct& SharpTria1 = m_BlockSharpTria[nBlock][n1] ; + for ( int n2 = n1 ; n2 < nVoxelNum ; ++ n2) { + const SharpTriaStruct& SharpTria2 = m_BlockSharpTria[nBlock][n2] ; + // Se non adiacenti o coincidenti vado oltre + if ( abs( SharpTria2.i - SharpTria1.i) > 1 || + abs( SharpTria2.j - SharpTria1.j) > 1 || + abs( SharpTria2.k - SharpTria1.k) > 1) + continue ; + // Ciclo sulle componenti connesse del primo voxel + int nNumCompo1 = int( SharpTria1.ptCompoVert.size()) ; + for ( int nCompo1 = 0 ; nCompo1 < nNumCompo1 ; ++ nCompo1) { + const TRIA3DEXVECTOR& vTria1 = SharpTria1.vCompoTria[nCompo1] ; + // Numero di triangoli della componente connessa + int nTriNum1 = int( vTria1.size()) ; + // Ciclo sulle componenti connesse del secondo voxel + int nNumCompo2 = int( SharpTria2.ptCompoVert.size()) ; + int nCompo2 = ( n1 == n2 ? nCompo1 + 1 : 0) ; + for ( ; nCompo2 < nNumCompo2 ; ++ nCompo2) { + const TRIA3DEXVECTOR& vTria2 = SharpTria2.vCompoTria[nCompo2] ; + // Numero di triangoli della componente connessa + int nTriNum2 = int( vTria2.size()) ; + for ( int nTri1 = 0 ; nTri1 < nTriNum1 ; ++ nTri1) { + for ( int nTri2 = 0 ; nTri2 < nTriNum2 ; ++ nTri2) { + // Punti che devono essere in comune fra i due triangoli + const Point3d& ptP10 = vTria1[nTri1].GetP( 0) ; + const Point3d& ptP11 = vTria1[nTri1].GetP( 1) ; + const Point3d& ptP20 = vTria2[nTri2].GetP( 0) ; + const Point3d& ptP21 = vTria2[nTri2].GetP( 1) ; + // I triangoli sono sono stati flippati + if ( AreSamePointEpsilon( ptP10, ptP21, EPS_ZERO) && + AreSamePointEpsilon( ptP11, ptP20, EPS_ZERO) && + ! AreSameVectorApprox( vTria1[nTri1].GetN(), vTria2[nTri2].GetN())) { + // Segmento che congiunge le sharp-features + CurveComposite cvLine ; + if ( cvLine.AddPoint( ptP10) && cvLine.AddLine( ptP11)) + vLine.emplace_back( cvLine) ; + } + } + } + } + } + } + } + } + + // Ciclo sui triangoli feature al confine tra blocchi + for ( int tFB = 0 ; tFB < m_nNumBlock ; ++ tFB) { + int nFBijk[3] ; + GetBlockIJKFromN( int( tFB), nFBijk) ; + for ( int tLB = tFB ; tLB < m_nNumBlock ; ++ tLB) { + int nLBijk[3] ; + GetBlockIJKFromN( int( tLB), nLBijk) ; + // Se i blocchi non sono adiacenti salto l'iterazione + if ( abs( nFBijk[0] - nLBijk[0]) > 1 || + abs( nFBijk[1] - nLBijk[1]) > 1 || + abs( nFBijk[2] - nLBijk[2]) > 1) + continue ; + // Numero di voxel nei blocchi correnti + int nVoxelNumFB = int( m_InterBlockSharpTria[tFB].size()) ; + int nVoxelNumLB = int( m_InterBlockSharpTria[tLB].size()) ; + // Ciclo sui voxel dei due blocchi + for ( int tVFB = 0 ; tVFB < nVoxelNumFB ; ++ tVFB) { + for ( int tVLB = 0 ; tVLB < nVoxelNumLB ; ++ tVLB) { + // Se i voxel non sono adiacenti salto l'iterazione + if ( abs( m_InterBlockSharpTria[tFB][tVFB].i - m_InterBlockSharpTria[tLB][tVLB].i) > 1 || + abs( m_InterBlockSharpTria[tFB][tVFB].j - m_InterBlockSharpTria[tLB][tVLB].j) > 1 || + abs( m_InterBlockSharpTria[tFB][tVFB].k - m_InterBlockSharpTria[tLB][tVLB].k) > 1) + continue ; + // Numero di componenti connesse dei voxel + int nCompoVFBNum = int( m_InterBlockSharpTria[tFB][tVFB].ptCompoVert.size()) ; + int nCompoVLBNum = int( m_InterBlockSharpTria[tLB][tVLB].ptCompoVert.size()) ; + // Ciclo sulle componenti connesse + for ( int tCmpF = 0 ; tCmpF < nCompoVFBNum ; ++ tCmpF) { + for ( int tCmpL = 0 ; tCmpL < nCompoVLBNum ; ++ tCmpL) { + // Numero di triangoli delle componenti connesse + int nTriFBNum = int( m_InterBlockSharpTria[tFB][tVFB].vCompoTria[tCmpF].size()) ; + int nTriLBNum = int( m_InterBlockSharpTria[tLB][tVLB].vCompoTria[tCmpL].size()) ; + // Ciclo sui triangoli + for ( int tTriFB = 0 ; tTriFB < nTriFBNum ; ++ tTriFB) { + for ( int tTriLB = 0 ; tTriLB < nTriLBNum ; ++ tTriLB) { + // Punti che devono essere in comune fra i due triangoli + Point3d ptPF0 = m_InterBlockSharpTria[tFB][tVFB].vCompoTria[tCmpF][tTriFB].GetP( 0) ; + Point3d ptPF1 = m_InterBlockSharpTria[tFB][tVFB].vCompoTria[tCmpF][tTriFB].GetP( 1) ; + Point3d ptPL0 = m_InterBlockSharpTria[tLB][tVLB].vCompoTria[tCmpL][tTriLB].GetP( 0) ; + Point3d ptPL1 = m_InterBlockSharpTria[tLB][tVLB].vCompoTria[tCmpL][tTriLB].GetP( 1) ; + // I triangoli sono stati flippati + if ( AreSamePointEpsilon( ptPF0, ptPL1, EPS_ZERO) && + AreSamePointEpsilon( ptPF1, ptPL0, EPS_ZERO) && + ! AreSameVectorApprox( m_InterBlockSharpTria[tFB][tVFB].vCompoTria[tCmpF][tTriFB].GetN(), + m_InterBlockSharpTria[tLB][tVLB].vCompoTria[tCmpL][tTriLB].GetN())) { + // Segmento che congiunge le sharp-features + CurveComposite cvLine ; + if ( cvLine.AddPoint( ptPF0) && cvLine.AddLine( ptPF1)) + vLine.emplace_back( cvLine) ; + } + } + } + } + } + } + } + } + } + + // Creo le curve + for ( int n = 0 ; n < int( vLine.size()) ; ++ n) { + bool bExpanded = false ; + int nNumSt = 0 ; + int nNumEn = 0 ; + int nMSt = - 1 ; + int nMEn = - 1 ; + Point3d ptSt, ptEn ; + vLine[n].GetStartPoint( ptSt) ; + vLine[n].GetEndPoint( ptEn) ; + for ( int m = 0 ; m < int( vLine.size()) ; ++ m) { + if ( m == n) + continue ; + Point3d ptStM, ptEnM ; + vLine[m].GetStartPoint( ptStM) ; + vLine[m].GetEndPoint( ptEnM) ; + if ( AreSamePointEpsilon( ptSt, ptStM, 100 * EPS_SMALL) || AreSamePointEpsilon( ptSt, ptEnM, 100 * EPS_SMALL)) { + nMSt = m ; + ++ nNumSt ; + } + if ( AreSamePointEpsilon( ptEn, ptStM, 100 * EPS_SMALL) || AreSamePointEpsilon( ptEn, ptEnM, 100 * EPS_SMALL)) { + nMEn = m ; + ++ nNumEn ; + } + } + if ( nNumSt == 1) { + Point3d ptStM ; + vLine[nMSt].GetStartPoint( ptStM) ; + if ( AreSamePointEpsilon( ptSt, ptStM, 100 * EPS_SMALL)) + vLine[nMSt].Invert() ; + bool bAdded = vLine[n].AddCurve( vLine[nMSt], false) ; + vLine.erase( vLine.begin() + nMSt) ; + bExpanded = true ; + } + else if ( nNumEn == 1) { + Point3d ptEnM ; + vLine[nMEn].GetEndPoint( ptEnM) ; + if ( AreSamePointEpsilon( ptEn, ptEnM, 100 * EPS_SMALL)) + vLine[nMEn].Invert() ; + bool bAdded = vLine[n].AddCurve( vLine[nMEn]) ; + vLine.erase( vLine.begin() + nMEn) ; + bExpanded = true ; + } + if ( bExpanded) + -- n ; + nMSt = - 1 ; + nMEn = - 1 ; + } + + for ( int n = 0 ; n < int( vLine.size()) ; ++ n) { + PtrOwner pCurve( vLine[n].Clone()) ; + if ( IsNull( pCurve)) + return false ; + pCurve->MergeCurves( EPS_SMALL, ANG_TOL_STD_DEG) ; + // Inserisco la curva composita nella raccolta da ritornare + vpCurve.emplace_back( Release( pCurve)) ; + } + + return true ; +}