diff --git a/ArcPntDirTgCurve.cpp b/ArcPntDirTgCurve.cpp index bb74150..9c2a9ad 100644 --- a/ArcPntDirTgCurve.cpp +++ b/ArcPntDirTgCurve.cpp @@ -204,7 +204,7 @@ GetArcPntDirTgArc( const Point3d& ptP, const Vector3d& vtDir, const CurveArc& cr if ( bOk1) { double dOffset = ( bOutSide ? crvArcL.GetRadius() : - crvArcL.GetRadius()) ; if ( pCrv1->GetType() == CRV_ARC) - bOk1 = (dynamic_cast(Get(pCrv1)))->ExtendedOffset( dOffset) ; + bOk1 = (static_cast( Get( pCrv1)))->ExtendedOffset( dOffset) ; else bOk1 = pCrv1->SimpleOffset( dOffset) ; } @@ -235,7 +235,7 @@ GetArcPntDirTgArc( const Point3d& ptP, const Vector3d& vtDir, const CurveArc& cr if ( bOk2) { double dOffset = ( bOutSide ? - crvArcL.GetRadius() : crvArcL.GetRadius()) ; if ( pCrv2->GetType() == CRV_ARC) - bOk2 = (dynamic_cast(Get(pCrv2)))->ExtendedOffset( dOffset) ; + bOk2 = (static_cast( Get( pCrv2)))->ExtendedOffset( dOffset) ; else bOk2 = pCrv2->SimpleOffset( dOffset) ; } diff --git a/ArcSpecial.cpp b/ArcSpecial.cpp index 908e39c..b06b486 100644 --- a/ArcSpecial.cpp +++ b/ArcSpecial.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2022 +// EgalTech 2014-2023 //---------------------------------------------------------------------------- -// File : ArcSpecial.cpp Data : 18.08.22 Versione : 2.4h2 +// File : ArcSpecial.cpp Data : 04.08.23 Versione : 2.5h1 // Contenuto : Implementazione funzioni per calcoli speciali archi. // // @@ -20,7 +20,6 @@ using namespace std ; - //---------------------------------------------------------------------------- // Come la CurveArc::Set2PD, ma se raggio infinito restituisce una retta //---------------------------------------------------------------------------- @@ -28,7 +27,7 @@ ICurve* GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; @@ -43,7 +42,7 @@ GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg) // verifico se i punti sono allineati con la direzione e nel giusto verso if ( abs( CrossXY( vtDiff, vtDir)) < EPS_SMALL && ScalarXY( vtDiff, vtDir) > EPS_SMALL) { // creo l'oggetto retta - PtrOwner pLine( CreateCurveLine()) ; + PtrOwner pLine( CreateBasicCurveLine()) ; if ( IsNull( pLine)) return nullptr ; // calcolo retta, se ok la restituisco ed esco @@ -61,7 +60,7 @@ ICurve* GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS, const Vector3d& vtN) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; @@ -74,7 +73,7 @@ GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS // verifico se i punti sono allineati con la direzione e nel giusto verso nel piano perpendicolare a vtN if ( abs( ( vtDiff ^ vtDirS) * vtN) < EPS_SMALL && vtDiff * vtDirS > EPS_SMALL) { // creo l'oggetto retta - PtrOwner pLine( CreateCurveLine()) ; + PtrOwner pLine( CreateBasicCurveLine()) ; if ( IsNull( pLine)) return nullptr ; // calcolo retta, se ok la restituisco ed esco @@ -85,6 +84,35 @@ GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS return nullptr ; } +//---------------------------------------------------------------------------- +// Come la CurveArc::Set2PNB, ma se bulge nullo restituisce una retta +//---------------------------------------------------------------------------- +ICurve* +GetArc2PNB( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtN, double dBulge) +{ + // creo l'oggetto arco + PtrOwner pArc( CreateBasicCurveArc()) ; + if ( IsNull( pArc)) + return nullptr ; + + // calcolo l'arco, se ok lo restituisco ed esco + if ( pArc->Set2PNB( ptStart, ptEnd, vtN, dBulge)) + return Release( pArc) ; + + // calcolo arco non riuscito, verifico se retta va bene + if ( abs( dBulge) > EPS_SMALL) + return nullptr ; + // creo l'oggetto retta + PtrOwner pLine( CreateBasicCurveLine()) ; + if ( IsNull( pLine)) + return nullptr ; + // calcolo retta, se ok la restituisco ed esco + if ( pLine->Set( ptStart, ptEnd)) + return Release( pLine) ; + + return nullptr ; +} + //---------------------------------------------------------------------------- // Come la CurveArc::Set3P, ma se raggio infinito restituisce una retta //---------------------------------------------------------------------------- @@ -92,7 +120,7 @@ ICurve* GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd, bool bCirc) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; @@ -108,7 +136,7 @@ GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd, // verifico se i punti sono allineati nel giusto verso if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) { // creo l'oggetto retta - PtrOwner pLine( CreateCurveLine()) ; + PtrOwner pLine( CreateBasicCurveLine()) ; if ( IsNull( pLine)) return nullptr ; // calcolo retta, se ok la restituisco ed esco @@ -126,7 +154,7 @@ ICurveArc* GetArc2PCN( const Point3d& ptStart, const Point3d& ptEnd, const Point3d& ptNearCen, const Vector3d& vtN) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; diff --git a/BBox3d.cpp b/BBox3d.cpp index 12b14fe..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)) ; } @@ -447,69 +448,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/BiArcs.cpp b/BiArcs.cpp index fac2397..0906fc3 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -20,6 +20,7 @@ #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkArcSpecial.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; @@ -97,7 +98,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir CurveArc* pArc = GetBasicCurveArc( pJCrv) ; if ( pArc == nullptr) return nullptr ; - double dU = - 1 ; + double dU = -1 ; double dRad = pArc->GetRadius() ; double dSqRad = dRad * dRad ; Point3d ptCen = pArc->GetCenter() ; @@ -121,9 +122,11 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir } } } - // elimino casi vicino agli estremi, danno solo problemi - if ( dU < 0.1 || dU > 0.9) + // non c'è intersezione, assegno valore medio + if ( dU < -0.5) dU = 0.5 ; + // elimino casi vicino agli estremi, danno solo problemi + dU = Clamp( dU, 0.1, 0.9) ; pBiArc.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, dU)) ; } @@ -132,15 +135,24 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir return nullptr ; // determino la massima distanza tra la curva e il biarco - Point3d ptP ; double dSqDist = 0 ; - for ( bool bPnt = PL.GetFirstPoint( ptP) ; - bPnt ; - bPnt = PL.GetNextPoint( ptP)) { - DistPointCurve dstPC( ptP, *pBiArc) ; - double dSqDistPC ; - if ( dstPC.GetSqDist( dSqDistPC) && dSqDistPC > dSqDist) - dSqDist = dSqDistPC ; + const double STEP = 10 ; + Point3d ptCurr ; + bool bPnt = PL.GetFirstPoint( ptCurr) ; + Point3d ptPrev = ptCurr ; + while ( bPnt) { + double dLen = Dist( ptCurr, ptPrev) ; + int nStep = ( dLen < STEP ? 2 : 1) * int( dLen / STEP) + 1 ; + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCoeff = double( i) / nStep ; + Point3d ptP = Media( ptPrev, ptCurr, dCoeff) ; + DistPointCurve dstPC( ptP, *pBiArc) ; + double dSqDistPC ; + if ( dstPC.GetSqDist( dSqDistPC) && dSqDistPC > dSqDist) + dSqDist = dSqDistPC ; + } + ptPrev = ptCurr ; + bPnt = PL.GetNextPoint( ptCurr) ; } dDist = sqrt( dSqDist) ; 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/CDeBoxTria.cpp b/CDeBoxTria.cpp index f55023c..34ec61d 100644 --- a/CDeBoxTria.cpp +++ b/CDeBoxTria.cpp @@ -182,78 +182,21 @@ CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, cons return CDeSimpleBoxTria( Frame3d(), vtDiag, trTriaL) ; // Verifica preliminare con box esteso - Frame3d frEst( Point3d( -dSafeDist, -dSafeDist, -dSafeDist)) ; - if ( ! CDeSimpleBoxTria( frEst, vtDiag + 2 * Vector3d( dSafeDist, dSafeDist, dSafeDist), trTriaL)) + Frame3d frTmp( Point3d( -dSafeDist, -dSafeDist, -dSafeDist)) ; + if ( ! CDeSimpleBoxTria( frTmp, vtDiag + 2 * Vector3d( dSafeDist, dSafeDist, dSafeDist), trTriaL)) return false ; // Tre box aumentati con distanza di sicurezza in un sola dimensione - Frame3d frTmp = frBox ; frTmp.Translate( - dSafeDist * frBox.VersX()) ; + frTmp.ChangeOrig( Point3d( -dSafeDist, 0, 0)) ; if ( CDeSimpleBoxTria( frTmp, vtDiag + 2 * dSafeDist * X_AX, trTriaL)) return true ; - frTmp = frBox ; frTmp.Translate( - dSafeDist * frBox.VersY()) ; + frTmp.ChangeOrig( Point3d( 0, -dSafeDist, 0)) ; if ( CDeSimpleBoxTria( frTmp, vtDiag + 2 * dSafeDist * Y_AX, trTriaL)) return true ; - frTmp = frBox ; frTmp.Translate( - dSafeDist * frBox.VersZ()) ; + frTmp.ChangeOrig( Point3d( 0, 0, -dSafeDist)) ; if ( CDeSimpleBoxTria( frTmp, vtDiag + 2 * dSafeDist * Z_AX, trTriaL)) return true ; -#if 1 - // Sfere centrate negli otto vertici - if ( CDeSimpleSpheTria( Point3d( 0, 0, 0), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( vtDiag.x, 0, 0), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( vtDiag.x, vtDiag.y, 0), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( 0, vtDiag.y, 0), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( 0, 0, vtDiag.z), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( vtDiag.x, 0, vtDiag.z), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( vtDiag.x, vtDiag.y, vtDiag.z), dSafeDist, trTriaL)) - return true ; - if ( CDeSimpleSpheTria( Point3d( 0, vtDiag.y, vtDiag.z), dSafeDist, trTriaL)) - return true ; - - // Cilindri centrati sui dodici spigoli - frTmp.Set( Point3d( 0, 0, 0), X_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.x, trTriaL)) - return true ; - frTmp.Set( Point3d( 0, vtDiag.y, 0), X_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.x, trTriaL)) - return true ; - frTmp.Set( Point3d( 0, 0, 0), Y_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.y, trTriaL)) - return true ; - frTmp.Set( Point3d( vtDiag.x, 0, 0), Y_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.y, trTriaL)) - return true ; - frTmp.Set( Point3d( 0, 0, vtDiag.z), X_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.x, trTriaL)) - return true ; - frTmp.Set( Point3d( 0, vtDiag.y, vtDiag.z), X_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.x, trTriaL)) - return true ; - frTmp.Set( Point3d( 0, 0, vtDiag.z), Y_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.y, trTriaL)) - return true ; - frTmp.Set( Point3d( vtDiag.x, 0, vtDiag.z), Y_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.y, trTriaL)) - return true ; - frTmp.Set( Point3d( 0., 0., 0.), Z_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.z, trTriaL)) - return true ; - frTmp.Set( Point3d( vtDiag.x, 0., 0.), Z_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.z, trTriaL)) - return true ; - frTmp.Set( Point3d( vtDiag.x, vtDiag.y, 0.), Z_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.z, trTriaL)) - return true ; - frTmp.Set( Point3d( 0., vtDiag.y, 0.), Z_AX) ; - if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.z, trTriaL)) - return true ; -#else // Capsule centrati sui dodici spigoli if ( CDeSimpleCapsTria( Point3d( 0, 0, 0), Point3d( vtDiag.x, 0, 0), dSafeDist, trTriaL)) return true ; @@ -279,7 +222,6 @@ CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, cons return true ; if ( CDeSimpleCapsTria( Point3d( 0, vtDiag.y, 0), Point3d( 0, vtDiag.y, vtDiag.z), dSafeDist, trTriaL)) return true ; -#endif return false ; } diff --git a/CDeCapsTria.cpp b/CDeCapsTria.cpp index 5daf951..4212adc 100644 --- a/CDeCapsTria.cpp +++ b/CDeCapsTria.cpp @@ -16,6 +16,7 @@ #include "CDeCapsTria.h" #include "CDeSpheTria.h" #include "ProjPlane.h" +#include "IntersLineCaps.h" #include "/EgtDev/Include/EGkPolygon3d.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkDistPointTria.h" @@ -31,6 +32,7 @@ CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Tr // Dati della capsule come sfera che si muove Point3d ptC = ptP1 ; + Point3d ptE = ptP2 ; Vector3d vtDir = ptP2 - ptP1 ; double dLen = vtDir.Len() ; if ( dLen < EPS_SMALL) @@ -39,6 +41,13 @@ CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Tr if ( vtDir * trTria.GetN() > 0) { vtDir.Invert() ; ptC = ptP2 ; + ptE = ptP1 ; + } + // Se sfera finale dista dal piano come o meno del raggio, devo verificarla direttamente (il retro è escluso dal calcolo standard) + double dDistE = DistPointPlane( ptE, trTria.GetPlane()) ; + if ( abs( dDistE) <= dR) { + if ( CDeSimpleSpheTria( ptE, dR, trTria)) + return true ; } // Determinazione primo possibile punto di contatto della sfera con il piano Point3d ptD = ptC - trTria.GetN() * dR ; @@ -48,15 +57,20 @@ CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Tr // Se non c'è intersezione passante if ( nLpRes != ILPT_YES) { // se il centro dista dal piano non meno del raggio, allora non c'è sicuramente collisione - double dDist = DistPointPlane( ptP, trTria.GetPlane()) ; - if ( abs( dDist) >= dR) + double dDistM = DistPointPlane( Media( ptP1, ptP2), trTria.GetPlane()) ; + if ( abs( dDistM) >= dR) return false ; - // !!! DA FARE !!!! - // si deve intersecare l'asse del capsule con i cilindri centrati sui lati del triangolo - // se intersezione inferiore a dLen allora collisione - // altrimenti si deve intersecare l'asse del capsule con le sfere centrate sui vertici del triangolo - // se intersezione inferiore a dLen allora collisione - // per ora salto + // interseco l'asse del capsule con capsule di pari raggio con asse i lati del triangolo + double dU1 = INFINITO, dU2 = -INFINITO ; + for ( int i = 0 ; i < 3 ; ++ i) { + double dInt1, dInt2 ; + if ( IntersLineCaps( ptC, vtDir, trTria.GetP( i), trTria.GetP( ( i + 1) % 3), dR, dInt1, dInt2)) { + dU1 = min( dU1, dInt1) ; + dU2 = max( dU2, dInt2) ; + if ( ! ( dU1 >= dLen || dU2 <= 0)) + return true ; + } + } return false ; } // Determino la posizione dell'intersezione rispetto al triangolo @@ -65,7 +79,7 @@ CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Tr double dSqDist ; if ( dptDist.GetSqDist( dSqDist) && dSqDist < 4 * SQ_EPS_SMALL) { double dPos = ( ptP - ptD) * vtDir ; - return ( dPos > -dR && dPos < dLen) ; + return ( dPos > 0 && dPos < dLen) ; } // Altrimenti, recupero il punto del triangolo più vicino all'intersezione Point3d ptQ ; @@ -75,7 +89,7 @@ CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Tr if ( nLsRes != ILST_SEC) return false ; double dPos = ( ptQ - ptI1) * vtDir ; - return ( dPos > -dR && dPos < dLen) ; + return ( dPos > 0 && dPos < dLen) ; } return false ; diff --git a/CDeClosedSurfTmClosedSurfTm.cpp b/CDeClosedSurfTmClosedSurfTm.cpp index d625dc6..8d1cfd1 100644 --- a/CDeClosedSurfTmClosedSurfTm.cpp +++ b/CDeClosedSurfTmClosedSurfTm.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- // EgalTech 2020-2020 //---------------------------------------------------------------------------- -// File : CDeSurfTmSurfTm.h Data : 13.11.20 Versione : +// File : CDeSurfTmSurfTm.h Data : 14.06.23 Versione : 2.5f3 // Contenuto : Implementazione funzione verifica collisione tra // SurfTm e SurfTm. // @@ -18,8 +18,6 @@ #include "/EgtDev/Include/EGkBBox3d.h" #include "/EgtDev/Include/EGkCDeClosedSurfTmClosedSurfTm.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" -#include -#include using namespace std ; @@ -33,63 +31,67 @@ using namespace std ; // originale traslato di una costante pari alla distanza di sicurezza lungo la // sua normale. bool -CDeClosedSurfTmClosedSurfTm( const SurfTriMesh& SurfA, const SurfTriMesh& SurfB, double dSafeDist) +CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist) { - // Se le superfici non sono valide o non sono chiuse, non ha senso proseguire. - if ( ! ( SurfA.IsValid() && SurfB.IsValid()) || ! ( SurfA.IsClosed() && SurfB.IsClosed())) + // Recupero le superfici base + const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ; + const SurfTriMesh* pSrfB = GetBasicSurfTriMesh( &SurfB) ; + // Se le superfici non sono valide o non sono chiuse, non ha senso proseguire. + if ( pSrfA == nullptr || ! pSrfA->IsValid() || ! pSrfA->IsClosed() || + pSrfB == nullptr || ! pSrfB->IsValid() || ! pSrfB->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. + pSrfA->GetLocalBBox( b3BoxA) ; + pSrfB->GetLocalBBox( b3BoxB) ; + // Se è necessario, espando il box di B 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. + b3BoxB.Expand( dSafeDist) ; + // 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 A che interferiscono col box di B INTVECTOR vTriaIndex ; - SurfA.GetAllTriaOverlapBox( b3BoxB, vTriaIndex) ; - // Ciclo sui triangoli della superficie A che cadono nel box della superficie B. + pSrfA->GetAllTriaOverlapBox( b3BoxB, vTriaIndex) ; + // Ciclo sui triangoli della superficie A che interferiscono col box della superficie B. for ( int nTA : vTriaIndex) { Triangle3d trTriaA ; - if ( ! ( SurfA.GetTriangle( nTA, trTriaA) && trTriaA.Validate())) + if ( ! ( pSrfA->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. - SurfB.ResetTempInt() ; - // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. + pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ; + // Settare tutti i triangoli come già processati. + // Al termine della chiamata i TempInt dei triangoli valgono 0. + pSrfB->ResetTempInts() ; + // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. for ( int nTB : vNearTria) { - // Recupero il triangolo corrente della superficie B. - // 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())) + if ( ! ( pSrfB->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. + pSrfB->GetTriangleAdjacencies( nTB, nAdjTriaId) ; + // 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)) + if ( ! ( pSrfB->GetTempInt( 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. - Vector3d vtEdgeV = trTriaB.GetP( nVB) - trTriaB.GetP( ( nVB + 1) % 3) ; + // Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito. + Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ; double dEdgeLen = vtEdgeV.Len() ; vtEdgeV /= dEdgeLen ; Frame3d frCyl ; @@ -97,22 +99,25 @@ 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 - SurfB.SetTempInt( nTB, 1) ; + // Segno il triangolo come processato: nTemp = 1 + pSrfB->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) ; - DistPointSurfTm DistPoinASurfB( ptPointA, SurfB) ; - DistPointSurfTm DistPoinBSurfA( ptPointB, SurfA) ; - return ( DistPoinASurfB.IsPointInside() || DistPoinBSurfA.IsPointInside()) ; -} \ No newline at end of file + pSrfA->GetFirstVertex( ptPointA) ; + pSrfB->GetFirstVertex( ptPointB) ; + DistPointSurfTm DistPoinASrfB( ptPointA, *pSrfB) ; + DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ; + return ( DistPoinASrfB.IsPointInside() || DistPoinBSrfA.IsPointInside()) ; +} 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/CDeRectPrismoidTria.cpp b/CDeRectPrismoidTria.cpp index 9eefc88..1464549 100644 --- a/CDeRectPrismoidTria.cpp +++ b/CDeRectPrismoidTria.cpp @@ -14,6 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CDeRectPrismoidTria.h" +#include "CDeCapsTria.h" #include "CDeBoxTria.h" #include "CDeCylTria.h" #include "CDeSpheTria.h" @@ -141,9 +142,13 @@ CDeRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX, double dLen dHeight < EPS_SMALL || ! trTria.IsValid()) return false ; + // Porto il triangolo nel riferimento del prismoide + Triangle3d trTriaL = trTria ; + trTriaL.ToLoc( frPrismoid) ; + // Se distanza di sicurezza nulla if ( dSafeDist < EPS_SMALL) - return CDeSimpleRectPrismoidTria( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, trTria) ; + return CDeSimpleRectPrismoidTria( Frame3d(), dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, trTriaL) ; // Verifiche con offset esteso double dHDiffX = ( dLenghtBaseX - dLenghtTopX) / 2 ; @@ -156,37 +161,37 @@ CDeRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX, double dLen double dSecAy = sqrt( 1 + dTgAy * dTgAy) ; double dOffsBaseY = dSafeDist * ( dSecAy + dTgAy) ; double dOffsTopY = dSafeDist * ( dSecAy - dTgAy) ; - Frame3d frFrame = frPrismoid ; frFrame.Translate( - dSafeDist * frFrame.VersZ()) ; - if ( ! CDeSimpleRectPrismoidTria( frFrame, dLenghtBaseX + 2 * dOffsBaseX, dLenghtBaseY + 2 * dOffsBaseY, - dLenghtTopX + 2 * dOffsTopX, dLenghtTopY + 2 * dOffsTopY, dHeight + 2 * dSafeDist, trTria)) + Frame3d frTmp( Point3d( 0, 0, -dSafeDist)) ; + if ( ! CDeSimpleRectPrismoidTria( frTmp, dLenghtBaseX + 2 * dOffsBaseX, dLenghtBaseY + 2 * dOffsBaseY, + dLenghtTopX + 2 * dOffsTopX, dLenghtTopY + 2 * dOffsTopY, dHeight + 2 * dSafeDist, trTriaL)) return false ; // Offset fine // Box sotto - frFrame = frPrismoid ; frFrame.Translate( - dSafeDist * frFrame.VersZ()) ; - if ( CDeSimpleBoxTria( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), trTria)) + frTmp.ChangeOrig( Point3d( 0, 0, -dSafeDist)) ; + if ( CDeSimpleBoxTria( frTmp, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), trTriaL)) return true ; // Box sopra - frFrame = frPrismoid ; frFrame.Translate( dHeight * frFrame.VersZ()) ; - if ( CDeSimpleBoxTria( frFrame, Vector3d( dLenghtTopX, dLenghtTopY, dSafeDist), trTria)) + frTmp.ChangeOrig( Point3d( 0, 0, dHeight)) ; + if ( CDeSimpleBoxTria( frTmp, Vector3d( dLenghtTopX, dLenghtTopY, dSafeDist), trTriaL)) return true ; // Prismoide allungato in X double dHypoX = sqrt( dHDiffX * dHDiffX + dHeight * dHeight) ; double dOffsX = dSafeDist * dHeight / dHypoX ; double dMoveXZ = dSafeDist * dHDiffX / dHypoX ; - frFrame = frPrismoid ; frFrame.Translate( dMoveXZ * frFrame.VersZ()) ; - if ( CDeSimpleRectPrismoidTria( frFrame, dLenghtBaseX + 2 * dOffsX, dLenghtBaseY, - dLenghtTopX + 2 * dOffsX, dLenghtTopY, dHeight, trTria)) + frTmp.ChangeOrig( Point3d( 0, 0, dMoveXZ)) ; + if ( CDeSimpleRectPrismoidTria( frTmp, dLenghtBaseX + 2 * dOffsX, dLenghtBaseY, + dLenghtTopX + 2 * dOffsX, dLenghtTopY, dHeight, trTriaL)) return true ; // Prismoide allungato in Y double dHypoY = sqrt( dHDiffY * dHDiffY + dHeight * dHeight) ; double dOffsY = dSafeDist * dHeight / dHypoY ; double dMoveYZ = dSafeDist * dHDiffY / dHypoY ; - frFrame = frPrismoid ; frFrame.Translate( dMoveYZ * frFrame.VersZ()) ; - if ( CDeSimpleRectPrismoidTria( frFrame, dLenghtBaseX, dLenghtBaseY + 2 * dOffsY, - dLenghtTopX, dLenghtTopY + 2 * dOffsY, dHeight, trTria)) + frTmp.ChangeOrig( Point3d( 0, 0, dMoveYZ)) ; + if ( CDeSimpleRectPrismoidTria( frTmp, dLenghtBaseX, dLenghtBaseY + 2 * dOffsY, + dLenghtTopX, dLenghtTopY + 2 * dOffsY, dHeight, trTriaL)) return true ; - // Sfere centrate nei vertici + // Vertici double dHalfBaseX = dLenghtBaseX / 2 ; double dHalfBaseY = dLenghtBaseY / 2 ; double dHalfTopX = dLenghtTopX / 2 ; @@ -199,55 +204,30 @@ CDeRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX, double dLen Point3d( dHalfTopX, -dHalfTopY, dHeight), Point3d( dHalfTopX, dHalfTopY, dHeight), Point3d( -dHalfTopX, dHalfTopY, dHeight)} ; - for ( auto& ptV : vVert) { - ptV.ToGlob( frPrismoid) ; - if ( CDeSimpleSpheTria( ptV, dSafeDist, trTria)) - return true ; - } - // Cilindri con i segmenti come asse - frFrame.Set( vVert[0], frPrismoid.VersX()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtBaseX, trTria)) + // Capsule centrati sui dodici spigoli + if ( CDeSimpleCapsTria( vVert[0], vVert[1], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[1], frPrismoid.VersY()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtBaseY, trTria)) + if ( CDeSimpleCapsTria( vVert[1], vVert[2], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[2], -frPrismoid.VersX()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtBaseX, trTria)) + if ( CDeSimpleCapsTria( vVert[2], vVert[3], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[3], -frPrismoid.VersY()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtBaseY, trTria)) + if ( CDeSimpleCapsTria( vVert[3], vVert[0], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[4], frPrismoid.VersX()) ; - if (CDeSimpleCylTria( frFrame, dSafeDist, dLenghtTopX, trTria)) + if ( CDeSimpleCapsTria( vVert[4], vVert[5], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[5], frPrismoid.VersY()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtTopY, trTria)) + if ( CDeSimpleCapsTria( vVert[5], vVert[6], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[6], -frPrismoid.VersX()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtTopX, trTria)) + if ( CDeSimpleCapsTria( vVert[6], vVert[7], dSafeDist, trTriaL)) return true ; - frFrame.Set( vVert[7], -frPrismoid.VersY()) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenghtTopY, trTria)) + if ( CDeSimpleCapsTria( vVert[7], vVert[4], dSafeDist, trTriaL)) return true ; - Vector3d vtSeg04 = vVert[4] - vVert[0] ; - double dLenSeg04 = vtSeg04.Len() ; - frFrame.Set( vVert[0], vtSeg04) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenSeg04, trTria)) + if ( CDeSimpleCapsTria( vVert[0], vVert[4], dSafeDist, trTriaL)) return true ; - Vector3d vtSeg15 = vVert[5] - vVert[1] ; - double dLenSeg15 = vtSeg15.Len() ; - frFrame.Set( vVert[1], vtSeg15) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenSeg15, trTria)) + if ( CDeSimpleCapsTria( vVert[1], vVert[5], dSafeDist, trTriaL)) return true ; - Vector3d vtSeg26 = vVert[6] - vVert[2] ; - double dLenSeg26 = vtSeg26.Len() ; - frFrame.Set( vVert[2], vtSeg26) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenSeg26, trTria)) + if ( CDeSimpleCapsTria( vVert[2], vVert[6], dSafeDist, trTriaL)) return true ; - Vector3d vtSeg37 = vVert[7] - vVert[3] ; - double dLenSeg37 = vtSeg37.Len(); - frFrame.Set( vVert[3], vtSeg37) ; - if ( CDeSimpleCylTria( frFrame, dSafeDist, dLenSeg37, trTria)) + if ( CDeSimpleCapsTria( vVert[3], vVert[7], dSafeDist, trTriaL)) return true ; return false ; 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/CurveArc.cpp b/CurveArc.cpp index f78f842..63f27bf 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -26,6 +26,7 @@ #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/ENkPolynomialRoots.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include @@ -567,7 +568,7 @@ CurveArc::Clone( void) const bool CurveArc::CopyFrom( const IGeoObj* pGObjSrc) { - const CurveArc* pCA = dynamic_cast( pGObjSrc) ; + const CurveArc* pCA = GetBasicCurveArc( pGObjSrc) ; if ( pCA == nullptr) return false ; return CopyFrom( *pCA) ; @@ -824,10 +825,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) ; @@ -950,10 +951,7 @@ CurveArc::GetDir( double dU, Vector3d& vtDir) const return false ; // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; + dU = Clamp( dU, 0., 1.) ; // versore al punto nel piano della circonferenza (ruoto m_VtS di dU * m_dAngCenDeg attorno a m_VtN) double dAng = dU * m_dAngCenDeg * DEGTORAD ; @@ -975,10 +973,7 @@ CurveArc::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, V return false ; // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; + dU = Clamp( dU, 0., 1.) ; // versore al punto nel piano della circonferenza (ruoto m_VtS di dU di m_dAngCenDeg attorno a m_VtN) double dAng = dU * m_dAngCenDeg * DEGTORAD ; @@ -1427,7 +1422,7 @@ bool CurveArc::TrimStartAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -1443,7 +1438,7 @@ bool CurveArc::TrimEndAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -1803,11 +1798,14 @@ CurveArc::ToGlob( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1825,11 +1823,14 @@ CurveArc::ToLoc( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1850,11 +1851,14 @@ CurveArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; + // trasformo il centro e i versori return ( m_PtCen.LocToLoc( frOri, frDest) && m_VtN.LocToLoc( frOri, frDest) && diff --git a/CurveArc.h b/CurveArc.h index 69ba383..02eba06 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -217,12 +217,16 @@ class CurveArc : public ICurveArc, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveArc* CreateBasicCurveArc( void) - { return (static_cast( CreateGeoObj( CRV_ARC))) ; } + { return ( static_cast( CreateGeoObj( CRV_ARC))) ; } inline CurveArc* CloneBasicCurveArc( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveArc* GetBasicCurveArc( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveArc* GetBasicCurveArc( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC) + return nullptr ; + return ( static_cast( pGObj)) ; } 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/CurveBezier.cpp b/CurveBezier.cpp index ac0e967..703ddec 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -266,7 +266,7 @@ CurveBezier::Clone( void) const bool CurveBezier::CopyFrom( const IGeoObj* pGObjSrc) { - const CurveBezier* pCB = dynamic_cast( pGObjSrc) ; + const CurveBezier* pCB = GetBasicCurveBezier( pGObjSrc) ; if ( pCB == nullptr) return false ; return CopyFrom( *pCB) ; @@ -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) ; @@ -1974,11 +1991,14 @@ CurveBezier::ToGlob( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1998,11 +2018,14 @@ CurveBezier::ToLoc( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2022,11 +2045,14 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché + if ( AreSameFrame( frOri, frDest)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; diff --git a/CurveBezier.h b/CurveBezier.h index d5e96ac..ade321d 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -195,12 +195,16 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveBezier* CreateBasicCurveBezier( void) - { return (static_cast( CreateGeoObj( CRV_BEZIER))) ; } + { return ( static_cast( CreateGeoObj( CRV_BEZIER))) ; } inline CurveBezier* CloneBasicCurveBezier( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZIER) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveBezier* GetBasicCurveBezier( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveBezier* GetBasicCurveBezier( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/CurveByApprox.cpp b/CurveByApprox.cpp index 89e30f3..fd5ff91 100644 --- a/CurveByApprox.cpp +++ b/CurveByApprox.cpp @@ -57,11 +57,17 @@ ICurve* CurveByApprox::GetCurve( int nType, double dLinTol, double dAngTolDeg, double dLinFea) { // se da approssimare con archi - if ( nType == ARCS_CORNER) { + if ( nType == ARCS || nType == ARCS_CORNER) { // calcolo approssimazione PolyArc PA ; - if ( ! GetArcs( dLinTol, dAngTolDeg, dLinFea, PA)) - return nullptr ; + if ( nType == ARCS) { + if ( ! GetArcs( dLinTol, dAngTolDeg, PA)) + return nullptr ; + } + else { + if ( ! GetArcsCorner( dLinTol, dAngTolDeg, dLinFea, PA)) + return nullptr ; + } // creo la composita formata da questa approssimazione PtrOwner pCC( CreateBasicCurveComposite()) ; if ( ! pCC->FromPolyArc( PA)) @@ -74,13 +80,55 @@ CurveByApprox::GetCurve( int nType, double dLinTol, double dAngTolDeg, double dL return Release( pCC) ; } // altrimenti con curve di Bezier cubiche - // !!! NON ANCORA IMPLEMENTATA !!! + else if ( nType == CUBIC_BEZIERS) { + // !!! NON ANCORA IMPLEMENTATA !!! + return nullptr ; + } + // tipi non previsti return nullptr ; } //---------------------------------------------------------------------------- bool -CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) +CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) +{ + // pulisco il poliarco + PA.Clear() ; + + // calcolo una parametrizzazione + if ( ! CalcParameterization()) + return false ; + + // calcolo le tangenti + if ( ! CalcAkimaTangents( false)) + return false ; + + // approssimo come unico tratto + + // creo la polilinea che unisce i punti + PolyLine PL ; + int nPnt = int( m_vPnt.size()) ; + for ( int j = 0 ; j < nPnt ; ++ j) + PL.AddUPoint( j, m_vPnt[j]) ; + // verifico se retta verticale + BBox3d b3PL ; + if ( ! PL.GetLocalBBox( b3PL)) + return false ; + if ( b3PL.GetDimX() < EPS_SMALL && b3PL.GetDimY() < EPS_SMALL) { + PA.AddUPoint( 0, m_vPnt[0], 0) ; + PA.AddUPoint( nPnt - 1, m_vPnt[nPnt - 1], 0) ; + } + // altrimenti eseguo l'approssimazione con archi + else { + if ( ! BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA)) + return false ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::GetArcsCorner( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) { // pulisco il poliarco PA.Clear() ; @@ -105,9 +153,18 @@ CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, double dLinFea, PolyA PolyLine PL ; for ( int j = nPrev ; j <= m_vSplits[i] ; ++ j) PL.AddUPoint( j, m_vPnt[j]) ; - // eseguo l'approssimazione con archi - if ( ! BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA)) + // verifico se retta verticale + BBox3d b3PL ; + if ( ! PL.GetLocalBBox( b3PL)) return false ; + if ( b3PL.GetDimX() < EPS_SMALL && b3PL.GetDimY() < EPS_SMALL) { + PA.AddUPoint( m_vSplits[i], m_vPnt[m_vSplits[i]], 0) ; + } + // altrimenti eseguo l'approssimazione con archi + else { + if ( ! BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA)) + return false ; + } // salvo fine come prox inizio nPrev = m_vSplits[i] ; } @@ -456,9 +513,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng return true ; // costruisco la retta che li unisce PtrOwner pCC( CreateBasicCurveComposite()) ; - if ( IsNull( pCC)) - return false ; - if ( ! pCC->FromPolyLine( PL)) + if ( IsNull( pCC) || ! pCC->FromPolyLine( PL)) return false ; pCrv.Set( pCC) ; dMaxDist = 0 ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index a642003..68d74e0 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -258,16 +258,16 @@ CurveComposite::Close( void) // verifico curva valida if ( m_nStatus != OK) return false ; - // se già chiusa, non faccio alcunché - if ( IsClosed()) - return true ; // determino la distanza tra gli estremi Point3d ptStart, ptEnd ; if ( ! GetStartPoint( ptStart) || ! GetEndPoint( ptEnd)) return false ; + // se distanza inferiore al limite ridotto, non faccio alcunché + if ( AreSamePointEpsilon( ptStart, ptEnd, EPS_SMALL / 10)) + return true ; // se molto vicini li modifico - if ( SqDist( ptStart, ptEnd) < 100 * SQ_EPS_SMALL) { + if ( AreSamePointEpsilon( ptStart, ptEnd, 10 * EPS_SMALL)) { Point3d ptMid = Media( ptStart, ptEnd) ; if ( ! ModifyStart( ptMid) || ! ModifyEnd( ptMid)) @@ -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 @@ -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) ; @@ -1373,30 +1385,52 @@ CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) if ( m_nStatus != OK) return false ; + // determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla + Frame3d frNat ; + if ( ! m_VtExtr.IsSmall()) { + frNat.Set( ORIG, m_VtExtr) ; + } + else { + Plane3d plPlane ; + IsFlat( plPlane, false) ; + if ( plPlane.IsValid()) { + if ( plPlane.GetVersN().z < -EPS_ZERO) + plPlane.Invert() ; + frNat.Set( ORIG, plPlane.GetVersN()) ; + } + } + // eseguo approssimazione double dStartPar = 0 ; - for ( auto& pCrv : m_CrvSmplS) { + for ( const auto& pCrv : m_CrvSmplS) { + // ne faccio una copia + PtrOwner pCrvL( pCrv->Clone()) ; + if ( IsNull( pCrvL)) + return false ; // assegno estrusione e spessore della curva composita - pCrv->SetExtrusion( m_VtExtr) ; - pCrv->SetThickness( m_dThick) ; + pCrvL->SetExtrusion( m_VtExtr) ; + pCrvL->SetThickness( m_dThick) ; + // la porto nel riferimento naturale + pCrvL->ToLoc( frNat) ; // recupero approssimazione per curva semplice PolyArc PASmpl ; - if ( ! pCrv->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) + if ( ! pCrvL->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dStartPar)) return false ; - // ripristino estrusione e spessore della curva semplice (annullandoli) - pCrv->SetExtrusion( V_NULL) ; - pCrv->SetThickness( 0) ; // incremento inizio parametro per prossima curva semplice dStartPar += 1 ; } + // riporto l'approssimazione nel riferimento della composita + PA.ToGlob( frNat) ; + // assegno estrusione della curva composita PA.SetExtrusion( m_VtExtr) ; - return true ; + // eliminazione dei punti in tolleranza (opportunamente diminuita) + return PA.RemoveAlignedPoints( 0.5 * dLinTol) ; } //---------------------------------------------------------------------------- @@ -1415,16 +1449,37 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin double dMlStartPar = 0 ; CurveByApprox crvByApprox ; + // determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla + Frame3d frNat ; + if ( ! m_VtExtr.IsSmall()) { + frNat.Set( ORIG, m_VtExtr) ; + } + else { + Plane3d plPlane ; + IsFlat( plPlane, false) ; + if ( plPlane.IsValid()) { + if ( plPlane.GetVersN().z < -EPS_ZERO) + plPlane.Invert() ; + frNat.Set( ORIG, plPlane.GetVersN()) ; + } + } + // eseguo approssimazione double dStartPar = 0 ; - for ( auto& pCrv : m_CrvSmplS) { + for ( const auto& pCrv : m_CrvSmplS) { + // ne faccio una copia + PtrOwner pCrvL( pCrv->Clone()) ; + if ( IsNull( pCrvL)) + return false ; // assegno estrusione e spessore della curva composita - pCrv->SetExtrusion( m_VtExtr) ; - pCrv->SetThickness( m_dThick) ; + pCrvL->SetExtrusion( m_VtExtr) ; + pCrvL->SetThickness( m_dThick) ; + // la porto nel riferimento naturale + pCrvL->ToLoc( frNat) ; // se segmento di linea non feature double dLen ; - if ( pCrv->GetType() == CRV_LINE && pCrv->GetLength( dLen) && dLen < dLinFea) { - CurveLine* pLine = GetBasicCurveLine( pCrv) ; + if ( pCrvL->GetType() == CRV_LINE && pCrvL->GetLength( dLen) && dLen < dLinFea) { + CurveLine* pLine = GetBasicCurveLine( pCrvL) ; // se inizio di approx multilinea if ( ! bMultiLine) { bMultiLine = true ; @@ -1432,23 +1487,38 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin crvByApprox.Reset() ; crvByApprox.AddPoint( pLine->GetStart()) ; } - // aggiungo punti a distanza opportuna - const double STEP = 5 ; - int nStep = int( dLen / STEP) ; - for ( int i = 1 ; i < nStep ; ++ i) { - double dCoeff = i / double( nStep) ; - crvByApprox.AddPoint( Media( pLine->GetStart(), pLine->GetEnd(), dCoeff)) ; - } // aggiungo il punto finale crvByApprox.AddPoint( pLine->GetEnd()) ; } + // se altrimenti arco di circonferenza o curva di Bezier non feature + else if ( ( pCrvL->GetType() == CRV_ARC || pCrvL->GetType() == CRV_BEZIER) && + pCrvL->GetLength( dLen) && dLen < dLinFea) { + // se inizio di approx multilinea + if ( ! bMultiLine) { + bMultiLine = true ; + dMlStartPar = dStartPar ; + crvByApprox.Reset() ; + Point3d ptStart ; + if ( ! pCrvL->GetStartPoint( ptStart)) + return false ; + crvByApprox.AddPoint( ptStart) ; + } + // aggiungo i punti opportunamente campionati sulla curva (compreso il finale) + PolyLine PL ; + if ( ! pCrvL->ApproxWithLines( dLinTol / 2, dAngTolDeg / 2, ICurve::APL_STD, PL)) + return false ; + Point3d ptFin ; + PL.GetFirstPoint( ptFin) ; + while ( PL.GetNextPoint( ptFin)) + crvByApprox.AddPoint( ptFin) ; + } // altrimenti else { // se in corso approx multilinee if ( bMultiLine) { bMultiLine = false ; PolyArc PASmpl ; - if ( ! crvByApprox.GetArcs( dLinTol, dAngTolDeg, dLinFea, PASmpl)) + if ( ! crvByApprox.GetArcsCorner( dLinTol, dAngTolDeg, dLinFea, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dMlStartPar)) @@ -1456,15 +1526,12 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin } // recupero approssimazione per curva semplice PolyArc PASmpl ; - if ( ! pCrv->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) + if ( ! pCrvL->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dStartPar)) return false ; } - // ripristino estrusione e spessore della curva semplice (annullandoli) - pCrv->SetExtrusion( V_NULL) ; - pCrv->SetThickness( 0) ; // incremento inizio parametro per prossima curva semplice dStartPar += 1 ; } @@ -1472,13 +1539,16 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin if ( bMultiLine) { bMultiLine = false ; PolyArc PASmpl ; - if ( ! crvByApprox.GetArcs( dLinTol, dAngTolDeg, dLinFea, PASmpl)) + if ( ! crvByApprox.GetArcsCorner( dLinTol, dAngTolDeg, dLinFea, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dMlStartPar)) return false ; } + // riporto l'approssimazione nel riferimento della composita + PA.ToGlob( frNat) ; + // assegno estrusione della curva composita PA.SetExtrusion( m_VtExtr) ; @@ -1530,7 +1600,7 @@ CurveComposite::CopyParamRange( double dUStart, double dUEnd) const // eseguo il trim della copia if ( ! pCopy->TrimStartEndAtParam( dUStart, dUEnd)) return nullptr ; - return ( ::Release( pCopy)) ; + return ( pCopy->m_CrvSmplS.empty() ? nullptr : ::Release( pCopy)) ; } //---------------------------------------------------------------------------- @@ -2100,7 +2170,15 @@ CurveComposite::ModifyCurveToLine( int nCrv) bool CurveComposite::TrimStartAtParam( double dUTrim) { - // ciclo sulle diverse curve dall'inizio + // verifico validità parametro + double dMaxU = double( m_CrvSmplS.size()) ; + if ( dUTrim < -EPS_PARAM || dUTrim > dMaxU - EPS_PARAM) + return false ; + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + // ciclo sulle diverse curve dall'inizio double dUToTrim = dUTrim ; for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice @@ -2111,17 +2189,13 @@ CurveComposite::TrimStartAtParam( double dUTrim) // se lunghezza ancora da tagliare non nulla if ( dUToTrim > EPS_PARAM) { delete (*Iter) ; - Iter ++ ; - m_CrvSmplS.pop_front() ; + Iter = m_CrvSmplS.erase( Iter) ; } // se lunghezza ancora da tagliare nulla (entro la tolleranza) else if ( dUToTrim > - EPS_PARAM || ! (*Iter)->TrimStartAtParam( 1 + dUToTrim)) { delete (*Iter) ; - Iter ++ ; - m_CrvSmplS.pop_front() ; - if ( m_CrvSmplS.empty()) - return false ; + Iter = m_CrvSmplS.erase( Iter) ; break ; } // altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra) @@ -2130,9 +2204,6 @@ CurveComposite::TrimStartAtParam( double dUTrim) } } - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - return true ; } @@ -2140,6 +2211,14 @@ CurveComposite::TrimStartAtParam( double dUTrim) bool CurveComposite::TrimEndAtParam( double dUTrim) { + // verifico validità parametro + double dMaxU = double( m_CrvSmplS.size()) ; + if ( dUTrim < EPS_PARAM || dUTrim > dMaxU + EPS_PARAM) + return false ; + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + // ciclo sulle diverse curve dalla fine bool bToErase = false ; double dUToTrim = dUTrim ; @@ -2181,9 +2260,6 @@ CurveComposite::TrimEndAtParam( double dUTrim) } } - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - return true ; } @@ -2406,6 +2482,9 @@ CurveComposite::ExtendEndByLen( double dLenExt) bool CurveComposite::Translate( const Vector3d& vtMove) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2420,6 +2499,9 @@ CurveComposite::Translate( const Vector3d& vtMove) bool CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -2441,6 +2523,9 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn bool CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; @@ -2525,6 +2610,9 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou bool CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -2546,6 +2634,9 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) bool CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -2576,10 +2667,17 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector bool CurveComposite::ToGlob( const Frame3d& frRef) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2597,10 +2695,17 @@ CurveComposite::ToGlob( const Frame3d& frRef) bool CurveComposite::ToLoc( const Frame3d& frRef) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2618,6 +2723,9 @@ CurveComposite::ToLoc( const Frame3d& frRef) bool CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; @@ -2939,9 +3047,11 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn } } // verifico compatibilità delle proprietà - int nTprP = pCrvP->GetTempProp() ; - int nTprC = pCrvC->GetTempProp() ; - if ( bNeedSameProp && nTprP != nTprC) + int nTpr0P = pCrvP->GetTempProp( 0) ; + int nTpr0C = pCrvC->GetTempProp( 0) ; + int nTpr1P = pCrvP->GetTempProp( 1) ; + int nTpr1C = pCrvC->GetTempProp( 1) ; + if ( bNeedSameProp && ( nTpr0P != nTpr0C || nTpr1P != nTpr1C)) return 0 ; // coefficiente deduzione tolleranza const double COEFF_TOL = 0.7 ; @@ -2963,8 +3073,10 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn // diminuisco la tolleranza corrente dell'errore attuale dCurrLinTol -= COEFF_TOL * sqrt( dSqDist) ; // se curve originali con proprietà diversa, la cancello - if ( nTprP != nTprC) - pLineC->SetTempProp( 0) ; + if ( nTpr0P != nTpr0C) + pLineC->SetTempProp( 0, 0) ; + if ( nTpr1P != nTpr1C) + pLineC->SetTempProp( 0, 1) ; // torno flag modifica return -1 ; } @@ -3014,8 +3126,10 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0) NewArc.InvertN() ; // se curve originali con la stessa proprietà, la riporto - if ( nTprP == nTprC) - NewArc.SetTempProp( nTprC) ; + if ( nTpr0P == nTpr0C) + NewArc.SetTempProp( nTpr0C, 0) ; + if ( nTpr1P == nTpr1C) + NewArc.SetTempProp( nTpr1C, 1) ; // aggiorno l'arco corrente e torno flag modifica *pArcC = NewArc ; return -1 ; @@ -3037,8 +3151,10 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn CurveArc NewArc ; if ( NewArc.Set2PVN( ptP1, ptP3, vtDir1, pArcC->GetNormVersor())) { // se curve originali con la stessa proprietà, la riporto - if ( nTprP == nTprC) - NewArc.SetTempProp( nTprC) ; + if ( nTpr0P == nTpr0C) + NewArc.SetTempProp( nTpr0C, 0) ; + if ( nTpr1P == nTpr1C) + NewArc.SetTempProp( nTpr1C, 1) ; // aggiorno l'arco corrente e torno flag modifica *pArcC = NewArc ; return -1 ; diff --git a/CurveComposite.h b/CurveComposite.h index eac578d..5f1cf2f 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -215,12 +215,41 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveComposite* CreateBasicCurveComposite( void) - { return (static_cast( CreateGeoObj( CRV_COMPO))) ; } + { return ( static_cast( CreateGeoObj( CRV_COMPO))) ; } inline CurveComposite* CloneBasicCurveComposite( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveComposite* GetBasicCurveComposite( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveComposite* GetBasicCurveComposite( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline CurveComposite* ConvertCurveToBasicComposite( IGeoObj* pGObj) + { if ( pGObj == nullptr || ( pGObj->GetType() & GEO_CURVE) == 0) { + delete pGObj ; + return nullptr ; + } + CurveComposite* pCrvCo = CreateBasicCurveComposite() ; + if ( pCrvCo == nullptr) { + delete pGObj ; + return nullptr ; + } + ICurve* pCrv = static_cast( pGObj) ; + Vector3d vtExtr ; + if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) + pCrvCo->SetExtrusion( vtExtr) ; + double dThick ; + if ( pCrv->GetThickness( dThick) && abs( dThick) > EPS_SMALL) + pCrvCo->SetThickness( dThick) ; + for ( int i = 0 ; i < 2 ; ++ i) { + int nProp = pCrv->GetTempProp( i) ; + if ( nProp != 0) + pCrvCo->SetTempProp( nProp, i) ; + } + pCrvCo->AddCurve( pCrv) ; + return pCrvCo ; + } diff --git a/CurveLine.cpp b/CurveLine.cpp index 79ee00a..aee34df 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -19,6 +19,7 @@ #include "NgeWriter.h" #include "NgeReader.h" #include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include @@ -32,7 +33,7 @@ CurveLine::CurveLine( void) : m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick() { m_nTempProp[0] = 0 ; - m_nTempProp[0] = 0 ; + m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -111,7 +112,7 @@ CurveLine::Clone( void) const bool CurveLine::CopyFrom( const IGeoObj* pGObjSrc) { - const CurveLine* pCL = dynamic_cast( pGObjSrc) ; + const CurveLine* pCL = GetBasicCurveLine( pGObjSrc) ; if ( pCL == nullptr) return false ; return CopyFrom( *pCL) ; @@ -259,7 +260,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) ; } @@ -356,10 +357,7 @@ CurveLine::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, return false ; // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; + dU = Clamp( dU, 0., 1.) ; // calcolo del punto ptPos = Media( m_PtStart, m_PtEnd, dU) ; @@ -642,7 +640,7 @@ bool CurveLine::TrimStartAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -658,7 +656,7 @@ bool CurveLine::TrimEndAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -787,6 +785,7 @@ CurveLine::Translate( const Vector3d& vtMove) // la curva deve essere validata if ( m_nStatus != OK) return false ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -919,6 +918,10 @@ CurveLine::ToGlob( const Frame3d& frRef) if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -937,6 +940,10 @@ CurveLine::ToLoc( const Frame3d& frRef) if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -954,6 +961,7 @@ CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; diff --git a/CurveLine.h b/CurveLine.h index a3179d6..53d4fd6 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -170,12 +170,16 @@ class CurveLine : public ICurveLine, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveLine* CreateBasicCurveLine( void) - { return (static_cast( CreateGeoObj( CRV_LINE))) ; } + { return ( static_cast( CreateGeoObj( CRV_LINE))) ; } inline CurveLine* CloneBasicCurveLine( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveLine* GetBasicCurveLine( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveLine* GetBasicCurveLine( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/DistPointSurfTm.cpp b/DistPointSurfTm.cpp index 31ef065..44b340f 100644 --- a/DistPointSurfTm.cpp +++ b/DistPointSurfTm.cpp @@ -12,6 +12,7 @@ //---------------------------------------------------------------------------- #include "stdafx.h" +#include "SurfTriMesh.h" #include "/EgtDev/Include/EGkDistPointTria.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" @@ -24,7 +25,7 @@ using namespace std ; // I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto // nel box B; uno di questi si verifica se il box A è vuoto. // Nel vettore vBoxDiff vengono restituiti i box la cui unione costituisce la differenza fra A e B. -bool +static bool BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff) { // Svuoto il risultato @@ -93,30 +94,33 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // Inizializzo distanza non calcolata m_dDist = - 1. ; + // Lavoro con l'oggetto superficie trimesh di base + const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; + if ( pStm == nullptr) + return ; + // Recupero e verifico il box locale della superficie - BBox3d b3Stm = tmSurf.GetAllTriaBox() ; + BBox3d b3Stm = pStm->GetAllTriaBox() ; if ( b3Stm.IsEmpty()) return ; - // Determino i triangoli vicini e fra di essi cerco quello di minima distanza. - // Considero un box centrato nel punto P; finché all'interno del box non trovo un set di triangoli - // fra cui quello a distanza minima dal punto P ha distanza minore del minimo semi-lato del box, - // continuo a ingrandire il box. La condizione di terminazione garantisce di trovare il tiangolo di - // distanza minima della trimesh intera. + // Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // Termino quando non trovo più triangoli che possano soddisfare la richiesta. Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; - double dDeltaLen = max( min( min( ptMax.x - ptMin.x, ptMax.y - ptMin.y), ptMax.z - ptMin.z) / 40., 10.) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; - // Considero anche il box precedente per poter analizzare solo lo spazio differenza tra i due + // Considero anche il box precedente per poter analizzare solo il volume differenza tra i due BBox3d boxPPrev( ptP) ; BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; // Variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima double dMinSqDist = DBL_MAX ; int nMinDistTriaIndex = SVT_NULL ; Point3d ptMinDistPoint ; - bool bContinue = true ; // Finché non si verifica la condizione di terminazione ingrandisco il box. + pStm->ResetTempInts() ; + bool bContinue = true ; while ( bContinue) { // Calcolo il box differenza con il precedente per non esplorare parti già considerate BOXVECTOR vBox ; @@ -131,18 +135,21 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // ricerca sui triangoli nel box bCollide = true ; INTVECTOR vnIds ; - if ( tmSurf.GetAllTriaOverlapBox( b3Int, vnIds)) { + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { // Ciclo sui triangoli del sotto-box corrente for ( auto nT : vnIds) { + int nTriaTemp ; Triangle3d trCurTria ; - tmSurf.GetTriangle( nT, trCurTria) ; - DistPointTriangle distPT( ptP, trCurTria) ; - double dCurSqDist ; - // Se la distanza del triangolo è valida e minore di quella attuale aggiorno - if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) { - dMinSqDist = dCurSqDist ; - nMinDistTriaIndex = nT ; - distPT.GetMinDistPoint( ptMinDistPoint) ; + if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, trCurTria)) { + pStm->SetTempInt( nT, 1) ; + DistPointTriangle distPT( ptP, trCurTria) ; + double dCurSqDist ; + // Se la distanza del triangolo è valida e minore di quella attuale aggiorno + if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) { + dMinSqDist = dCurSqDist ; + nMinDistTriaIndex = nT ; + distPT.GetMinDistPoint( ptMinDistPoint) ; + } } } } @@ -161,9 +168,9 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) m_nMinDistTriaIndex = nMinDistTriaIndex ; m_ptMinDistPoint = ptMinDistPoint ; Triangle3d trMinDistTria ; - tmSurf.GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; + pStm->GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; trMinDistTria.Validate() ; - m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && tmSurf.IsClosed() ; + m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && pStm->IsClosed() ; } } @@ -202,3 +209,80 @@ DistPointSurfTm::GetMinDistTriaIndex( int& nMinDistIndex) nMinDistIndex = m_nMinDistTriaIndex ; return true ; } + +//---------------------------------------------------------------------------- +int +GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf) +{ + // Lavoro con l'oggetto superficie trimesh di base + const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; + if ( pStm == nullptr) + return SVT_NULL ; + + // Recupero e verifico il box locale della superficie + BBox3d b3Stm = pStm->GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return SVT_NULL ; + + // Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // Termino quando non trovo più triangoli che possano soddisfare la richiesta. + Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; + double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; + double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; + double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; + // Considero anche il box precedente per poter analizzare solo il volume differenza tra i due + BBox3d boxPPrev( ptP) ; + BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; + // Variabili distanza minima + int nVert = SVT_NULL ; + double dMinSqDist = DBL_MAX ; + // Finché non si verifica la condizione di terminazione ingrandisco il box. + pStm->ResetTempInts() ; + bool bContinue = true ; + while ( bContinue) { + // Calcolo il box differenza con il precedente per non esplorare parti già considerate + BOXVECTOR vBox ; + BoundingBoxDifference( boxP, boxPPrev, vBox) ; + // Ciclo sui box differenza + bool bCollide = false ; + for ( const auto& b3Box : vBox) { + // interseco il box con quello della superficie e ne verifico la distanza minima dal punto + BBox3d b3Int ; + if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.SqDistFromPoint( ptP) > dMinSqDist) + continue ; + // ricerca sui triangoli nel box + bCollide = true ; + INTVECTOR vnIds ; + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { + // Ciclo sui triangoli del sotto-box corrente + for ( auto nT : vnIds) { + int nTriaTemp ; + int nIdVert[3] ; + if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, nIdVert)) { + pStm->SetTempInt( nT, 1) ; + for ( int i = 0 ; i < 3 ; ++ i) { + Point3d ptVert ; + if ( ! pStm->GetVertex( nIdVert[i], ptVert)) + continue ; + double dCurrSqDist = SqDist( ptP, ptVert) ; + if ( dCurrSqDist < dMinSqDist) { + dMinSqDist = dCurrSqDist ; + nVert = nIdVert[i] ; + } + } + } + } + } + } + // Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box + if ( ! bCollide || dMinSqDist < EPS_SMALL * EPS_SMALL) + bContinue = false ; + else { + boxPPrev = boxP ; + boxP.Expand( dDeltaLen) ; + } + } + + return nVert ; +} diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 40c1ad1..fa4a6cf 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index f1ddf40..89db29d 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -331,6 +331,9 @@ copy $(TargetPath) \EgtProg\Dll64 + + + @@ -394,6 +397,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -599,6 +603,9 @@ copy $(TargetPath) \EgtProg\Dll64 + + + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index f6a5e4c..6f8b271 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -46,6 +46,9 @@ {865b76ee-b10d-41fc-861c-b48ce52fa277} + + {d96752da-1884-4a73-ba1b-5b20b606e469} + @@ -471,6 +474,18 @@ File di origine\GeoOffset + + File di origine\GeoInters + + + File di origine\GeoInters + + + File di origine\GeoInters + + + File di origine\GeoProject + @@ -1103,6 +1118,15 @@ File di intestazione + + File di intestazione + + + File di intestazione + + + File di intestazione + diff --git a/ExtDimension.cpp b/ExtDimension.cpp index ac154a9..8506cab 100644 --- a/ExtDimension.cpp +++ b/ExtDimension.cpp @@ -290,7 +290,7 @@ ExtDimension::Clone( void) const bool ExtDimension::CopyFrom( const IGeoObj* pGObjSrc) { - const ExtDimension* pDim = dynamic_cast( pGObjSrc) ; + const ExtDimension* pDim = GetBasicExtDimension( pGObjSrc) ; if ( pDim == nullptr) return false ; return CopyFrom( *pDim) ; @@ -656,6 +656,7 @@ ExtDimension::Translate( const Vector3d& vtMove) // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { m_ptP1.Translate( vtMove) ; @@ -675,9 +676,14 @@ ExtDimension::Translate( const Vector3d& vtMove) bool ExtDimension::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { return ( m_vtN.Rotate( vtAx, dCosAng, dSinAng) && @@ -701,9 +707,11 @@ ExtDimension::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, doubl // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // sistemo i vettori @@ -749,9 +757,11 @@ ExtDimension::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // eseguo il mirror dei versori @@ -787,9 +797,11 @@ ExtDimension::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // sistemo i vettori @@ -835,13 +847,16 @@ ExtDimension::ToGlob( const Frame3d& frRef) // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se riferimento globale, non devo fare alcunch� - if ( AreSameFrame( frRef, GLOB_FRM)) + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) return true ; - // imposto ricalcolo + + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; - // se valido + + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori return ( m_vtN.ToGlob( frRef) && @@ -865,12 +880,15 @@ ExtDimension::ToLoc( const Frame3d& frRef) // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se riferimento globale, non devo fare alcunch� - if ( AreSameFrame( frRef, GLOB_FRM)) + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) return true ; - // imposto ricalcolo + + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori @@ -895,12 +913,15 @@ ExtDimension::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori diff --git a/ExtDimension.h b/ExtDimension.h index 7ebae29..50dbab3 100644 --- a/ExtDimension.h +++ b/ExtDimension.h @@ -159,3 +159,19 @@ class ExtDimension : public IExtDimension, public IGeoObjRW double m_dTextHeight ; // altezza del testo int m_nTempProp[2] ; // vettore propriet� temporanee } ; + +//----------------------------------------------------------------------------- +inline ExtDimension* CreateBasicExtDimension( void) + { return ( static_cast( CreateGeoObj( EXT_DIMENSION))) ; } +inline ExtDimension* CloneBasicExtDimension( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_DIMENSION) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const ExtDimension* GetBasicExtDimension( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_DIMENSION) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline ExtDimension* GetBasicExtDimension( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_DIMENSION) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/ExtText.cpp b/ExtText.cpp index 6662878..150a6dc 100644 --- a/ExtText.cpp +++ b/ExtText.cpp @@ -161,7 +161,7 @@ ExtText::Clone( void) const bool ExtText::CopyFrom( const IGeoObj* pGObjSrc) { - const ExtText* pTxt = dynamic_cast( pGObjSrc) ; + const ExtText* pTxt = GetBasicExtText( pGObjSrc) ; if ( pTxt == nullptr) return false ; return CopyFrom( *pTxt) ; @@ -399,8 +399,11 @@ ExtText::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const bool ExtText::Translate( const Vector3d& vtMove) { + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + + // eseguo m_ptP.Translate( vtMove) ; return true ; } @@ -409,8 +412,15 @@ ExtText::Translate( const Vector3d& vtMove) bool ExtText::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + + // eseguo return ( m_ptP.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_vtN.Rotate( vtAx, dCosAng, dSinAng) && m_vtD.Rotate( vtAx, dCosAng, dSinAng)) ; @@ -532,9 +542,18 @@ ExtText::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD bool ExtText::ToGlob( const Frame3d& frRef) { + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo punto e versori return ( m_ptP.ToGlob( frRef) && m_vtN.ToGlob( frRef) && @@ -545,9 +564,18 @@ ExtText::ToGlob( const Frame3d& frRef) bool ExtText::ToLoc( const Frame3d& frRef) { + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo punto e versori return ( m_ptP.ToLoc( frRef) && m_vtN.ToLoc( frRef) && @@ -561,12 +589,15 @@ ExtText::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo punto e versori return ( m_ptP.ToGlob( frOri) && m_ptP.ToLoc( frDest) && m_vtN.ToGlob( frOri) && m_vtN.ToLoc( frDest) && diff --git a/ExtText.h b/ExtText.h index 053ed4a..4b56bff 100644 --- a/ExtText.h +++ b/ExtText.h @@ -146,3 +146,19 @@ class ExtText : public IExtText, public IGeoObjRW int m_nInsPos ; // posizione del punto di inserimento rispetto al testo int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline ExtText* CreateBasicExtText( void) + { return ( static_cast( CreateGeoObj( EXT_TEXT))) ; } +inline ExtText* CloneBasicExtText( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_TEXT) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const ExtText* GetBasicExtText( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_TEXT) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline ExtText* GetBasicExtText( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_TEXT) + return nullptr ; + return ( static_cast( pGObj)) ; } 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/GdbGeo.h b/GdbGeo.h index cdc5c0d..acb42d4 100644 --- a/GdbGeo.h +++ b/GdbGeo.h @@ -54,6 +54,10 @@ class GdbGeo : public GdbObj //---------------------------------------------------------------------------- inline const GdbGeo* GetGdbGeo( const GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GEO) + return nullptr ; + return static_cast( pGObj) ; } inline GdbGeo* GetGdbGeo( GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GEO) + return nullptr ; + return static_cast( pGObj) ; } diff --git a/GdbGroup.h b/GdbGroup.h index 45981a2..b7d38f5 100644 --- a/GdbGroup.h +++ b/GdbGroup.h @@ -91,6 +91,10 @@ class GdbGroup : public GdbObj //---------------------------------------------------------------------------- inline const GdbGroup* GetGdbGroup( const GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GROUP) + return nullptr ; + return static_cast( pGObj) ; } inline GdbGroup* GetGdbGroup( GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GROUP) + return nullptr ; + return static_cast( pGObj) ; } diff --git a/GdbIterator.cpp b/GdbIterator.cpp index ddf3b8a..f5f7d26 100644 --- a/GdbIterator.cpp +++ b/GdbIterator.cpp @@ -24,7 +24,7 @@ using namespace std ; IGdbIterator* CreateGdbIterator( IGeomDB* pGDB) { - if ( dynamic_cast( pGDB) == nullptr) + if ( static_cast( pGDB) == nullptr) return nullptr ; return static_cast ( new( nothrow) GdbIterator( pGDB)) ; } @@ -53,7 +53,7 @@ GdbIterator::~GdbIterator( void) bool GdbIterator::SetGDB( IGeomDB* pGDB) { - m_pGDB = dynamic_cast( pGDB) ; + m_pGDB = static_cast( pGDB) ; if ( m_pGDB == nullptr) return false ; @@ -105,7 +105,7 @@ GdbIterator::GoToFirstInGroup( const IGdbIterator& iIter) return false ; } - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -167,7 +167,7 @@ GdbIterator::GoToLastInGroup( const IGdbIterator& iIter) return false ; } - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -263,7 +263,7 @@ GdbIterator::GoToFirstNameInGroup( const IGdbIterator& iIter, const string& sNam return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -345,7 +345,7 @@ GdbIterator::GoToLastNameInGroup( const IGdbIterator& iIter, const string& sName return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -474,7 +474,7 @@ GdbIterator::GoToFirstGroupInGroup( const IGdbIterator& iIter) return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -553,7 +553,7 @@ GdbIterator::GoToLastGroupInGroup( const IGdbIterator& iIter) return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -1637,7 +1637,7 @@ GdbIterator::CopyAllInfoFrom( const IGdbIterator& iIter) return false ; // recupero l'oggetto sorgente - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB || pIter->m_pCurrObj == nullptr) return false ; const GdbObj* pGdbObjSou = pIter->m_pCurrObj ; @@ -1651,6 +1651,29 @@ GdbIterator::CopyAllInfoFrom( const IGdbIterator& iIter) return true ; } +//---------------------------------------------------------------------------- +// Stipple (significativo solo per curve) + +//---------------------------------------------------------------------------- +bool +GdbIterator::SetStipple( int nFactor, int nPattern) +{ + if ( m_pGDB == nullptr || m_pCurrObj == nullptr) + return false ; + // imposto lo stipple + return m_pCurrObj->SetStipple( nFactor, nPattern) ; +} + +//---------------------------------------------------------------------------- +bool +GdbIterator::GetStipple( int& nFactor, int& nPattern) const +{ + if ( m_pGDB == nullptr || m_pCurrObj == nullptr) + return false ; + // recupero lo stipple + return m_pCurrObj->GetStipple( nFactor, nPattern) ; +} + //---------------------------------------------------------------------------- // TextureData //---------------------------------------------------------------------------- diff --git a/GdbIterator.h b/GdbIterator.h index 89a5848..f43ccac 100644 --- a/GdbIterator.h +++ b/GdbIterator.h @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2013-2022 +// EgalTech 2013-2023 //---------------------------------------------------------------------------- -// File : GdbIterator.h Data : 29.01.23 Versione : 2.5a2 +// File : GdbIterator.h Data : 09.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe GdbIterator. // // @@ -144,6 +144,9 @@ class GdbIterator : public IGdbIterator bool RemoveInfo( const std::string& sKey) override ; bool GetAllInfo( STRVECTOR& vsInfo) const override ; bool CopyAllInfoFrom( const IGdbIterator& iIter) override ; + // Stipple + bool SetStipple( int nFactor, int nPattern) override ; + bool GetStipple( int& nFactor, int& nPattern) const override ; // TextureData bool SetTextureName( const std::string& sTxrName) override ; bool SetTextureFrame( const Frame3d& frTxrRef) override ; diff --git a/GdbObj.cpp b/GdbObj.cpp index a9a4bd9..0bdda80 100644 --- a/GdbObj.cpp +++ b/GdbObj.cpp @@ -31,10 +31,9 @@ using namespace std ; //---------------------------------------------------------------------------- GdbObj::GdbObj( void) - : m_nId( GDB_ID_NULL), m_pAttribs( nullptr), m_pTxrData( nullptr), m_pUserObj( nullptr), - m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr), + : m_nId( GDB_ID_NULL), m_pAttribs( nullptr), m_nStpFactor( 0), m_nStpPattern( 0), m_pTxrData( nullptr), + m_pUserObj( nullptr), m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr), m_pSelNext( nullptr), m_pSelPrev( nullptr) - { } @@ -73,6 +72,9 @@ GdbObj::CopyFrom( const GdbObj* pSou) if ( m_pAttribs != nullptr) delete m_pAttribs ; m_pAttribs = nullptr ; + // reset stipple + m_nStpFactor = 0 ; + m_nStpPattern = 0 ; // elimino eventuali dati della texture pre-esistenti if ( m_pTxrData != nullptr) delete m_pTxrData ; @@ -91,6 +93,10 @@ GdbObj::CopyFrom( const GdbObj* pSou) // copio Id m_nId = pSou->m_nId ; + // copio stipple + m_nStpFactor = pSou->m_nStpFactor ; + m_nStpPattern = pSou->m_nStpPattern ; + // copio gli attributi, i dati della texture e UserObj return ( CopyAttribsFrom( pSou) && CopyTextureDataFrom( pSou) && CopyUserObjFrom( pSou)) ; } @@ -1037,6 +1043,26 @@ GdbObj::GetAllInfo( STRVECTOR& vsInfo) const return m_pAttribs->GetAllInfo( vsInfo) ; } +//---------------------------------------------------------------------------- +// Stipple (significativo solo per curve, per ora non viene salvato) +//---------------------------------------------------------------------------- +bool +GdbObj::SetStipple( int nFactor, int nPattern) +{ + m_nStpFactor = nFactor ; + m_nStpPattern = nPattern ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbObj::GetStipple( int& nFactor, int& nPattern) const +{ + nFactor = m_nStpFactor ; + nPattern = m_nStpPattern ; + return true ; +} + //---------------------------------------------------------------------------- // TextureData //---------------------------------------------------------------------------- diff --git a/GdbObj.h b/GdbObj.h index 5e1ae02..8b2a50b 100644 --- a/GdbObj.h +++ b/GdbObj.h @@ -120,6 +120,8 @@ class GdbObj bool ExistsInfo( const std::string& sKey) const ; bool RemoveInfo( const std::string& sKey) ; bool GetAllInfo( STRVECTOR& vsInfo) const ; + bool SetStipple( int nFactor, int nPattern) ; + bool GetStipple( int& nFactor, int& nPattern) const ; bool SaveTextureData( NgeWriter& ngeOut) const ; bool LoadTextureData( NgeReader& ngeIn) ; TextureData* GetTextureData( void) @@ -161,6 +163,8 @@ class GdbObj public : int m_nId ; Attribs* m_pAttribs ; + int m_nStpFactor ; + int m_nStpPattern ; TextureData* m_pTxrData ; IUserObj* m_pUserObj ; diff --git a/GeoFrame3d.cpp b/GeoFrame3d.cpp index 54d2be4..e3ca1f0 100644 --- a/GeoFrame3d.cpp +++ b/GeoFrame3d.cpp @@ -104,7 +104,7 @@ GeoFrame3d::Clone( void) const bool GeoFrame3d::CopyFrom( const IGeoObj* pGObjSrc) { - const GeoFrame3d* pGFr = dynamic_cast( pGObjSrc) ; + const GeoFrame3d* pGFr = GetBasicGeoFrame3d( pGObjSrc) ; if ( pGFr == nullptr) return false ; return CopyFrom( *pGFr) ; diff --git a/GeoFrame3d.h b/GeoFrame3d.h index 728c1b0..850a0a1 100644 --- a/GeoFrame3d.h +++ b/GeoFrame3d.h @@ -98,3 +98,19 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW Frame3d m_frF ; // oggetto int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline GeoFrame3d* CreateBasicGeoFrame3d( void) + { return ( static_cast( CreateGeoObj( GEO_FRAME3D))) ; } +inline GeoFrame3d* CloneBasicGeoFrame3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_FRAME3D) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const GeoFrame3d* GetBasicGeoFrame3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_FRAME3D) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline GeoFrame3d* GetBasicGeoFrame3d( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_FRAME3D) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GeoPoint3d.cpp b/GeoPoint3d.cpp index 0f53b5d..6f02969 100644 --- a/GeoPoint3d.cpp +++ b/GeoPoint3d.cpp @@ -72,7 +72,7 @@ GeoPoint3d::Clone( void) const bool GeoPoint3d::CopyFrom( const IGeoObj* pGObjSrc) { - const GeoPoint3d* pGP = dynamic_cast( pGObjSrc) ; + const GeoPoint3d* pGP = GetBasicGeoPoint3d( pGObjSrc) ; if ( pGP == nullptr) return false ; return CopyFrom( *pGP) ; diff --git a/GeoPoint3d.h b/GeoPoint3d.h index 59f08a0..532d6a4 100644 --- a/GeoPoint3d.h +++ b/GeoPoint3d.h @@ -92,3 +92,19 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW Point3d m_ptP ; // oggetto int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline GeoPoint3d* CreateBasicGeoPoint3d( void) + { return ( static_cast( CreateGeoObj( GEO_PNT3D))) ; } +inline GeoPoint3d* CloneBasicGeoPoint3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_PNT3D) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const GeoPoint3d* GetBasicGeoPoint3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_PNT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline GeoPoint3d* GetBasicGeoPoint3d( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_PNT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GeoVector3d.cpp b/GeoVector3d.cpp index eef867a..2a9d94d 100644 --- a/GeoVector3d.cpp +++ b/GeoVector3d.cpp @@ -29,7 +29,7 @@ GEOOBJ_REGISTER( GEO_VECT3D, NGE_G_VEC, GeoVector3d) ; //---------------------------------------------------------------------------- GeoVector3d::GeoVector3d( void) - : m_vtV() + : m_vtV(), m_ptBase() { m_nTempProp[0] = 0 ; m_nTempProp[1] = 0 ; @@ -88,7 +88,7 @@ GeoVector3d::Clone( void) const bool GeoVector3d::CopyFrom( const IGeoObj* pGObjSrc) { - const GeoVector3d* pGV = dynamic_cast( pGObjSrc) ; + const GeoVector3d* pGV = GetBasicGeoVector3d( pGObjSrc) ; if ( pGV == nullptr) return false ; return CopyFrom( *pGV) ; diff --git a/GeoVector3d.h b/GeoVector3d.h index aaeac07..b824f2e 100644 --- a/GeoVector3d.h +++ b/GeoVector3d.h @@ -107,3 +107,19 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW Point3d m_ptBase ; // punto base da cui tracciare il vettore int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline GeoVector3d* CreateBasicGeoVector3d( void) + { return ( static_cast( CreateGeoObj( GEO_VECT3D))) ; } +inline GeoVector3d* CloneBasicGeoVector3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_VECT3D) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const GeoVector3d* GetBasicGeoVector3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_VECT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline GeoVector3d* GetBasicGeoVector3d( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_VECT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GeomDB.cpp b/GeomDB.cpp index 87f2b92..80a13bc 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2013-2013 +// EgalTech 2013-2023 //---------------------------------------------------------------------------- -// File : GeomDB.cpp Data : 08.04.13 Versione : 1.3a5 +// File : GeomDB.cpp Data : 29.05.23 Versione : 2.5e5 // Contenuto : Implementazione della classe GeomDB. // // @@ -21,38 +21,63 @@ #include "NgeReader.h" #include "NgeWriter.h" #include "/EgtDev/Include/EGkStringUtils3d.h" -#include "/EgtDev/Include/SELkLockId.h" -#include "/EgtDev/Include/SELkKeyProc.h" +#include "/EgtDev/Include/EGnGetKeyData.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtNumCollection.h" #include "/EgtDev/Include/EgtKeyCodes.h" +#include "/EgtDev/Include/SELkLockId.h" +#include "/EgtDev/Include/SELkKeyProc.h" #include #include +#include using namespace std ; +//---------------------------------------------------------------------------- +class LockAddErase +{ + public : + LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) + { if ( ! m_bUse) return ; + while ( m_bAddEraseOn.test_and_set()) { + this_thread::sleep_for( chrono::nanoseconds{ 1}) ; + } + } ; + + ~LockAddErase( void) + { if ( ! m_bUse) return ; + m_bAddEraseOn.clear() ; + } ; + + private : + std::atomic_flag& m_bAddEraseOn ; + bool m_bUse ; +} ; + //---------------------------------------------------------------------------- IGeomDB* CreateGeomDB( void) { // verifico la chiave e le opzioni - if ( ! GetEGkNetHwKey()) { - unsigned int nOpt1, nOpt2 ; - int nOptExpDays ; - int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, + unsigned int nOpt1, nOpt2 ; + int nOptExpDays ; + int nRet = GetEGnKeyOptions( KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nOpt1, nOpt2, nOptExpDays) ; - if ( nRet != KEY_OK && ! EqualNoCase( GetEGkKey(), "EGkBase")) { - if ( nRet != KEY_OK) { - string sErr = "Error on Key (GKC/" + ToString( nRet) + ")" ; - LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; - return nullptr ; - } - if ( (nOpt1 & KEYOPT_EGK_BASE) == 0 || nOptExpDays < GetCurrDay()) { - string sErr = "Error on Key (GKC/OPT)" ; - LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; - return nullptr ; - } + if ( ! GetEGkNetHwKey()) + nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, + nOpt1, nOpt2, nOptExpDays) ; + // controllo i risultati + if ( nRet != KEY_OK && ! EqualNoCase( GetEGkKey(), "EGkBase")) { + if ( nRet != KEY_OK) { + string sErr = "Error on Key (GKC/" + ToString( nRet) + ")" ; + LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; + return nullptr ; + } + if ( ( nOpt1 & KEYOPT_EGK_BASE) == 0 || nOptExpDays < GetCurrDay()) { + string sErr = "Error on Key (GKC/OPT)" ; + LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; + return nullptr ; } } @@ -65,6 +90,7 @@ CreateGeomDB( void) //---------------------------------------------------------------------------- GeomDB::GeomDB( void) { + m_bAddEraseOn.clear() ; m_GrpRadix.SetGeomDB( this) ; m_GrpRadix.m_nId = GDB_ID_ROOT ; m_GrpRadix.SetMaterial( Color()) ; @@ -275,21 +301,23 @@ bool GeomDB::Save( int nId, const string& sFileOut, int nFlag) const { // verifico la chiave e le opzioni - if ( ! GetEGkNetHwKey()) { - unsigned int nOpt1, nOpt2 ; - int nOptExpDays ; - int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, + unsigned int nOpt1, nOpt2 ; + int nOptExpDays ; + int nRet = GetEGnKeyOptions( KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nOpt1, nOpt2, nOptExpDays) ; - if ( nRet != KEY_OK) { - string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ; - LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; - return false ; - } - if ( (nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) { - string sErr = "Error on Key (GKS/OPT)" ; - LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; - return false ; - } + if ( ! GetEGkNetHwKey()) + nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, + nOpt1, nOpt2, nOptExpDays) ; + // controllo i risultati + if ( nRet != KEY_OK) { + string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ; + LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; + return false ; + } + if ( ( nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) { + string sErr = "Error on Key (GKS/OPT)" ; + LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; + return false ; } // assegno Id base @@ -387,21 +415,23 @@ bool GeomDB::Save( const INTVECTOR& vId, const string& sFileOut, int nFlag) const { // verifico la chiave e le opzioni - if ( ! GetEGkNetHwKey()) { - unsigned int nOpt1, nOpt2 ; - int nOptExpDays ; - int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, + unsigned int nOpt1, nOpt2 ; + int nOptExpDays ; + int nRet = GetEGnKeyOptions( KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nOpt1, nOpt2, nOptExpDays) ; - if ( nRet != KEY_OK) { - string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ; - LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; - return false ; - } - if ( (nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) { - string sErr = "Error on Key (GKS/OPT)" ; - LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; - return false ; - } + if ( ! GetEGkNetHwKey()) + nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, + nOpt1, nOpt2, nOptExpDays) ; + // controllo i risultati + if ( nRet != KEY_OK) { + string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ; + LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; + return false ; + } + if ( ( nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) { + string sErr = "Error on Key (GKS/OPT)" ; + LOG_ERROR( GetEGkLogger(), sErr.c_str()) ; + return false ; } // assegno Id base (nessuna riduzione degli Id) @@ -423,7 +453,7 @@ GeomDB::Save( const INTVECTOR& vId, const string& sFileOut, int nFlag) const return false ; // ciclo sugli oggetti da esportare - unordered_set usSavedId ; + INTUNORDSET usSavedId ; for ( const auto nId : vId) { // se già salvato, passo oltre @@ -588,25 +618,32 @@ GeomDB::GetGdbObj( int nId) const //---------------------------------------------------------------------------- bool -GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTestId) +GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLockAddErase, bool bTestId) { // verifico validità oggetto puntato if ( pGObj == nullptr) return false ; - // se richiesta, verifica validità e unicità del nome - if ( bTestId && ( pGObj->m_nId <= GDB_ID_ROOT || ExistsObj( pGObj->m_nId))) + // verifico validità del riferimento + if ( nRefId < GDB_ID_ROOT) return false ; // oggetto e riferimento non possono essere la stessa cosa if ( pGObj->m_nId == nRefId) return ( ! IS_GDB_SON( nSonBeforeAfter)) ; + // verifico unicità esecuzione, se necessaria + LockAddErase Lock( m_bAddEraseOn, bLockAddErase) ; + // cerco il riferimento GdbObj* pGRef = GetGdbObj( nRefId) ; if ( pGRef == nullptr) return false ; + // se richiesta, verifica validità e unicità del nome + if ( bTestId && ( pGObj->m_nId <= GDB_ID_ROOT || ExistsObj( pGObj->m_nId))) + return false ; + // assegno il riferimento al DB geometrico pGObj->SetGeomDB( this) ; @@ -622,7 +659,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTe } // inserisco come figlio, in testa alla lista del padre else if ( nSonBeforeAfter == GDB_FIRST_SON){ - GdbGroup* pGroup = dynamic_cast ( pGRef) ; + GdbGroup* pGroup = ::GetGdbGroup( pGRef) ; if ( pGroup == nullptr) return false ; // inserisco in testa alla lista del padre @@ -631,7 +668,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTe } // inserisco come figlio, in coda alla lista del padre else { - GdbGroup* pGroup = dynamic_cast ( pGRef) ; + GdbGroup* pGroup = ::GetGdbGroup( pGRef) ; if ( pGroup == nullptr) return false ; // inserisco in coda alla lista del padre @@ -660,6 +697,8 @@ GeomDB::InsertGroup( int nId, int nRefId, int nSonBeforeAfter, const Frame3d& fr // verifico validità apparente RefId if ( nRefId < GDB_ID_ROOT) return GDB_ID_NULL ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; // verifico validità Id if ( nId <= GDB_ID_ROOT) nId = m_IdManager.GetNewId() ; @@ -674,7 +713,7 @@ GeomDB::InsertGroup( int nId, int nRefId, int nSonBeforeAfter, const Frame3d& fr // assegno riferimento pGdbGroup->SetFrame( frFrame) ; // inserisco nel DB - if ( ! InsertInGeomDB( pGdbGroup, nRefId, nSonBeforeAfter)) { + if ( ! InsertInGeomDB( pGdbGroup, nRefId, nSonBeforeAfter, false)) { delete pGdbGroup ; return GDB_ID_NULL ; } @@ -695,6 +734,8 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj { // assegno GeoObj a gestore puntatore con rilascio automatico PtrOwner pRPGeoObj( pGeoObj) ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; // verifico validità identificativo if ( nId <= GDB_ID_ROOT) nId = m_IdManager.GetNewId() ; @@ -712,7 +753,7 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj // assegno dati pGdbGeo->m_pGeoObj = Release( pRPGeoObj) ; // inserisco nel DB - if ( ! InsertInGeomDB( pGdbGeo, nRefId, nSonBeforeAfter)) { + if ( ! InsertInGeomDB( pGdbGeo, nRefId, nSonBeforeAfter, false)) { delete pGdbGeo ; return GDB_ID_NULL ; } @@ -1195,6 +1236,9 @@ GeomDB::GetRefBBox( int nId, const Frame3d& frRef, BBox3d& b3Ref, int nFlag) con int GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGlob) { + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // verifico Id destinazione if ( nIdDest <= GDB_ID_ROOT) nIdDest = m_IdManager.GetNewId() ; @@ -1237,7 +1281,7 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl } // inserisco nel DB (non rilascio il puntatore) - if ( ! InsertInGeomDB( pGdODest, nRefId, nSonBeforeAfter)) + if ( ! InsertInGeomDB( pGdODest, nRefId, nSonBeforeAfter, false)) return GDB_ID_NULL ; // rilascio il puntatore @@ -1249,10 +1293,17 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl bool GeomDB::Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) { - // l'oggetto e il riferimento non possono coincidere + // verifico validità del riferimento + if ( nRefId < GDB_ID_ROOT) + return false ; + + // l'oggetto e il riferimento non possono coincidere if ( nId == nRefId) return ( ! IS_GDB_SON( nSonBeforeAfter)) ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // verifico esistenza dell'oggetto GdbObj* pGdbObj = GetGdbObj( nId) ; if ( pGdbObj == nullptr) @@ -1296,7 +1347,7 @@ GeomDB::Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) pGdbObj->Remove() ; // lo inserisco nella posizione opportuna - if ( ! InsertInGeomDB( pGdbObj, nRefId, nSonBeforeAfter, false)) { + if ( ! InsertInGeomDB( pGdbObj, nRefId, nSonBeforeAfter, false, false)) { // in caso di errore (condizione assai remota qui) cancello tutto m_IdManager.RemoveObj( pGdbObj->m_nId) ; m_SelManager.RemoveObj( pGdbObj) ; @@ -1377,9 +1428,14 @@ GeomDB::GetNewId( void) const bool GeomDB::ChangeId( int nId, int nNewId) { + // se Id non validi, ritorno errore + if ( nId <= GDB_ID_ROOT || nNewId <= GDB_ID_ROOT) + return false ; // se Id identici, non faccio alcunché if ( nNewId == nId) return true ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; // verifico nuovo Id if ( ExistsObj( nNewId)) return false ; @@ -1420,7 +1476,10 @@ GeomDB::Erase( GdbObj* pGdbObj) if ( pGdbObj == nullptr || pGdbObj == &m_GrpRadix) return false ; - // notifico eventuale UserObj + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + + // notifico eventuale UserObj if ( pGdbObj->m_pUserObj != nullptr) { // recupero il successivo const GdbObj* pGdbNext = pGdbObj->GetNext() ; @@ -1445,6 +1504,10 @@ GeomDB::RemoveGeoObjAndErase( int nId) // non si può cancellare il gruppo radice (escludo anche Id non validi) if ( nId <= GDB_ID_ROOT) return nullptr ; + + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // recupero l'oggetto geometrico GdbGeo* pGdbGeo = ::GetGdbGeo( m_IdManager.FindObj( nId)) ; if ( pGdbGeo == nullptr) @@ -1452,6 +1515,7 @@ GeomDB::RemoveGeoObjAndErase( int nId) IGeoObj* pGeoObj = pGdbGeo->m_pGeoObj ; // annullo il riferimento alla geometria nell'entità pGdbGeo->m_pGeoObj = nullptr ; + // tolgo dalla lista e disalloco pGdbGeo->Remove() ; delete pGdbGeo ; @@ -1487,6 +1551,10 @@ GeomDB::EmptyGroup( GdbObj* pGdbObj) GdbGroup* pGrp = ::GetGdbGroup( pGdbObj) ; if ( pGrp == nullptr) return false ; + + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // lo svuoto return pGrp->Clear() ; } @@ -2922,6 +2990,51 @@ GeomDB::CopyAllInfoFrom( int nId, int nSouId) return true ; } +//---------------------------------------------------------------------------- +// Stipple (significativo solo per curve) +//---------------------------------------------------------------------------- +bool +GeomDB::DumpStipple( int nId, string& sOut, bool bMM, const char* szNewLine) const +{ + // recupero l'oggetto + const GdbObj* pGdbObj = GetGdbObj( nId) ; + if ( pGdbObj == nullptr) + return false ; + // eseguo il dump + if ( pGdbObj->m_nStpFactor != 0) { + // nome della texture + sOut += "Stipple=" ; + sOut += ToString( pGdbObj->m_nStpFactor) ; + sOut += "-" + ToString( pGdbObj->m_nStpPattern, 1, 16) ; + sOut += szNewLine ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GeomDB::SetStipple( int nId, int nFactor, int nPattern) +{ + // recupero l'oggetto + GdbObj* pGdbObj = GetGdbObj( nId) ; + if ( pGdbObj == nullptr) + return false ; + // imposto lo stipple + return pGdbObj->SetStipple( nFactor, nPattern) ; +} + +//---------------------------------------------------------------------------- +bool +GeomDB::GetStipple( int nId, int& nFactor, int& nPattern) const +{ + // recupero l'oggetto + const GdbObj* pGdbObj = GetGdbObj( nId) ; + if ( pGdbObj == nullptr) + return false ; + // recupero lo stipple + return pGdbObj->GetStipple( nFactor, nPattern) ; +} + //---------------------------------------------------------------------------- // TextureData //---------------------------------------------------------------------------- @@ -2933,7 +3046,7 @@ GeomDB::DumpTextureData( int nId, string& sOut, bool bMM, const char* szNewLine) if ( pGdbObj == nullptr) return false ; // eseguo il dump - if ( pGdbObj->m_pTxrData != nullptr) + if ( pGdbObj->m_pTxrData != nullptr) return pGdbObj->m_pTxrData->Dump( *this, sOut, bMM, szNewLine) ; else return true ; diff --git a/GeomDB.h b/GeomDB.h index 5295b92..3454ba9 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- -// EgalTech 2013-2014 +// EgalTech 2013-2023 //---------------------------------------------------------------------------- -// File : GeomDB.h Data : 03.12.14 Versione : 1.5l1 +// File : GeomDB.h Data : 09.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe GeomDB. // // // // Modifiche : 22.01.13 DS Creazione modulo. -// 03.12.14 DS Aggiunta gestione riferimento di griglia. +// // //---------------------------------------------------------------------------- @@ -20,6 +20,7 @@ #include "SelManager.h" #include "GdbMaterialMgr.h" #include "/EgtDev/Include/EGkGeomDB.h" +#include //---------------------------------------------------------------------------- class GeomDB : public IGeomDB @@ -181,6 +182,10 @@ class GeomDB : public IGeomDB bool RemoveInfo( int nId, const std::string& sKey) override ; bool GetAllInfo( int nId, STRVECTOR& vsInfo) const override ; bool CopyAllInfoFrom( int nId, int nSouId) override ; + // Stipple (significativo solo per curve) + bool DumpStipple( int nId, std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ; + bool SetStipple( int nId, int nFactor, int nPattern) override ; + bool GetStipple( int nId, int& nFactor, int& nPattern) const override ; // TextureData bool DumpTextureData( int nId, std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ; bool SetTextureName( int nId, const std::string& sTxrName) override ; @@ -222,14 +227,14 @@ class GeomDB : public IGeomDB GdbObj* GetGdbObj( int nId) ; const GdbObj* GetGdbObj( int nId) const ; GdbGeo* GetGdbGeo( int nId) - { return dynamic_cast( GetGdbObj( nId)) ; } + { return ::GetGdbGeo( GetGdbObj( nId)) ; } const GdbGeo* GetGdbGeo( int nId) const - { return dynamic_cast( GetGdbObj( nId)) ; } + { return ::GetGdbGeo( GetGdbObj( nId)) ; } GdbGroup* GetGdbGroup( int nId) - { return dynamic_cast( GetGdbObj( nId)) ; } + { return ::GetGdbGroup( GetGdbObj( nId)) ; } const GdbGroup* GetGdbGroup( int nId) const - { return dynamic_cast( GetGdbObj( nId)) ; } - bool InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTestId = true) ; + { return ::GetGdbGroup( GetGdbObj( nId)) ; } + bool InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLockAddErase = true, bool bTestId = true) ; int Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGlob) ; bool Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) ; bool Erase( GdbObj* pGObj) ; @@ -253,10 +258,11 @@ class GeomDB : public IGeomDB { return m_IterManager.RemoveGdbIterator( pIter) ; } private : - IdManager m_IdManager ; // gestore del nuovo Id - IterManager m_IterManager ; // gestore lista iteratori attivi - SelManager m_SelManager ; // gestore lista oggetti selezionati - GdbMaterialMgr m_MatManager ; // gestore lista materiali - GdbGroup m_GrpRadix ; // gruppo radice di tutto il DB - Frame3d m_GridFrame ; // riferimento della griglia + IdManager m_IdManager ; // gestore del nuovo Id + IterManager m_IterManager ; // gestore lista iteratori attivi + SelManager m_SelManager ; // gestore lista oggetti selezionati + GdbMaterialMgr m_MatManager ; // gestore lista materiali + GdbGroup m_GrpRadix ; // gruppo radice di tutto il DB + Frame3d m_GridFrame ; // riferimento della griglia + std::atomic_flag m_bAddEraseOn ; // flag esecuzione inserimento o cancellazione in corso (per multi thread) } ; diff --git a/IntersLineCaps.cpp b/IntersLineCaps.cpp new file mode 100644 index 0000000..0b1553f --- /dev/null +++ b/IntersLineCaps.cpp @@ -0,0 +1,58 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : IntersLineCaps.cpp Data : 22.05.23 Versione : 2.5e3 +// Contenuto : Implementazione della intersezione linea/capsule. +// +// +// +// Modifiche : 22.05.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersLineCaps.h" +#include "DistLineLine.h" +#include "/EgtDev/Include/EGkIntersLineSphere.h" + +using namespace std ; + + +//---------------------------------------------------------------------------- +// Linea e capsule sono nel medesimo riferimento. +// Il capsule è definito con centri delle due estremità, e raggio. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCaps( const Point3d& ptL, const Vector3d& vtL, + const Point3d& ptCaps1, const Point3d& ptCaps2, double dRad, + double& dU1, double& dU2) +{ + // Determino versore e lunghezza asse Capsule + Vector3d vtCaps = ptCaps2 - ptCaps1 ; + double dLen = vtCaps.Len() ; + if ( dLen < EPS_SMALL) { + Point3d ptInt1, ptInt2 ; + if ( IntersLineSphere( ptL, vtL, Media( ptCaps1, ptCaps2), dRad, ptInt1, ptInt2) != ILST_SEC) + return false ; + dU1 = ( ptInt1 - ptL) * vtL ; + dU2 = ( ptInt2 - ptL) * vtL ; + return true ; + } + vtCaps /= dLen ; + // Distanza tra la linea e il segmento asse del capsule + DistLineLine dstLL( ptL, vtL, 1, ptCaps1, vtCaps, dLen, false, true) ; + double dSqDist ; + if ( dstLL.GetSqDist( dSqDist) && dSqDist >= dRad * dRad) + return false ; + // Calcolo i punti di intersezione + Point3d ptRef, ptTmp ; + dstLL.GetMinDistPoints( ptRef, ptTmp) ; + double dSqDelta = dRad * dRad - dSqDist ; + double dDist = sqrt( dSqDelta) ; + dU1 = ( ptRef - ptL) * vtL - dDist ; + dU2 = dU1 + 2 * dDist ; + return true ; +} diff --git a/IntersLineCaps.h b/IntersLineCaps.h new file mode 100644 index 0000000..0e6aeae --- /dev/null +++ b/IntersLineCaps.h @@ -0,0 +1,25 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : IntersLineCaps.h Data : 22.05.23 Versione : 2.5e4 +// Contenuto : Dichiarazione funzioni base per intersezione linea/capsule. +// +// +// +// Modifiche : 22.05.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkPoint3d.h" + +//---------------------------------------------------------------------------- +// Linea e capsule sono nel medesimo riferimento. +// Il capsule è definito con centri delle due estremità, e raggio. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool IntersLineCaps( const Point3d& ptL, const Vector3d& vtL, + const Point3d& ptCaps1, const Point3d& ptCaps2, double dRad, + double& dU1, double& dU2) ; 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..dac9242 --- /dev/null +++ b/IntersLineCyl.cpp @@ -0,0 +1,161 @@ +//---------------------------------------------------------------------------- +// 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/EGkFrame3d.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 ; +} + +//---------------------------------------------------------------------------- +// Linea e cilindro sono nel medesimo riferimento. +// Il cilindro è definito con centro della base, asse, raggio e altezza. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + const Point3d& ptCyl, const Vector3d& vtCyl, double dRad, double dHeight, + double& dU1, double& dU2) +{ + // Riferimento intrinseco del cilindro + Frame3d frCyl ; + if ( ! frCyl.Set( ptCyl, vtCyl)) + return false ; + // Ora eseguo i conti nel riferimento intrinseco + return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ; +} + +//---------------------------------------------------------------------------- +// Linea e cilindro sono nel medesimo riferimento. +// Il cilindro è definito con centri delle due basi, e raggio. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool +IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad, + double& dU1, double& dU2) +{ + // Determino asse ed altezza del cilindro + Vector3d vtCyl = ptCyl2 - ptCyl1 ; + double dHeight = vtCyl.Len() ; + if ( dHeight < EPS_SMALL) + return false ; + vtCyl /= dHeight ; + // Riferimento intrinseco del cilindro + Frame3d frCyl ; + if ( ! frCyl.Set( ptCyl1, vtCyl)) + return false ; + // Ora eseguo i conti nel riferimento intrinseco + return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ; +} diff --git a/IntersLineCyl.h b/IntersLineCyl.h new file mode 100644 index 0000000..fd14e4b --- /dev/null +++ b/IntersLineCyl.h @@ -0,0 +1,52 @@ +//---------------------------------------------------------------------------- +// 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) ; +} + +//---------------------------------------------------------------------------- +// Linea e cilindro sono nel medesimo riferimento. +// Il cilindro è definito con centro della base, asse raggio e altezza. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + const Point3d& ptCyl, const Vector3d& vtCyl, double dRad, double dHeight, + double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Linea e cilindro sono nel medesimo riferimento. +// Il cilindro è definito con centri delle due basi, e raggio. +// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. +//---------------------------------------------------------------------------- +bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, + const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad, + double& dU1, double& 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/IntersLineSurfStd.cpp b/IntersLineSurfStd.cpp index 7657f19..41a2ae8 100644 --- a/IntersLineSurfStd.cpp +++ b/IntersLineSurfStd.cpp @@ -800,7 +800,7 @@ IntersLineCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, // Parte della retta appartenente al cilindro if ( nIntType == CC_INF_INT) { - dU1 = ( ptPCyl- ptPLine) * vtVLine ; + dU1 = ( ptPCyl - ptPLine) * vtVLine ; // Retta e cilindro equiversi if ( vtVCyl * vtVLine > 0) dU2 = dU1 + dCylHeigth ; @@ -819,8 +819,7 @@ IntersLineCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, } // Caso di due intersezioni else if ( nIntType == CC_TWO_INT) { - // Rigetto le soluzioni fuori dalla - // regione ammissibile del cilindro. + // Elimino le soluzioni fuori dal cilindro finito Point3d ptInt1 = ptPLine + dU1 * vtVLine ; Point3d ptInt2 = ptPLine + dU2 * vtVLine ; int nSolNum = 2 ; @@ -832,8 +831,7 @@ IntersLineCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, if ( ( ptInt2 - ptPCyl) * vtVCyl < 0 || ( ptInt2 - ptPCyl) * vtVCyl > dCylHeigth) -- nSolNum ; - // Dal numero di soluzioni rimaste - // aggiorno la tipologia di interferenza. + // Aggiorno il tipo di intersezione if ( nSolNum == 1) nIntType = CC_ONE_INT_SEC ; else if ( nSolNum == 0) @@ -896,8 +894,7 @@ IntersSegmentCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, double d if ( nIntType == CC_ERROR_INT) return nIntType ; - // Parte della retta associata - // appartiene al cilindro + // Parte della retta associata appartiene al cilindro if ( nIntType == CC_INF_INT) { // Segmento non interferisce if ( dU1 > dLen + EPS_SMALL) @@ -925,7 +922,7 @@ IntersSegmentCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, double d if ( dU1 < - EPS_SMALL || dU1 > dLen + EPS_SMALL) nIntType = CC_NO_INTERS ; } - // Retta associata è secante + // Retta associata è secante con due punti di intersezione else if ( nIntType == CC_TWO_INT) { // Il segmento non interferisce if ( dU1 > dLen + EPS_SMALL) @@ -951,6 +948,11 @@ IntersSegmentCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, double d nIntType = CC_NO_INTERS ; } } + // Retta associata è secante con un punto di intersezione + else if ( nIntType == CC_ONE_INT_SEC) { + if ( dU1 < -EPS_SMALL || dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } return nIntType ; } diff --git a/IntersLineSurfStd.h b/IntersLineSurfStd.h index 4a0dee0..2a76d2d 100644 --- a/IntersLineSurfStd.h +++ b/IntersLineSurfStd.h @@ -17,12 +17,11 @@ // In tutte le funzioni dichiarate i punti e i vettori che definiscono gli oggetti geometrici // devono essere espressi nel medesimo sistema di riferimento. I vettori devono essere normalizzati. -// Il valore di ritorno è una costante intera che individua la tipologia di interferenza. +// Il valore di ritorno è una costante intera che individua la tipologia di intersezione. // Se si verificano irregolarità, essa vale ERROR_INT. // Per riferimento vengono restituiti i parametri lungo la retta a cui avvengono le -// intersezioni. Se non vi sono intersezioni i valori di dU1 e dU2 non hanno senso, -// se vi è un'intersezione solo il valore di dU1 ha senso. Se vi sono più intersezioni, -// dU1 e dU2 hanno entrambi senso. +// intersezioni. Se non vi sono intersezioni i valori di dU1 e dU2 non sono definiti, +// se vi è un'intersezione vale solo dU1, con due soluzioni valgono entrambi. // Nelle routine per la semi-sfera come argomento appare un versore, che ne individua l'orientazione // nello spazio. Si immagini uno spazio con origine nel centro della sfera e asse Z diretto come tale // versore. La sfera è divisa in due parti: una nel semi spazio Z+ e una in quello Z-. @@ -130,7 +129,7 @@ int IntersRayInfiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, //---------------------------------------------------------------------------- // Valuta la posizione reciproca fra un cilindro infinito e un segmento. -// Nel caso in cui il sgmento giaccia sul cilindro, nIntType vale INF_INT e dU1 e dU2 +// Nel caso in cui il segmento giaccia sul cilindro, nIntType vale INF_INT e dU1 e dU2 // valgono rispettivamente 0 e dLen (lunghezza del segmento). int IntersSegmentInfiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, double dLen, const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad, diff --git a/IntersLineSurfTm.cpp b/IntersLineSurfTm.cpp index 1031d5a..959071a 100644 --- a/IntersLineSurfTm.cpp +++ b/IntersLineSurfTm.cpp @@ -156,13 +156,13 @@ IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfT bool IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vInfo, bool bFinite) const { - // verifico validità - if ( ! m_bOk) - return false ; // verifico parametro di ritorno if ( &vInfo == nullptr) return false ; vInfo.clear() ; + // verifico validità + if ( ! m_bOk) + return false ; // calcolo box linea (nel riferimento) BBox3d b3Line ; diff --git a/LineTgTwoCurves.cpp b/LineTgTwoCurves.cpp index 48fd0d6..16cb6e4 100644 --- a/LineTgTwoCurves.cpp +++ b/LineTgTwoCurves.cpp @@ -171,7 +171,7 @@ GetLineTgTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, return nullptr ; // porto il secondo arco nel riferimento intrinseco del primo - CurveArc crvArc2Loc = dynamic_cast( crvArc2) ; + CurveArc crvArc2Loc = crvArc2 ; crvArc2Loc.ToLoc( frIntr) ; // calcolo le linee di tangenza alle due circonferenze diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index d3e5adc..466bacb 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2020 +// EgalTech 2015-2023 //---------------------------------------------------------------------------- -// File : OffsetCurve.cpp Data : 10.10.20 Versione : 2.2j2 +// File : OffsetCurve.cpp Data : 03.08.23 Versione : 2.5h1 // Contenuto : Classe per offset avanzato di Curve. // // @@ -9,16 +9,17 @@ // Modifiche : 23.09.15 DS Creazione modulo. // 24.06.19 DS Agg. GetShorterCurve. // 10.10.20 DS Migliorata gestione angoli interni. +// 03.08.23 DS Migliorato riconoscimento angoli esterni di valore circa 180deg. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "CurveComposite.h" +#include "GeoConst.h" #include "CurveLine.h" #include "CurveArc.h" +#include "CurveComposite.h" #include "RemoveCurveDefects.h" -#include "GeoConst.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EGkDistPointCurve.h" @@ -83,9 +84,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd)) bIsLine = true ; } - // verifico che la curva sia piana + // verifico che la curva sia piana (per le linee è comunque sempre vero) Plane3d plPlane ; - if ( ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL)) + if ( ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL) && ! bIsLine) return false ; // recupero o assegno estrusione Vector3d vtExtr ; @@ -454,7 +455,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 +466,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 +473,15 @@ 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 + bool bFirstLastSame = false ; + if ( dUPrev > EPS_PARAM) { + // trimmo l'ultima parte pCompo1->TrimStartAtParam( dUPrev) ; + // 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 if ( ! bClosed) { @@ -581,6 +586,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 @@ -591,8 +597,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 @@ -709,6 +731,15 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) break ; } + // se originale era chiusa, verifico le risultanti e se necessario cerco di chiuderle + if ( bClosed) { + for ( auto pCrv : m_CrvLst) { + CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ; + if ( pCrvCo != nullptr) + pCrvCo->Close() ; + } + } + return true ; } @@ -835,16 +866,30 @@ CalcAngle( const ICurve* pCrv1, const ICurve* pCrv2, double& dAngDeg) if ( ! vtDir1.GetAngleXY( vtDir2, dAngDeg)) return false ; // se vicino all'angolo piatto, si devono ricalcolare spostandosi un poco - if ( abs( dAngDeg) > ( ANG_STRAIGHT - EPS_ANG_SMALL)) { - // eseguo calcolo spostato + const double MAX_ANG_DELTA = 2 ; + double dAngDelta = abs( abs( dAngDeg) - ANG_STRAIGHT) ; + if ( dAngDelta < MAX_ANG_DELTA) { + // angolo al centro delle curve + double dAngCen1 = 0 ; + if ( pCrv1->GetType() == CRV_ARC) + dAngCen1 = abs( GetBasicCurveArc( pCrv1)->GetAngCenter()) ; + double dAngCen2 = 0 ; + if ( pCrv2->GetType() == CRV_ARC) + dAngCen2 = abs( GetBasicCurveArc( pCrv2)->GetAngCenter()) ; + // determino posizioni spostate double dU1 = 1 ; + if ( dAngCen1 > EPS_ANG_SMALL) { + dU1 = 1 - min( 1.1 * dAngDelta / ( dAngCen1 + dAngCen2), 0.5) ; + } double dU2 = 0 ; + if ( dAngCen2 > EPS_ANG_SMALL) { + dU2 = 0 + min( 1.1 * dAngDelta / ( dAngCen1 + dAngCen2), 0.5) ; + } + // eseguo calcolo spostato Point3d ptDummy ; Vector3d vtDir1b ; Vector3d vtDir2b ; - if ( ! MoveParamToAvoidTg( dU1, ICurve::FROM_MINUS, *pCrv1) || - ! pCrv1->GetPointTang( dU1, ICurve::FROM_MINUS, ptDummy, vtDir1b) || - ! MoveParamToAvoidTg( dU2, ICurve::FROM_PLUS, *pCrv2) || + if ( ! pCrv1->GetPointTang( dU1, ICurve::FROM_MINUS, ptDummy, vtDir1b) || ! pCrv2->GetPointTang( dU2, ICurve::FROM_PLUS, ptDummy, vtDir2b)) return false ; if ( ! vtDir1b.GetAngleXY( vtDir2b, dAngDeg)) diff --git a/Point3d.cpp b/Point3d.cpp index 236342d..c115d30 100644 --- a/Point3d.cpp +++ b/Point3d.cpp @@ -133,7 +133,7 @@ Point3d::ToGlob( const Frame3d& frRef) y = ptT.x * frRef.VersX().y + ptT.y * frRef.VersY().y + ptT.z * frRef.VersZ().y + frRef.Orig().y ; z = ptT.x * frRef.VersX().z + ptT.y * frRef.VersY().z + ptT.z * frRef.VersZ().z + frRef.Orig().z ; } - else { + else if ( ! frRef.Orig().IsZero()) { x += frRef.Orig().x ; y += frRef.Orig().y ; z += frRef.Orig().z ; @@ -159,7 +159,7 @@ Point3d::ToLoc( const Frame3d& frRef) y = vtT.x * frRef.VersY().x + vtT.y * frRef.VersY().y + vtT.z * frRef.VersY().z ; z = vtT.x * frRef.VersZ().x + vtT.y * frRef.VersZ().y + vtT.z * frRef.VersZ().z ; } - else { + else if ( ! frRef.Orig().IsZero()) { x -= frRef.Orig().x ; y -= frRef.Orig().y ; z -= frRef.Orig().z ; diff --git a/ProjectCurveSurfTm.cpp b/ProjectCurveSurfTm.cpp new file mode 100644 index 0000000..8eed4df --- /dev/null +++ b/ProjectCurveSurfTm.cpp @@ -0,0 +1,66 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : ProjectCurveSurfTm.cpp Data : 31.08.23 Versione : 2.5h3 +// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh. +// +// +// +// Modifiche : 31.08.23 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "GeoConst.h" +#include "/EgtDev/Include/EGkIntersLineSurfTm.h" +#include "/EgtDev/Include/EGkProjectCurveSurfTm.h" + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, + PNT5AXVECTOR& vPt5ax) +{ + // approssimo la curva con una polilinea entro la metà della tolleranza + PolyLine PL ; + if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) + return false ; + const double MAX_SEG_LEN = 10 ; + if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) + return false ; + + // Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie + Frame3d frRefLine ; + if ( ! frRefLine.Set( ORIG, vtDir)) + return false ; + IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ; + + // Riservo spazio nel vettore risultato + vPt5ax.reserve( PL.GetPointNbr()) ; + + // proietto i punti della polilinea sulla superficie + double dU ; + Point3d ptP ; + bool bFound = PL.GetFirstUPoint( &dU, &ptP) ; + while ( bFound) { + Point3d ptL = GetToLoc( ptP, frRefLine) ; + ILSIVECTOR vIntRes ; + intPLSTM.GetInters( ptL, 1, vIntRes, false) ; + if ( vIntRes.size() > 0) { + int nI = int( vIntRes.size()) - 1 ; + Point3d ptInt ; + if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) + ptInt = vIntRes[nI].ptI2 ; + else + ptInt = vIntRes[nI].ptI ; + Triangle3d trTria ; + if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria)) + return false ; + vPt5ax.emplace_back( ptInt, trTria.GetN(), dU, 1) ; + } + bFound = PL.GetNextUPoint( &dU, &ptP) ; + } + + return true ; +} diff --git a/SfrCreate.cpp b/SfrCreate.cpp index c3daeb9..00392cf 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -124,8 +124,8 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; if ( vtExtr.IsSmall()) vtExtr = Z_AX ; - PtrOwner pCompo1( CreateBasicCurveComposite()) ; - if ( IsNull( pCompo1) || ! pCompo1->AddCurve( Release( pCurve))) + PtrOwner pCompo1 ; + if ( ! pCompo1.Set( ConvertCurveToBasicComposite( Release( pCurve)))) return nullptr ; pCompo1->SetExtrusion( vtExtr) ; // se distanza tra gli estremi minore di due volte il raggio la chiudo, purchè curva abbastanza lunga @@ -154,12 +154,13 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b Vector3d vtSLoc( vtStart) ; vtSLoc.ToLoc( frLoc) ; double dAngEnd ; vtELoc.ToSpherical( nullptr, nullptr, &dAngEnd) ; double dAngStart ; vtSLoc.ToSpherical( nullptr, nullptr, &dAngStart) ; - PtrOwner pClose( GetBiArc( ptEnd, dAngEnd, ptStart, dAngStart, 0.5)) ; - // porto il biarco in globale - pClose->ToGlob( frLoc) ; + PtrOwner pClose( GetBiArc( ptEnd, dAngEnd, ptStart, dAngStart, 0.5)) ; // aggiungo il biarco - if ( ! IsNull( pClose)) + if ( ! IsNull( pClose)) { + // porto il biarco in globale + pClose->ToGlob( frLoc) ; pCompo1->AddCurve( Release( pClose)) ; + } else pCompo1->Close() ; } diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 65d1bf7..1f47f22 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) @@ -540,30 +550,22 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub return nullptr ; if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL)) return nullptr ; - // aggiungo il cap sull'inizio + // calcolo il cap sull'inizio PtrOwner pSci( CreateSurfTriMesh()) ; if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0])) return nullptr ; pSci->Invert() ; - pSTM->DoSewing( *pSci) ; - // aggiungo il cap sulla fine + // calcolo il cap sulla fine PtrOwner pSce( CreateSurfTriMesh()) ; if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1])) return nullptr ; pSce->Invert() ; - pSTM->DoSewing( *pSce) ; + // cucio i tappi all'estrusione + if ( ! pSTM->DoSewing( *pSci) || ! pSTM->DoSewing( *pSce)) + return nullptr ; } // 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 +585,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 +603,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..08db0c7 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 = true ; + 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/SurfBezier.cpp b/SurfBezier.cpp index ef96e0d..228fad5 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -550,7 +550,7 @@ SurfBezier::Clone( void) const bool SurfBezier::CopyFrom( const IGeoObj* pGObjSrc) { - const SurfBezier* pSbz = dynamic_cast( pGObjSrc) ; + const SurfBezier* pSbz = GetBasicSurfBezier( pGObjSrc) ; if ( pSbz == nullptr) return false ; return CopyFrom( *pSbz) ; @@ -822,7 +822,6 @@ SurfBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, d // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -845,7 +844,6 @@ SurfBezier::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; @@ -880,7 +878,6 @@ SurfBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -904,7 +901,6 @@ SurfBezier::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -927,11 +923,14 @@ SurfBezier::ToGlob( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -950,11 +949,14 @@ SurfBezier::ToLoc( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -973,7 +975,6 @@ SurfBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; diff --git a/SurfBezier.h b/SurfBezier.h index f64e5a1..d4d929d 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -177,6 +177,10 @@ inline SurfBezier* CloneBasicSurfBezier( const IGeoObj* pGObj) return nullptr ; return ( static_cast( pGObj->Clone())) ; } inline const SurfBezier* GetBasicSurfBezier( const IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } inline SurfBezier* GetBasicSurfBezier( IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 0fdb481..da62396 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -378,7 +378,7 @@ SurfFlatRegion::Clone( void) const bool SurfFlatRegion::CopyFrom( const IGeoObj* pGObjSrc) { - const SurfFlatRegion* pSfr = dynamic_cast( pGObjSrc) ; + const SurfFlatRegion* pSfr = GetBasicSurfFlatRegion( pGObjSrc) ; if ( pSfr == nullptr) return false ; return CopyFrom( *pSfr) ; @@ -597,7 +597,7 @@ SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const // è il bounding box dei loop esterni for ( auto i : m_vExtInd) { BBox3d b3Tmp ; - if ( m_vpLoop[i]->GetBBox( frCompo, b3Ref, nFlag)) + if ( m_vpLoop[i]->GetBBox( frCompo, b3Tmp, nFlag)) b3Ref.Add( b3Tmp) ; } return ( ! b3Ref.IsEmpty()) ; @@ -625,9 +625,14 @@ SurfFlatRegion::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // ruoto il riferimento return m_frF.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; } @@ -639,6 +644,10 @@ SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou // verifico lo stato if ( m_nStatus != OK || m_vpLoop.empty()) return false ; + // verifico non sia nulla + if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -688,6 +697,10 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico lo stato if ( m_nStatus != OK || m_vpLoop.empty()) return false ; + // verifico validità del piano di specchiatura + if ( vtNorm.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -732,6 +745,10 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector // verifico lo stato if ( m_nStatus != OK || m_vpLoop.empty()) return false ; + // verifico validità dei parametri + if ( vtNorm.IsSmall() || vtDir.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -796,9 +813,18 @@ SurfFlatRegion::ToGlob( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo il riferimento return m_frF.ToGlob( frRef) ; ; } @@ -810,9 +836,18 @@ SurfFlatRegion::ToLoc( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo il riferimento return m_frF.ToLoc( frRef) ; ; } @@ -824,9 +859,18 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dei frame + if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) + return false ; + + // se i due riferimenti coincidono, non devo fare alcunché + if ( AreSameFrame( frOri, frDest)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo il riferimento return m_frF.LocToLoc( frOri, frDest) ; ; } diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index 37d8195..eb29c2d 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -152,12 +152,16 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW //----------------------------------------------------------------------------- inline SurfFlatRegion* CreateBasicSurfFlatRegion( void) - { return (static_cast( CreateGeoObj( SRF_FLATRGN))) ; } + { return ( static_cast( CreateGeoObj( SRF_FLATRGN))) ; } inline SurfFlatRegion* CloneBasicSurfFlatRegion( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != SRF_FLATRGN) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const SurfFlatRegion* GetBasicSurfFlatRegion( const IGeoObj* pGObj) - { return (dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_FLATRGN) + return nullptr ; + return ( static_cast( pGObj)) ; } inline SurfFlatRegion* GetBasicSurfFlatRegion( IGeoObj* pGObj) - { return (dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_FLATRGN) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/SurfFlatRegionBooleans.cpp b/SurfFlatRegionBooleans.cpp index aa92e4d..a06921e 100644 --- a/SurfFlatRegionBooleans.cpp +++ b/SurfFlatRegionBooleans.cpp @@ -27,9 +27,10 @@ bool SurfFlatRegion::Add( const ISurfFlatRegion& Other) { // converto l'altra regione nell'oggetto base - const SurfFlatRegion& SfrOther = dynamic_cast( Other) ; - if ( &SfrOther == nullptr) + const SurfFlatRegion* pSfrOther = GetBasicSurfFlatRegion( &Other) ; + if ( pSfrOther == nullptr) return false ; + const SurfFlatRegion& SfrOther = *pSfrOther ; // verifico che le due regioni giacciano in piani paralleli if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ())) @@ -110,9 +111,10 @@ bool SurfFlatRegion::Subtract( const ISurfFlatRegion& Other) { // converto l'altra regione nell'oggetto base - const SurfFlatRegion& SfrOther = dynamic_cast( Other) ; - if ( &SfrOther == nullptr) + const SurfFlatRegion* pSfrOther = GetBasicSurfFlatRegion( &Other) ; + if ( pSfrOther == nullptr) return false ; + const SurfFlatRegion& SfrOther = *pSfrOther ; // verifico che le due regioni giacciano in piani paralleli if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ())) @@ -197,9 +199,10 @@ bool SurfFlatRegion::Intersect( const ISurfFlatRegion& Other) { // converto l'altra regione nell'oggetto base - const SurfFlatRegion& SfrOther = dynamic_cast( Other) ; - if ( &SfrOther == nullptr) + const SurfFlatRegion* pSfrOther = GetBasicSurfFlatRegion( &Other) ; + if ( pSfrOther == nullptr) return false ; + const SurfFlatRegion& SfrOther = *pSfrOther ; // verifico che le due regioni giacciano in piani paralleli if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ())) @@ -355,9 +358,10 @@ SurfFlatRegion::MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) // recupero le curve e le inserisco nella nuova curva composita for ( auto i : vIds) { // la aggiungo alla curva composta - if ( ! pCrvCompo->AddCurve( vpCurve[i-1], true, dToler)) - return false ; + bool bOk = pCrvCompo->AddCurve( vpCurve[i-1], true, dToler) ; vpCurve[i-1] = nullptr ; + if ( ! bOk) + return false ; } // aggiorno il nuovo punto vicino if ( pCrvCompo->GetCurveCount() > 0) diff --git a/SurfFlatRegionOffset.cpp b/SurfFlatRegionOffset.cpp index a54fc51..92846c9 100644 --- a/SurfFlatRegionOffset.cpp +++ b/SurfFlatRegionOffset.cpp @@ -13,6 +13,8 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" +#include "GeoConst.h" +#include "CurveComposite.h" #include "SurfFlatRegion.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" @@ -55,12 +57,15 @@ SurfFlatRegion::Offset( double dDist, int nType) // recupero le curve di offset PtrOwner pOffs( OffsCrv.GetLongerCurve()) ; while ( bOk && ! IsNull( pOffs)) { - if( pOffs->GetType() == CRV_COMPO) { - PtrOwner pOffsCompo( CloneCurveComposite( pOffs)) ; + if ( pOffs->GetType() == CRV_COMPO) { + CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ; + // assegno proprietà pOffsCompo->SetTempProp( j, 1) ; - for( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k) + for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k) pOffsCompo->SetCurveTempProp( k, j, 1) ; - pOffs.Set( pOffsCompo) ; + // unisco parti allineate + if ( ! pOffsCompo->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, true)) + return false ; } else pOffs->SetTempProp( j, 1) ; diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 75de929..76ad9e9 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -121,6 +121,27 @@ SurfTriMesh::AddVertex( const Point3d& ptVert) return int( m_vVert.size() - 1) ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::MoveVertex( int nInd, const Point3d& ptNewVert) +{ + // verifico validità indice + if ( nInd < 0 || nInd >= int( m_vVert.size())) + return false ; + // verifico non sia già cancellato + if ( m_vVert[nInd].nIdTria == SVT_DEL) + return false ; + // sposto il vertice + m_vVert[nInd].ptP = ptNewVert ; + // imposto ricalcolo + m_nStatus = TO_VERIFY ; + m_nParts = - 1 ; + m_OGrMgr.Reset() ; + ResetHashGrids3d() ; + // per aggiornare completamente la superficie chiamare DoCompacting + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::SetVertex( int nInd, const StmVert& vV) @@ -758,23 +779,23 @@ SurfTriMesh::GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const //---------------------------------------------------------------------------- bool -SurfTriMesh::GetTriangleFlag( int nId, int& nFlag) const +SurfTriMesh::GetTFlag( int nTriaId, int& nTFlag) const { // verifico esistenza del triangolo - if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nTriaId < 0 || nTriaId >= GetTriangleSize() || m_vTria[nTriaId].nIdVert[0] == SVT_DEL) return false ; - nFlag = m_vTria[nId].nTFlag ; + nTFlag = m_vTria[nTriaId].nTFlag ; return true ; } //---------------------------------------------------------------------------- bool -SurfTriMesh::GetTriangleTempInt( int nId, int& nTempInt) const +SurfTriMesh::GetTempInt( int nTriaId, int& nTempInt) const { // verifico esistenza del triangolo - if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nTriaId < 0 || nTriaId >= GetTriangleSize() || m_vTria[nTriaId].nIdVert[0] == SVT_DEL) return false ; - nTempInt = m_vTria[nId].nTemp ; + nTempInt = m_vTria[nTriaId].nTemp ; return true ; } @@ -1199,7 +1220,7 @@ SurfTriMesh::Clone( void) const bool SurfTriMesh::CopyFrom( const IGeoObj* pGObjSrc) { - const SurfTriMesh* pStm = dynamic_cast( pGObjSrc) ; + const SurfTriMesh* pStm = GetBasicSurfTriMesh( pGObjSrc) ; if ( pStm == nullptr) return false ; return CopyFrom( *pStm) ; @@ -2950,14 +2971,13 @@ SurfTriMesh::DoCompacting( double dTol) // sistemo gli indici dei vertici nei triangoli for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) { - // recupero gli indici dei vertici del triangolo - int vOId[3] ; - vOId[0] = m_vTria[nId].nIdVert[0] ; - vOId[1] = m_vTria[nId].nIdVert[1] ; - vOId[2] = m_vTria[nId].nIdVert[2] ; // salto i triangoli cancellati - if ( vOId[0] == SVT_DEL) + if ( m_vTria[nId].nIdVert[0] == SVT_DEL) continue ; + // recupero gli indici dei vertici del triangolo + int vOId[3]{ m_vTria[nId].nIdVert[0], + m_vTria[nId].nIdVert[1], + m_vTria[nId].nIdVert[2]} ; // verifico la validità degli indici if ( vOId[0] < 0 || vOId[0] >= nVIdSize || vOId[1] < 0 || vOId[1] >= nVIdSize || @@ -2967,11 +2987,12 @@ SurfTriMesh::DoCompacting( double dTol) m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ; m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ; m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ; - // se due vertici coincidono, cancello il triangolo + // se due vertici coincidono o la normale non è calcolabile, cancello il triangolo if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] || m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] || - m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) - RemoveTriangle( nId) ; + m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] || + ! CalcTriangleNormal( nId)) + RemoveTriangle( nId) ; } // compatto il vettore dei vertici @@ -2992,7 +3013,7 @@ bool SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, double dTol) { // recupero l'altra superficie - const SurfTriMesh* pOther = dynamic_cast( &stmOther) ; + const SurfTriMesh* pOther = GetBasicSurfTriMesh( &stmOther) ; if ( pOther == nullptr) return false ; @@ -3003,7 +3024,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) @@ -3284,7 +3305,6 @@ SurfTriMesh::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -3317,7 +3337,6 @@ SurfTriMesh::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -3349,11 +3368,14 @@ SurfTriMesh::ToGlob( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica e di hashgrids3d m_OGrMgr.Reset() ; ResetHashGrids3d() ; @@ -3380,11 +3402,14 @@ SurfTriMesh::ToLoc( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica e di hashgrids3d m_OGrMgr.Reset() ; ResetHashGrids3d() ; @@ -3411,7 +3436,6 @@ SurfTriMesh::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; @@ -3662,7 +3686,7 @@ SurfTriMesh::ResetTFlags( void) //---------------------------------------------------------------------------- bool -SurfTriMesh::ResetTempInt( void) const +SurfTriMesh::ResetTempInts( void) const { for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) m_vTria[i].nTemp = 0 ; diff --git a/SurfTriMesh.h b/SurfTriMesh.h index f5fa0d2..6ae2946 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2022 +// EgalTech 2014-2023 //---------------------------------------------------------------------------- -// File : SurfTriMesh.h Data : 10.10.22 Versione : 2.4i4 +// File : SurfTriMesh.h Data : 07.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe Superficie TriMesh. // // @@ -216,6 +216,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; m_OGrMgr.Reset() ; } int AddVertex( const Point3d& ptVert) override ; + bool MoveVertex( int nInd, const Point3d& ptNewVert) override ; int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ; bool RemoveTriangle( int nId) override ; bool AdjustTopology( void) override ; @@ -266,6 +267,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW { return int( m_vFacet.size()) ; } int GetFacetFromTria( int nT) const override ; bool GetAllTriaInFacet( int nF, INTVECTOR& vT) const override ; + bool GetAllVertInFacet( int nF, INTVECTOR& vVert) const override ; bool GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const override ; bool GetFacetAdjacencies( int nF, INTMATRIX& vAdj) const override ; bool GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const override ; @@ -315,9 +317,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool ExistsTriangle( int nT) const { return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; } bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ; - bool GetTriangleFlag( int nId, int& nFlag) const ; - bool GetTriangleTempInt( int nId, int& nTempInt) const ; - bool ResetTempInt( void) const ; + bool GetTFlag( int nId, int& nFlag) const ; + bool GetTempInt( int nId, int& nTempInt) const ; + bool ResetTempInts( void) const ; bool SetTFlag( int nId, int nTFlag) ; bool SetTempInt( int nId, int nTempInt) const ; @@ -360,7 +362,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 ; @@ -412,6 +414,10 @@ inline SurfTriMesh* CloneBasicSurfTriMesh( const IGeoObj* pGObj) return nullptr ; return ( static_cast( pGObj->Clone())) ; } inline const SurfTriMesh* GetBasicSurfTriMesh( const IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH) + return nullptr ; + return ( static_cast( pGObj)) ; } inline SurfTriMesh* GetBasicSurfTriMesh( IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index b8a27ad..c3dfa8e 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]) ; @@ -1448,8 +1441,18 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) if ( ! IsValid() || ! Other.IsValid()) return false ; + // Se la seconda è vuota non devo fare alcunchè + if ( Other.IsEmpty()) + return true ; + m_OGrMgr.Clear() ; + // Se la prima è vuota, copio la seconda nella prima + if ( IsEmpty()) { + CopyFrom( &Other) ; + return true ; + } + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; @@ -1508,8 +1511,20 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) if ( ! IsValid() || ! Other.IsValid()) return false ; + // Se la prima è vuota non devo fare alcunchè + if ( IsEmpty()) + return true ; + m_OGrMgr.Clear() ; + // Se la seconda è vuota, basta vuotare la prima + if ( Other.IsEmpty()) { + Clear() ; + m_bOriented = true ; + m_bClosed = true ; + return true ; + } + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; @@ -1568,6 +1583,10 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) if ( ! IsValid() || ! Other.IsValid()) return false ; + // Se una delle due è vuota non devo fare alcunchè + if ( IsEmpty() || Other.IsEmpty()) + return true ; + m_OGrMgr.Clear() ; SurfTriMesh SurfB ; @@ -1616,7 +1635,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 ; } @@ -1678,6 +1697,10 @@ SurfTriMesh::CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bo if ( ! IsValid() || ! CutterSurf.IsValid()) return false ; + // Se una delle due è vuota non devo fare alcunchè + if ( IsEmpty() || CutterSurf.IsEmpty()) + return true ; + m_OGrMgr.Clear() ; SurfTriMesh SurfC ; @@ -1750,7 +1773,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 ; } diff --git a/SurfTriMeshCuts.cpp b/SurfTriMeshCuts.cpp index 8bfda97..7e8991c 100644 --- a/SurfTriMeshCuts.cpp +++ b/SurfTriMeshCuts.cpp @@ -32,10 +32,14 @@ const double CUT_SCALE = 1024 ; bool SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) { - // la superficie deve essere validata + // La superficie deve essere validata if ( m_nStatus != OK) return false ; + // Se la superficie è vuota non devo fare alcunchè + if ( IsEmpty()) + return true ; + // recupero il numero originale di triangoli e di facce int nTriaOriCnt = GetTriangleCount() ; int nFacetOriCnt = GetFacetCount() ; @@ -354,6 +358,10 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) if ( ! cvCurve.GetExtrusion( vtExtr) || vtExtr.IsSmall() || ! cvCurve.IsClosed()) return false ; + // Se la superficie è vuota non devo fare alcunchè + if ( IsEmpty()) + return true ; + // Recupero il numero originale di triangoli e di facce int nTriaOriCnt = GetTriangleCount() ; int nFacetOriCnt = GetFacetCount() ; @@ -367,7 +375,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) } // Eseguo scalature - Frame3d frScalingRef; + Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ; cvCompo.Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index 363325b..ce55f56 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,57 @@ 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 ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetAllVertInFacet( int nF, INTVECTOR& vVert) const +{ + // recupero tutti i triangoli della faccia + INTVECTOR vTria ; + if ( ! GetAllTriaInFacet( nF, vTria)) + return false ; + // ne ricavo i vertici + vVert.clear() ; + INTUNORDSET usTempVert ; + for ( int nT : vTria) { + for ( int i = 0 ; i < 3 ; ++ i) { + int nV = m_vTria[nT].nIdVert[i] ; + if ( usTempVert.find( nV) == usTempVert.end()) { + usTempVert.insert( nV) ; + vVert.push_back( nV) ; + } + } + } + return true ; } diff --git a/Tool.cpp b/Tool.cpp index eac5034..46b5756 100644 --- a/Tool.cpp +++ b/Tool.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2022 +// EgalTech 2015-2023 //---------------------------------------------------------------------------- -// File : Tool.cpp Data : 04.07.18 Versione : 2.4f3 +// File : Tool.cpp Data : 08.09.23 Versione : 2.5i1 // Contenuto : Implementazione della classe Tool // // @@ -87,6 +87,8 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, if ( dH < EPS_SMALL || dR < EPS_SMALL || dCornR < - EPS_SMALL) return false ; + bool bApproxWithLines = false ; + // utensile cilindrico if ( dCornR < EPS_SMALL) { m_nType = CYLMILL ; @@ -126,9 +128,8 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, m_Outline.AddLine( pt2); m_Outline.AddArcTg( pt3) ; m_Outline.AddLine( pt4) ; - // se da approosimare - if ( m_bApproxWithLines) - return SetGenTool( sToolName, &m_Outline, nToolNum) ; + // se da approssimare + bApproxWithLines = m_bApproxWithLines ; } // utensile sferico else { @@ -151,7 +152,7 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, } // eventuali sistemazioni per altezza tagliente - if ( ModifyForCutterHeight()) + if ( ModifyForCutterHeight() || bApproxWithLines) return SetGenTool( sToolName, &m_Outline, nToolNum) ; else return true ; @@ -381,7 +382,7 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR, } // altrimenti con raggio corner else { - double dCR = Clamp( dCornR, 0., dThick / 2) ; + double dCR = Clamp( dCornR, 0., min( dThick / 2, dR - 10 * EPS_SMALL)) ; // creazione profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt1) ; @@ -410,7 +411,7 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR, } // altrimenti con raggio corner else { - double dCR = Clamp( dCornR, 0., dThick / 2) ; + double dCR = Clamp( dCornR, 0., min( dThick / 2, dR - 10 * EPS_SMALL)) ; // creazione profilo m_Outline.AddPoint( pt0) ; m_Outline.AddLine( pt3 - X_AX * dCR) ; diff --git a/VolZmap.cpp b/VolZmap.cpp index 7630931..481095d 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -108,7 +108,7 @@ VolZmap::Clone( void) const bool VolZmap::CopyFrom( const IGeoObj* pGObjSrc) { - const VolZmap* pVzm = dynamic_cast( pGObjSrc) ; + const VolZmap* pVzm = GetBasicVolZmap( pGObjSrc) ; if ( pVzm == nullptr) return false ; return CopyFrom( *pVzm) ; @@ -208,7 +208,7 @@ VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const } sOut += szNewLine ; // passo - sOut += "Step=" + ToString( GetInUiUnits( m_dStep, bMM), 3) + szNewLine ; + sOut += "Step=" + ToString( GetInUiUnits( m_dStep, bMM), 6) + szNewLine ; // dimensioni if ( m_nMapNum == 1) sOut += "Dim=" + ToString( m_nDim[0]) + @@ -630,8 +630,10 @@ VolZmap::Translate( const Vector3d& vtMove) // verifico lo stato if ( m_nStatus != OK) return false ; + // imposto ricalcolo della grafica ResetGraphics() ; + // traslo il riferimento m_MapFrame.Translate( vtMove) ; return true ; @@ -644,8 +646,13 @@ VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetGraphics() ; + // ruoto il riferimento m_MapFrame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; return true ; @@ -658,6 +665,10 @@ VolZmap::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCo // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico non sia nulla + if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) + return false ; + return false ; } @@ -668,6 +679,10 @@ VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del piano di specchiatura + if ( vtNorm.IsSmall()) + return false ; + return false ; } @@ -678,6 +693,10 @@ VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dei parametri + if ( vtNorm.IsSmall() || vtDir.IsSmall()) + return false ; + return false ; } @@ -688,8 +707,17 @@ VolZmap::ToGlob( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetGraphics() ; + // trasformo il riferimento m_MapFrame.ToGlob( frRef) ; return true ; @@ -702,8 +730,17 @@ VolZmap::ToLoc( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetGraphics() ; + // trasformo il riferimento m_MapFrame.ToLoc( frRef) ; return true ; @@ -716,8 +753,17 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dei frame + if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) + return false ; + + // se i due riferimenti coincidono, non devo fare alcunché + if ( AreSameFrame( frOri, frDest)) + return true ; + // imposto ricalcolo della grafica ResetGraphics() ; + // trasformo il riferimento m_MapFrame.LocToLoc( frOri, frDest) ; return true ; @@ -1938,6 +1984,11 @@ VolZmap::CalcBlockNum( void) if ( m_nMapNum == 1) { m_nFracLin[2] = 1 ; m_nNumBlock = m_nFracLin[0] * m_nFracLin[1] * m_nFracLin[2] ; + m_BlockToUpdate.clear() ; + m_BlockToUpdate.resize( m_nNumBlock, true) ; + m_BlockUpdatingCounter.clear() ; + m_BlockUpdatingCounter.resize( m_nNumBlock, 0) ; + m_SingleMapTria.resize( m_nNumBlock) ; return true ; } // Calcolo il numero di voxel lungo Z @@ -1949,7 +2000,7 @@ VolZmap::CalcBlockNum( void) m_BlockToUpdate.clear() ; m_BlockToUpdate.resize( m_nNumBlock, true) ; m_BlockUpdatingCounter.clear() ; - m_BlockUpdatingCounter.resize( m_nNumBlock + ( m_nMapNum == 1 ? 0 : 1), 0) ; + m_BlockUpdatingCounter.resize( m_nNumBlock + 1, 0) ; // Dimensiono raccolta di voxel, triangoli di feature tra blocchi e di segnalatori di materiale fra voxel m_InterBlockVox.resize( m_nNumBlock) ; diff --git a/VolZmap.h b/VolZmap.h index 6df1369..8361860 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2020 +// EgalTech 2015-2023 //---------------------------------------------------------------------------- -// File : VolZmap.h Data : 12.05.19 Versione : 2.2k1 +// File : VolZmap.h Data : 12.09.23 Versione : 2.5i1 // Contenuto : Dichiarazione della classe Volume Zmap. // // // // Modifiche : 22.01.15 DS Creazione modulo. -// +// 12.09.23 DS Aggiunto metodo IsTriDexel. // //---------------------------------------------------------------------------- @@ -77,6 +77,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ; bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ; bool GetVolume( double& dVol) const override ; + bool IsTriDexel( void) const override + { return m_nMapNum == 3 ; } bool GetDexelLines( int nDir, int nPos1, int nPos2, POLYLINELIST& lstPL) const override ; int GetResolution( void) const override { return m_nDexVoxRatio ; } @@ -394,9 +396,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY, double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise = false) const ; bool AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise = false) const ; - // Funzioni ausiliarie per metodi avoid - bool SingleMapDexelConeCollision( int nStI, int nEnI, int nStJ, int nEnJ, const Point3d& ptRefPoint, const Vector3d& vtRefAx, - double dMinRad, double dMaxRad, double dHeight, double dMinBoxH, double dMaxBoxH) const ; // Funzione per crezione solido in parallelo bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; @@ -469,16 +468,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW //----------------------------------------------------------------------------- inline VolZmap* CreateBasicVolZmap( void) - { return (static_cast( CreateGeoObj( VOL_ZMAP))) ; } + { return ( static_cast( CreateGeoObj( VOL_ZMAP))) ; } inline VolZmap* CloneBasicVolZmap( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const VolZmap* GetBasicVolZmap( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; - return (static_cast(pGObj)) ; } + return ( static_cast( pGObj)) ; } inline VolZmap* GetBasicVolZmap( IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; - return (static_cast(pGObj)) ; } + return ( static_cast( pGObj)) ; } diff --git a/VolZmapCalculus.cpp b/VolZmapCalculus.cpp index 9f4f8cd..a4db450 100644 --- a/VolZmapCalculus.cpp +++ b/VolZmapCalculus.cpp @@ -17,6 +17,9 @@ #include "VolZmap.h" #include "GeoConst.h" #include "IntersLineBox.h" +#include "IntersLineCyl.h" +#include "IntersLineCone.h" +#include "IntersLineCaps.h" #include "IntersLineSurfStd.h" #include "/EgtDev/Include/EGkIntersLineTria.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" @@ -411,21 +414,24 @@ 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 ; // Se verifico solo prima mappa - if ( ! bPrecise) { + if ( ! bPrecise || m_nMapNum == 1) { // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nNx[0] - 1) ; @@ -434,32 +440,31 @@ 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) { 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) + if ( nSize == 0 || + m_Values[0][nPos][0].dMin > b3Int.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z) 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) { @@ -503,10 +508,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) ; @@ -653,7 +658,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise) return true ; // Se verifico solo prima mappa - if ( ! bPrecise) { + if ( ! bPrecise || m_nMapNum == 1) { // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nNx[0] - 1) ; @@ -666,7 +671,9 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise) 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) + if ( nSize == 0 || + m_Values[0][nPos][0].dMin > b3Int.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z) continue ; if ( m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z || m_Values[0][nPos][0].dMin > b3Int.GetMax().z) continue ; @@ -780,37 +787,45 @@ 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 - if ( ! bPrecise) { + if ( ! bPrecise || m_nMapNum == 1) { // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nNx[0] - 1) ; @@ -818,29 +833,36 @@ 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) { int nPos = j * m_nNx[0] + i ; int nSize = int( m_Values[0][nPos].size()) ; - if ( nSize == 0) + if ( nSize == 0 || + m_Values[0][nPos][0].dMin > b3Int.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z) 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 = 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, frC, 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) @@ -856,6 +878,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 ; @@ -880,6 +903,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) ; @@ -894,27 +922,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, frC, 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 ; @@ -933,346 +947,192 @@ 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 ; return true ; } -//---------------------------------------------------------------------------- -bool -VolZmap::SingleMapDexelConeCollision( int nStI, int nEnI, int nStJ, int nEnJ, const Point3d& ptRefPoint, const Vector3d& vtRefAx, - double dMinRad, double dMaxRad, double dHeight, double dMinBoxH, double dMaxBoxH) const -{ - // Ciclo di intersezione dei dexel con il 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 ; - double dParMin = m_Values[0][nPos][0].dMin ; - double dParMax = m_Values[0][nPos][nSize-1].dMax ; - if ( dParMax < dMinBoxH || dParMin > dMaxBoxH) - continue ; - for ( int k = 0 ; k < 5 ; ++ k) { - // se richiesta interruzione, esco - if ( m_bBreak) - return false ; - // Calcolo spillone - Point3d ptLineSt = ORIG + ( i + 0.5) * m_dStep * X_AX + ( j + 0.5) * m_dStep * Y_AX ; - switch ( k) { - case 0 : break ; - case 1 : ptLineSt += -0.4 * m_dStep * X_AX - 0.4 * m_dStep * Y_AX ; break ; - case 2 : ptLineSt += +0.4 * m_dStep * X_AX - 0.4 * m_dStep * Y_AX ; break ; - case 3 : ptLineSt += +0.4 * m_dStep * X_AX + 0.4 * m_dStep * Y_AX ; break ; - case 4 : ptLineSt += -0.4 * m_dStep * X_AX + 0.4 * m_dStep * Y_AX ; break ; - } - // Cono proprio - if ( dMinRad < EPS_SMALL) { - Point3d ptSegSt = ptLineSt + dParMin * Z_AX ; - double dU1, dU2 ; - int nIntType = SegmentCone( ptSegSt, Z_AX, dParMax - dParMin, ptRefPoint, vtRefAx, - dMaxRad, dHeight, dU1, dU2) ; - if ( nIntType == LinCompCCIntersType::CC_ERROR_INT) - return true ; - else if ( nIntType != LinCompCCIntersType::CC_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - if ( m_Values[0][nPos][nIndex].dMax >= dU1 && m_Values[0][nPos][nIndex].dMin <= dU2) - return true ; - } - } - nIntType = SegmentDisc( ptSegSt, Z_AX, dParMax - dParMin, ptRefPoint + dHeight * vtRefAx, - vtRefAx, dMaxRad, dU1, dU2) ; - if ( nIntType == LinCompDiscIntersType::D_ERROR_INT) - return true ; - else if ( nIntType != LinCompDiscIntersType::D_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - if ( m_Values[0][nPos][nIndex].dMax >= dU1 && m_Values[0][nPos][nIndex].dMin <= dU2) - return true ; - } - } - } - // Tronco di cono - else { - Point3d ptSegSt = ptLineSt + dParMin * Z_AX ; - double dU1, dU2 ; - int nIntType = SegmentConeFrustum( ptSegSt, Z_AX, dParMax - dParMin, ptRefPoint, vtRefAx, - dMinRad, dMaxRad, dHeight, dU1, dU2) ; - if ( nIntType == LinCompCCIntersType::CC_ERROR_INT) - return true ; - else if ( nIntType != LinCompCCIntersType::CC_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - if ( m_Values[0][nPos][nIndex].dMax >= dU1 && m_Values[0][nPos][nIndex].dMin <= dU2) - return true ; - } - } - nIntType = SegmentDisc( ptSegSt, Z_AX, dParMax - dParMin, ptRefPoint + dHeight * vtRefAx, - vtRefAx, dMaxRad, dU1, dU2) ; - if ( nIntType == LinCompDiscIntersType::D_ERROR_INT) - return true ; - else if ( nIntType != LinCompDiscIntersType::D_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - if ( m_Values[0][nPos][nIndex].dMax >= dU1 && m_Values[0][nPos][nIndex].dMin <= dU2) - return true ; - } - } - nIntType = SegmentDisc( ptSegSt, Z_AX, dParMax - dParMin, ptRefPoint, vtRefAx, dMinRad, dU1, dU2) ; - if ( nIntType == LinCompDiscIntersType::D_ERROR_INT) - return true ; - else if ( nIntType != LinCompDiscIntersType::D_NO_INTERS) { - for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - if ( m_Values[0][nPos][nIndex].dMax >= dU1 && m_Values[0][nPos][nIndex].dMin <= dU2) - return true ; - } - } - } - } - } - } - - return false ; -} - //---------------------------------------------------------------------------- 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 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 BBox3d b3Int ; - if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) + if ( ! b3Zmap.FindIntersection( b3Cone, b3Int)) return true ; // Uso solo la prima mappa - if ( ! bPrecise) { + if ( ! bPrecise || m_nMapNum == 1) { // 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) ; - // 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 || + m_Values[0][nPos][0].dMin > b3Int.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z) + 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 ; } } @@ -1286,7 +1146,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, @@ -1381,150 +1241,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 ; } //---------------------------------------------------------------------------- @@ -1534,19 +1272,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) @@ -1559,78 +1295,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 ; } //---------------------------------------------------------------------------- @@ -1638,39 +1383,58 @@ 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 ; - if ( ! bPrecise) { - // Limiti su indici + // 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( b3Prism, b3Int)) + return true ; + + // Se verifico solo prima mappa + if ( ! bPrecise || m_nMapNum == 1) { + // 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 ; int nSize = int( m_Values[0][nPos].size()) ; - if ( nSize == 0) + if ( nSize == 0 || + m_Values[0][nPos][0].dMin > b3Int.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z) continue ; double dParMin = m_Values[0][nPos][0].dMin ; double dParMax = m_Values[0][nPos][nSize-1].dMax ; @@ -1688,7 +1452,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) @@ -1699,12 +1463,14 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX } } } + + // altrimenti verifico con tutte e tre le mappe 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 +1483,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 +1492,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 +1519,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) @@ -1798,6 +1564,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 ; @@ -1893,40 +1660,48 @@ 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 - if ( ! bPrecise) { + if ( ! bPrecise || m_nMapNum == 1) { // 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) ; @@ -1937,7 +1712,9 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa 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) + if ( nSize == 0 || + m_Values[0][nPos][0].dMin > b3Int.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3Int.GetMin().z) continue ; double dParMin = m_Values[0][nPos][0].dMin ; double dParMax = m_Values[0][nPos][nSize-1].dMax ; @@ -2070,124 +1847,123 @@ VolZmap::AvoidTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise) const { - // Controllo sulla validità della superficie ed eventualmente sulla sua chiusura + // Controllo sulla validità della superficie ed eventualmente sulla sua chiusura if ( ! ( tmSurf.IsValid() && tmSurf.IsClosed())) return false ; - // Bounding box della superficie espresso nel sistema locale + // Bounding box della superficie espresso nel sistema locale BBox3d b3SurfBox ; tmSurf.GetLocalBBox( b3SurfBox) ; - // Se la distanza di sicurezza è significativa, espando il box - if ( dSafeDist > EPS_SMALL ) - b3SurfBox.Expand( dSafeDist) ; - // Box dello Zmap nel suo sistema locale + // Box dello Zmap nel suo sistema locale BBox3d b3ZmapBox( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; b3ZmapBox.ToGlob( m_MapFrame) ; - // Box intersezione: se non c'è intersezione ho finito. + // Se la distanza di sicurezza è significativa, espando il box + if ( dSafeDist > EPS_SMALL ) + b3ZmapBox.Expand( dSafeDist) ; + // Box intersezione: se non c'è intersezione ho finito. BBox3d b3IntBox ; if ( ! b3ZmapBox.FindIntersection( b3SurfBox, b3IntBox)) return true ; - // Recupero i triangoli della superficie che cadono nel box intersezione. + // Recupero i triangoli della superficie che cadono nel box intersezione. INTVECTOR vTriaIndex ; tmSurf.GetAllTriaOverlapBox( b3IntBox, vTriaIndex) ; - // Non è richeista precisione - if ( ! bPrecise) { - // Ciclo sui triangoli che cadono nel box + + // Se verifico solo prima mappa + if ( ! bPrecise || m_nMapNum == 1) { + // Vettore direzione dei dexel nel riferimento locale Zmap + Vector3d vtK = GetToGlob( Z_AX, m_MapFrame) ; + // Riferimento intrinseco dei dexel nel riferimento locale Zmap + Point3d ptO = GetToGlob( ORIG, m_MapFrame) ; + Vector3d vtX = GetToGlob( X_AX, m_MapFrame) ; + Vector3d vtY = GetToGlob( Y_AX, m_MapFrame) ; + // Ciclo sui triangoli che cadono nel box for ( int nT : vTriaIndex) { Triangle3d trTria ; if ( ! ( tmSurf.GetTriangle( nT, trTria) && trTria.Validate())) continue ; BBox3d b3TriaBox ; trTria.GetLocalBBox( b3TriaBox) ; - // 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) b3TriaBox.Expand( dSafeDist) ; - // Porto il bounding-box del triangolo nel sistema intrinseco. + // Copia del triangolo con eventuale traslazione + Triangle3d trNewTria = trTria ; + if ( dSafeDist > EPS_SMALL) + trNewTria.Translate( dSafeDist * trTria.GetN()) ; + // Porto il bounding-box del triangolo nel sistema intrinseco. b3TriaBox.ToLoc( m_MapFrame) ; - // Limiti su indici + // Limiti su indici int nStI = Clamp( int( b3TriaBox.GetMin().x / m_dStep), 0, m_nNx[0] - 1) ; int nEnI = Clamp( int( b3TriaBox.GetMax().x / m_dStep), 0, m_nNx[0] - 1) ; int nStJ = Clamp( int( b3TriaBox.GetMin().y / m_dStep), 0, m_nNy[0] - 1) ; int nEnJ = Clamp( int( b3TriaBox.GetMax().y / m_dStep), 0, m_nNy[0] - 1) ; - // Ciclo di intersezione dei dexel con il toro (nel riferimento intrinseco) + // Ciclo di intersezione dei dexel con il triangolo (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) + if ( nSize == 0 || + m_Values[0][nPos][0].dMin > b3TriaBox.GetMax().z || + m_Values[0][nPos][nSize-1].dMax < b3TriaBox.GetMin().z) continue ; for ( int k = 0 ; k < 5 ; ++ k) { - Point3d ptLineSt = ORIG + ( i + 0.5) * m_dStep * X_AX + ( j + 0.5) * m_dStep * Y_AX ; - if ( k == 0) - ; - else if ( k == 1) - ptLineSt += - 0.4 * m_dStep * X_AX - 0.4 * m_dStep * Y_AX ; - else if ( k == 2) - ptLineSt += + 0.4 * m_dStep * X_AX - 0.4 * m_dStep * Y_AX ; - else if ( k == 3) - ptLineSt += + 0.4 * m_dStep * X_AX + 0.4 * m_dStep * Y_AX ; - else if ( k == 4) - ptLineSt += - 0.4 * m_dStep * X_AX + 0.4 * m_dStep * Y_AX ; - Vector3d vtLineDir = Z_AX ; - // Porto punto iniziale e vettore nel sistema locale - ptLineSt.ToGlob( m_MapFrame) ; - vtLineDir.ToGlob( m_MapFrame) ; - for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { - // Segmento ormai nel sistema locale - Point3d ptSegSt = ptLineSt + m_Values[0][nPos][nIndex].dMin * vtLineDir ; - double dSegLen = m_Values[0][nPos][nIndex].dMax - m_Values[0][nPos][nIndex].dMin ; - // Copia del triangolo che può essere evenutalmente traslata - Triangle3d trNewTria = trTria ; - // Se la distanza di sicurezza è significativa - if ( dSafeDist > EPS_SMALL) { - // Valuto sfere nei vertici e cilindri lungo gli edge. - for ( int nV = 0 ; nV < 3 ; ++ nV) { - Point3d ptVertP = trTria.GetP( nV) ; - Vector3d vtEdgeV = trTria.GetP( ( nV + 1)) - ptVertP ; - double dEdgeLen = vtEdgeV.Len() ; - vtEdgeV /= dEdgeLen ; - double dU1, dU2 ; - int nIntersType = SegmentSphere( ptSegSt, vtLineDir, dSegLen, ptVertP, dSafeDist, dU1, dU2) ; - if ( nIntersType != LinCompSphereIntersType::S_NO_INTERS) - return false ; - nIntersType = IntersSegmentCylinder( ptSegSt, vtLineDir, dSegLen, ptVertP, vtEdgeV, - dSafeDist, dEdgeLen, dU1, dU2) ; - if ( nIntersType != LinCompCCIntersType::CC_NO_INTERS ) - return false ; + 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 ; + } + // Se la distanza di sicurezza è significativa + if ( dSafeDist > EPS_SMALL) { + // Intersezione della linea con i capsule dei lati + for ( int nV = 0 ; nV < 3 ; ++ nV) { + double dZmin, dZmax ; + if ( IntersLineCaps( ptT, vtK, trTria.GetP( nV), trTria.GetP( ( nV + 1) % 3), dSafeDist, 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 ; + } } - // Traslo il triangolo. - trNewTria.Translate( dSafeDist * trTria.GetN()) ; } - // Intersezione segento triangolo - Point3d ptInt, ptInt2 ; - int nIntersType = IntersLineTria( ptSegSt, vtLineDir, dSegLen, trNewTria, ptInt, ptInt2) ; - // Collisione - if ( nIntersType != IntLineTriaType::ILTT_NO) - return false ; + } + // Intersezione della linea con triangolo eventualmente offsettato + Point3d ptInt, ptInt2 ; + if ( IntersLineTria( ptT, vtK, 1, trNewTria, ptInt, ptInt2, false) != IntLineTriaType::ILTT_NO) { + double dZmin = ( ptInt - ptT) * vtK ; + double dZmax = ( ptInt2 - ptT) * vtK ; + 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 ; + } } } } } } } - // È richiesta precisione + + // altrimenti verifico con tutte e tre le mappe else { - // Ciclo sui triangoli che cadono nel box + // Ciclo sui triangoli che cadono nel box for ( int nT : vTriaIndex) { Triangle3d trTria ; if ( ! ( tmSurf.GetTriangle( nT, trTria) && trTria.Validate())) continue ; BBox3d b3TriaBox ; trTria.GetLocalBBox( b3TriaBox) ; - // 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) b3TriaBox.Expand( dSafeDist) ; - // Porto il bounding-box del triangolo nel sistema intrinseco. + // Porto il bounding-box del triangolo nel sistema intrinseco. b3TriaBox.ToLoc( m_MapFrame) ; - // Ciclo sulle mappe + // Ciclo sulle mappe for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) { Point3d ptInfIntBox = b3TriaBox.GetMin() ; Point3d ptSupIntBox = b3TriaBox.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) ; @@ -2200,24 +1976,24 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis 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) ; int nEnJ = Clamp( int( ptSupIntBox.y / m_dStep), 0, m_nNy[nMap] - 1) ; for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) { - // 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) ; @@ -2230,22 +2006,22 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis swap( vtLineDir.x, vtLineDir.y) ; swap( vtLineDir.y, vtLineDir.z) ; } - // Porto punto iniziale e vettore nel sistema locale + // Porto punto iniziale e vettore nel sistema locale ptLineSt.ToGlob( m_MapFrame) ; vtLineDir.ToGlob( m_MapFrame) ; - // Ciclo sui segmenti del dexel. + // Ciclo sui segmenti del dexel. for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) { - // Segmento ormai nel sistema locale + // Segmento ormai nel sistema locale Point3d ptSegSt = ptLineSt + m_Values[nMap][nDex][nInt].dMin * vtLineDir ; double dSegLen = m_Values[nMap][nDex][nInt].dMax - m_Values[nMap][nDex][nInt].dMin ; - // Copia del triangolo che può essere evenutalmente traslata + // Copia del triangolo che può essere eventualmente traslata Triangle3d trNewTria = trTria ; - // Se la distanza di sicurezza è significativa + // Se la distanza di sicurezza è significativa if ( dSafeDist > EPS_SMALL) { - // Valuto sfere nei vertici e cilindri lungo gli edge. + // Valuto sfere nei vertici e cilindri lungo gli edge. for ( int nV = 0 ; nV < 3 ; ++ nV) { Point3d ptVertP = trTria.GetP( nV) ; - Vector3d vtEdgeV = trTria.GetP( ( nV + 1)) - ptVertP ; + Vector3d vtEdgeV = trTria.GetP( ( nV + 1) % 3) - ptVertP ; double dEdgeLen = vtEdgeV.Len() ; vtEdgeV /= dEdgeLen ; double dU1, dU2 ; @@ -2254,16 +2030,16 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis return false ; nIntersType = IntersSegmentCylinder( ptSegSt, vtLineDir, dSegLen, ptVertP, vtEdgeV, dSafeDist, dEdgeLen, dU1, dU2) ; - if ( nIntersType != LinCompCCIntersType::CC_NO_INTERS ) + if ( nIntersType != LinCompCCIntersType::CC_NO_INTERS) return false ; } - // Traslo il triangolo. + // Traslo il triangolo. trNewTria.Translate( dSafeDist * trTria.GetN()) ; } - // Intersezione segento triangolo + // Intersezione segmento triangolo Point3d ptInt, ptInt2 ; int nIntersType = IntersLineTria( ptSegSt, vtLineDir, dSegLen, trNewTria, ptInt, ptInt2) ; - // Collisione + // Collisione if ( nIntersType != IntLineTriaType::ILTT_NO) return false ; } @@ -2271,6 +2047,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis } } } + return true ; } @@ -2282,10 +2059,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 ; @@ -2316,13 +2093,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) ; @@ -2332,7 +2107,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 ; @@ -2407,8 +2182,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 ; @@ -2445,19 +2220,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 ; @@ -2545,8 +2319,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 ; @@ -2688,8 +2462,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 @@ -2837,10 +2611,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)) diff --git a/VolZmapGraphics.cpp b/VolZmapGraphics.cpp index 077f084..5dfc8ab 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 ; } } @@ -4577,6 +4569,10 @@ VolZmap::Remove( FlatVoxelContainer& VoxCont, int nI, int nJ, int nK) const bool VolZmap::GetEdges( ICURVEPOVECTOR& vpCurve) const { + // Se mappa singola, non calcolabili + if ( m_nMapNum == 1) + return false ; + // Garantisco grafica aggiornata UpdateTripleMapGraphics() ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index 5b665e7..1ad3af4 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -18,8 +18,8 @@ #include "CurveArc.h" #include "VolZmap.h" #include "GeoConst.h" -#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include @@ -501,9 +501,9 @@ VolZmap::MillingStep( int nCurrTool, m_nCurrTool = nCurrTool ; Tool& CurrTool = m_vTool[m_nCurrTool] ; - // Se non è definito l'utensile, non devo fare alcunchè + // Se non è definito l'utensile, non posso fare alcunchè if ( CurrTool.GetType() == Tool::UNDEF) - return true ; + return false ; // Controllo definizione vettori direzione if ( vtDs.IsSmall() || vtDe.IsSmall()) return false ; @@ -520,21 +520,15 @@ VolZmap::MillingStep( int nCurrTool, m_nConnectedCompoCount = - 1 ; // Punti e vettori descriventi il moto nel sistema intrinseco dello Zmap - Point3d ptPLs = ptPs ; - ptPLs.ToLoc( m_MapFrame) ; - Point3d ptPLe = ptPe ; - ptPLe.ToLoc( m_MapFrame) ; - Vector3d vtDLs = vtDs ; - vtDLs.ToLoc( m_MapFrame) ; + Point3d ptPLs = GetToLoc( ptPs, m_MapFrame) ; + Point3d ptPLe = GetToLoc( ptPe, m_MapFrame) ; + Vector3d vtDLs = GetToLoc( vtDs, m_MapFrame) ; vtDLs.Normalize() ; - Vector3d vtDLe = vtDe ; - vtDLe.ToLoc( m_MapFrame) ; + Vector3d vtDLe = GetToLoc( vtDe, m_MapFrame) ; vtDLe.Normalize() ; - Vector3d vtALs = vtAs ; - vtALs.ToLoc( m_MapFrame) ; + Vector3d vtALs = GetToLoc( vtAs, m_MapFrame) ; vtALs.Normalize() ; - Vector3d vtALe = vtAe ; - vtALe.ToLoc( m_MapFrame) ; + Vector3d vtALe = GetToLoc( vtAe, m_MapFrame) ; vtALe.Normalize() ; //static PerformanceCounter Counter ; @@ -600,7 +594,15 @@ VolZmap::MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d vtLs[N_MAPS] ; Vector3d vtALs[N_MAPS] ; InitializePointsAndVectors( ptPs, ptPe, vtD, vtA, ptLs, ptLe, vtLs, vtALs) ; - // Ciclo sulle mappe + // Ciclo sulle mappe (scommentare solo per DEBUG) + //{ + // bool bOk = true ; + // for ( int i = 0 ; i < m_nMapNum ; ++ i) { + // bOk = SelectMotion( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) && bOk ; + // } + // return true ; + //} + // Ciclo sulle mappe vector< future> vRes ; vRes.resize( m_nMapNum) ; for ( int i = 0 ; i < m_nMapNum ; ++ i) { @@ -616,7 +618,7 @@ VolZmap::MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const } } } - return true ; + return bOk ; } //---------------------------------------------------------------------------- @@ -669,21 +671,16 @@ VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, cons if ( vtMove.SqLenXY() < EPS_SMALL * EPS_SMALL) { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_ZDrilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_ZDrilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_ZDrilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_ZDrilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_ZDrilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_ZDrilling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ; case Tool::CHISEL : - Chs_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Chs_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } @@ -691,21 +688,16 @@ VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, cons else if ( abs( vtMove.z) < EPS_SMALL) { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_ZPerp( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_ZPerp( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_ZPerp( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_ZPerp( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; case Tool::CHISEL : - Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } @@ -713,18 +705,14 @@ VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, cons else { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_ZMilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_ZMilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_ZMilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_ZMilling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } } @@ -743,62 +731,48 @@ VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, cons if ( dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_XYDrilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_XYDrilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_XYDrilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_XYDrilling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; case Tool::CHISEL : - Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } // Fresatura con vettore movimento perpendicolare all'utensile else if ( dSqLLong < EPS_SMALL * EPS_SMALL) { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_Milling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_Milling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_XYPerp( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_XYPerp( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : // Usiamo la generica per via dell'intsabilità di Conus_XYPerp - //Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; - Conus_Milling( nGrid, ptLs, ptLe, vtL) ; - break ; + //return Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; + return Conus_Milling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; case Tool::CHISEL : - Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_Milling( nGrid, ptLs, ptLe, vtL); - break ; + return GenTool_Milling( nGrid, ptLs, ptLe, vtL); case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_XYMilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_XYMilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_XYMilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_XYMilling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } } @@ -816,48 +790,39 @@ VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, cons if ( dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_Drilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_Drilling( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_Drilling( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_Drilling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; case Tool::CHISEL : - Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( CurrTool.GetType()) { case Tool::GEN : - GenTool_Milling( nGrid, ptLs, ptLe, vtL) ; - break ; + return GenTool_Milling( nGrid, ptLs, ptLe, vtL) ; case Tool::CYLMILL : case Tool::BALLMILL : - CylBall_Milling( nGrid, ptLs, ptLe, vtL) ; - break ; + return CylBall_Milling( nGrid, ptLs, ptLe, vtL) ; case Tool::CONEMILL : - Conus_Milling( nGrid, ptLs, ptLe, vtL) ; - break ; + return Conus_Milling( nGrid, ptLs, ptLe, vtL) ; case Tool::MORTISER : - Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; - break ; + return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; case Tool::CHISEL : // ammesso solo movimento perpendicolare all'asse utensile if ( dSqLLong < EPS_SMALL * EPS_SMALL) - Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; + return Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } } - return true ; + return false ; } @@ -3222,13 +3187,13 @@ VolZmap::GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, con const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; - int nNormNum = pLine->GetTempProp(); - Vector3d vtNormSt, vtNormEn; + int nNormNum = pLine->GetTempProp() ; + Vector3d vtNormSt, vtNormEn ; if ( nNormNum != 0) { vtNormSt = vArcNorm[nNormNum - 1] ; vtNormEn = vArcNorm[nNormNum] ; - vtNormSt.ToLoc(frNormFrame); - vtNormEn.ToLoc(frNormFrame); + vtNormSt.ToLoc( frNormFrame) ; + vtNormEn.ToLoc( frNormFrame) ; } // Ne determino l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; @@ -3258,21 +3223,21 @@ VolZmap::GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, con if ( dRadius > 10 * EPS_SMALL) CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT, CurrTool.GetToolNum()) ; } - // Se X crescente, è un cono con vettore equiverso a quello dell'utensile + // se altrimenti X decrescente, è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; CompConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT, vtNormSt, vtNormEn, CurrTool.GetToolNum()) ; } - // Se X decrescente, è un cono con vettore opposto a quello dell'utensile - else if ( ptStart.x < ptEnd.x) { + // altrimenti X crescente, è un cono con vettore opposto a quello dell'utensile + else { double dMaxRad = ptEnd.x ; double dMinRad = ptStart.x ; Point3d ptIn = ptI - vtToolDir * dHeight ; Point3d ptFn = ptIn + vtMove ; - vtNormEn.z *= -1 ; - vtNormSt.z *= -1 ; + vtNormEn.z = -vtNormEn.z ; + vtNormSt.z = -vtNormSt.z ; CompConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt, CurrTool.GetToolNum()) ; } @@ -4287,7 +4252,23 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, } return true ; } - + +//---------------------------------------------------------------------------- +static Vector3d +AdjustConeNormal( const Point3d& ptInt, const Vector3d& vtN, const Point3d& ptV, const Vector3d& vtToolDir, + double dMinRad, double dDeltaR, const Vector3d& vtArcNormMinR, const Vector3d& vtArcNormMaxR) +{ + if ( AreSameOrOppositeVectorEpsilon( vtN, vtToolDir, 0.1 * EPS_SMALL)) + return vtN ; + Vector3d vtL = ( ptInt - ptV) - (( ptInt - ptV) * vtToolDir) * vtToolDir ; + double dL = vtL.Len() ; + vtL /= dL ; + Vector3d vtOriginalN = ( ( dDeltaR - dL + dMinRad) / dDeltaR) * vtArcNormMinR + ((dL - dMinRad) / dDeltaR) * vtArcNormMaxR ; + Vector3d vtNewN = - vtOriginalN.z * vtToolDir - vtOriginalN.x * vtL ; + vtNewN.Normalize() ; + return vtNewN ; +} + //---------------------------------------------------------------------------- bool VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, @@ -4303,8 +4284,10 @@ VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, c double dDeltaR = dMaxRad - dMinRad ; // Studio simmetrie - Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ; - Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ; + Point3d ptI = ptS ; + Point3d ptF = ptE ; + if ( vtToolDir * ( ptE - ptS) <= 0) + swap( ptI, ptF) ; double dL = ( dMaxRad * dHei) / dDeltaR ; double dl = dL - dHei ; @@ -4366,7 +4349,8 @@ VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, c Point3d ptFacet135( 0, 0, dLenZ) ; Point3d ptFacet246( dLenX + dDeltaX, dLenY + dDeltaY, - dLenZ - dDeltaZ) ; - Vector3d vtUmv = vtMove ; vtUmv.Normalize() ; + // Necessità ricalcolo normali (perchè variabili per approx curve) + bool bRecalNorm = ( ! vtArcNormMaxR.IsSmall() && ! vtArcNormMinR.IsSmall()) ; if ( dRatio * dTan <= 1) { @@ -4381,27 +4365,9 @@ VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, c // Cono iniziale ConusFrame.ChangeOrig( ptV) ; if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { - if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { - if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) { - Vector3d vtL1 = ptInt1 - ptV ; - vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; - double dL1 = vtL1.Len() ; - vtL1 /= dL1 ; - Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ((dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR; - vtOriginalN1.Normalize() ; - vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; - vtN1.Normalize() ; - } - if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) { - Vector3d vtL2 = ptInt2 - ptV ; - vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ; - double dL2 = vtL2.Len() ; - vtL2 /= dL2 ; - Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; - vtOriginalN2.Normalize() ; - vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; - vtN2.Normalize() ; - } + if ( bRecalNorm) { + vtN1 = AdjustConeNormal( ptInt1, vtN1, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ; + vtN2 = AdjustConeNormal( ptInt2, vtN2, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ; } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; } @@ -4409,191 +4375,246 @@ VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, c // Cono finale ConusFrame.ChangeOrig( ptV + vtMove) ; if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { - if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { - if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) { - Vector3d vtL1 = ptInt1 - ptV - vtMove ; - vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; - double dL1 = vtL1.Len() ; - vtL1 /= dL1 ; - Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ; - vtOriginalN1.Normalize() ; - vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; - vtN1.Normalize() ; - } - if ( ! AreSameOrOppositeVectorEpsilon(vtN2, vtToolDir, 0.1 * EPS_SMALL)) { - Vector3d vtL2 = ptInt2 - ptV - vtMove ; - vtL2 -= (vtL2 * vtToolDir) * vtToolDir; - double dL2 = vtL2.Len() ; - vtL2 /= dL2 ; - Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; - vtOriginalN2.Normalize() ; - vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; - vtN2.Normalize() ; - } + if ( bRecalNorm) { + vtN1 = AdjustConeNormal( ptInt1, vtN1, ptV + vtMove, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ; + vtN2 = AdjustConeNormal( ptInt2, vtN2, ptV + vtMove, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ; } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; } // Solido interno - Point3d ptPoly = ptC ; - Vector3d vtPoly = Z_AX ; + Point3d ptPoly = GetToLoc( ptC, PolyFrame) ; + Vector3d vtPoly = GetToLoc( Z_AX, PolyFrame) ; - ptPoly.ToLoc( PolyFrame) ; - vtPoly.ToLoc( PolyFrame) ; + // Intervallo di intersezione (infinito) e normali (nulle) + bool bValid = true ; + double dPar1 = -INFINITO ; + double dPar2 = +INFINITO ; + vtN1 = V_NULL ; + vtN2 = V_NULL ; - Point3d ptPoly1 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtNs) / ( vtPoly * vtNs)) * vtPoly ; - Point3d ptPoly2 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtNd) / ( vtPoly * vtNd)) * vtPoly ; - Point3d ptPoly3 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtIF) / ( vtPoly * vtIF)) * vtPoly ; - Point3d ptPoly4 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtIF) / ( vtPoly * vtIF)) * vtPoly ; - Point3d ptPoly5 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtUD) / ( vtPoly * vtUD)) * vtPoly ; - Point3d ptPoly6 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtUD) / ( vtPoly * vtUD)) * vtPoly ; - - int nIntNum = 0 ; - - // Intersezione con la prima faccia - if ( abs( vtPoly * vtNs) > COS_ORTO_ANG_ZERO) { - if ( dLenY * ptPoly1.x >= dLenX * ptPoly1.y && - dLenY * ( ptPoly1.x - dDeltaX) <= dLenX * ( ptPoly1.y - dDeltaY) && - dDeltaX * ptPoly1.y >= dDeltaY * ptPoly1.x && - dDeltaX * ( ptPoly1.y - dLenY) <= dDeltaY * ( ptPoly1.x - dLenX)) { - ptInt1 = ptPoly1 ; - vtN1 = - vtNs ; - if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { - Vector3d vtRadial( 0, dMinRad * dCos, dMinRad * dSin) ; - vtRadial.Normalize() ; - Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; - Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; - vtOrigMaxR.Normalize() ; - vtOrigMinR.Normalize() ; - vtN1 = ( ( dDeltaZ - ptInt1.z + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( ptInt1.z - dLenZ) / dDeltaZ) * vtOrigMaxR ; - vtN1.Normalize() ; + // Verifica con facce iniziale e finale + if ( bValid) { + // Distanza con segno del punto di riferimento del dexel dal piano delle facce iniziale e finale + double dDistI = ( ptPoly - ptFacet135) * -vtIF ; + double dDistF = ( ptPoly - ptFacet246) * vtIF ; + // Se dexel non parallelo alle facce + if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) { + // posizione parametrica delle intersezioni + double dParI = -dDistI / ( vtPoly * -vtIF) ; + double dParF = -dDistF / ( vtPoly * vtIF) ; + // se intervallo tra intersezioni praticamente nullo + if ( abs( dParI - dParF) < EPS_ZERO) + bValid = false ; + // altrimenti + else { + if ( dParI < dParF) { + dPar1 = dParI ; + vtN1 = vtIF ; + dPar2 = dParF ; + vtN2 = -vtIF ; + } + else { + dPar1 = dParF ; + vtN1 = -vtIF ; + dPar2 = dParI ; + vtN2 = vtIF ; + } } - ++ nIntNum ; + } + // altrimenti praticamente parallelo + else { + // se esterno ad almeno uno invalida tutto + if ( dDistI > 0 || dDistF > 0) + bValid = false ; + // altrimenti non cambia niente } } - // Intersezione con la seconda faccia - if ( abs( vtPoly * vtNd) > COS_ORTO_ANG_ZERO) { - if ( dLenY * ptPoly2.x >= dLenX * ptPoly2.y && - dLenY * ( ptPoly2.x - dDeltaX) <= dLenX * ( ptPoly2.y - dDeltaY) && - dDeltaX * ptPoly2.y >= dDeltaY * ptPoly2.x && - dDeltaX * ( ptPoly2.y - dLenY) <= dDeltaY * ( ptPoly2.x - dLenX)) { - if ( nIntNum == 0) { - ptInt1 = ptPoly2 ; - vtN1 = - vtNd ; - if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { - Vector3d vtRadial( 0, dMinRad * dCos, - dMinRad * dSin) ; + // Verifica con facce sopra e sotto + if ( bValid) { + // Distanza con segno del punto di riferimento del dexel dal piano delle facce sopra e sotto + double dDistU = ( ptPoly - ptFacet246) * -vtUD ; + double dDistD = ( ptPoly - ptFacet135) * vtUD ; + // Se dexel non parallelo alle facce + if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) { + // posizione parametrica delle intersezioni + double dParU = -dDistU / ( vtPoly * -vtUD) ; + double dParD = -dDistD / ( vtPoly * vtUD) ; + // se intervallo tra intersezioni praticamente nullo + if ( abs( dParU - dParD) < EPS_ZERO) + bValid = false ; + // altrimenti + else { + if ( dParU < dParD) { + if ( dParD < dPar1 + EPS_ZERO || dParU > dPar2 - EPS_ZERO) + bValid = false ; + else { + if ( dParU > dPar1) { + dPar1 = dParU ; + vtN1 = vtUD ; + } + if ( dParD < dPar2) { + dPar2 = dParD ; + vtN2 = -vtUD ; + } + } + } + else { + if ( dParU < dPar1 + EPS_ZERO || dParD > dPar2 - EPS_ZERO) + bValid = false ; + else { + if ( dParD > dPar1) { + dPar1 = dParD ; + vtN1 = -vtUD ; + } + if ( dParU < dPar2) { + dPar2 = dParU ; + vtN2 = vtUD ; + } + } + } + } + } + // altrimenti praticamente parallelo + else { + // se esterno ad almeno uno invalida tutto + if ( dDistU > 0 || dDistD > 0) + bValid = false ; + // altrimenti non cambia niente + } + } + + // Taglio con la faccia sinistra + if ( bValid) { + // Distanza con segno del punto di riferimento del dexel dal piano della faccia sinistra + double dDistS = ( ptPoly - ptFacet135) * vtNs ; + // Se dexel non parallelo alla faccia + if ( abs( vtPoly * vtNs) > COS_ORTO_ANG_ZERO) { + // posizione parametrica della intersezione + double dParS = -dDistS / ( vtPoly * vtNs) ; + // verifico limitazioni su inizio e fine dell'intervallo + int nLimit = 0 ; + // se limita inizio + if ( vtPoly * vtNs < 0) { + // se oltre la fine, invalida tutto + if ( dParS > dPar2 - EPS_ZERO) + bValid = false ; + // se altrimenti solo oltre inizio, riduce + else if ( dParS >= dPar1) { + dPar1 = dParS ; + nLimit = 1 ; + } + } + // altrimenti limita fine + else { + // se prima dell'inizio, invalida tutto + if ( dParS < dPar1 + EPS_ZERO) + bValid = false ; + // se altrimenti solo prima della fine, riduce + else if ( dParS <= dPar2) { + dPar2 = dParS ; + nLimit = 2 ; + } + } + // se limita, devo aggiornare la normale + if ( nLimit != 0) { + Vector3d vtNewN = -vtNs ; + if ( bRecalNorm) { + Vector3d vtRadial( 0, dMinRad * dCos, dMinRad * dSin) ; vtRadial.Normalize() ; Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; - vtN1 = ( ( dDeltaZ - abs( ptInt1.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt1.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ; - vtN1.Normalize() ; + Point3d ptInt = ptPoly + dParS * vtPoly ; + vtNewN = ( ( dDeltaZ - ptInt.z + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( ptInt.z - dLenZ) / dDeltaZ) * vtOrigMaxR ; + vtNewN.Normalize() ; } - ++ nIntNum ; - } - else if ( ( ptInt1 - ptPoly2).SqLen() > SQ_EPS_SMALL) { - ptInt2 = ptPoly2 ; - vtN2 = - vtNd ; - if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { + if ( nLimit == 1) + vtN1 = vtNewN ; + else + vtN2 = vtNewN ; + } + } + // altrimenti praticamente parallelo + else { + // se esterno invalida tutto + if ( dDistS > 0) + bValid = false ; + // altrimenti non cambia niente + } + } + + // Taglio con la faccia destra + if ( bValid) { + // Distanza con segno del punto di riferimento del dexel dal piano della faccia destra + double dDistD = ( ptPoly - ptFacet246) * vtNd ; + // Se dexel non parallelo alla faccia + if ( abs( vtPoly * vtNd) > COS_ORTO_ANG_ZERO) { + // posizione parametrica della intersezione + double dParD = -dDistD / ( vtPoly * vtNd) ; + // verifico limitazioni su inizio e fine dell'intervallo + int nLimit = 0 ; + // se limita inizio + if ( vtPoly * vtNd < 0) { + // se oltre la fine, invalida tutto + if ( dParD > dPar2 - EPS_ZERO) + bValid = false ; + // se altrimenti solo oltre inizio, riduce + else if ( dParD >= dPar1) { + dPar1 = dParD ; + nLimit = 1 ; + } + } + // altrimenti limita fine + else { + // se prima dell'inizio, invalida tutto + if ( dParD < dPar1 + EPS_ZERO) + bValid = false ; + // se altrimenti solo prima della fine, riduce + else if ( dParD <= dPar2) { + dPar2 = dParD ; + nLimit = 2 ; + } + } + // se limita, devo aggiornare la normale + if ( nLimit != 0) { + Vector3d vtNewN = -vtNd ; + if ( bRecalNorm) { Vector3d vtRadial( 0, dMinRad * dCos, -dMinRad * dSin) ; vtRadial.Normalize() ; - Vector3d vtOrigMaxR = -vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; - Vector3d vtOrigMinR = -vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; + Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; + Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; - vtN2 = ( ( dDeltaZ - abs( ptInt2.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt2.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ; - vtN2.Normalize() ; + Point3d ptInt = ptPoly + dParD * vtPoly ; + vtNewN = ( ( dDeltaZ - abs( ptInt.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ; + vtNewN.Normalize() ; } - ++ nIntNum ; + if ( nLimit == 1) + vtN1 = vtNewN ; + else + vtN2 = vtNewN ; } } - } - // Intersezione con la terza faccia - if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) { - if ( nIntNum < 2 && - ptPoly3.x >= 0 && ptPoly3.x <= dDeltaX && - dDeltaX * abs( ptPoly3.z) < dDeltaX * dLenZ + dDeltaZ * ptPoly3.x) { - - if ( nIntNum == 0) { - ptInt1 = ptPoly3 ; - vtN1 = vtIF ; - ++ nIntNum ; - } - else if ( ( ptInt1 - ptPoly3).SqLen() > SQ_EPS_SMALL) { - ptInt2 = ptPoly3 ; - vtN2 = vtIF ; - ++ nIntNum ; - } + // altrimenti praticamente parallelo + else { + // se esterno invalida tutto + if ( dDistD > 0) + bValid = false ; + // altrimenti non cambia niente } } - // Intersezione con la quarta faccia - if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) { - if ( nIntNum < 2 && - ptPoly4.x >= dLenX && ptPoly4.x <= dLenX + dDeltaX && - dDeltaX * abs( ptPoly4.z) < dDeltaX * dLenZ + dDeltaZ * ( ptPoly4.x - dLenX)) { - - if ( nIntNum == 0) { - ptInt1 = ptPoly4 ; - vtN1 = - vtIF ; - ++ nIntNum ; - } - else if ( ( ptInt1 - ptPoly4).SqLen() > SQ_EPS_SMALL) { - ptInt2 = ptPoly4 ; - vtN2 = - vtIF ; - ++ nIntNum ; - } - } - } - - // Intersezione con la quinta faccia - if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) { - if ( nIntNum < 2 && - ptPoly5.y >= 0 && ptPoly5.y <= dLenY && - abs( ptPoly5.z) <= dLenZ) { - - if ( nIntNum == 0) { - ptInt1 = ptPoly5 ; - vtN1 = - vtUD ; - ++ nIntNum ; - } - else if ( ( ptInt1 - ptPoly5).SqLen() > SQ_EPS_SMALL) { - ptInt2 = ptPoly5 ; - vtN2 = - vtUD ; - ++ nIntNum ; - } - } - } - - // Intersezione con la sesta faccia - if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) { - if ( nIntNum < 2 && - ptPoly6.y >= dDeltaY && ptPoly6.y <= dLenY + dDeltaY && - abs( ptPoly6.z) <= dLenZ + dDeltaZ) { - - if ( nIntNum == 0) { - ptInt1 = ptPoly6; - vtN1 = vtUD ; - ++ nIntNum ; - } - else if ( ( ptInt1 - ptPoly6).SqLen() > SQ_EPS_SMALL) { - ptInt2 = ptPoly6; - vtN2 = vtUD ; - ++ nIntNum ; - } - } - } - // Se il poliedro è attraversato taglio - if ( nIntNum == 2) { - - // Riporto le intersezioni nel sistema griglia - ptInt1.ToGlob( PolyFrame) ; + // Se rimasto qualcosa lo sottraggo al dexel + if ( bValid) { + // Punti di intersezione e normali nel sistema griglia + ptInt1 = ptC + dPar1 * Z_AX ; vtN1.ToGlob( PolyFrame) ; - ptInt2.ToGlob( PolyFrame) ; + ptInt2 = ptC + dPar2 * Z_AX ; vtN2.ToGlob( PolyFrame) ; - + // Eseguo sottrazione SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; } @@ -4631,27 +4652,9 @@ VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, c // Cono ConusFrame.ChangeOrig( ptV) ; if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) { - if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { - if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) { - Vector3d vtL1 = ptInt1 - ptV ; - vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; - double dL1 = vtL1.Len() ; - vtL1 /= dL1 ; - Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ; - vtOriginalN1.Normalize() ; - vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; - vtN1.Normalize() ; - } - if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) { - Vector3d vtL2 = ptInt2 - ptV ; - vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ; - double dL2 = vtL2.Len() ; - vtL2 /= dL2 ; - Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; - vtOriginalN2.Normalize() ; - vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; - vtN2.Normalize() ; - } + if ( bRecalNorm) { + vtN1 = AdjustConeNormal( ptInt1, vtN1, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ; + vtN2 = AdjustConeNormal( ptInt2, vtN2, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ; } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; } @@ -4876,7 +4879,7 @@ VolZmap::TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, con // I punti e i vettori devono essere nel sistema di riferimento opportuno // Controllo sull'ammissibilità del numero di griglia - if ( nGrid < 0 || nGrid > 2) + if ( nGrid < 0 || nGrid > 2) return false ; // BBox dello Zmap @@ -4939,10 +4942,10 @@ VolZmap::TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const return false ; // Limiti su indici - nStI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; - nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : static_cast ( dMaxX / m_dStep)) ; - nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; - nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : static_cast ( dMaxY / m_dStep)) ; - + nStI = ( dMinX < EPS_SMALL ? 0 : int( dMinX / m_dStep)) ; + nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : int( dMaxX / m_dStep)) ; + nStJ = ( dMinY < EPS_SMALL ? 0 : int( dMinY / m_dStep)) ; + nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : int ( dMaxY / m_dStep)) ; + return true ; }