From 469e660da085903e4abecceece07d1baf6848813 Mon Sep 17 00:00:00 2001 From: DarioS Date: Mon, 24 Apr 2023 15:47:41 +0200 Subject: [PATCH 01/10] EgtGeomKernel 2.5d4 : - in ApproxWithLines di CurveComposite aggiunta gestione tipo approssimazione APL_SPECIAL_INT (come SPECIAL ma con garanzia di tre punti su curve non rettilinee) - migliorato calcolo AreaXY e Area di Curve grazie al nuovo tipo di approssimazione - migliorata in Dump gestione decimali di Area - in OffsetCurve corretto possibile errore con curve chiuse dovuto a mancata unione tratti tra autointersezioni suddiviso tra inizio e fine curva. --- CurveAux.cpp | 12 +++++++----- CurveComposite.cpp | 16 ++++++++++++++-- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes OffsetCurve.cpp | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 239b8df..4e0ba4d 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -294,7 +294,7 @@ CurveGetAreaXY( const ICurve& crvC, double& dArea) return false ; // approssimo la curva con una polilinea PolyLine PL ; - crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ; + crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL) ; // calcolo l'area double dAreaXY = 0 ; PL.GetAreaXY( dAreaXY) ; @@ -313,7 +313,7 @@ CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) return false ; // approssimo la curva con una polilinea PolyLine PL ; - crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ; + crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL) ; // calcolo l'area Plane3d plMyPlane ; double dMyArea = 0 ; @@ -364,9 +364,11 @@ CurveDump( const ICurve& crvC, string& sOut, bool bMM, const char* szNewLine) // altri dati per curva chiusa double dAreaXY ; if ( CurveGetAreaXY( crvC, dAreaXY)) { - bool bCCW = ( dAreaXY > 0) ; + bool bCCW = ( dAreaXY > 0) ; + double dAreaUi = GetAreaInUiUnits( abs( dAreaXY), bMM) ; + int nDec = ( dAreaUi > 100 ? 1 : ( dAreaUi > 0.1 ? 3 : 6)) ; sOut += string( "Closed") + ( bCCW ? " CCW" : " CW") + " AreaXY=" + - ToString( GetAreaInUiUnits( abs( dAreaXY), bMM),1) + szNewLine ; + ToString( dAreaUi, nDec) + szNewLine ; } return true ; @@ -728,7 +730,7 @@ FlattenCurve( const ICurve& crCrv, double dToler, double dAngToler, int nFlag) return nullptr ; // Verifico se curva già piatta PolyLine PL ; - if ( ! crCrv.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + if ( ! crCrv.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL)) return nullptr ; bool bFlat = true ; Plane3d plFlat ; plFlat.Set( ptCen, plMid.GetVersN()) ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index a642003..d94b97a 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -985,7 +985,7 @@ CurveComposite::GetCentroid( Point3d& ptCen) const return false ; // approssimo la curva con una polilinea PolyLine PL ; - if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, APL_SPECIAL, PL)) + if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, APL_SPECIAL_INT, PL)) return false ; // calcolo il centro mediante PolygonPlane Point3d ptP ; @@ -1313,7 +1313,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ; // se speciale, approssimo ogni singola entità e conservo le estremità interne (joint) - if ( nType == APL_SPECIAL) { + if ( nType == APL_SPECIAL || nType == APL_SPECIAL_INT) { // eseguo approssimazione double dStartPar = 0 ; for ( auto& pCrv : m_CrvSmplS) { @@ -1324,6 +1324,18 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P PolyLine PLSmpl ; if ( ! pCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, PLSmpl)) return false ; + // se richiesto almeno un punto interno con curve non rettilinee e ci sono solo gli estremi + if ( nType == APL_SPECIAL_INT && pCrv->GetType() != CRV_LINE && PLSmpl.GetPointNbr() == 2) { + // aggiungo il punto interno + Point3d ptMid ; + if ( ! pCrv->GetMidPoint( ptMid)) + return false ; + double dU ; + PLSmpl.GetLastU( dU) ; + dU /= 2 ; + PNTULIST& List = PLSmpl.GetUPointList() ; + List.insert( ++ List.begin(), { ptMid, dU}) ; + } // ripristino estrusione e spessore della curva semplice (annullandoli) pCrv->SetExtrusion( V_NULL) ; pCrv->SetThickness( 0) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 40c1ad1bd2ee110498c80bafc2197922d8e985ac..895c8519d66f4df6570b11769272dccd40f8a290 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&P#&A-_cnHfzcD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-WjGrO delta 94 zcmdlNy)SyhFE&Qw&A-_cnHh~ID{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-W11TR diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index d3e5adc..a41817d 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -422,6 +422,10 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) m_CrvLst.push_back( Release( pCrvCompo)) ; CurveComposite* pCompo1 = GetBasicCurveComposite( m_CrvLst.front()) ; + // salvo punto iniziale + Point3d ptStart ; + pCompo1->GetStartPoint( ptStart) ; + // quinto passo : spezzatura della curva composita negli eventuali punti di auto-intersezione // calcolo le auto-intersezioni SelfIntersCurve sintC( *pCompo1) ; @@ -454,7 +458,6 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) vLen.pop_back() ; } // eseguo la divisione - int nCount = 1 ; double dUPrev = 0 ; double dLenPrev = 0 ; for ( int i = 0 ; i < int( vU.size()) ; ++ i) { @@ -466,7 +469,6 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) if ( IsNull( pCopy)) return false ; m_CrvLst.push_back( Release( pCopy)) ; - ++ nCount ; // trimmo l'originale pCompo1->TrimStartEndAtParam( dUPrev, vU[i]) ; // la copia diventa il nuovo corrente @@ -474,9 +476,20 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) dUPrev = vU[i] ; dLenPrev = vLen[i] ; } - // se fatta almeno una suddivisione, trimmo l'ultima parte - if ( dUPrev > EPS_PARAM) + // se fatta almeno una suddivisione + if ( dUPrev > EPS_PARAM) { + // trimmo l'ultima parte pCompo1->TrimStartAtParam( dUPrev) ; + // sistemo le curve chiuse con due parti di una stessa curva all'inizio e alla fine + if ( bClosed) { + if ( vU[0] > EPS_PARAM && vLen[0] >= 2 * EPS_SMALL) { + // accodo il finale al'iniziale + pCompo1 = GetBasicCurveComposite( m_CrvLst.front()) ; + pCompo1->AddCurve( m_CrvLst.back(), false, 10 * EPS_SMALL) ; + m_CrvLst.pop_back() ; + } + } + } // sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi if ( ! bClosed) { @@ -631,6 +644,19 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) } ++ iIter ; } + // se chiusa riporto l'inizio del primo loop alla posizione iniziale + if ( bClosed) { + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { + CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; + DistPointCurve dstPC( ptStart, *pCrvCo) ; + if ( dstPC.IsEpsilon( 10 * EPS_SMALL)) { + double dU ; int nFlag ; + dstPC.GetParamAtMinDistPoint( 0, dU, nFlag) ; + pCrvCo->ChangeStartPoint( round( dU)) ; + break ; + } + } + } // nono passo : se con smusso o estensione, sostituisco i fillet con questi if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { From 545e37b7cd18e7df432812efaa7d59604dce0aea Mon Sep 17 00:00:00 2001 From: DarioS Date: Tue, 25 Apr 2023 17:40:18 +0200 Subject: [PATCH 02/10] EgtGeomKernel 2.5d5 : - semplificata la precedente correzione all'offset avanzato delle curve. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes OffsetCurve.cpp | 47 +++++++++++++++++++++-------------------------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 895c8519d66f4df6570b11769272dccd40f8a290..c16d5886f434badcd0bdddadc26a9346d6ec897d 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&Qg&A-_cnHfzdD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-X4V@L delta 94 zcmdlNy)SyhFE&P#&A-_cnHfzcD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-WjGrO diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index a41817d..ed433dc 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -422,10 +422,6 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) m_CrvLst.push_back( Release( pCrvCompo)) ; CurveComposite* pCompo1 = GetBasicCurveComposite( m_CrvLst.front()) ; - // salvo punto iniziale - Point3d ptStart ; - pCompo1->GetStartPoint( ptStart) ; - // quinto passo : spezzatura della curva composita negli eventuali punti di auto-intersezione // calcolo le auto-intersezioni SelfIntersCurve sintC( *pCompo1) ; @@ -477,18 +473,13 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) dLenPrev = vLen[i] ; } // se fatta almeno una suddivisione + bool bFirstLastSame = false ; if ( dUPrev > EPS_PARAM) { // trimmo l'ultima parte pCompo1->TrimStartAtParam( dUPrev) ; - // sistemo le curve chiuse con due parti di una stessa curva all'inizio e alla fine - if ( bClosed) { - if ( vU[0] > EPS_PARAM && vLen[0] >= 2 * EPS_SMALL) { - // accodo il finale al'iniziale - pCompo1 = GetBasicCurveComposite( m_CrvLst.front()) ; - pCompo1->AddCurve( m_CrvLst.back(), false, 10 * EPS_SMALL) ; - m_CrvLst.pop_back() ; - } - } + // rilevo le curve chiuse con due parti di una stessa curva all'inizio e alla fine + if ( bClosed && vU[0] > EPS_PARAM && vLen[0] >= 2 * EPS_SMALL) + bFirstLastSame = true ; } // sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi @@ -594,6 +585,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) } // settimo passo : elimino le parti che sono troppo vicine al percorso originale + bool bFirstLastDeleted = false ; for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { ICurve* pCrv = *iIter ; // distanza minima di alcuni punti interni della curva dalla curva originale @@ -604,8 +596,24 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) GetMinDist( 0.875, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || GetMinDist( 0.0625, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || GetMinDist( 0.9375, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL) { + // se prima e ultima sono la stessa curva e non ancora cancellate e prima da cancellare + if ( bFirstLastSame && ! bFirstLastDeleted && iIter == m_CrvLst.begin()) { + bFirstLastDeleted = true ; + // cancello ultima + delete *prev( m_CrvLst.end()) ; + m_CrvLst.pop_back() ; + } + // se prima e ultima sono la stessa curva e non ancora cancellate e ultima da cancellare + if ( bFirstLastSame && ! bFirstLastDeleted && iIter == prev( m_CrvLst.end())) { + bFirstLastDeleted = true ; + // cancello prima + delete *m_CrvLst.begin() ; + m_CrvLst.pop_front() ; + } + // cancello la corrente delete pCrv ; iIter = m_CrvLst.erase( iIter) ; + // evito incremento continue ; } // passo alla successiva @@ -644,19 +652,6 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) } ++ iIter ; } - // se chiusa riporto l'inizio del primo loop alla posizione iniziale - if ( bClosed) { - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { - CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; - DistPointCurve dstPC( ptStart, *pCrvCo) ; - if ( dstPC.IsEpsilon( 10 * EPS_SMALL)) { - double dU ; int nFlag ; - dstPC.GetParamAtMinDistPoint( 0, dU, nFlag) ; - pCrvCo->ChangeStartPoint( round( dU)) ; - break ; - } - } - } // nono passo : se con smusso o estensione, sostituisco i fillet con questi if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { From 5c0848797cd412fb5445696d2a0bc94003b8e301 Mon Sep 17 00:00:00 2001 From: DarioS Date: Thu, 4 May 2023 12:37:47 +0200 Subject: [PATCH 03/10] EgtGeomKernel 2.5e1 : - modifiche al recupero dei triangoli che appartengono ad una stessa faccia (eliminata recursione). --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes SurfTriMesh.h | 2 +- SurfTriMeshFaceting.cpp | 33 +++++++++++++++++++++------------ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index c16d5886f434badcd0bdddadc26a9346d6ec897d..696300bdfd9d64fcde673cc5d3d1dd10ce23cc55 100644 GIT binary patch delta 118 zcmdlNy)SyhH#SyN1|0^&&A-{?nVC}=3@0mc>u&bq>S2M3-{!MM7I$OZ+#~G9j8n2h Q8ZL=uq6g#VEaea`09ZC23IG5A delta 118 zcmdlNy)SyhH#Sxi1|0^|&A-{?nVC}u&bq>S2M3-{!MM7I$OZ+#~G9j8n2h Q8ZL=uq6g#VEaea`0A1)FA^-pY diff --git a/SurfTriMesh.h b/SurfTriMesh.h index f5fa0d2..2082811 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -360,7 +360,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool UpdateOneFace( int nFacet, int nT) ; bool UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT) ; bool SetFacet( int nInd, int nT) ; - bool VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const ; + bool VerifyAdjacTriaFacet( INTVECTOR& vT) const ; bool MarchAlongFacetLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& PL) const ; bool MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ; void ResetHashGrids3d( void) const ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index 363325b..0188cc4 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -17,6 +17,7 @@ #include "GeoConst.h" #include "PolygonPlane.h" #include "/EgtDev/Include/EgtPointerOwner.h" +#include #include #include @@ -223,25 +224,33 @@ SurfTriMesh::GetAllTriaInFacet( int nF, INTVECTOR& vT) const vT.reserve( 10) ; vT.push_back( nT) ; m_vTria[nT].nTemp = m_nTimeStamp ; - return VerifyAdjacTriaFacet( nT, vT) ; + return VerifyAdjacTriaFacet( vT) ; } //---------------------------------------------------------------------------- bool -SurfTriMesh::VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const +SurfTriMesh::VerifyAdjacTriaFacet( INTVECTOR& vT) const { - // verifico i triangoli adiacenti - for ( int j = 0 ; j < 3 ; ++ j) { - int nAdjT = m_vTria[nT].nIdAdjac[j] ; - if ( nAdjT != SVT_NULL && - m_vTria[nAdjT].nTemp != m_nTimeStamp && - m_vTria[nAdjT].nIdFacet == m_vTria[nT].nIdFacet) { - vT.push_back( nAdjT) ; - m_vTria[nAdjT].nTemp = m_nTimeStamp ; - if ( ! VerifyAdjacTriaFacet( nAdjT, vT)) - return false ; + INTVECTOR vStack{ vT.back()} ; + while ( ! vStack.empty()) { + array vNew{ SVT_NULL, SVT_NULL, SVT_NULL} ; + for ( int j = 0 ; j < 3 ; ++ j) { + int nAdjT = m_vTria[vStack.back()].nIdAdjac[j] ; + if ( nAdjT != SVT_NULL && + m_vTria[nAdjT].nTemp != m_nTimeStamp && + m_vTria[nAdjT].nIdFacet == m_vTria[vStack.back()].nIdFacet) { + vT.push_back( nAdjT) ; + vNew[j] = nAdjT ; + m_vTria[nAdjT].nTemp = m_nTimeStamp ; + } + } + vStack.pop_back() ; + for ( int j = 0 ; j < 3 ; ++ j) { + if ( vNew[j] != SVT_NULL) + vStack.push_back( vNew[j]) ; } } + return true ; } From ec3389633c483e0ced8fd9b8d66d993d2614e8cd Mon Sep 17 00:00:00 2001 From: DarioS Date: Thu, 4 May 2023 16:10:31 +0200 Subject: [PATCH 04/10] EgtGeomKernel : - piccoli ritocchi. --- SurfTriMeshBooleans.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index b8a27ad..71620a5 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -394,20 +394,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } // Fra le catene trovate separo le aperte dalle chiuse - int nDegenerateChainNum = 0 ; INTVECTOR vnDegVec ; CHAINVECTOR cvClosedChain ; CHAINVECTOR cvOpenChain ; for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) { - bool bChainDegenerate = false ; - if ( vChain[nL].size() == 1 && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][0].ptEn)) { - bChainDegenerate = true ; - } - - if ( bChainDegenerate) - ++ nDegenerateChainNum ; + bool bChainDegenerate = ( vChain[nL].size() == 1 && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][0].ptEn)) ; int nCurLoopLast = max( int( vChain[nL].size()) - 1, 0) ; - if ( ( ! bChainDegenerate) && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn)) + if ( ! bChainDegenerate && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn)) cvClosedChain.emplace_back( vChain[nL]) ; else { cvOpenChain.emplace_back( vChain[nL]) ; @@ -446,7 +439,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } // Gestione tagli piccoli - if ( int( cvOpenChain.size()) == 1 && int( cvOpenChain[0].size()) == 1 && int( cvClosedChain.size()) == 0) { + if ( cvOpenChain.size() == 1 && cvOpenChain[0].size() == 1 && cvClosedChain.empty()) { if ( AreSamePointEpsilon( cvOpenChain[0][0].ptSt, cvOpenChain[0][0].ptEn, EPS_SMALL)) { Plane3d plPlane ; plPlane.Set( cvOpenChain[0][0].ptSt, cvOpenChain[0][0].vtOuter) ; @@ -511,7 +504,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT vbInOut.push_back( true) ; // Divido il loop usando le catene if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) { - if ( int( cvBoundClosedLoopVec.size()) == 1 && int( cvOpenChain.size()) == 2) { + if ( cvBoundClosedLoopVec.size() == 1 && cvOpenChain.size() == 2) { Point3d ptLink0St = cvOpenChain[0][0].ptSt ; Point3d ptLink0En = cvOpenChain[0].back().ptEn ; Point3d ptLink1St = cvOpenChain.back()[0].ptSt ; @@ -571,7 +564,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT POLYLINEVECTOR vplPolyVec ; vplPolyVec.resize( cvBoundClosedLoopVec.size()) ; for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) { - for (int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) { + for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) { vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ; } vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ; @@ -1616,7 +1609,7 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; if ( ! SimplifyFacets()) - LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Intersect") + LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Subtract") return bOk ; } @@ -1750,7 +1743,7 @@ SurfTriMesh::Repair( double dMaxEdgeLen) // Ritriangolo le facce if ( ! SimplifyFacets( dMaxEdgeLen, true)) - LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Intersect") + LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Repair") return true ; } From 0f530271f0594ca70c7dae72927e2945ee9c3373 Mon Sep 17 00:00:00 2001 From: DarioS Date: Mon, 8 May 2023 08:24:04 +0200 Subject: [PATCH 05/10] EgtGeomKernel 2.5e2 : - aggiunta AddSurfTriMesh a StmFromTriangleSoup - velocizzazione dei calcoli in GetSurfTriMeshBeveledRectSwept (solidi di AM). --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes StmFromCurves.cpp | 122 +++++++++++++++++++++++----------------- StmFromTriangleSoup.cpp | 31 ++++++++-- SurfTriMesh.cpp | 2 +- 4 files changed, 97 insertions(+), 58 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 696300bdfd9d64fcde673cc5d3d1dd10ce23cc55..50d8062ddc566051bbd4be8078da6498feab407a 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&P_&A-_cnHh~HD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-Vf-5U delta 94 zcmdlNy)SyhFE&QQ&A-_cnHdcyD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-U|t&X diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 65d1bf7..168422e 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -20,8 +20,11 @@ #include "SurfTriMesh.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkStmFromCurves.h" +#include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include +#include +#include using namespace std ; @@ -394,15 +397,6 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, } // se altrimenti guida aperta e tappi arrotondati if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { - // verifico che le due estremità siano chiuse e piatte - //POLYLINEVECTOR vPL ; - //if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) - // return nullptr ; - //Plane3d plEnds ; double dArea ; - //if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) - // return nullptr ; - //if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) - // return nullptr ; // step di rotazione per rispettare la tolleranza double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ; // aggiungo il cap sull'inizio @@ -437,8 +431,6 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, return nullptr ; pSce->Invert() ; pSTM->DoSewing( *pSce) ; - // elimino eventuali fessure - //pSTM->Repair() ; } // restituisco la superficie return Release( pSTM) ; @@ -461,29 +453,37 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; // curve di offset - OffsetCurve OffsCrvR ; - if ( ! OffsCrvR.Make( pGuide, dDimH / 2 - dBevelH, ICurve::OFF_FILLET) || OffsCrvR.GetCurveCount() == 0) + const int NUM_OFFS = 4 ; + OffsetCurve vOffsCrv[NUM_OFFS] ; + double vDist[NUM_OFFS] = { dDimH / 2 - dBevelH, -dDimH / 2 + dBevelH, dDimH / 2, -dDimH / 2} ; + future vRes[NUM_OFFS] ; + for ( int i = 0 ; i < NUM_OFFS ; ++ i) + vRes[i] = async( launch::async, &OffsetCurve::Make, &vOffsCrv[i], pGuide, vDist[i], ICurve::OFF_FILLET) ; + bool bOk = true ; + int nFin = 0 ; + while ( nFin < NUM_OFFS) { + for ( int i = 0 ; i < NUM_OFFS ; ++ i) { + if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) { + bOk = vRes[i].get() && bOk ; + ++ nFin ; + } + } + } + if ( ! bOk || + vOffsCrv[0].GetCurveCount() == 0 || vOffsCrv[1].GetCurveCount() == 0 || + vOffsCrv[2].GetCurveCount() == 0 || vOffsCrv[3].GetCurveCount() == 0) return nullptr ; - PtrOwner pCrvR( OffsCrvR.GetLongerCurve()) ; + PtrOwner pCrvR( vOffsCrv[0].GetLongerCurve()) ; if ( IsNull( pCrvR)) return nullptr ; - OffsetCurve OffsCrvL ; - if ( ! OffsCrvL.Make( pGuide, -dDimH / 2 + dBevelH, ICurve::OFF_FILLET) || OffsCrvL.GetCurveCount() == 0) - return nullptr ; - PtrOwner pCrvL( OffsCrvL.GetLongerCurve()) ; + PtrOwner pCrvL( vOffsCrv[1].GetLongerCurve()) ; if ( IsNull( pCrvL)) return nullptr ; - OffsetCurve OffsCrvRb ; - if ( ! OffsCrvRb.Make( pGuide, dDimH / 2, ICurve::OFF_FILLET) || OffsCrvRb.GetCurveCount() == 0) - return nullptr ; - PtrOwner pCrvRb( OffsCrvRb.GetLongerCurve()) ; + PtrOwner pCrvRb( vOffsCrv[2].GetLongerCurve()) ; if ( IsNull( pCrvRb)) return nullptr ; pCrvRb->Translate( - dBevelV * vtNorm) ; - OffsetCurve OffsCrvLb ; - if ( ! OffsCrvLb.Make( pGuide, -dDimH / 2, ICurve::OFF_FILLET) || OffsCrvLb.GetCurveCount() == 0) - return nullptr ; - PtrOwner pCrvLb( OffsCrvLb.GetLongerCurve()) ; + PtrOwner pCrvLb( vOffsCrv[3].GetLongerCurve()) ; if ( IsNull( pCrvLb)) return nullptr ; pCrvLb->Translate( - dBevelV * vtNorm) ; @@ -518,19 +518,29 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub if ( IsNull( pSrfLft)) return nullptr ; // unisco le parti - PtrOwner pSTM( Release( pSrfTop)) ; - pSTM->DoSewing( *pSrfTopR) ; - pSTM->DoSewing( *pSrfTopL) ; - pSTM->DoSewing( *pSrfRgt) ; - pSTM->DoSewing( *pSrfLft) ; - pSTM->DoSewing( *pSrfBotR) ; - pSTM->DoSewing( *pSrfBotL) ; - pSTM->DoSewing( *pSrfBot) ; - // salvo tolleranza lineare usata e imposto angolo per smooth - pSTM->SetLinearTolerance( dLinTol) ; - pSTM->SetSmoothAngle( 20) ; + int nBuckets = max( 4 * ( pSrfRgt->GetVertexSize() + pSrfLft->GetVertexSize()), 1000) ; + StmFromTriangleSoup stmSoup ; + if ( ! stmSoup.Start( nBuckets)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pSrfTop) ; + stmSoup.AddSurfTriMesh( *pSrfTopR) ; + stmSoup.AddSurfTriMesh( *pSrfTopL) ; + stmSoup.AddSurfTriMesh( *pSrfRgt) ; + stmSoup.AddSurfTriMesh( *pSrfLft) ; + stmSoup.AddSurfTriMesh( *pSrfBotR) ; + stmSoup.AddSurfTriMesh( *pSrfBotL) ; + stmSoup.AddSurfTriMesh( *pSrfBot) ; + PtrOwner pSTM ; // se guida aperta e tappi piatti if ( ! bGuideClosed && nCapType == RSCAP_FLAT) { + // completo unione e recupero la superficie risultante + if ( ! stmSoup.End()) + return nullptr ; + pSTM.Set( stmSoup.GetSurf()) ; + // preparo seconda zuppa di triangoli per inserire i tappi + StmFromTriangleSoup stmCapSoup ; + if ( ! stmCapSoup.Start( nBuckets)) + return nullptr ; // verifico che le due estremità siano chiuse e piatte POLYLINEVECTOR vPL ; if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) @@ -545,25 +555,20 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0])) return nullptr ; pSci->Invert() ; - pSTM->DoSewing( *pSci) ; + stmCapSoup.AddSurfTriMesh( *pSci) ; // aggiungo il cap sulla fine PtrOwner pSce( CreateSurfTriMesh()) ; if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1])) return nullptr ; pSce->Invert() ; - pSTM->DoSewing( *pSce) ; + stmCapSoup.AddSurfTriMesh( *pSce) ; + // completo unione con i tappi e recupero la superficie risultante + if ( ! stmCapSoup.End()) + return nullptr ; + pSTM.Set( stmCapSoup.GetSurf()) ; } // se altrimenti guida aperta e tappi arrotondati - if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { - // verifico che le due estremità siano chiuse e piatte - //POLYLINEVECTOR vPL ; - //if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) - // return nullptr ; - //Plane3d plEnds ; double dArea ; - //if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) - // return nullptr ; - //if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) - // return nullptr ; + else if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { // step di rotazione per rispettare il tipo o la tolleranza double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ; // aggiungo il cap sull'inizio @@ -583,7 +588,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) return nullptr ; pSci->Invert() ; - pSTM->DoSewing( *pSci) ; + stmSoup.AddSurfTriMesh( *pSci) ; // aggiungo il cap sulla fine Point3d ptEnd ; pGuide->GetEndPoint( ptEnd) ; @@ -601,10 +606,21 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) return nullptr ; pSce->Invert() ; - pSTM->DoSewing( *pSce) ; - // elimino eventuali fessure - //pSTM->Repair() ; + stmSoup.AddSurfTriMesh( *pSce) ; + // completo unione e recupero la superficie risultante + if ( ! stmSoup.End()) + return nullptr ; + pSTM.Set( stmSoup.GetSurf()) ; } + else { + // completo unione e recupero la superficie risultante + if ( ! stmSoup.End()) + return nullptr ; + pSTM.Set( stmSoup.GetSurf()) ; + } + // salvo tolleranza lineare usata e imposto angolo per smooth + pSTM->SetLinearTolerance( dLinTol) ; + pSTM->SetSmoothAngle( 20) ; // restituisco la superficie return Release( pSTM) ; } diff --git a/StmFromTriangleSoup.cpp b/StmFromTriangleSoup.cpp index 23838da..fb72490 100644 --- a/StmFromTriangleSoup.cpp +++ b/StmFromTriangleSoup.cpp @@ -1,10 +1,10 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2015 +// EgalTech 2014-2023 //---------------------------------------------------------------------------- -// File : StmFromTriangleSoup.cpp Data : 19.05.14 Versione : 1.5e7 +// File : StmFromTriangleSoup.cpp Data : 07.05.23 Versione : 2.5e2 // Contenuto : Implementazione della classe StmFromTriangleSoup, per creare -// una superficie trimesh da un insieme disordinato di triangoli(STL). -// +// una superficie trimesh da un insieme di triangoli +// (può essere disordinato come STL o può essere una superficie). // // Modifiche : 19.05.14 DS Creazione modulo. // @@ -112,6 +112,29 @@ StmFromTriangleSoup::AddVertex( const Point3d& ptP) return nId ; } +//---------------------------------------------------------------------------- +bool +StmFromTriangleSoup::AddSurfTriMesh( const ISurfTriMesh& stmSource) +{ + // verifico inizializzazione + if ( m_pSTM == nullptr) + return false ; + // verifico superficie sorgente + if ( &stmSource == nullptr || ! stmSource.IsValid()) + return false ; + // recupero tutti i triangoli della superficie + bool bOk ; + Triangle3d Tria ; + int nT = stmSource.GetFirstTriangle( Tria) ; + while ( nT != SVT_NULL) { + // inserisco il triangolo nella zuppa + bOk = AddTriangle( Tria) && bOk ; + // passo al triangolo successivo + nT = stmSource.GetNextTriangle( nT, Tria) ; + } + return bOk ; +} + //---------------------------------------------------------------------------- bool StmFromTriangleSoup::End( void) diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 75de929..dbf19d5 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -3003,7 +3003,7 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, dou // definisco un Grid per i vertici delle due superfici PointGrid3d VertGrid ; - int nBuckets = GetVertexSize() + pOther->GetVertexSize() ; + int nBuckets = max( GetVertexSize() + pOther->GetVertexSize(), 1000) ; VertGrid.Init( nBuckets) ; // inserisco i vertici della trimesh corrente (li considero tutti diversi tra loro) From 7023d721f4eb8a18ec53046f38200d586bbd8dda Mon Sep 17 00:00:00 2001 From: DarioS Date: Mon, 8 May 2023 09:32:12 +0200 Subject: [PATCH 06/10] EgtGeomKernel : - modifica a IsFlat per renderla compatibile con l'esecuzione in parallelo. --- CurveComposite.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CurveComposite.cpp b/CurveComposite.cpp index d94b97a..46d3ce8 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -849,9 +849,9 @@ CurveComposite::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) con return false ; // ciclo sulle curve semplici (aggiungo solo eventuali punti intermedi e finali) int nCount = 0 ; - for ( const ICurve* pCrv = GetFirstCurve() ; + for ( const ICurve* pCrv = GetCurve( nCount) ; pCrv != nullptr ; - pCrv = GetNextCurve(), ++ nCount) { + pCrv = GetCurve( ++ nCount)) { switch ( pCrv->GetType()) { case CRV_LINE : // punto finale From 2d8c815032fd34ac03482cf72837d228ad0f615f Mon Sep 17 00:00:00 2001 From: DarioS Date: Sun, 14 May 2023 11:58:48 +0200 Subject: [PATCH 07/10] =?UTF-8?q?EgtGeomKernel=202.5e3=20:=20-=20a=20BBox3?= =?UTF-8?q?d=20aggiunto=202=C2=B0=20metodo=20Overlaps=20con=20box=20aventi?= =?UTF-8?q?=20diverso=20orientamento=20-=20nelle=20funzioni=20di=20Collisi?= =?UTF-8?q?on=20Detection=20migliorato=20controllo=20non=20interne=20-=20n?= =?UTF-8?q?ele=20funzioni=20Avoid=20di=20Zmap=20si=20utilizza=20confronto?= =?UTF-8?q?=20box=20con=20diverso=20orientamento.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BBox3d.cpp | 130 +++++++++++++---- CAvToolSurfTm.cpp | 6 +- CDeBoxClosedSurfTm.cpp | 19 +-- CDeClosedSurfTmClosedSurfTm.cpp | 51 +++---- CDeConeFrustumClosedSurfTm.cpp | 16 ++- CDeConvexTorusClosedSurfTm.cpp | 34 ++--- CDeCylClosedSurfTm.cpp | 30 ++-- CDeRectPrismoidClosedSurfTm.cpp | 18 ++- CDeSpheClosedSurfTm.cpp | 13 +- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes VolZmapCalculus.cpp | 243 ++++++++++++++++++-------------- VolZmapGraphics.cpp | 12 +- 12 files changed, 341 insertions(+), 231 deletions(-) diff --git a/BBox3d.cpp b/BBox3d.cpp index 12b14fe..2d67e7f 100644 --- a/BBox3d.cpp +++ b/BBox3d.cpp @@ -447,69 +447,141 @@ BBox3d::EnclosesXY( const BBox3d& b3Box) const //---------------------------------------------------------------------------- bool -BBox3d::Overlaps( const BBox3d& b3B) const +BBox3d::Overlaps( const BBox3d& b3Box) const { - if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) + if ( m_ptMax.x < b3Box.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3Box.m_ptMax.x + EPS_SMALL) return false ; - if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) + if ( m_ptMax.y < b3Box.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3Box.m_ptMax.y + EPS_SMALL) return false ; - if ( m_ptMax.z < b3B.m_ptMin.z - EPS_SMALL || m_ptMin.z > b3B.m_ptMax.z + EPS_SMALL) + if ( m_ptMax.z < b3Box.m_ptMin.z - EPS_SMALL || m_ptMin.z > b3Box.m_ptMax.z + EPS_SMALL) return false ; return true ; } //---------------------------------------------------------------------------- bool -BBox3d::OverlapsXY( const BBox3d& b3B) const +BBox3d::OverlapsXY( const BBox3d& b3Box) const { - if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) + if ( m_ptMax.x < b3Box.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3Box.m_ptMax.x + EPS_SMALL) return false ; - if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) + if ( m_ptMax.y < b3Box.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3Box.m_ptMax.y + EPS_SMALL) return false ; return true ; } //---------------------------------------------------------------------------- -bool -BBox3d::FindIntersection( const BBox3d& b3B, BBox3d& b3Int) const +inline bool +TestSeparatingAxis( const Vector3d& vtAx, const Vector3d& vtDiff, const Vector3d& vtHe, + const Vector3d& vtHe2X, const Vector3d& vtHe2Y, const Vector3d& vtHe2Z) { - if ( ! IsValid() || ! b3B.IsValid()) + if ( vtAx.IsSmall()) + return false ; + double dLen = ( vtAx.IsNormalized() ? 1 : vtAx.Len()) ; + return ( abs( vtDiff * vtAx) > + abs( vtHe.x * vtAx.x) + abs( vtHe.y * vtAx.y) + abs( vtHe.z * vtAx.z) + + abs( vtHe2X * vtAx) + abs( vtHe2Y * vtAx) + abs( vtHe2Z * vtAx) + EPS_SMALL * dLen) ; +} + +//---------------------------------------------------------------------------- +bool +BBox3d::Overlaps( const Frame3d& frBox, const BBox3d& b3Box) const +{ + // Verifico validità di entrambi i box + if ( ! IsValid() || ! b3Box.IsValid()) + return false ; + + // Centro e semiampiezza del box + Point3d ptCen = ( m_ptMin + m_ptMax) / 2 ; + Vector3d vtHe = ( m_ptMax - m_ptMin) / 2 ; + // Centro e semiampiezza dell'altro box + Point3d ptCen2 = GetToGlob( ( b3Box.m_ptMin + b3Box.m_ptMax) / 2, frBox) ; + Vector3d vtHe2X = GetToGlob( Vector3d( ( b3Box.GetDimX()) / 2, 0, 0), frBox) ; + Vector3d vtHe2Y = GetToGlob( Vector3d( 0, ( b3Box.GetDimY()) / 2, 0), frBox) ; + Vector3d vtHe2Z = GetToGlob( Vector3d( 0, 0, ( b3Box.GetDimZ()) / 2), frBox) ; + // Vettore tra i due centri + Vector3d vtDiff = ptCen2 - ptCen ; + + // Verifico separazione sulle normali ai piani principali del riferimento globale + if ( TestSeparatingAxis( X_AX, vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Y_AX, vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Z_AX, vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + + // Verifico separazione sulle normali ai piani principali del secondo riferimento + if ( TestSeparatingAxis( frBox.VersX(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( frBox.VersY(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( frBox.VersZ(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + + // Verifico separazione sulle altre normali ottenute come prodotto vettoriali di quelle precedenti + if ( TestSeparatingAxis( X_AX ^ frBox.VersX(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( X_AX ^ frBox.VersY(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( X_AX ^ frBox.VersZ(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Y_AX ^ frBox.VersX(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Y_AX ^ frBox.VersY(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Y_AX ^ frBox.VersZ(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Z_AX ^ frBox.VersX(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Z_AX ^ frBox.VersY(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + if ( TestSeparatingAxis( Z_AX ^ frBox.VersZ(), vtDiff, vtHe, vtHe2X, vtHe2Y, vtHe2Z)) + return false ; + + // Si sovrappongono + return true ; +} + +//---------------------------------------------------------------------------- +bool +BBox3d::FindIntersection( const BBox3d& b3Box, BBox3d& b3Int) const +{ + if ( ! IsValid() || ! b3Box.IsValid()) return false ; // verifico direttamente la sovrapposizione - if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) + if ( m_ptMax.x < b3Box.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3Box.m_ptMax.x + EPS_SMALL) return false ; - if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) + if ( m_ptMax.y < b3Box.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3Box.m_ptMax.y + EPS_SMALL) return false ; - if ( m_ptMax.z < b3B.m_ptMin.z - EPS_SMALL || m_ptMin.z > b3B.m_ptMax.z + EPS_SMALL) + if ( m_ptMax.z < b3Box.m_ptMin.z - EPS_SMALL || m_ptMin.z > b3Box.m_ptMax.z + EPS_SMALL) return false ; // calcolo il box intersezione - b3Int.m_ptMin.x = (( m_ptMin.x >= b3B.m_ptMin.x) ? m_ptMin.x : b3B.m_ptMin.x) ; - b3Int.m_ptMin.y = (( m_ptMin.y >= b3B.m_ptMin.y) ? m_ptMin.y : b3B.m_ptMin.y) ; - b3Int.m_ptMin.z = (( m_ptMin.z >= b3B.m_ptMin.z) ? m_ptMin.z : b3B.m_ptMin.z) ; - b3Int.m_ptMax.x = (( m_ptMax.x <= b3B.m_ptMax.x) ? m_ptMax.x : b3B.m_ptMax.x) ; - b3Int.m_ptMax.y = (( m_ptMax.y <= b3B.m_ptMax.y) ? m_ptMax.y : b3B.m_ptMax.y) ; - b3Int.m_ptMax.z = (( m_ptMax.z <= b3B.m_ptMax.z) ? m_ptMax.z : b3B.m_ptMax.z) ; + b3Int.m_ptMin.x = (( m_ptMin.x >= b3Box.m_ptMin.x) ? m_ptMin.x : b3Box.m_ptMin.x) ; + b3Int.m_ptMin.y = (( m_ptMin.y >= b3Box.m_ptMin.y) ? m_ptMin.y : b3Box.m_ptMin.y) ; + b3Int.m_ptMin.z = (( m_ptMin.z >= b3Box.m_ptMin.z) ? m_ptMin.z : b3Box.m_ptMin.z) ; + b3Int.m_ptMax.x = (( m_ptMax.x <= b3Box.m_ptMax.x) ? m_ptMax.x : b3Box.m_ptMax.x) ; + b3Int.m_ptMax.y = (( m_ptMax.y <= b3Box.m_ptMax.y) ? m_ptMax.y : b3Box.m_ptMax.y) ; + b3Int.m_ptMax.z = (( m_ptMax.z <= b3Box.m_ptMax.z) ? m_ptMax.z : b3Box.m_ptMax.z) ; return true ; } //---------------------------------------------------------------------------- bool -BBox3d::FindIntersectionXY( const BBox3d& b3B, BBox3d& b3Int) const +BBox3d::FindIntersectionXY( const BBox3d& b3Box, BBox3d& b3Int) const { - if ( ! IsValid() || ! b3B.IsValid()) + if ( ! IsValid() || ! b3Box.IsValid()) return false ; // verifico direttamente la sovrapposizione - if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) + if ( m_ptMax.x < b3Box.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3Box.m_ptMax.x + EPS_SMALL) return false ; - if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) + if ( m_ptMax.y < b3Box.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3Box.m_ptMax.y + EPS_SMALL) return false ; // calcolo il box intersezione - b3Int.m_ptMin.x = (( m_ptMin.x >= b3B.m_ptMin.x) ? m_ptMin.x : b3B.m_ptMin.x) ; - b3Int.m_ptMin.y = (( m_ptMin.y >= b3B.m_ptMin.y) ? m_ptMin.y : b3B.m_ptMin.y) ; - b3Int.m_ptMin.z = 0.5 * ( m_ptMin.z + b3B.m_ptMin.z) ; - b3Int.m_ptMax.x = (( m_ptMax.x <= b3B.m_ptMax.x) ? m_ptMax.x : b3B.m_ptMax.x) ; - b3Int.m_ptMax.y = (( m_ptMax.y <= b3B.m_ptMax.y) ? m_ptMax.y : b3B.m_ptMax.y) ; - b3Int.m_ptMax.z = 0.5 * ( m_ptMax.z + b3B.m_ptMax.z) ; + b3Int.m_ptMin.x = (( m_ptMin.x >= b3Box.m_ptMin.x) ? m_ptMin.x : b3Box.m_ptMin.x) ; + b3Int.m_ptMin.y = (( m_ptMin.y >= b3Box.m_ptMin.y) ? m_ptMin.y : b3Box.m_ptMin.y) ; + b3Int.m_ptMin.z = 0.5 * ( m_ptMin.z + b3Box.m_ptMin.z) ; + b3Int.m_ptMax.x = (( m_ptMax.x <= b3Box.m_ptMax.x) ? m_ptMax.x : b3Box.m_ptMax.x) ; + b3Int.m_ptMax.y = (( m_ptMax.y <= b3Box.m_ptMax.y) ? m_ptMax.y : b3Box.m_ptMax.y) ; + b3Int.m_ptMax.z = 0.5 * ( m_ptMax.z + b3Box.m_ptMax.z) ; return true ; } diff --git a/CAvToolSurfTm.cpp b/CAvToolSurfTm.cpp index d03bc8a..ba73ba0 100644 --- a/CAvToolSurfTm.cpp +++ b/CAvToolSurfTm.cpp @@ -301,11 +301,11 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) Vector3d vtDirL = vtDir ; vtDirL.ToLoc( m_frMove) ; b3Tool.Add( ptTL) ; b3Tool.Add( ptTL - vtDirL * m_Tool.GetHeigth()) ; - if ( vtDirL.IsXplus() || vtDirL.IsXminus()) + if ( vtDirL.IsX()) b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ; - else if ( vtDirL.IsYplus() || vtDirL.IsYminus()) + else if ( vtDirL.IsY()) b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ; - else if ( vtDirL.IsZplus() || vtDirL.IsZminus()) + else if ( vtDirL.IsZ()) b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ; else { double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDirL.x * vtDirL.x) ; diff --git a/CDeBoxClosedSurfTm.cpp b/CDeBoxClosedSurfTm.cpp index ca39b66..6b29905 100644 --- a/CDeBoxClosedSurfTm.cpp +++ b/CDeBoxClosedSurfTm.cpp @@ -23,17 +23,17 @@ using namespace std ; bool CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, const ISurfTriMesh& Stm) { - // recupero BBox del poliedro + // Recupero BBox del poliedro BBox3d b3Poly = Stm.GetAllTriaBox() ; - // calcolo il BBox del parallelepipedo - BBox3d b3Box( ORIG, ORIG + vtDiag) ; + // Calcolo il BBox del parallelepipedo + BBox3d b3BoxL( ORIG, ORIG + vtDiag) ; if ( dSafeDist > EPS_SMALL) - b3Box.Expand( dSafeDist) ; - b3Box.ToGlob( frBox) ; + b3BoxL.Expand( dSafeDist) ; + BBox3d b3Box = GetToGlob( b3BoxL, frBox) ; // Se i BBox non interferiscono, non c'è collisione - if ( ! b3Box.Overlaps( b3Poly)) + if ( ! b3Poly.Overlaps( b3Box) || ! b3Poly.Overlaps( frBox, b3BoxL)) return false ; - // recupero i triangoli che interferiscono con il box + // Verifico se il parallelepipedo interferisce con i triangoli del poliedro presenti nel suo BBox INTVECTOR vT ; Stm.GetAllTriaOverlapBox( b3Box, vT) ; for ( int nT : vT) { @@ -46,7 +46,10 @@ CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDi // Se superficie aperta, non c'è collisione if ( ! Stm.IsClosed()) return false ; - // Verifico se il box è dentro la superficie tramite calcolo distanza minima. + // Se il BBox del parallelepipedo non è interno a quello del poliedro e viceversa, non c'è collisione + if ( ! b3Poly.Encloses( b3Box) && ! b3Box.Encloses( b3Poly)) + return false ; + // Verifico se il box è dentro la superficie tramite calcolo distanza minima del suo centro Point3d ptBoxCen = ORIG + vtDiag / 2 ; ptBoxCen.ToGlob( frBox) ; DistPointSurfTm DistBoxCenSurfCalc( ptBoxCen, Stm) ; diff --git a/CDeClosedSurfTmClosedSurfTm.cpp b/CDeClosedSurfTmClosedSurfTm.cpp index d625dc6..81bdc5a 100644 --- a/CDeClosedSurfTmClosedSurfTm.cpp +++ b/CDeClosedSurfTmClosedSurfTm.cpp @@ -35,60 +35,60 @@ using namespace std ; bool CDeClosedSurfTmClosedSurfTm( const SurfTriMesh& SurfA, const SurfTriMesh& SurfB, double dSafeDist) { - // Se le superfici non sono valide o non sono chiuse, non ha senso proseguire. + // Se le superfici non sono valide o non sono chiuse, non ha senso proseguire. if ( ! ( SurfA.IsValid() && SurfB.IsValid()) || ! ( SurfA.IsClosed() && SurfB.IsClosed())) return false ; - // Se i box delle superfici non si intersecano, ho finito. + // Se i box delle superfici non si intersecano, ho finito. BBox3d b3BoxA, b3BoxB ; SurfA.GetLocalBBox( b3BoxA) ; SurfB.GetLocalBBox( b3BoxB) ; - // Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza. + // Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza. if ( dSafeDist > EPS_SMALL) b3BoxA.Expand( dSafeDist) ; - // Se i box non si sovrappongono, non c'è collisione. Ho finito. + // Se i box non si sovrappongono, non c'è collisione. Ho finito. if ( ! b3BoxA.Overlaps( b3BoxB)) return false ; - // Recupero i triangoli di B che interferiscono col box del triangolo di A + // Recupero i triangoli di B che interferiscono col box del triangolo di A INTVECTOR vTriaIndex ; SurfA.GetAllTriaOverlapBox( b3BoxB, vTriaIndex) ; - // Ciclo sui triangoli della superficie A che cadono nel box della superficie B. + // Ciclo sui triangoli della superficie A che cadono nel box della superficie B. for ( int nTA : vTriaIndex) { Triangle3d trTriaA ; if ( ! ( SurfA.GetTriangle( nTA, trTriaA) && trTriaA.Validate())) continue ; BBox3d b3BoxTriaA ; trTriaA.GetLocalBBox( b3BoxTriaA) ; - // Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza. + // Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza. if ( dSafeDist > EPS_SMALL) b3BoxTriaA.Expand( dSafeDist) ; - // Recupero i triangoli di B che interferiscono col box del triangolo di A + // Recupero i triangoli di B che interferiscono col box del triangolo di A INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ; - // Settare tutti i triangoli come già processati. - // Al termine della chiamata i TFlags dei triangoli valgono 0. + // Settare tutti i triangoli come già processati. + // Al termine della chiamata i TFlags dei triangoli valgono 0. SurfB.ResetTempInt() ; - // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. + // 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. - // Se triangolo non valido salto al successivo. + // Recupero il triangolo corrente della superficie B. + // Se triangolo non valido salto al successivo. Triangle3d trTriaB ; if ( ! ( SurfB.GetTriangle( nTB, trTriaB) && trTriaB.Validate())) continue ; - // Se necessario considero l'offset + // Se necessario considero l'offset if ( dSafeDist > EPS_SMALL) { int nAdjTriaId[3] ; SurfB.GetTriangleAdjacencies( nTB, nAdjTriaId) ; - // Ciclo sui vertici del triangolo. + // Ciclo sui vertici del triangolo. for ( int nVB = 0 ; nVB < 3 ; ++ nVB) { - // Se il triangolo adiacente al triangolo corrente su questo edge - // non è stato processato, processo il vertice e l'edge. + // Se il triangolo adiacente al triangolo corrente su questo edge + // non è stato processato, processo il vertice e l'edge. int nAdjTriaTempFlag ; if ( ! ( SurfB.GetTriangleTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) continue ; - // Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito. + // Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito. if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA)) return true ; - // Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito. + // Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito. Vector3d vtEdgeV = trTriaB.GetP( nVB) - trTriaB.GetP( ( nVB + 1) % 3) ; double dEdgeLen = vtEdgeV.Len() ; vtEdgeV /= dEdgeLen ; @@ -97,18 +97,21 @@ CDeClosedSurfTmClosedSurfTm( const SurfTriMesh& SurfA, const SurfTriMesh& SurfB, if ( CDeSimpleCylTria( frCyl, dSafeDist, dEdgeLen, trTriaA)) return true ; } - // Traslo il triangolo + // Traslo il triangolo trTriaB.Translate( dSafeDist * trTriaB.GetN()) ; } - // Processo il triangolo: se i due triangoli collidono ho finito. + // Processo il triangolo: se i due triangoli collidono ho finito. if ( CDeTriaTria( trTriaA, trTriaB)) return true ; - // Segno il triangolo come processato: nTFlag = 1 + // Segno il triangolo come processato: nTFlag = 1 SurfB.SetTempInt( nTB, 1) ; } } - // Non ho trovato collisioni fra triangoli delle superfici. - // La collisione c'è se una superficie è dentro l'altra. + // Non ho trovato collisioni fra triangoli delle superfici. + // Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione + if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA)) + return false ; + // La collisione c'è se una superficie è dentro l'altra. Point3d ptPointA, ptPointB ; SurfA.GetFirstVertex( ptPointA) ; SurfB.GetFirstVertex( ptPointB) ; diff --git a/CDeConeFrustumClosedSurfTm.cpp b/CDeConeFrustumClosedSurfTm.cpp index b01fcb3..f425e18 100644 --- a/CDeConeFrustumClosedSurfTm.cpp +++ b/CDeConeFrustumClosedSurfTm.cpp @@ -27,24 +27,25 @@ bool CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopRad, double dHeight, double dSafeDist, const ISurfTriMesh& Stm) { - // Se il tronco di cono non è ben definito non ha senso proseguire. + // Se il tronco di cono non è ben definito non ha senso proseguire if ( max( dBaseRad, dTopRad) < EPS_SMALL || dHeight < EPS_SMALL) return false ; // Recupero BBox della trimesh BBox3d b3Surf = Stm.GetAllTriaBox() ; // Calcolo il BBox del tronco di cono double dMaxRad = max( dBaseRad, dTopRad) ; - BBox3d b3Cone( - dMaxRad, - dMaxRad, 0, dMaxRad, dMaxRad, dHeight) ; + BBox3d b3ConeL( Point3d( -dMaxRad, -dMaxRad, 0), + Point3d( dMaxRad, dMaxRad, dHeight)) ; if ( dSafeDist > EPS_SMALL) - b3Cone.Expand( dSafeDist) ; - b3Cone.ToGlob( frCone) ; + b3ConeL.Expand( dSafeDist) ; + BBox3d b3Cone = GetToGlob( b3ConeL, frCone) ; // Se i BBox non interferiscono, non c'è collisione - if ( ! b3Cone.Overlaps( b3Surf)) + if ( ! b3Surf.Overlaps( b3Cone) || ! b3Surf.Overlaps( frCone, b3ConeL)) return false ; // Recupero i triangoli che interferiscono con il box del cono INTVECTOR vT ; Stm.GetAllTriaOverlapBox( b3Cone, vT) ; - // Ciclo sui triangoli che interferiscono col box del cono + // Verifico se il tronco di cono interferisce con i triangoli del poliedro presenti nel suo BBox for ( int nT : vT) { Triangle3d trTria ; if ( Stm.GetTriangle( nT, trTria)) { @@ -55,6 +56,9 @@ CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopR // Se superficie aperta, non c'è collisione if ( ! Stm.IsClosed()) return false ; + // Se il BBox del tronco di cono non è interno a quello del poliedro e viceversa, non c'è collisione + if ( ! b3Surf.Encloses( b3Cone) && ! b3Cone.Encloses( b3Surf)) + return false ; // Verifico se il tronco di cono è dentro la superficie tramite calcolo distanza minima. Point3d ptConeCen( 0, 0, dHeight / 2) ; ptConeCen.ToGlob( frCone) ; diff --git a/CDeConvexTorusClosedSurfTm.cpp b/CDeConvexTorusClosedSurfTm.cpp index c8ef0b0..280cd13 100644 --- a/CDeConvexTorusClosedSurfTm.cpp +++ b/CDeConvexTorusClosedSurfTm.cpp @@ -23,42 +23,42 @@ using namespace std ; // Il toro è posto nel piano XY del suo riferimento, centrato sull'origine. // La funzione restituisce true in caso di collisione. bool -CDeConvexTorusClosedSurfTm( const Frame3d& frTorusFrame, double dRad1, double dRad2, +CDeConvexTorusClosedSurfTm( const Frame3d& frTorus, double dRad1, double dRad2, double dSafeDist, const ISurfTriMesh& Stm) { // I raggi devono essere non nulli e la superficie ben definita. if ( dRad1 < EPS_SMALL || dRad2 < EPS_SMALL || ! Stm.IsValid()) return false ; - // Box del toro (sempre completo) - BBox3d b3ConvTorusBox ; - b3ConvTorusBox.Set( Point3d( - dRad1 - dRad2, - dRad1 - dRad2, - dRad2), - Point3d( dRad1 + dRad2, dRad1 + dRad2, dRad2)) ; - // Aggiungo eventuale distanza di sicurezza - if ( dSafeDist > EPS_SMALL) - b3ConvTorusBox.Expand( dSafeDist) ; - // Porto il box del toro nel riferimento della superficie (inteso some globale) - b3ConvTorusBox.ToGlob( frTorusFrame) ; // Box della superficie - BBox3d b3SurfBox = Stm.GetAllTriaBox() ; + BBox3d b3Surf = Stm.GetAllTriaBox() ; + // Box del toro (sempre completo) + BBox3d b3TorusL( Point3d( -dRad1 - dRad2, -dRad1 - dRad2, -dRad2), + Point3d( dRad1 + dRad2, dRad1 + dRad2, dRad2)) ; + if ( dSafeDist > EPS_SMALL) + b3TorusL.Expand( dSafeDist) ; + BBox3d b3Torus = GetToGlob( b3TorusL, frTorus) ; // Se i BBox non interferiscono, non c'è collisione - if ( ! b3ConvTorusBox.Overlaps( b3SurfBox)) + if ( ! b3Surf.Overlaps( b3Torus) || ! b3Surf.Overlaps( frTorus, b3TorusL)) return false ; // Recupero i triangoli che interferiscono con il box del toro INTVECTOR vT ; - Stm.GetAllTriaOverlapBox( b3ConvTorusBox, vT) ; - // Ciclo sui triangoli recuperati + Stm.GetAllTriaOverlapBox( b3Torus, vT) ; + // Verifico se il toro interferisce con i triangoli del poliedro presenti nel suo BBox for ( int nT : vT) { Triangle3d trTria ; if ( Stm.GetTriangle( nT, trTria)) { - if ( CDeConvexTorusTria( frTorusFrame, dRad1, dRad2, CT_TOT, dSafeDist, trTria)) + if ( CDeConvexTorusTria( frTorus, dRad1, dRad2, CT_TOT, dSafeDist, trTria)) return true ; } } // Se superficie aperta, non c'è collisione if ( ! Stm.IsClosed()) return false ; - // Verifico se il toro è dentro la superficie tramite calcolo distanza minima. - Point3d ptTorusOrig = frTorusFrame.Orig() ; + // Se il BBox del toro non è interno a quello del poliedro e viceversa, non c'è collisione + if ( ! b3Surf.Encloses( b3Torus) && ! b3Torus.Encloses( b3Surf)) + return false ; + // Verifico se il toro è dentro la superficie tramite calcolo distanza minima del suo centro + Point3d ptTorusOrig = frTorus.Orig() ; DistPointSurfTm DistConeOrigSurfCalc( ptTorusOrig, Stm) ; // Se il toro è interno c'è collisione return ( DistConeOrigSurfCalc.IsPointInside()) ; diff --git a/CDeCylClosedSurfTm.cpp b/CDeCylClosedSurfTm.cpp index 6bbe5d2..f8feab3 100644 --- a/CDeCylClosedSurfTm.cpp +++ b/CDeCylClosedSurfTm.cpp @@ -23,38 +23,42 @@ using namespace std ; bool CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, double dSafeDist, const ISurfTriMesh& Stm) { - // recupero BBox del poliedro + // Recupero BBox del poliedro BBox3d b3Poly = Stm.GetAllTriaBox() ; - // sistemazioni cilindro - Frame3d frC = frCyl ; + // Sistemazioni cilindro + Frame3d frMyCyl = frCyl ; if ( dH < 0) { - frC.Translate( dH * frC.VersZ()) ; + frMyCyl.Translate( dH * frMyCyl.VersZ()) ; dH = - dH ; } - // calcolo il BBox del cilindro - BBox3d b3Cyl( -dR, -dR, 0, dR, dR, dH) ; + // Calcolo il BBox del cilindro + BBox3d b3CylL( Point3d( -dR, -dR, 0), + Point3d( dR, dR, dH)) ; if ( dSafeDist > EPS_SMALL) - b3Cyl.Expand( dSafeDist) ; - b3Cyl.ToGlob( frC) ; + b3CylL.Expand( dSafeDist) ; + BBox3d b3Cyl = GetToGlob( b3CylL, frMyCyl) ; // Se i BBox non interferiscono, non c'è collisione - if ( ! b3Cyl.Overlaps( b3Poly)) + if ( ! b3Poly.Overlaps( b3Cyl) || ! b3Poly.Overlaps( frMyCyl, b3CylL)) return false ; - // recupero i triangoli che interferiscono con il box del Cilindro + // Verifico se il cilindro interferisce con i triangoli del poliedro presenti nel suo BBox INTVECTOR vT ; Stm.GetAllTriaOverlapBox( b3Cyl, vT) ; for ( int nT : vT) { Triangle3d Tria ; if ( Stm.GetTriangle( nT, Tria)) { - if ( CDeCylTria( frC, dR, dH, dSafeDist, Tria)) + if ( CDeCylTria( frMyCyl, dR, dH, dSafeDist, Tria)) return true ; } } // Se superficie aperta, non c'è collisione if ( ! Stm.IsClosed()) return false ; - // Verifico se il cilindro è dentro la superficie tramite calcolo distanza minima. + // Se il BBox del cilindro non è interno a quello del poliedro e viceversa, non c'è collisione + if ( ! b3Poly.Encloses( b3Cyl) && ! b3Cyl.Encloses( b3Poly)) + return false ; + // Verifico se il cilindro è dentro la superficie tramite calcolo distanza minima del suo centro Point3d ptCylCen( 0, 0, dH / 2) ; - ptCylCen.ToGlob( frC) ; + ptCylCen.ToGlob( frMyCyl) ; DistPointSurfTm DistCylCenSurfCalc( ptCylCen, Stm) ; // Se il cilindro è interno c'è collisione return ( DistCylCenSurfCalc.IsPointInside()) ; diff --git a/CDeRectPrismoidClosedSurfTm.cpp b/CDeRectPrismoidClosedSurfTm.cpp index 62e9da8..0c1d1e0 100644 --- a/CDeRectPrismoidClosedSurfTm.cpp +++ b/CDeRectPrismoidClosedSurfTm.cpp @@ -37,17 +37,18 @@ CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, dou // Calcolo il BBox del tronco di piramide double dMaxLenX = max( dLenghtBaseX, dLenghtTopX) ; double dMaxLenY = max( dLenghtBaseY, dLenghtTopY) ; - BBox3d b3Pyr( -dMaxLenX / 2, -dMaxLenY / 2, 0., dMaxLenX / 2, dMaxLenY / 2, dHeight) ; + BBox3d b3PyrL( Point3d( -dMaxLenX / 2, -dMaxLenY / 2, 0.), + Point3d( dMaxLenX / 2, dMaxLenY / 2, dHeight)) ; if ( dSafeDist > EPS_SMALL) - b3Pyr.Expand( dSafeDist) ; - b3Pyr.ToGlob( frPrismoid) ; + b3PyrL.Expand( dSafeDist) ; + BBox3d b3Pyr = GetToGlob( b3PyrL, frPrismoid) ; // Se i BBox non interferiscono, non c'è collisione - if ( ! b3Pyr.Overlaps( b3Surf)) + if ( ! b3Surf.Overlaps( b3Pyr) || ! b3Surf.Overlaps( frPrismoid, b3PyrL)) return false ; // Recupero i triangoli che interferiscono con il box del tronco di piramide. INTVECTOR vT ; Stm.GetAllTriaOverlapBox( b3Pyr, vT) ; - // Ciclo sui triangoli che interferiscono col box del tronco di piramide. + // Verifico se il tronco di piramide interferisce con i triangoli del poliedro presenti nel suo BBox for ( int nT : vT) { Triangle3d trTria ; if ( Stm.GetTriangle( nT, trTria)) { @@ -59,10 +60,13 @@ CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, dou // Se superficie aperta, non c'è collisione if ( ! Stm.IsClosed()) return false ; - // Verifico se il tronco di piramide è dentro la superficie tramite calcolo distanza minima. + // Se il BBox del tronco di piramide non è interno a quello del poliedro e viceversa, non c'è collisione + if ( ! b3Surf.Encloses( b3Pyr) && ! b3Pyr.Encloses( b3Surf)) + return false ; + // Verifico se il tronco di piramide è dentro la superficie tramite calcolo distanza minima del suo centro Point3d ptPyrCen( 0, 0, dHeight / 2) ; ptPyrCen.ToGlob( frPrismoid) ; DistPointSurfTm DistPyrCenSurfCalc( ptPyrCen, Stm) ; - // C'è collisione se il tronco di piramide è interno. + // C'è collisione se il tronco di piramide è interno return ( DistPyrCenSurfCalc.IsPointInside()) ; } diff --git a/CDeSpheClosedSurfTm.cpp b/CDeSpheClosedSurfTm.cpp index cfbdec9..e6ab0c8 100644 --- a/CDeSpheClosedSurfTm.cpp +++ b/CDeSpheClosedSurfTm.cpp @@ -23,16 +23,16 @@ using namespace std ; bool CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, double dSafeDist, const ISurfTriMesh& Stm) { - // recupero BBox del poliedro + // Recupero BBox del poliedro BBox3d b3Poly = Stm.GetAllTriaBox() ; - // calcolo il BBox della sfera + // Calcolo il BBox della sfera BBox3d b3Sphe( ptCen, dR) ; if ( dSafeDist > EPS_SMALL) b3Sphe.Expand( dSafeDist) ; // Se i BBox non interferiscono, non c'è collisione if ( ! b3Sphe.Overlaps( b3Poly)) return false ; - // recupero i triangoli che interferiscono con il box della Sfera + // Verifico se la sfera interferisce con i triangoli del poliedro presenti nel suo BBox INTVECTOR vT ; Stm.GetAllTriaOverlapBox( b3Sphe, vT) ; for ( int nT : vT) { @@ -45,8 +45,11 @@ CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, double dSafeDist, const IS // Se superficie aperta, non c'è collisione if ( ! Stm.IsClosed()) return false ; - // Verifico se la sfera è dentro la superficie tramite calcolo distanza minima. + // Se il BBox della sfera non è interno a quello del poliedro e viceversa, non c'è collisione + if ( ! b3Sphe.Encloses( b3Poly) && ! b3Poly.Encloses( b3Sphe)) + return false ; + // Verifico se la sfera è dentro la superficie tramite calcolo distanza minima del suo centro DistPointSurfTm DistCenSurfCalc( ptCen, Stm) ; - // C'è collisione se la sfera è interna. + // C'è collisione se la sfera è interna. return ( DistCenSurfCalc.IsPointInside()) ; } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 50d8062ddc566051bbd4be8078da6498feab407a..f04937a9fbeea82f9a67ba1720cb87e0af740d31 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&Qw&A-_cnHh~ID{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-W11TR delta 94 zcmdlNy)SyhFE&P_&A-_cnHh~HD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-Vf-5U diff --git a/VolZmapCalculus.cpp b/VolZmapCalculus.cpp index 9f4f8cd..c24fd29 100644 --- a/VolZmapCalculus.cpp +++ b/VolZmapCalculus.cpp @@ -411,15 +411,18 @@ bool VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise) const { // BBox - BBox3d b3Box( ORIG, ORIG + vtDiag) ; + BBox3d b3BoxL( ORIG, ORIG + vtDiag) ; // Porto il box nel riferimento intrinseco dello Zmap - b3Box.LocToLoc( frBox, m_MapFrame) ; + Frame3d frBoxInt = GetToLoc( frBox, m_MapFrame) ; + BBox3d b3Box = GetToGlob( b3BoxL, frBoxInt) ; // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; // Se non interferiscono, posso uscire + if ( ! b3Zmap.Overlaps( b3Box) || ! b3Zmap.Overlaps( frBoxInt, b3BoxL)) + return true ; BBox3d b3Int ; if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) return true ; @@ -434,12 +437,12 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre int nEnJ = Clamp( int( b3Int.GetMax().y / m_dStep), 0, m_nNy[0] - 1) ; // Vettore direzione dei dexel nel riferimento del Box - Vector3d vtK = Z_AX ; vtK.LocToLoc( m_MapFrame, frBox) ; + Vector3d vtK = Z_AX ; vtK.ToLoc( frBoxInt) ; // Riferimento intrinseco dei dexel nel riferimento del box - Point3d ptO = ORIG ; ptO.LocToLoc( m_MapFrame, frBox) ; - Vector3d vtX = X_AX ; vtX.LocToLoc( m_MapFrame, frBox) ; - Vector3d vtY = Y_AX ; vtY.LocToLoc( m_MapFrame, frBox) ; + Point3d ptO = ORIG ; ptO.ToLoc( frBoxInt) ; + Vector3d vtX = X_AX ; vtX.ToLoc( frBoxInt) ; + Vector3d vtY = Y_AX ; vtY.ToLoc( frBoxInt) ; // Ciclo di intersezione dei dexel con il BBox for ( int i = nStI ; i <= nEnI ; ++ i) { @@ -503,10 +506,10 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre vtK = Y_AX ; } // Passo da sistema griglia a sistema BBox - ptO.ToLoc( frBox) ; - vtX.ToLoc( frBox) ; - vtY.ToLoc( frBox) ; - vtK.ToLoc( frBox) ; + ptO.ToLoc( frBoxInt) ; + vtX.ToLoc( frBoxInt) ; + vtY.ToLoc( frBoxInt) ; + vtK.ToLoc( frBoxInt) ; // Limiti su indici int nStI = Clamp( int( ptBoxInf.x / m_dStep), 0, m_nNx[nMap] - 1) ; int nEnI = Clamp( int( ptBoxSup.x / m_dStep), 0, m_nNx[nMap] - 1) ; @@ -780,33 +783,41 @@ VolZmap::AvoidSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bo bool VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise) const { - // Porto il cilindro nel riferimento intrinseco dello Zmap - Frame3d frC = frCyl ; - frC.ToLoc( m_MapFrame) ; + // BBox del cilindro in locale + BBox3d b3CylL( Point3d( -dR, -dR, 0), Point3d( dR, dR, dH)) ; - // BBox del cilindro - Vector3d vtDirL = frC.VersZ() ; - BBox3d b3Box( frC.Orig()) ; - b3Box.Add( frC.Orig() + frC.VersZ() * dH) ; - if ( vtDirL.IsXplus() || vtDirL.IsXminus()) - b3Box.Expand( 0, dR, dR) ; - else if ( vtDirL.IsYplus() || vtDirL.IsYminus()) - b3Box.Expand( dR, 0, dR) ; - else if ( vtDirL.IsZplus() || vtDirL.IsZminus()) - b3Box.Expand( dR, dR, 0) ; - else { - double dExpandX = dR * sqrt( 1 - vtDirL.x * vtDirL.x) ; - double dExpandY = dR * sqrt( 1 - vtDirL.y * vtDirL.y) ; - double dExpandZ = dR * sqrt( 1 - vtDirL.z * vtDirL.z) ; - b3Box.Expand( dExpandX, dExpandY, dExpandZ) ; - } + // BBox del cilindro nel riferimento intrinseco dello Zmap + Frame3d frCylInt = GetToLoc( frCyl, m_MapFrame) ; + BBox3d b3CylI = GetToGlob( b3CylL, frCylInt) ; // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; + // Se non interferiscono, posso uscire + if ( ! b3Zmap.Overlaps( b3CylI) || ! b3Zmap.Overlaps( frCylInt, b3CylL)) + return true ; + + // BBox del cilindro ottimizzato nel riferimento intrinseco dello Zmap + Point3d ptMyCen = frCylInt.Orig() ; + Vector3d vtMyAx = frCylInt.VersZ() ; + BBox3d b3Cyl( ptMyCen) ; + b3Cyl.Add( ptMyCen + vtMyAx * dH) ; + if ( vtMyAx.IsX()) + b3Cyl.Expand( 0, dR, dR) ; + else if ( vtMyAx.IsY()) + b3Cyl.Expand( dR, 0, dR) ; + else if ( vtMyAx.IsZ()) + b3Cyl.Expand( dR, dR, 0) ; + else { + double dExpandX = dR * sqrt( 1 - vtMyAx.x * vtMyAx.x) ; + double dExpandY = dR * sqrt( 1 - vtMyAx.y * vtMyAx.y) ; + double dExpandZ = dR * sqrt( 1 - vtMyAx.z * vtMyAx.z) ; + b3Cyl.Expand( dExpandX, dExpandY, dExpandZ) ; + } + // Se non interferiscono, posso uscire BBox3d b3Int ; - if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) + if ( ! b3Zmap.FindIntersection( b3Cyl, b3Int)) return true ; // Se verifico solo prima mappa @@ -838,7 +849,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b } Point3d ptI1, ptI2 ; Vector3d vtN1, vtN2 ; - if ( IntersLineCylinder( ptT, Z_AX, frC, dH, dR, true, true, ptI1, vtN1, ptI2, vtN2)) { + if ( IntersLineCylinder( ptT, Z_AX, frCylInt, dH, dR, true, true, ptI1, vtN1, ptI2, vtN2)) { double dZmin = min( ptI1.z, ptI2.z) ; double dZmax = max( ptI1.z, ptI2.z) ; for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { @@ -898,7 +909,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b Point3d ptI1, ptI2 ; Vector3d vtN1, vtN2 ; // La linea del dexel interseca il cilindro. - if ( IntersLineCylinder( ptT, vtK, frC, dH, dR, true, true, ptI1, vtN1, ptI2, vtN2)) { + if ( IntersLineCylinder( ptT, vtK, frCylInt, dH, dR, true, true, ptI1, vtN1, ptI2, vtN2)) { double dMinU, dMaxU ; if ( nMap == 0) { dMinU = min( ptI1.z, ptI2.z) ; @@ -933,33 +944,33 @@ bool VolZmap::AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise) const { // Se altezza negativa, sposto riferimento da faccia sopra a quella sotto - Frame3d frC = frCyl ; + Frame3d frMyCyl = frCyl ; if ( dH < 0) { - frC.Translate( dH * frC.VersZ()) ; + frMyCyl.Translate( dH * frMyCyl.VersZ()) ; dH = - dH ; } // Se distanza di sicurezza nulla if ( dSafeDist < EPS_SMALL) - return AvoidSimpleCylinder( frC, dR, dH, bPrecise) ; + return AvoidSimpleCylinder( frMyCyl, dR, dH, bPrecise) ; // Verifica preliminare con cilindro esteso - Frame3d frEst = frC ; frEst.Translate( -dSafeDist * frC.VersZ()) ; + Frame3d frEst = frMyCyl ; frEst.Translate( -dSafeDist * frMyCyl.VersZ()) ; if ( AvoidSimpleCylinder( frEst, dR + dSafeDist, dH + 2 * dSafeDist, bPrecise)) return true ; // Cilindro allargato - if ( ! AvoidSimpleCylinder( frC, dR + dSafeDist, dH, bPrecise)) + if ( ! AvoidSimpleCylinder( frMyCyl, dR + dSafeDist, dH, bPrecise)) return false ; // Cilindro allungato - Frame3d frTmp = frC ; frTmp.Translate( - dSafeDist * frC.VersZ()) ; + Frame3d frTmp = frMyCyl ; frTmp.Translate( - dSafeDist * frMyCyl.VersZ()) ; if ( ! AvoidSimpleCylinder( frTmp, dR, dH + 2 * dSafeDist, bPrecise)) return false ; // Toro inferiore - if ( ! AvoidSimpleTorus( frC, dR, dSafeDist, bPrecise)) + if ( ! AvoidSimpleTorus( frMyCyl, dR, dSafeDist, bPrecise)) return false ; // Toro superiore - frTmp = frC ; frTmp.Translate( dH * frC.VersZ()) ; + frTmp = frMyCyl ; frTmp.Translate( dH * frMyCyl.VersZ()) ; if ( ! AvoidSimpleTorus( frTmp, dR, dSafeDist, bPrecise)) return false ; @@ -1065,34 +1076,41 @@ VolZmap::SingleMapDexelConeCollision( int nStI, int nEnI, int nStJ, int nEnJ, co bool VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise) const { - // Porto il tronco di cono nel sistema intrinseco e normalizzo il vettore. - Point3d ptRefPoint = frCone.Orig() ; - Vector3d vtRefAx = frCone.VersZ() ; - ptRefPoint.ToLoc( m_MapFrame) ; - vtRefAx.ToLoc( m_MapFrame) ; + // BBox del tronco di cono in locale + BBox3d b3ConeL( Point3d( -dMaxRad, -dMaxRad, 0), Point3d( dMaxRad, dMaxRad, dHeight)) ; - // BBox del tronco di cono - BBox3d b3Box( ptRefPoint) ; - b3Box.Add( ptRefPoint + vtRefAx * dHeight) ; - if ( vtRefAx.IsXplus() || vtRefAx.IsXminus()) - b3Box.Expand( 0, dMaxRad, dMaxRad) ; - else if ( vtRefAx.IsYplus() || vtRefAx.IsYminus()) - b3Box.Expand( dMaxRad, 0, dMaxRad) ; - else if ( vtRefAx.IsZplus() || vtRefAx.IsZminus()) - b3Box.Expand( dMaxRad, dMaxRad, 0) ; - else { - double dExpandX = dMaxRad * sqrt( 1 - vtRefAx.x * vtRefAx.x) ; - double dExpandY = dMaxRad * sqrt( 1 - vtRefAx.y * vtRefAx.y) ; - double dExpandZ = dMaxRad * sqrt( 1 - vtRefAx.z * vtRefAx.z) ; - b3Box.Expand( dExpandX, dExpandY, dExpandZ) ; - } + // BBox del tronco di cono nel riferimento intrinseco dello Zmap + Frame3d frConeInt = GetToLoc( frCone, m_MapFrame) ; + BBox3d b3ConeI = GetToGlob( b3ConeL, frConeInt) ; // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; + // Se non interferiscono, posso uscire + if ( ! b3Zmap.Overlaps( b3ConeI) || ! b3Zmap.Overlaps( frConeInt, b3ConeL)) + return true ; + + // BBox del tronco di cono ottimizzato nel riferimento intrinseco dello Zmap + Point3d ptRefPoint = frConeInt.Orig() ; + Vector3d vtRefAx = frConeInt.VersZ() ; + BBox3d b3Cone( ptRefPoint) ; + b3Cone.Add( ptRefPoint + vtRefAx * dHeight) ; + if ( vtRefAx.IsX()) + b3Cone.Expand( 0, dMaxRad, dMaxRad) ; + else if ( vtRefAx.IsY()) + b3Cone.Expand( dMaxRad, 0, dMaxRad) ; + else if ( vtRefAx.IsZ()) + b3Cone.Expand( dMaxRad, dMaxRad, 0) ; + else { + double dExpandX = dMaxRad * sqrt( 1 - vtRefAx.x * vtRefAx.x) ; + double dExpandY = dMaxRad * sqrt( 1 - vtRefAx.y * vtRefAx.y) ; + double dExpandZ = dMaxRad * sqrt( 1 - vtRefAx.z * vtRefAx.z) ; + b3Cone.Expand( dExpandX, dExpandY, dExpandZ) ; + } + // Se non interferiscono, posso uscire BBox3d b3Int ; - if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) + if ( ! b3Zmap.FindIntersection( b3Cone, b3Int)) return true ; // Uso solo la prima mappa @@ -1638,34 +1656,33 @@ bool VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY, double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise) const { - // IL sistema del tronco di piramide generalizzato è definito nel sistema locale. - // Lo porto nel sistema intrinseco. - Frame3d frMyFrame = frPrismoid ; - frMyFrame.ToLoc( m_MapFrame) ; - - // Box del tronco nel suo sistema + // Box del tronco di prismoide nel suo sistema locale double dMaxLenX = max( dLenghtBaseX, dLenghtTopX) ; double dMaxLenY = max( dLenghtBaseY, dLenghtTopY) ; - BBox3d b3GenPyrBox( Point3d( -dMaxLenX / 2, -dMaxLenY / 2, 0.), - Point3d( dMaxLenX / 2, dMaxLenY / 2, dHeight)) ; - // Porto il box nel sistema intrinseco dello Zmap - b3GenPyrBox.ToGlob( frMyFrame) ; + BBox3d b3PrismL( Point3d( -dMaxLenX / 2, -dMaxLenY / 2, 0.), + Point3d( dMaxLenX / 2, dMaxLenY / 2, dHeight)) ; - // Box del solido + // BBox del tronco di prismoide nel riferimento intrinseco dello Zmap + Frame3d frPrismInt = GetToLoc( frPrismoid, m_MapFrame) ; + BBox3d b3PrismI = GetToGlob( b3PrismL, frPrismInt) ; + + // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; - BBox3d b3Int ; - // Se i box non si si sovrappongono, ho finito. - if ( ! b3Zmap.FindIntersection( b3GenPyrBox, b3Int)) + // Se i box non interferiscono, posso uscire + if ( ! b3Zmap.Overlaps( b3PrismI) || ! b3Zmap.Overlaps( frPrismInt, b3PrismL)) + return true ; + BBox3d b3Int ; + if ( ! b3Zmap.FindIntersection( b3PrismI, b3Int)) return true ; if ( ! bPrecise) { - // Limiti su indici + // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nNx[0] - 1) ; int nEnI = Clamp( int( b3Int.GetMax().x / m_dStep), 0, m_nNx[0] - 1) ; int nStJ = Clamp( int( b3Int.GetMin().y / m_dStep), 0, m_nNy[0] - 1) ; int nEnJ = Clamp( int( b3Int.GetMax().y / m_dStep), 0, m_nNy[0] - 1) ; - // Ciclo di intersezione dei dexel con il cilindro (nel riferimento intrinseco) + // Ciclo di intersezione dei dexel con il cilindro (nel riferimento intrinseco) for ( int i = nStI ; i <= nEnI ; ++ i) { for ( int j = nStJ ; j <= nEnJ ; ++ j) { int nPos = j * m_nNx[0] + i ; @@ -1688,7 +1705,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX double dStU, dEnU ; Point3d ptSegSt = ptLineSt + m_Values[0][nPos][0].dMin * Z_AX ; Point3d ptSegEn = ptLineSt + m_Values[0][nPos][nSize-1].dMax * Z_AX ; - if ( RectPrismoidSegmentCollisionPlus( frMyFrame, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, + if ( RectPrismoidSegmentCollisionPlus( frPrismInt, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, ptSegSt, ptSegEn, dStU, dEnU)) { for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { if ( m_Values[0][nPos][nIndex].dMax >= dStU && m_Values[0][nPos][nIndex].dMin <= dEnU) @@ -1700,11 +1717,11 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX } } else { - // Ciclo sulle mappe + // Ciclo sulle mappe for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) { Point3d ptInfIntBox = b3Int.GetMin(); Point3d ptSupIntBox = b3Int.GetMax(); - // Dal sistema intrinseco al sistema griglia (per la prima griglia coincidono). + // Dal sistema intrinseco al sistema griglia (per la prima griglia coincidono). if ( nMap == 1) { swap( ptInfIntBox.x, ptInfIntBox.z) ; swap( ptInfIntBox.x, ptInfIntBox.y) ; @@ -1717,7 +1734,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX swap( ptSupIntBox.y, ptSupIntBox.z) ; swap( ptSupIntBox.x, ptSupIntBox.y) ; } - // Limiti su indici + // Limiti su indici int nStI = Clamp( int( ptInfIntBox.x / m_dStep), 0, m_nNx[nMap] - 1) ; int nEnI = Clamp( int( ptSupIntBox.x / m_dStep), 0, m_nNx[nMap] - 1) ; int nStJ = Clamp( int( ptInfIntBox.y / m_dStep), 0, m_nNy[nMap] - 1) ; @@ -1726,18 +1743,18 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX int nSize = int( m_Values[nMap][nDex].size()) ; if ( nSize == 0) continue ; - // Indici del dexel + // Indici del dexel int nI = nDex % m_nNx[nMap] ; int nJ = nDex / m_nNx[nMap] ; - // Se fuori dalla regione ammissibile salto l'iterazione + // Se fuori dalla regione ammissibile salto l'iterazione if ( nI < nStI || nI > nEnI || nJ < nStJ || nJ > nEnJ) continue ; - // Posizione del dexel + // Posizione del dexel double dX = ( nI + 0.5) * m_dStep ; double dY = ( nJ + 0.5) * m_dStep ; Point3d ptLineSt( dX, dY, 0.) ; Vector3d vtLineDir( 0., 0., 1.) ; - // Dal sistema griglia al sistema intrinseco (per la prima griglia coincidono). + // Dal sistema griglia al sistema intrinseco (per la prima griglia coincidono). if ( nMap == 1) { swap( ptLineSt.x, ptLineSt.y) ; swap( ptLineSt.x, ptLineSt.z) ; @@ -1753,7 +1770,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX double dStU, dEnU ; Point3d ptSegSt = ptLineSt + m_Values[nMap][nDex][0].dMin * vtLineDir ; Point3d ptSegEn = ptLineSt + m_Values[nMap][nDex][nSize-1].dMax * vtLineDir ; - if ( RectPrismoidSegmentCollisionPlus( frMyFrame, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, + if ( RectPrismoidSegmentCollisionPlus( frPrismInt, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, ptSegSt, ptSegEn, dStU, dEnU)) { for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { if ( m_Values[nMap][nDex][nIndex].dMax >= dStU && m_Values[nMap][nDex][nIndex].dMin <= dEnU) @@ -1893,36 +1910,44 @@ VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, doub bool VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise) const { - // Porto il toro nel sistema intrinseco dello Zmap. - Point3d ptMyCen = frTorus.Orig() ; - Vector3d vtMyAx = frTorus.VersZ() ; - ptMyCen.ToLoc( m_MapFrame) ; - vtMyAx.ToLoc( m_MapFrame) ; + // BBox del toro in locale + BBox3d b3TorusL( Point3d( -dMaxRad - dMinRad, -dMaxRad - dMinRad, -dMinRad), + Point3d( dMaxRad + dMinRad, dMaxRad + dMinRad, dMinRad)) ; - // BBox del toro - BBox3d b3Box( ptMyCen) ; - b3Box.Add( ptMyCen + vtMyAx * dMinRad) ; - b3Box.Add( ptMyCen - vtMyAx * dMinRad) ; - double dTotRad = dMaxRad + dMinRad ; - if ( vtMyAx.IsXplus() || vtMyAx.IsXminus()) - b3Box.Expand( 0, dTotRad, dTotRad) ; - else if ( vtMyAx.IsYplus() || vtMyAx.IsYminus()) - b3Box.Expand( dTotRad, 0, dTotRad) ; - else if ( vtMyAx.IsZplus() || vtMyAx.IsZminus()) - b3Box.Expand( dTotRad, dTotRad, 0) ; - else { - double dExpandX = dTotRad * sqrt( 1 - vtMyAx.x * vtMyAx.x) ; - double dExpandY = dTotRad * sqrt( 1 - vtMyAx.y * vtMyAx.y) ; - double dExpandZ = dTotRad * sqrt( 1 - vtMyAx.z * vtMyAx.z) ; - b3Box.Expand( dExpandX, dExpandY, dExpandZ) ; - } + // BBox del toro nel riferimento intrinseco dello Zmap + Frame3d frTorusInt = GetToLoc( frTorus, m_MapFrame) ; + BBox3d b3TorusI = GetToGlob( b3TorusL, frTorusInt) ; // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; + // Se non interferiscono, posso uscire + if ( ! b3Zmap.Overlaps( b3TorusI) || ! b3Zmap.Overlaps( frTorusInt, b3TorusL)) + return true ; + + // BBox del toro ottimizzato nel riferimento intrinseco dello Zmap + Point3d ptMyCen = frTorusInt.Orig() ; + Vector3d vtMyAx = frTorusInt.VersZ() ; + BBox3d b3Torus( ptMyCen) ; + b3Torus.Add( ptMyCen + vtMyAx * dMinRad) ; + b3Torus.Add( ptMyCen - vtMyAx * dMinRad) ; + double dTotRad = dMaxRad + dMinRad ; + if ( vtMyAx.IsX()) + b3Torus.Expand( 0, dTotRad, dTotRad) ; + else if ( vtMyAx.IsY()) + b3Torus.Expand( dTotRad, 0, dTotRad) ; + else if ( vtMyAx.IsZ()) + b3Torus.Expand( dTotRad, dTotRad, 0) ; + else { + double dExpandX = dTotRad * sqrt( 1 - vtMyAx.x * vtMyAx.x) ; + double dExpandY = dTotRad * sqrt( 1 - vtMyAx.y * vtMyAx.y) ; + double dExpandZ = dTotRad * sqrt( 1 - vtMyAx.z * vtMyAx.z) ; + b3Torus.Expand( dExpandX, dExpandY, dExpandZ) ; + } + // Se non interferiscono, posso uscire BBox3d b3Int ; - if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) + if ( ! b3Zmap.FindIntersection( b3Torus, b3Int)) return true ; // Se verifico solo prima mappa diff --git a/VolZmapGraphics.cpp b/VolZmapGraphics.cpp index 077f084..fb5b8eb 100644 --- a/VolZmapGraphics.cpp +++ b/VolZmapGraphics.cpp @@ -2047,14 +2047,6 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const else { if ( nVertComp[nComp] == 5) { - double dDotAvarage = 0.; - for (int m = 0; m < nVertComp[nComp] - 1; ++m) { - for (int l = m + 1 ; l < nVertComp[nComp]; ++l) { - dDotAvarage += CompoVert[nComp][m].vtVec * CompoVert[nComp][l].vtVec; - } - } - dDotAvarage /= (( nVertComp[nComp] * ( nVertComp[nComp] - 1)) / 2) ; - int nNumPar = 0 ; for ( int m = 0 ; m < nVertComp[nComp] - 1 ; ++ m) { for ( int l = m + 1 ; l < nVertComp[nComp] ; ++ l) { @@ -2062,9 +2054,9 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const ++ nNumPar ; } } - bExtConfirmed = nNumPar == 3 ; + bExtConfirmed = ( nNumPar == 3) ; } - else if (nVertComp[nComp] < 5) { + else if ( nVertComp[nComp] < 5) { bExtConfirmed = false ; } } From 7c6ddf2a6fa729e74e40d7a66543afafeba012c8 Mon Sep 17 00:00:00 2001 From: DarioS Date: Mon, 15 May 2023 14:50:32 +0200 Subject: [PATCH 08/10] =?UTF-8?q?EgtGeomKernel=20:=20-=20aggiunto=20contro?= =?UTF-8?q?llo=20validit=C3=A0=20coordinate=20di=20punti=20e=20vettori=20(?= =?UTF-8?q?isfinite).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BBox3d.cpp | 3 ++- CurveArc.cpp | 8 ++++---- CurveBezier.cpp | 17 ++++++++++++++++ CurveLine.cpp | 2 +- Frame3d.cpp | 3 +++ VolZmapCalculus.cpp | 48 +++++++++++++++++++++------------------------ 6 files changed, 49 insertions(+), 32 deletions(-) diff --git a/BBox3d.cpp b/BBox3d.cpp index 2d67e7f..da639aa 100644 --- a/BBox3d.cpp +++ b/BBox3d.cpp @@ -53,7 +53,8 @@ BBox3d::Set( double dX1, double dY1, double dZ1, double dX2, double dY2, double bool BBox3d::IsValid( void) const { - return ( m_ptMin.x < ( m_ptMax.x + EPS_SMALL) && + return ( m_ptMin.IsValid() && m_ptMax.IsValid() && + m_ptMin.x < ( m_ptMax.x + EPS_SMALL) && m_ptMin.y < ( m_ptMax.y + EPS_SMALL) && m_ptMin.z < ( m_ptMax.z + EPS_SMALL)) ; } diff --git a/CurveArc.cpp b/CurveArc.cpp index f78f842..b9f8fb9 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -824,10 +824,10 @@ CurveArc::Validate( void) m_dAngCenDeg = - ANG_FULL ; } // eseguo il controllo - m_nStatus = ( ( m_VtN.IsNormalized() && m_VtS.IsNormalized() && - AreOrthoApprox( m_VtN, m_VtS) && - m_dRad > EPS_SMALL && m_dRad < MAX_ARC_RAD && - abs( m_dAngCenDeg) > EPS_ANG_ZERO) ? OK : ERR) ; + m_nStatus = ( ( m_PtCen.IsValid() && + m_VtN.IsNormalized() && m_VtS.IsNormalized() && AreOrthoApprox( m_VtN, m_VtS) && + m_dRad > EPS_SMALL && m_dRad < MAX_ARC_RAD && + abs( m_dAngCenDeg) > EPS_ANG_ZERO) ? OK : ERR) ; } return ( m_nStatus == OK) ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index ac0e967..3514473 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -424,6 +424,23 @@ CurveBezier::Load( NgeReader& ngeIn) bool CurveBezier::Validate( void) { + if ( m_nStatus == TO_VERIFY) { + for ( const auto& ptP : m_vPtCtrl) { + if ( ! ptP.IsValid()) { + m_nStatus = ERR ; + break ; + } + } + } + if ( m_nStatus == TO_VERIFY) { + for ( const auto& dWe : m_vWeCtrl) { + if ( ! isfinite( dWe)) { + m_nStatus = ERR ; + break ; + } + } + } + if ( m_nStatus == TO_VERIFY) m_nStatus = ( ( m_nDeg > 0 && m_vPtCtrl.size() > 0) ? OK : ERR) ; diff --git a/CurveLine.cpp b/CurveLine.cpp index 79ee00a..dbdc8c1 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -259,7 +259,7 @@ bool CurveLine::Validate( void) { if ( m_nStatus == TO_VERIFY) - m_nStatus = ( ! AreSamePointApprox( m_PtStart, m_PtEnd) ? OK : ERR) ; + m_nStatus = ( m_PtStart.IsValid() && m_PtEnd.IsValid() && ! AreSamePointApprox( m_PtStart, m_PtEnd) ? OK : ERR) ; return ( m_nStatus == OK) ; } diff --git a/Frame3d.cpp b/Frame3d.cpp index 0338468..0216924 100644 --- a/Frame3d.cpp +++ b/Frame3d.cpp @@ -456,6 +456,9 @@ Frame3d::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) bool Frame3d::Verify( void) { + // verifica origine + if ( ! m_ptOrig.IsValid()) + return false ; // verifica della ortogonalità dei versori e del senso destrorso double dOrtXY = m_vtVersX * m_vtVersY ; double dOrtYZ = m_vtVersY * m_vtVersZ ; diff --git a/VolZmapCalculus.cpp b/VolZmapCalculus.cpp index c24fd29..8876c95 100644 --- a/VolZmapCalculus.cpp +++ b/VolZmapCalculus.cpp @@ -1815,6 +1815,7 @@ VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, doub dLenghtTopX + 2 * dOffsTopX, dLenghtTopY + 2 * dOffsTopY, dHeight + 2 * dSafeDist, bPrecise)) return true ; + // Offset fine // Sfere centrate nei vertici double dHalfBaseX = dLenghtBaseX / 2 ; double dHalfBaseY = dLenghtBaseY / 2 ; @@ -2307,10 +2308,10 @@ bool VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp, Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const -{ +{ // Porto la linea nel riferimento del cilindro - Point3d ptP = ptLineSt ; ptP.ToLoc( CylFrame) ; - Vector3d vtV = vtLineDir ; vtV.ToLoc( CylFrame) ; + Point3d ptP = GetToLoc( ptLineSt, CylFrame) ; + Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ; // Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse) int nBasInt = 0 ; @@ -2341,13 +2342,11 @@ VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, } // Determino le intersezioni con la superficie laterale del cilindro - DBLVECTOR vdCoef(3) ; - double dSqRad = dRad * dRad ; - vdCoef[0] = ptP.x * ptP.x + ptP.y * ptP.y - dSqRad ; - vdCoef[1] = 2 * ( ptP.x * vtV.x + ptP.y * vtV.y) ; - vdCoef[2] = vtV.x * vtV.x + vtV.y * vtV.y ; + DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad, + 2 * ( ptP.x * vtV.x + ptP.y * vtV.y), + vtV.x * vtV.x + vtV.y * vtV.y} ; DBLVECTOR vdRoots ; - int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ; // Epsilon per piani di tappo double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ; @@ -2357,7 +2356,7 @@ VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, if ( nRoot == 2) { double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ; if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp) - nRoot = 1 ; + -- nRoot ; } if ( nRoot >= 1) { double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ; @@ -2432,8 +2431,8 @@ VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir, Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const { // Porto la linea nel riferimento del cono - Point3d ptP = ptLineSt ; ptP.ToLoc( ConusFrame) ; - Vector3d vtV = vtLineDir ; vtV.ToLoc( ConusFrame) ; + Point3d ptP = GetToLoc( ptLineSt, ConusFrame) ; + Vector3d vtV = GetToLoc( vtLineDir, ConusFrame) ; // Raggi delle due basi double dMinRad = dTan * dMinH ; @@ -2470,19 +2469,18 @@ VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir, } // Determino le intersezioni con la superficie laterale del cono - DBLVECTOR vdCoef( 3) ; double dSqTan = dTan * dTan ; - vdCoef[0] = dSqTan * ptP.z * ptP.z - ptP.x * ptP.x - ptP.y * ptP.y ; - vdCoef[1] = 2 * ( dSqTan * ptP.z * vtV.z - ptP.x * vtV.x - ptP.y * vtV.y) ; - vdCoef[2] = dSqTan * vtV.z * vtV.z - vtV.x * vtV.x - vtV.y * vtV.y ; + DBLVECTOR vdCoeff{ dSqTan * ptP.z * ptP.z - ptP.x * ptP.x - ptP.y * ptP.y, + 2 * ( dSqTan * ptP.z * vtV.z - ptP.x * vtV.x - ptP.y * vtV.y), + dSqTan * vtV.z * vtV.z - vtV.x * vtV.x - vtV.y * vtV.y} ; DBLVECTOR vdRoots ; - int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ; // Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del tronco if ( nRoot == 2) { double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ; if ( dIntZ2 < dMinH + dEpsLow || dIntZ2 > dMaxH + dEpsUp) - nRoot = 1 ; + -- nRoot ; } if ( nRoot >= 1) { double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ; @@ -2570,8 +2568,8 @@ VolZmap::IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& return false ; // Porto la linea nel riferimento del cilindro - Point3d ptP = ptLineSt ; ptP.ToLoc( CircFrame) ; - Vector3d vtV = vtLineDir ; vtV.ToLoc( CircFrame) ; + Point3d ptP = GetToLoc( ptLineSt, CircFrame) ; + Vector3d vtV = GetToLoc( vtLineDir, CircFrame) ; // Quadrato del raggio double dSqRad = dRad * dRad ; @@ -2713,8 +2711,8 @@ VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLine return false ; // Porto la linea nel riferimento del poliedro - Point3d ptP = ptLineSt ; ptP.ToLoc( PolyFrame) ; - Vector3d vtV = vtLineDir ; vtV.ToLoc( PolyFrame) ; + Point3d ptP = GetToLoc( ptLineSt, PolyFrame) ; + Vector3d vtV = GetToLoc( vtLineDir, PolyFrame) ; // Facce 1 e 2 parallele a XY // Facce 3 e 4 parallele a XZ @@ -2862,10 +2860,8 @@ VolZmap::IntersLineTruncatedPyramid( const Point3d& ptLineSt, const Vector3d& vt return false ; // Porto la linea nel riferimento del solido - Point3d ptP = ptLineSt ; - Vector3d vtV = vtLineDir ; - ptP.ToLoc( frTruncPyramFrame) ; - vtV.ToLoc( frTruncPyramFrame) ; + Point3d ptP = GetToLoc( ptLineSt, frTruncPyramFrame) ; + Vector3d vtV = GetToLoc( vtLineDir, frTruncPyramFrame) ; // Se la retta sta sopra o sotto il solido non vi può essere intersezione if ( abs( vtV.z) < EPS_ZERO && ( ptP.z < EPS_SMALL || ptP.z > dHeight + EPS_SMALL)) From 8420edecb5c24a8ce54861595c1be2fd7ce3108b Mon Sep 17 00:00:00 2001 From: DarioS Date: Tue, 16 May 2023 09:37:40 +0200 Subject: [PATCH 09/10] =?UTF-8?q?EgtGeomKernel=20:=20-=20miglioramenti=20n?= =?UTF-8?q?egli=20algoritmi=20di=20controllo=20collisioni=20tra=20solidi?= =?UTF-8?q?=20semplici=20e=20Zmap=20(aumento=20velocit=C3=A0=202x,=205x).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VolZmapCalculus.cpp | 325 ++++++++++++++++---------------------------- 1 file changed, 118 insertions(+), 207 deletions(-) diff --git a/VolZmapCalculus.cpp b/VolZmapCalculus.cpp index 8876c95..da84395 100644 --- a/VolZmapCalculus.cpp +++ b/VolZmapCalculus.cpp @@ -1102,10 +1102,16 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d else if ( vtRefAx.IsZ()) b3Cone.Expand( dMaxRad, dMaxRad, 0) ; else { - double dExpandX = dMaxRad * sqrt( 1 - vtRefAx.x * vtRefAx.x) ; - double dExpandY = dMaxRad * sqrt( 1 - vtRefAx.y * vtRefAx.y) ; - double dExpandZ = dMaxRad * sqrt( 1 - vtRefAx.z * vtRefAx.z) ; - b3Cone.Expand( dExpandX, dExpandY, dExpandZ) ; + double dCoeffX = sqrt( 1 - vtRefAx.x * vtRefAx.x) ; + double dCoeffY = sqrt( 1 - vtRefAx.y * vtRefAx.y) ; + double dCoeffZ = sqrt( 1 - vtRefAx.z * vtRefAx.z) ; + BBox3d b3Base( ptRefPoint) ; + b3Base.Expand( dMinRad * dCoeffX, dMinRad * dCoeffY, dMinRad * dCoeffZ) ; + BBox3d b3Top( ptRefPoint + vtRefAx * dHeight) ; + b3Top.Expand( dMaxRad * dCoeffX, dMaxRad * dCoeffY, dMaxRad * dCoeffZ) ; + b3Cone.Reset() ; + b3Cone.Add( b3Base) ; + b3Cone.Add( b3Top) ; } // Se non interferiscono, posso uscire @@ -1304,7 +1310,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d //---------------------------------------------------------------------------- // Ha come asse Z l'asse del cono/tronco di cono. Se è un cono proprio l'origine // è nel vertice del cono e l'asse Z è diretto verso l'apertura. -// Se è un tronco di cono l'origine è nel centro della base Bot e l'azze Z è diretto verso +// Se è un tronco di cono l'origine è nel centro della base Bot e l'asse Z è diretto verso // la base Top, a prescindere da quale base abbia raggio maggiore. bool VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight, @@ -1399,150 +1405,28 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop //---------------------------------------------------------------------------- static bool -RectPrismoidSegmentCollision( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY, - double dLenghtTopX, double dLenghtTopY, double dHeight, - const Point3d& ptSt, const Point3d& ptEn) +IntersSegmentPlanePlus( const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptP3, + const Point3d& ptLnSt, const Vector3d& vtLnDir, double dLnLen, + double& dStU, double& dEnU) { - // Se il solido non è ben definito, non ha senso continuare. - if ( max( dLenghtBaseX, dLenghtTopX) < EPS_SMALL || - max( dLenghtBaseY, dLenghtTopY) < EPS_SMALL || - dHeight < EPS_SMALL) + Plane3d plPlane ; + if ( ! plPlane.Set( ptP1, ptP2, ptP3)) return false ; - - // Porto il segmento nel sistema del tronco. - Point3d ptMySt = ptSt ; - ptMySt.ToLoc( frPrismoid) ; - Point3d ptMyEn = ptEn ; - ptMyEn.ToLoc( frPrismoid) ; - - // Se il segmento non è ben definito, non ha senso continuare. - Vector3d vtMySeg = ptMyEn - ptMySt ; - if ( ! vtMySeg.Normalize()) - return false ; - - double dHalfBaseX = 0.5 * dLenghtBaseX ; - double dHalfBaseY = 0.5 * dLenghtBaseY ; - double dHalfTopX = 0.5 * dLenghtTopX ; - double dHalfTopY = 0.5 * dLenghtTopY ; - - // Se almeno un vertice collide ho finito - if ( ( ptMySt.z > - EPS_SMALL && ptMySt.z < dHeight + EPS_SMALL && - ( ptMySt.x + dHalfBaseX + EPS_SMALL) * dHeight > ( dHalfBaseX - dHalfTopX) * ptMySt.z && - ( ptMySt.x - dHalfBaseX - EPS_SMALL) * dHeight < ( dHalfTopX - dHalfBaseX) * ptMySt.z && - ( ptMySt.y + dHalfBaseY + EPS_SMALL) * dHeight > ( dHalfBaseY - dHalfTopY) * ptMySt.z && - ( ptMySt.y - dHalfBaseY - EPS_SMALL) * dHeight < ( dHalfTopY - dHalfBaseY) * ptMySt.z) || - ( ptMyEn.z > - EPS_SMALL && ptMySt.z < dHeight + EPS_SMALL && - ( ptMyEn.x + dHalfBaseX + EPS_SMALL) * dHeight > ( dHalfBaseX - dHalfTopX) * ptMyEn.z && - ( ptMyEn.x - dHalfBaseX - EPS_SMALL) * dHeight < ( dHalfTopX - dHalfBaseX) * ptMyEn.z && - ( ptMyEn.y + dHalfBaseY + EPS_SMALL) * dHeight > ( dHalfBaseY - dHalfTopY) * ptMyEn.z && - ( ptMyEn.y - dHalfBaseY - EPS_SMALL) * dHeight < ( dHalfTopY - dHalfBaseY) * ptMyEn.z)) + Point3d ptInt ; + int nIntType = IntersLinePlane( ptLnSt, vtLnDir, dLnLen, plPlane, ptInt) ; + if ( nIntType == ILPT_INPLANE) return true ; - - // Se c'è collisione con almeno un triangolo delle facce ho finito - Triangle3d trFaceTria1, trFaceTria2 ; - Point3d ptInt, ptInt2 ; - // Faccia base - trFaceTria1.Set( Point3d( - dHalfBaseX, - dHalfBaseY, 0.), - Point3d( - dHalfBaseX, dHalfBaseY, 0.), - Point3d( dHalfBaseX, dHalfBaseY, 0.)) ; - if ( trFaceTria1.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria1, ptInt, ptInt2) != ILTT_NO) - return true ; - trFaceTria2.Set( Point3d( - dHalfBaseX, - dHalfBaseY, 0.), - Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( dHalfBaseX, - dHalfBaseY, 0.)) ; - if ( trFaceTria2.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria2, ptInt, ptInt2) != ILTT_NO) - return true ; - // Faccia top - trFaceTria1.Set( Point3d( - dHalfTopX, - dHalfTopY, dHeight), - Point3d( dHalfTopX, dHalfTopY, dHeight), - Point3d( - dHalfTopX, dHalfTopY, dHeight)) ; - if ( trFaceTria1.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria1, ptInt, ptInt2) != ILTT_NO) - return true ; - trFaceTria2.Set( Point3d( - dHalfTopX, - dHalfTopY, dHeight), - Point3d( dHalfTopX, - dHalfTopY, dHeight), - Point3d( dHalfTopX, dHalfTopY, dHeight)) ; - if ( trFaceTria2.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria2, ptInt, ptInt2) != ILTT_NO) - return true ; - // Faccia laterale 1 - trFaceTria1.Set( Point3d( - dHalfBaseX, - dHalfBaseY, 0.), - Point3d( dHalfTopX , - dHalfTopY , dHeight), - Point3d( - dHalfTopX , - dHalfTopY , dHeight)) ; - if ( trFaceTria1.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria1, ptInt, ptInt2) != ILTT_NO) - return true ; - trFaceTria2.Set( Point3d( - dHalfBaseX, - dHalfBaseY, 0.), - Point3d( dHalfBaseX, - dHalfBaseY, 0.), - Point3d( dHalfTopX, - dHalfTopY , dHeight)) ; - if ( trFaceTria2.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria2, ptInt, ptInt2) != ILTT_NO) - return true ; - // Faccia laterale 2 - trFaceTria1.Set( Point3d( dHalfBaseX, - dHalfBaseY, 0.), - Point3d( dHalfTopX , dHalfTopY , dHeight), - Point3d( dHalfTopX , - dHalfTopY , dHeight)) ; - if ( trFaceTria1.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria1, ptInt, ptInt2) != ILTT_NO) - return true ; - trFaceTria2.Set( Point3d( dHalfBaseX, - dHalfBaseY, 0.), - Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( dHalfTopX , dHalfTopY , dHeight)) ; - if ( trFaceTria2.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria2, ptInt, ptInt2) != ILTT_NO) - return true ; - // Faccia laterale 3 - trFaceTria1.Set( Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( - dHalfTopX , dHalfTopY , dHeight), - Point3d( dHalfTopX , dHalfTopY , dHeight)) ; - if ( trFaceTria1.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria1, ptInt, ptInt2) != ILTT_NO) - return true ; - trFaceTria2.Set( Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( - dHalfBaseX, dHalfBaseY, 0.), - Point3d( - dHalfTopX , dHalfTopY , dHeight)) ; - if ( trFaceTria2.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria2, ptInt, ptInt2) != ILTT_NO) - return true ; - // Faccia laterale 4 - trFaceTria1.Set( Point3d( - dHalfBaseX, dHalfBaseY, 0.), - Point3d( - dHalfTopX , - dHalfTopY , dHeight), - Point3d( - dHalfTopX , dHalfTopY , dHeight)) ; - if ( trFaceTria1.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria1, ptInt, ptInt2) != ILTT_NO) - return true ; - trFaceTria2.Set( Point3d( - dHalfBaseX, dHalfBaseY, 0.), - Point3d( - dHalfBaseX, - dHalfBaseY, 0.), - Point3d( - dHalfTopX , - dHalfTopY , dHeight)) ; - if ( trFaceTria2.Validate() && IntersLineTria( ptMySt, ptMyEn, trFaceTria2, ptInt, ptInt2) != ILTT_NO) - return true ; - - return false ; -} - -//---------------------------------------------------------------------------- -static bool -IntersSegmentTrianglePlus( const Point3d& ptTr1, const Point3d& ptTr2, const Point3d& ptTr3, - const Point3d& ptLnSt, const Vector3d& vtLnDir, double dLnLen, - double& dStU, double& dEnU) -{ - Triangle3d trFaceTria ; - trFaceTria.Set( ptTr1, ptTr2, ptTr3) ; - if ( trFaceTria.Validate()) { - Point3d ptMyIntSt, ptMyIntEn ; - int nIntType = IntersLineTria( ptLnSt, vtLnDir, dLnLen, trFaceTria, ptMyIntSt, ptMyIntEn, true) ; - if ( nIntType != ILTT_NO) { - if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) { - double dCurU = ( ptMyIntSt - ptLnSt) * vtLnDir ; - if ( dCurU < dStU) - dStU = dCurU ; - if ( dCurU > dEnU) - dEnU = dCurU ; - } - else { - double dCurStU = ( ptMyIntSt - ptLnSt) * vtLnDir ; - double dCurEnU = ( ptMyIntEn - ptLnSt) * vtLnDir ; - if ( dCurStU < dStU) - dStU = dCurStU ; - if ( dCurEnU > dEnU) - dEnU = dCurEnU ; - } - } + if ( nIntType == ILPT_NO) { + if ( DistPointPlane( ptLnSt, plPlane) > 0) + dEnU = -1 ; return true ; } - - return false ; + double dIntU = ( ptInt - ptLnSt) * vtLnDir ; + if ( vtLnDir * plPlane.GetVersN() > 0) + dEnU = min( dEnU, dIntU) ; + else + dStU = max( dStU, dIntU) ; + return true ; } //---------------------------------------------------------------------------- @@ -1552,19 +1436,17 @@ RectPrismoidSegmentCollisionPlus( const Frame3d& frPrismoid, double dLenghtBaseX const Point3d& ptSt, const Point3d& ptEn, double& dStU, double& dEnU) { - // Se il solido non è ben definito, non ha senso continuare. + // Se il solido non è ben definito, non ha senso continuare if ( max( dLenghtBaseX, dLenghtTopX) < EPS_SMALL || max( dLenghtBaseY, dLenghtTopY) < EPS_SMALL || dHeight < EPS_SMALL) return false ; // Porto il segmento nel sistema del prismoide a base rettangolare - Point3d ptMySt = ptSt ; - ptMySt.ToLoc( frPrismoid) ; - Point3d ptMyEn = ptEn ; - ptMyEn.ToLoc( frPrismoid) ; + Point3d ptMySt = GetToLoc( ptSt, frPrismoid) ; + Point3d ptMyEn = GetToLoc( ptEn, frPrismoid) ; - // Se il segmento non è ben definito, non ha senso continuare. + // Se il segmento non è ben definito, non ha senso continuare Vector3d vtMySeg = ptMyEn - ptMySt ; double dSegLen = vtMySeg.Len() ; if ( dSegLen < EPS_SMALL) @@ -1577,78 +1459,87 @@ RectPrismoidSegmentCollisionPlus( const Frame3d& frPrismoid, double dLenghtBaseX double dHalfTopX = 0.5 * dLenghtTopX ; double dHalfTopY = 0.5 * dLenghtTopY ; - // Inizializzo gli estremi della parte di retta che interseca il prismoide - dStU = INFINITO ; - dEnU = -INFINITO ; - // Interseco la retta con le facce e salvo i punti d'intersezione - // Faccia base - IntersSegmentTrianglePlus( Point3d( -dHalfBaseX, -dHalfBaseY, 0.), - Point3d( -dHalfBaseX, dHalfBaseY, 0.), - Point3d( dHalfBaseX, dHalfBaseY, 0.), + // Parametri estremi linea + dStU = 0 ; + dEnU = dSegLen ; + // Verifico con faccia base + IntersSegmentPlanePlus( Point3d( -dHalfBaseX, -dHalfBaseY, 0), + Point3d( -dHalfBaseX, dHalfBaseY, 0), + Point3d( dHalfBaseX, 0, 0), + ptMySt, vtMySeg, dSegLen, + dStU, dEnU) ; + if ( dEnU < dStU - EPS_ZERO) + return false ; + // Verifico con faccia top + IntersSegmentPlanePlus( Point3d( -dHalfTopX, dHalfTopY, dHeight), + Point3d( -dHalfTopX, -dHalfTopY, dHeight), + Point3d( dHalfTopX, 0, dHeight), + ptMySt, vtMySeg, dSegLen, + dStU, dEnU) ; + if ( dEnU < dStU - EPS_ZERO) + return false ; + // Verifico con faccia laterale 1 + if ( dHalfTopX > dHalfBaseX) + IntersSegmentPlanePlus( Point3d( 0, -dHalfBaseY, 0), + Point3d( dHalfTopX, -dHalfTopY, dHeight), + Point3d( -dHalfTopX, -dHalfTopY, dHeight), ptMySt, vtMySeg, dSegLen, dStU, dEnU) ; - IntersSegmentTrianglePlus( Point3d( -dHalfBaseX, -dHalfBaseY, 0.), - Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( dHalfBaseX, -dHalfBaseY, 0.), + else + IntersSegmentPlanePlus( Point3d( -dHalfBaseX, -dHalfBaseY, 0), + Point3d( dHalfBaseX, -dHalfBaseY, 0), + Point3d( 0, -dHalfTopY, dHeight), ptMySt, vtMySeg, dSegLen, dStU, dEnU) ; - // Faccia top - IntersSegmentTrianglePlus( Point3d( -dHalfTopX, -dHalfTopY, dHeight), + if ( dEnU < dStU - EPS_ZERO) + return false ; + // Verifico con faccia laterale 2 + if ( dHalfTopY > dHalfBaseY) + IntersSegmentPlanePlus( Point3d( dHalfBaseX, 0, 0), Point3d( dHalfTopX, dHalfTopY, dHeight), - Point3d( -dHalfTopX, dHalfTopY, dHeight), - ptMySt, vtMySeg, dSegLen, - dStU, dEnU) ; - IntersSegmentTrianglePlus( Point3d( -dHalfTopX, -dHalfTopY, dHeight), Point3d( dHalfTopX, -dHalfTopY, dHeight), + ptMySt, vtMySeg, dSegLen, + dStU, dEnU) ; + else + IntersSegmentPlanePlus( Point3d( dHalfBaseX, -dHalfBaseY, 0), + Point3d( dHalfBaseX, dHalfBaseY, 0), + Point3d( dHalfTopX, 0, dHeight), + ptMySt, vtMySeg, dSegLen, + dStU, dEnU) ; + if ( dEnU < dStU - EPS_ZERO) + return false ; + // Verifico con faccia laterale 3 + if ( dHalfTopX > dHalfBaseX) + IntersSegmentPlanePlus( Point3d( 0, dHalfBaseY, 0), + Point3d( -dHalfTopX, dHalfTopY, dHeight), Point3d( dHalfTopX, dHalfTopY, dHeight), ptMySt, vtMySeg, dSegLen, dStU, dEnU) ; - // Faccia laterale 1 - IntersSegmentTrianglePlus( Point3d( -dHalfBaseX, -dHalfBaseY, 0.), - Point3d( dHalfTopX , -dHalfTopY , dHeight), - Point3d( -dHalfTopX , -dHalfTopY , dHeight), + else + IntersSegmentPlanePlus( Point3d( dHalfBaseX, dHalfBaseY, 0), + Point3d( -dHalfBaseX, dHalfBaseY, 0), + Point3d( 0, dHalfTopY, dHeight), ptMySt, vtMySeg, dSegLen, dStU, dEnU) ; - IntersSegmentTrianglePlus( Point3d( -dHalfBaseX, -dHalfBaseY, 0.), - Point3d( dHalfBaseX, -dHalfBaseY, 0.), - Point3d( dHalfTopX, -dHalfTopY , dHeight), + if ( dEnU < dStU - EPS_ZERO) + return false ; + // Verifico con faccia laterale 4 + if ( dHalfTopY > dHalfBaseY) + IntersSegmentPlanePlus( Point3d( -dHalfBaseX, 0, 0), + Point3d( -dHalfTopX, -dHalfTopY, dHeight), + Point3d( -dHalfTopX, dHalfTopY, dHeight), ptMySt, vtMySeg, dSegLen, dStU, dEnU) ; - // Faccia laterale 2 - IntersSegmentTrianglePlus( Point3d( dHalfBaseX, -dHalfBaseY, 0.), - Point3d( dHalfTopX , dHalfTopY , dHeight), - Point3d( dHalfTopX , -dHalfTopY , dHeight), - ptMySt, vtMySeg, dSegLen, - dStU, dEnU) ; - IntersSegmentTrianglePlus( Point3d( dHalfBaseX, -dHalfBaseY, 0.), - Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( dHalfTopX , dHalfTopY , dHeight), - ptMySt, vtMySeg, dSegLen, - dStU, dEnU) ; - // Faccia laterale 3 - IntersSegmentTrianglePlus( Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( -dHalfTopX , dHalfTopY , dHeight), - Point3d( dHalfTopX , dHalfTopY , dHeight), - ptMySt, vtMySeg, dSegLen, - dStU, dEnU) ; - IntersSegmentTrianglePlus( Point3d( dHalfBaseX, dHalfBaseY, 0.), - Point3d( -dHalfBaseX, dHalfBaseY, 0.), - Point3d( -dHalfTopX , dHalfTopY , dHeight), - ptMySt, vtMySeg, dSegLen, - dStU, dEnU) ; - // Faccia laterale 4 - IntersSegmentTrianglePlus( Point3d( -dHalfBaseX, dHalfBaseY, 0.), - Point3d( -dHalfTopX , -dHalfTopY , dHeight), - Point3d( -dHalfTopX , dHalfTopY , dHeight), - ptMySt, vtMySeg, dSegLen, - dStU, dEnU) ; - IntersSegmentTrianglePlus( Point3d( -dHalfBaseX, dHalfBaseY, 0.), - Point3d( -dHalfBaseX, -dHalfBaseY, 0.), - Point3d( -dHalfTopX , -dHalfTopY , dHeight), + else + IntersSegmentPlanePlus( Point3d( -dHalfBaseX, dHalfBaseY, 0), + Point3d( -dHalfBaseX, -dHalfBaseY, 0), + Point3d( -dHalfTopX, 0, dHeight), ptMySt, vtMySeg, dSegLen, dStU, dEnU) ; + if ( dEnU < dStU - EPS_ZERO) + return false ; - return ( dEnU > dStU - EPS_ZERO && dStU < dSegLen + EPS_SMALL && dEnU > -EPS_SMALL) ; + return true ; } //---------------------------------------------------------------------------- @@ -1672,10 +1563,28 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX // Se i box non interferiscono, posso uscire if ( ! b3Zmap.Overlaps( b3PrismI) || ! b3Zmap.Overlaps( frPrismInt, b3PrismL)) return true ; + + // BBox del tronco di prismoide ottimizzato nel riferimento intrinseco dello Zmap + Point3d ptMyCen = frPrismInt.Orig() ; + Vector3d vtMyAxX = frPrismInt.VersX() ; + Vector3d vtMyAxY = frPrismInt.VersY() ; + Vector3d vtMyAxZ = frPrismInt.VersZ() ; + BBox3d b3Prism ; + b3Prism.Add( ptMyCen - dLenghtBaseX / 2 * vtMyAxX - dLenghtBaseY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen + dLenghtBaseX / 2 * vtMyAxX - dLenghtBaseY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen + dLenghtBaseX / 2 * vtMyAxX + dLenghtBaseY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen - dLenghtBaseX / 2 * vtMyAxX + dLenghtBaseY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen + dHeight * vtMyAxZ - dLenghtTopX / 2 * vtMyAxX - dLenghtTopY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen + dHeight * vtMyAxZ + dLenghtTopX / 2 * vtMyAxX - dLenghtTopY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen + dHeight * vtMyAxZ + dLenghtTopX / 2 * vtMyAxX + dLenghtTopY / 2 * vtMyAxY) ; + b3Prism.Add( ptMyCen + dHeight * vtMyAxZ - dLenghtTopX / 2 * vtMyAxX + dLenghtTopY / 2 * vtMyAxY) ; + + // Se i box non interferiscono, posso uscire BBox3d b3Int ; - if ( ! b3Zmap.FindIntersection( b3PrismI, b3Int)) + if ( ! b3Zmap.FindIntersection( b3Prism, b3Int)) return true ; + // Se verifico solo prima mappa if ( ! bPrecise) { // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nNx[0] - 1) ; @@ -1716,6 +1625,8 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX } } } + + // altrimenti verifico con tutte e tre le mappe else { // Ciclo sulle mappe for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) { From b78212c3a1e2ad9d123528a1579dbfd33ffd0532 Mon Sep 17 00:00:00 2001 From: DarioS Date: Tue, 16 May 2023 20:26:35 +0200 Subject: [PATCH 10/10] EgtGeomKernel : - miglioramenti e ottimizzazioni in CD su Zmap per cilindri e tronchi di cono. --- CDeClosedSurfTmClosedSurfTm.cpp | 2 +- EgtGeomKernel.vcxproj | 4 + EgtGeomKernel.vcxproj.filters | 12 ++ IntersLineCone.cpp | 138 ++++++++++++++ IntersLineCone.h | 35 ++++ IntersLineCyl.cpp | 118 ++++++++++++ IntersLineCyl.h | 35 ++++ IntersLineSphere.cpp | 21 ++- VolZmapCalculus.cpp | 314 ++++++++++++-------------------- 9 files changed, 474 insertions(+), 205 deletions(-) create mode 100644 IntersLineCone.cpp create mode 100644 IntersLineCone.h create mode 100644 IntersLineCyl.cpp create mode 100644 IntersLineCyl.h diff --git a/CDeClosedSurfTmClosedSurfTm.cpp b/CDeClosedSurfTmClosedSurfTm.cpp index 81bdc5a..50c7158 100644 --- a/CDeClosedSurfTmClosedSurfTm.cpp +++ b/CDeClosedSurfTmClosedSurfTm.cpp @@ -103,7 +103,7 @@ CDeClosedSurfTmClosedSurfTm( const SurfTriMesh& SurfA, const SurfTriMesh& SurfB, // Processo il triangolo: se i due triangoli collidono ho finito. if ( CDeTriaTria( trTriaA, trTriaB)) return true ; - // Segno il triangolo come processato: nTFlag = 1 + // Segno il triangolo come processato: nTemp = 1 SurfB.SetTempInt( nTB, 1) ; } } diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index f1ddf40..07e3f01 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -331,6 +331,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -599,6 +601,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index f6a5e4c..6e688e2 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -471,6 +471,12 @@ File di origine\GeoOffset + + File di origine\GeoInters + + + File di origine\GeoInters + @@ -1103,6 +1109,12 @@ File di intestazione + + File di intestazione + + + File di intestazione + diff --git a/IntersLineCone.cpp b/IntersLineCone.cpp new file mode 100644 index 0000000..97f5d61 --- /dev/null +++ b/IntersLineCone.cpp @@ -0,0 +1,138 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : IntersLineCone.cpp Data : 16.05.23 Versione : 2.5e3 +// Contenuto : Implementazione della intersezione linea/tronco di cono. +// +// +// +// Modifiche : 16.05.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersLineCone.h" +#include "IntersLineCyl.h" +#include "/EgtDev/Include/ENkPolynomialRoots.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +// Linea e tronco di cono sono nel medesimo riferimento. +// Il tronco di cono è centrato sull'asse Z e appoggiato con RMin sul piano XY. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCone( const Point3d& ptL, const Vector3d& vtL, + double dRadMin, double dRadMax, double dHeight, + double& dU1, double& dU2) +{ + // Verifico il versore + if ( vtL.IsSmall()) + return false ; + + // Verifico il tronco di cono + if ( ( dRadMin < EPS_SMALL && dRadMax < EPS_SMALL) || dHeight < EPS_SMALL) + return false ; + + // Se è un cilindro, rimando a questo + if ( abs( dRadMax - dRadMin) < EPS_SMALL) + return IntersLineCyl( ptL, vtL, ( dRadMin + dRadMax) / 2, dHeight, dU1, dU2) ; + + // Se raggi invertiti, li scambio + if ( dRadMin > dRadMax) + swap( dRadMin, dRadMax) ; + + // Tangente dell'angolo di semi-apertura del cono + double dTanTheta = ( dRadMax - dRadMin) / dHeight ; + double dSqTanTheta = dTanTheta * dTanTheta ; + double dSqCosTheta = 1 / ( 1 + dSqTanTheta) ; + + // Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non giace sul cono) + int nBasInt = 0 ; + if ( abs( vtL.z) > EPS_ZERO) { + // le linee tangenti al cono non sono considerate intersecanti + bool bSameHAng = ( abs( abs( vtL.x) - abs( vtL.y)) < EPS_SMALL && abs( dSqCosTheta - vtL.z * vtL.z) < 2 * abs( vtL.z) * EPS_SMALL) ; + double EpsRad = ( bSameHAng ? - EPS_SMALL : EPS_SMALL) ; + Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ; + if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRadMin * dRadMin + 2 * dRadMin * EpsRad) { + dU1 = ( ptInt1 - ptL) * vtL ; + nBasInt += 1 ; + } + Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ; + if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRadMax * dRadMax + 2 * dRadMax * EpsRad) { + dU2 = ( ptInt2 - ptL) * vtL ; + nBasInt += 2 ; + } + } + + // Se la linea interseca entrambe le basi, si sono trovate le due intersezioni + if ( nBasInt == 3) { + if ( dU1 > dU2) + swap( dU1, dU2) ; + // Trovate intersezioni + return true ; + } + + // Posizione del vertice del cono + double dDeltaH = ( dRadMin < EPS_SMALL ? 0 : dRadMin / dTanTheta) ; + // Sposto il punto di passaggio della linea di conseguenza + Point3d ptMyL = ptL + Z_AX * dDeltaH ; + + // Determino le intersezioni con la superficie laterale del cono + DBLVECTOR vdCoeff{ ptMyL.x * ptMyL.x + ptMyL.y * ptMyL.y - ptMyL.z * ptMyL.z * dSqTanTheta, + 2 * ( ptMyL.x * vtL.x + ptMyL.y * vtL.y - ptMyL.z * vtL.z * dSqTanTheta), + vtL.x * vtL.x + vtL.y * vtL.y - vtL.z * vtL.z * dSqTanTheta} ; + DBLVECTOR vdRoots ; + int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ; + + // Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del tronco di cono + if ( nRoot == 2) { + double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ; + if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL) + -- nRoot ; + } + if ( nRoot >= 1) { + double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ; + if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) { + if ( nRoot == 2) + vdRoots[0] = vdRoots[1] ; + -- nRoot ; + } + } + + // Due soluzioni: la retta interseca due volte la superficie laterale + if ( nRoot == 2) { + dU1 = vdRoots[0] ; + dU2 = vdRoots[1] ; + if ( dU1 > dU2) + swap( dU1, dU2) ; + // Trovate intersezioni + return true ; + } + + // Una soluzione : la retta interseca la superficie laterale e un piano + else if ( nRoot == 1) { + // Se piano superiore + if ( nBasInt == 2) { + dU1 = vdRoots[0] ; + } + // altrimenti piano inferiore + else if ( nBasInt == 1) { + dU2 = vdRoots[0] ; + } + // altrimenti niente + else + return false ; + if ( dU1 > dU2) + swap( dU1, dU2) ; + // Trovate intersezioni + return true ; + } + + // Nessuna soluzione : nessuna intersezione + else + return false ; +} diff --git a/IntersLineCone.h b/IntersLineCone.h new file mode 100644 index 0000000..8ffa732 --- /dev/null +++ b/IntersLineCone.h @@ -0,0 +1,35 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : IntersLineCone.h Data : 16.05.23 Versione : 2.5e3 +// Contenuto : Dichiarazione funzioni base per intersezione linea/cono tronco. +// +// +// +// Modifiche : 16.05.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkPoint3d.h" + +//---------------------------------------------------------------------------- +// Linea e tronco di cono sono nel medesimo riferimento. +// Il tronco di cono è centrato sull'asse Z e appoggiato con RMin sul piano XY. +// Con intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCone( const Point3d& ptL, const Vector3d& vtL, + double dRadMin, double dRadMax, double dHeight, + double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +inline bool +TestIntersLineCone( const Point3d& ptL, const Vector3d& vtL, + double dRadMin, double dRadMax, double dHeight) +{ + double dU1, dU2 ; + return IntersLineCone( ptL, vtL, dRadMin, dRadMax, dHeight, dU1, dU2) ; +} diff --git a/IntersLineCyl.cpp b/IntersLineCyl.cpp new file mode 100644 index 0000000..c78b3b7 --- /dev/null +++ b/IntersLineCyl.cpp @@ -0,0 +1,118 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : IntersLineCyl.cpp Data : 16.05.23 Versione : 2.5e3 +// Contenuto : Implementazione della intersezione linea/cilindro. +// +// +// +// Modifiche : 16.05.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersLineCyl.h" +#include "/EgtDev/Include/ENkPolynomialRoots.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +// Linea e cilindro sono nel medesimo riferimento. +// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + double dRad, double dHeight, + double& dU1, double& dU2) +{ + // Verifico il versore + if ( vtL.IsSmall()) + return false ; + + // Verifico il cilindro + if ( dRad < EPS_SMALL || dHeight < EPS_SMALL) + return false ; + + // Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse) + int nBasInt = 0 ; + if ( abs( vtL.z) > EPS_ZERO) { + // le linee tangenti al cilindro non sono considerate intersecanti + double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ; + Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ; + if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) { + dU1 = ( ptInt1 - ptL) * vtL ; + nBasInt += 1 ; + } + Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ; + if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) { + dU2 = ( ptInt2 - ptL) * vtL ; + nBasInt += 2 ; + } + } + + // Se la linea interseca entrambe le basi, si sono trovate le due intersezioni + if ( nBasInt == 3) { + if ( dU1 > dU2) + swap( dU1, dU2) ; + // Trovate intersezioni + return true ; + } + + // Determino le intersezioni con la superficie laterale del cilindro + DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad, + 2 * ( ptL.x * vtL.x + ptL.y * vtL.y), + vtL.x * vtL.x + vtL.y * vtL.y} ; + DBLVECTOR vdRoots ; + int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ; + + // Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro + if ( nRoot == 2) { + double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ; + if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL) + -- nRoot ; + } + if ( nRoot >= 1) { + double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ; + if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) { + if ( nRoot == 2) + vdRoots[0] = vdRoots[1] ; + -- nRoot ; + } + } + + // Due soluzioni: la retta interseca due volte la superficie laterale + if ( nRoot == 2) { + dU1 = vdRoots[0] ; + dU2 = vdRoots[1] ; + if ( dU1 > dU2) + swap( dU1, dU2) ; + // Trovate intersezioni + return true ; + } + + // Una soluzione : la retta interseca la superficie laterale e un piano + else if ( nRoot == 1) { + // Se piano superiore + if ( nBasInt == 2) { + dU1 = vdRoots[0] ; + } + // altrimenti piano inferiore + else if ( nBasInt == 1) { + dU2 = vdRoots[0] ; + } + // altrimenti niente + else + return false ; + if ( dU1 > dU2) + swap( dU1, dU2) ; + // Trovate intersezioni + return true ; + } + + // Nessuna soluzione : nessuna intersezione + else + return false ; +} diff --git a/IntersLineCyl.h b/IntersLineCyl.h new file mode 100644 index 0000000..4448739 --- /dev/null +++ b/IntersLineCyl.h @@ -0,0 +1,35 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : IntersLineCyl.h Data : 16.05.23 Versione : 2.5e3 +// Contenuto : Dichiarazione funzioni base per intersezione linea/cilindro. +// +// +// +// Modifiche : 16.05.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkPoint3d.h" + +//---------------------------------------------------------------------------- +// Linea e cilindro sono nel medesimo riferimento. +// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY. +// Con intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + double dRad, double dHeight, + double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +inline bool +TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + double dRad, double dHeight) +{ + double dU1, dU2 ; + return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ; +} diff --git a/IntersLineSphere.cpp b/IntersLineSphere.cpp index befeab1..6d2629b 100644 --- a/IntersLineSphere.cpp +++ b/IntersLineSphere.cpp @@ -26,20 +26,25 @@ IntersLineSphere( const Point3d& ptL, const Vector3d& vtL, const Point3d& ptCen, return ILST_NO ; // Proiezione del centro della sfera sulla linea Point3d ptP = ptL + (( ptCen - ptL) * vtL) * vtL ; - // Distanza di questo punto di proiezione dal centro della sfera - double dDist = Dist( ptCen, ptP) ; + // Quadrato della distanza di questo punto di proiezione dal centro della sfera + double dSqDist = SqDist( ptCen, ptP) ; + // Differenza tra quadrato del raggio e quadrato della distanza + double dSqDelta = dRad * dRad - dSqDist ; + + // Se distanza superiore al raggio, nessuna intersezione + if ( dSqDelta < - 2 * dRad * EPS_SMALL) + return ILST_NO ; + // Se distanza uguale al raggio, intersezione tangente - if ( abs( dDist - dRad) < EPS_SMALL) { + if ( dSqDelta < EPS_SMALL * EPS_SMALL) { ptI1 = ptP ; ptI2 = ptP ; return ILST_TG ; } - // Se distanza superiore al raggio, nessuna intersezione - if ( dDist > dRad) - return ILST_NO ; + // Distanza inferiore al raggio, due intersezioni secanti - double dDist2 = sqrt( dRad * dRad - dDist * dDist) ; + double dDist2 = sqrt( dSqDelta) ; ptI1 = ptP - dDist2 * vtL ; ptI2 = ptP + dDist2 * vtL ; return ILST_SEC ; -} \ No newline at end of file +} diff --git a/VolZmapCalculus.cpp b/VolZmapCalculus.cpp index da84395..1443894 100644 --- a/VolZmapCalculus.cpp +++ b/VolZmapCalculus.cpp @@ -17,6 +17,8 @@ #include "VolZmap.h" #include "GeoConst.h" #include "IntersLineBox.h" +#include "IntersLineCyl.h" +#include "IntersLineCone.h" #include "IntersLineSurfStd.h" #include "/EgtDev/Include/EGkIntersLineTria.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" @@ -453,16 +455,13 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre continue ; for ( int k = 0 ; k < 5 ; ++ k) { Point3d ptT = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; - if ( k == 0) - ; - else if ( k == 1) - ptT += - 0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; - else if ( k == 2) - ptT += + 0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; - else if ( k == 3) - ptT += + 0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; - else if ( k == 4) - ptT += - 0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; + switch ( k) { + case 0 : break ; + case 1 : ptT += -0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; break ; + case 2 : ptT += +0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; break ; + case 3 : ptT += +0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; break ; + case 4 : ptT += -0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; break ; + } double dZmin, dZmax ; if ( IntersLineBox( ptT, vtK, ORIG, ORIG + vtDiag, dZmin, dZmax)) { for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { @@ -829,6 +828,14 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b int nStJ = Clamp( int( b3Int.GetMin().y / m_dStep), 0, m_nNy[0] - 1) ; int nEnJ = Clamp( int( b3Int.GetMax().y / m_dStep), 0, m_nNy[0] - 1) ; + // Vettore direzione dei dexel nel riferimento del Box + Vector3d vtK = GetToLoc( Z_AX, frCylInt) ; + + // Riferimento intrinseco dei dexel nel riferimento del box + Point3d ptO = GetToLoc( ORIG, frCylInt) ; + Vector3d vtX = GetToLoc( X_AX, frCylInt) ; + Vector3d vtY = GetToLoc( Y_AX, frCylInt) ; + // Ciclo di intersezione dei dexel con il cilindro (nel riferimento intrinseco) for ( int i = nStI ; i <= nEnI ; ++ i) { for ( int j = nStJ ; j <= nEnJ ; ++ j) { @@ -839,19 +846,16 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b if ( m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z || m_Values[0][nPos][0].dMin > b3Int.GetMax().z) continue ; for ( int k = 0 ; k < 5 ; ++ k) { - Point3d ptT = ORIG + ( i + 0.5) * m_dStep * X_AX + ( j + 0.5) * m_dStep * Y_AX ; + Point3d ptT = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; switch ( k) { case 0 : break ; - case 1 : ptT += -0.4 * m_dStep * X_AX - 0.4 * m_dStep * Y_AX ; break ; - case 2 : ptT += +0.4 * m_dStep * X_AX - 0.4 * m_dStep * Y_AX ; break ; - case 3 : ptT += +0.4 * m_dStep * X_AX + 0.4 * m_dStep * Y_AX ; break ; - case 4 : ptT += -0.4 * m_dStep * X_AX + 0.4 * m_dStep * Y_AX ; break ; + case 1 : ptT += -0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; break ; + case 2 : ptT += +0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; break ; + case 3 : ptT += +0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; break ; + case 4 : ptT += -0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; break ; } - Point3d ptI1, ptI2 ; - Vector3d vtN1, vtN2 ; - if ( IntersLineCylinder( ptT, Z_AX, frCylInt, dH, dR, true, true, ptI1, vtN1, ptI2, vtN2)) { - double dZmin = min( ptI1.z, ptI2.z) ; - double dZmax = max( ptI1.z, ptI2.z) ; + double dZmin, dZmax ; + if ( IntersLineCyl( ptT, vtK, dR, dH, dZmin, dZmax)) { for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL && dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL) @@ -867,6 +871,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b else { // Ciclo di intersezione dei dexel con il cilindro (nel riferimento intrinseco) for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) { + Point3d ptO = ORIG ; Vector3d vtX = X_AX ; Vector3d vtY = Y_AX ; Vector3d vtK = Z_AX ; @@ -891,6 +896,11 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b vtY = X_AX ; vtK = Y_AX ; } + // Passo da riferimento intrinseco griglia a riferimento cilindro + ptO.ToLoc( frCylInt) ; + vtX.ToLoc( frCylInt) ; + vtY.ToLoc( frCylInt) ; + vtK.ToLoc( frCylInt) ; // Limiti su indici int nStI = Clamp( int( ptBoxInf.x / m_dStep), 0, m_nNx[nMap] - 1) ; int nEnI = Clamp( int( ptBoxSup.x / m_dStep), 0, m_nNx[nMap] - 1) ; @@ -905,27 +915,13 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b continue ; if ( m_Values[nMap][nPos][nSize-1].dMax < b3Int.GetMin().z || m_Values[nMap][nPos][0].dMin > b3Int.GetMax().z) continue ; - Point3d ptT = ORIG + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; - Point3d ptI1, ptI2 ; - Vector3d vtN1, vtN2 ; - // La linea del dexel interseca il cilindro. - if ( IntersLineCylinder( ptT, vtK, frCylInt, dH, dR, true, true, ptI1, vtN1, ptI2, vtN2)) { - double dMinU, dMaxU ; - if ( nMap == 0) { - dMinU = min( ptI1.z, ptI2.z) ; - dMaxU = max( ptI1.z, ptI2.z) ; - } - else if ( nMap == 1) { - dMinU = min( ptI1.x, ptI2.x) ; - dMaxU = max( ptI1.x, ptI2.x) ; - } - else { - dMinU = min( ptI1.y, ptI2.y) ; - dMaxU = max( ptI1.y, ptI2.y) ; - } - // Ciclo sui segmenti del dexel. + Point3d ptT = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; + double dMinU, dMaxU ; + // La retta associata al dexel interseca il cilindro. + if ( IntersLineCyl( ptT, vtK, dR, dH, dMinU, dMaxU)) { + // Ciclo sui segmenti del dexel for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - // Se il segmento è interno all'intervallo d'intersezione, ho finito. + // Se il segmento è interno all'intervallo d'intersezione, ho finito. if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL && dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL) return false ; @@ -1126,177 +1122,103 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d int nEnI = Clamp( int( b3Int.GetMax().x / m_dStep), 0, m_nNx[0] - 1) ; int nStJ = Clamp( int( b3Int.GetMin().y / m_dStep), 0, m_nNy[0] - 1) ; int nEnJ = Clamp( int( b3Int.GetMax().y / m_dStep), 0, m_nNy[0] - 1) ; - // Limiti su Z - double dZmin = b3Int.GetMin().z ; - double dZmax = b3Int.GetMax().z ; - // Numero massimo di thread - int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ; - // se un solo thread - if ( nThreadMax == 1) { - m_bBreak = false ; - bool bCollision = SingleMapDexelConeCollision( nStI, nEnI, nStJ, nEnJ, ptRefPoint, vtRefAx, - dMinRad, dMaxRad, dHeight, dZmin, dZmax) ; - return ( ! bCollision) ; - } - // altrimenti esecuzione in parallelo dei calcoli - else { - //string sOut = "I=" + ToString( nStI) + "," + ToString( nEnI) + " J=" + ToString( nStJ) + "," + ToString( nEnJ) ; - //LOG_INFO( GetEGkLogger(), sOut.c_str()) - m_bBreak = false ; - // lancio dei thread - int nSpanI = ( nEnI - nStI + 1) / nThreadMax + 1 ; - int nSpanJ = ( nEnJ - nStJ + 1) / nThreadMax + 1 ; - bool bOnI = ( nSpanI >= nSpanJ) ; - int nThreadTot = 0 ; - vector< future> vRes( nThreadMax) ; - for ( int nT = 0 ; nT < nThreadMax ; ++ nT) { - int nMyStI = ( bOnI ? nStI + nT * nSpanI : nStI) ; - int nMyEnI = ( bOnI ? min( nMyStI + nSpanI - 1, nEnI) : nEnI) ; - int nMyStJ = ( bOnI ? nStJ : nStJ + nT * nSpanJ) ; - int nMyEnJ = ( bOnI ? nEnJ : min( nMyStJ + nSpanJ - 1, nEnJ)) ; - if ( nMyStI > nEnI || nMyStJ > nEnJ) - break ; - //string sOut = "MyI=" + ToString( nMyStI) + "," + ToString( nMyEnI) + " MyJ=" + ToString( nMyStJ) + "," + ToString( nMyEnJ) ; - //LOG_INFO( GetEGkLogger(), sOut.c_str()) - vRes[nT] = async( launch::async, &VolZmap::SingleMapDexelConeCollision, this, - nMyStI, nMyEnI, nMyStJ, nMyEnJ, cref( ptRefPoint), cref( vtRefAx), - dMinRad, dMaxRad, dHeight, dZmin, dZmax) ; - ++ nThreadTot ; - } - // recupero i risultati dei thread alla loro terminazione - bool bCollision = false ; - int nTerminated = 0 ; - while ( nTerminated < nThreadTot) { - for ( int nT = 0 ; nT < nThreadTot ; ++ nT) { - // Async terminato - if ( vRes[nT].valid() && vRes[nT].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) { - ++ nTerminated ; - // Se c'è collisione ... - if ( vRes[nT].get()) { - bCollision = true ; - m_bBreak = true ; + + // Vettore direzione dei dexel nel riferimento del tronco di cono + Vector3d vtK = GetToLoc( Z_AX, frConeInt) ; + + // Riferimento intrinseco dei dexel nel riferimento del tronco di cono + Point3d ptO = GetToLoc( ORIG, frConeInt) ; + Vector3d vtX = GetToLoc( X_AX, frConeInt) ; + Vector3d vtY = GetToLoc( Y_AX, frConeInt) ; + + // Ciclo di intersezione dei dexel con il tronco di cono (nel riferimento intrinseco) + for ( int i = nStI ; i <= nEnI ; ++ i) { + for ( int j = nStJ ; j <= nEnJ ; ++ j) { + int nPos = j * m_nNx[0] + i ; + int nSize = int( m_Values[0][nPos].size()) ; + if ( nSize == 0) + continue ; + if ( m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z || m_Values[0][nPos][0].dMin > b3Int.GetMax().z) + continue ; + for ( int k = 0 ; k < 5 ; ++ k) { + Point3d ptT = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; + switch ( k) { + case 0 : break ; + case 1 : ptT += -0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; break ; + case 2 : ptT += +0.4 * m_dStep * vtX - 0.4 * m_dStep * vtY ; break ; + case 3 : ptT += +0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; break ; + case 4 : ptT += -0.4 * m_dStep * vtX + 0.4 * m_dStep * vtY ; break ; + } + double dZmin, dZmax ; + if ( IntersLineCone( ptT, vtK, dMinRad, dMaxRad, dHeight, dZmin, dZmax)) { + for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { + if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL && + dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL) + return false ; } } } } - return ( ! bCollision) ; } } // Uso tutte le mappe else { - // Ciclo sulle mappe. + // Ciclo di intersezione dei dexel con il cilindro (nel riferimento intrinseco) for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) { - Point3d ptInfIntBox = b3Int.GetMin() ; - Point3d ptSupIntBox = b3Int.GetMax() ; - // Dal sistema intrinseco al sistema griglia (per la prima griglia coincidono). + Point3d ptO = ORIG ; + Vector3d vtX = X_AX ; + Vector3d vtY = Y_AX ; + Vector3d vtK = Z_AX ; + // Estremi del box + Point3d ptBoxInf = b3Int.GetMin() ; + Point3d ptBoxSup = b3Int.GetMax() ; if ( nMap == 1) { - swap( ptInfIntBox.x, ptInfIntBox.z) ; - swap( ptInfIntBox.x, ptInfIntBox.y) ; - swap( ptSupIntBox.x, ptSupIntBox.z) ; - swap( ptSupIntBox.x, ptSupIntBox.y) ; + swap( ptBoxInf.x, ptBoxInf.z) ; + swap( ptBoxInf.x, ptBoxInf.y) ; + swap( ptBoxSup.x, ptBoxSup.z) ; + swap( ptBoxSup.x, ptBoxSup.y) ; + vtX = Y_AX ; + vtY = Z_AX ; + vtK = X_AX ; } else if ( nMap == 2) { - swap( ptInfIntBox.y, ptInfIntBox.z) ; - swap( ptInfIntBox.x, ptInfIntBox.y) ; - swap( ptSupIntBox.y, ptSupIntBox.z) ; - swap( ptSupIntBox.x, ptSupIntBox.y) ; + swap( ptBoxInf.y, ptBoxInf.z) ; + swap( ptBoxInf.x, ptBoxInf.y) ; + swap( ptBoxSup.y, ptBoxSup.z) ; + swap( ptBoxSup.x, ptBoxSup.y) ; + vtX = Z_AX ; + vtY = X_AX ; + vtK = Y_AX ; } + // Passo da riferimento intrinseco griglia a riferimento cilindro + ptO.ToLoc( frConeInt) ; + vtX.ToLoc( frConeInt) ; + vtY.ToLoc( frConeInt) ; + vtK.ToLoc( frConeInt) ; // Limiti su indici - int nStI = Clamp( int( ptInfIntBox.x / m_dStep), 0, m_nNx[nMap] - 1) ; - int nEnI = Clamp( int( ptSupIntBox.x / m_dStep), 0, m_nNx[nMap] - 1) ; - int nStJ = Clamp( int( ptInfIntBox.y / m_dStep), 0, m_nNy[nMap] - 1) ; - int nEnJ = Clamp( int( ptSupIntBox.y / m_dStep), 0, m_nNy[nMap] - 1) ; - // Ciclo sui dexel. - for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) { - int nDexSize = (int)m_Values[nMap][nDex].size() ; - if ( nDexSize == 0 || - m_Values[nMap][nDex][ nDexSize- 1].dMax < ptInfIntBox.z || - m_Values[nMap][nDex][0].dMin > ptSupIntBox.z) - continue ; - // Indici del dexel. - int nI = nDex % m_nNx[nMap] ; - int nJ = nDex / m_nNx[nMap] ; - // Se fuori dalla regione ammissibile salto l'iterazione - if ( nI < nStI || nI > nEnI || nJ < nStJ || nJ > nEnJ) - continue ; - // Posizione del dexel. - double dX = ( nI + 0.5) * m_dStep ; - double dY = ( nJ + 0.5) * m_dStep ; - Point3d ptLineSt( dX, dY, 0.) ; - Vector3d vtLineDir( 0., 0., 1.) ; - // Dal sistema griglia al sistema intrinseco (per la prima griglia coincidono). - if ( nMap == 1) { - swap( ptLineSt.x, ptLineSt.y) ; - swap( ptLineSt.x, ptLineSt.z) ; - swap( vtLineDir.x, vtLineDir.y) ; - swap( vtLineDir.x, vtLineDir.z) ; - } - else if ( nMap == 2) { - swap( ptLineSt.x, ptLineSt.y) ; - swap( ptLineSt.y, ptLineSt.z) ; - swap( vtLineDir.x, vtLineDir.y) ; - swap( vtLineDir.y, vtLineDir.z) ; - } - // Cono proprio - if ( dMinRad < EPS_SMALL) { - double dMinPar = m_Values[nMap][nDex][0].dMin ; - double dMaxPar = m_Values[nMap][nDex][nDexSize - 1].dMax ; - Point3d ptSegSt = ptLineSt + dMinPar * vtLineDir ; - double dU1, dU2 ; - int nIntType = SegmentCone( ptSegSt, vtLineDir, dMaxPar - dMinPar, ptRefPoint, vtRefAx, - dMaxRad, dHeight, dU1, dU2) ; - if ( nIntType == LinCompCCIntersType::CC_ERROR_INT) - return false ; - else if ( nIntType != LinCompCCIntersType::CC_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nDexSize ; nIndex += 1) { - if ( m_Values[nMap][nDex][nIndex].dMax >= dU1 && m_Values[nMap][nDex][nIndex].dMin <= dU2) - return false ; - } - } - nIntType = SegmentDisc( ptSegSt, vtLineDir, dMaxPar - dMinPar, ptRefPoint + dHeight * vtRefAx, - vtRefAx, dMaxRad, dU1, dU2) ; - if ( nIntType == LinCompDiscIntersType::D_ERROR_INT) - return false ; - else if ( nIntType != LinCompDiscIntersType::D_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nDexSize ; nIndex += 1) { - if ( m_Values[nMap][nDex][nIndex].dMax >= dU1 && m_Values[nMap][nDex][nIndex].dMin <= dU2) - return false ; - } - } - } - // Tronco di cono - else { - double dMinPar = m_Values[nMap][nDex][0].dMin ; - double dMaxPar = m_Values[nMap][nDex][nDexSize - 1].dMax ; - Point3d ptSegSt = ptLineSt + dMinPar * vtLineDir ; - double dU1, dU2 ; - int nIntType = SegmentConeFrustum( ptSegSt, vtLineDir, dMaxPar - dMinPar, ptRefPoint, vtRefAx, - dMinRad, dMaxRad, dHeight, dU1, dU2) ; - if ( nIntType == LinCompCCIntersType::CC_ERROR_INT) - return false ; - else if ( nIntType != LinCompCCIntersType::CC_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nDexSize ; nIndex += 1) { - if ( m_Values[nMap][nDex][nIndex].dMax >= dU1 && m_Values[nMap][nDex][nIndex].dMin <= dU2) - return false ; - } - } - nIntType = SegmentDisc( ptSegSt, vtLineDir, dMaxPar - dMinPar, ptRefPoint + dHeight * vtRefAx, - vtRefAx, dMaxRad, dU1, dU2) ; - if ( nIntType == LinCompDiscIntersType::D_ERROR_INT) - return false ; - else if ( nIntType != LinCompDiscIntersType::D_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nDexSize ; nIndex += 1) { - if ( m_Values[nMap][nDex][nIndex].dMax >= dU1 && m_Values[nMap][nDex][nIndex].dMin <= dU2) - return false ; - } - } - nIntType = SegmentDisc( ptSegSt, vtLineDir, dMaxPar - dMinPar, ptRefPoint, vtRefAx, dMinRad, dU1, dU2) ; - if ( nIntType == LinCompDiscIntersType::D_ERROR_INT) - return false ; - else if ( nIntType != LinCompDiscIntersType::D_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nDexSize ; nIndex += 1) { - if ( m_Values[nMap][nDex][nIndex].dMax >= dU1 && m_Values[nMap][nDex][nIndex].dMin <= dU2) + int nStI = Clamp( int( ptBoxInf.x / m_dStep), 0, m_nNx[nMap] - 1) ; + int nEnI = Clamp( int( ptBoxSup.x / m_dStep), 0, m_nNx[nMap] - 1) ; + int nStJ = Clamp( int( ptBoxInf.y / m_dStep), 0, m_nNy[nMap] - 1) ; + int nEnJ = Clamp( int( ptBoxSup.y / m_dStep), 0, m_nNy[nMap] - 1) ; + // Ciclo sui dexel. + for ( int i = nStI ; i <= nEnI ; ++ i) { + for ( int j = nStJ ; j <= nEnJ ; ++ j) { + int nPos = j * m_nNx[nMap] + i ; + int nSize = int( m_Values[nMap][nPos].size()) ; + if ( nSize == 0) + continue ; + if ( m_Values[nMap][nPos][nSize-1].dMax < b3Int.GetMin().z || m_Values[nMap][nPos][0].dMin > b3Int.GetMax().z) + continue ; + Point3d ptT = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; + double dMinU, dMaxU ; + // La retta associata al dexel interseca il tronco di cono + if ( IntersLineCone( ptT, vtK, dMinRad, dMaxRad, dHeight, dMinU, dMaxU)) { + // Ciclo sui segmenti del dexel + for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { + // Se il segmento è interno all'intervallo d'intersezione, ho finito. + if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL && + dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL) return false ; } }