diff --git a/BiArcs.cpp b/BiArcs.cpp index 5ebe256..6023a39 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -81,19 +81,9 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir //---------------------------------------------------------------------------- ICurve* -GetBiArc( const ICurve& Crv, const PolyLine& PL, double& dDist) +GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg, + const PolyLine& PL, double& dDist) { - // calcolo punti e direzioni estremi - double dU ; - Point3d ptP0, ptP1 ; - Vector3d vtDir ; - double dDir0Deg, dDir1Deg ; - if ( ! PL.GetFirstU( dU) || ! Crv.GetPointTang( dU, ICurve::FROM_PLUS, ptP0, vtDir)) - return false ; - vtDir.ToSpherical( nullptr, nullptr, &dDir0Deg) ; - if ( ! PL.GetLastU( dU) || ! Crv.GetPointTang( dU, ICurve::FROM_MINUS, ptP1, vtDir)) - return false ; - vtDir.ToSpherical( nullptr, nullptr, &dDir1Deg) ; // calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco PtrOwner pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ; if ( IsNull( pJCrv)) @@ -131,7 +121,8 @@ GetBiArc( const ICurve& Crv, const PolyLine& PL, double& dDist) } } } - if ( dU < 0) + // elimino casi vicino agli estremi, danno solo problemi + if ( dU < 0.1 || dU > 0.9) dU = 0.5 ; pBiArc.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, dU)) ; } diff --git a/BiArcs.h b/BiArcs.h index 2ce110e..40ed705 100644 --- a/BiArcs.h +++ b/BiArcs.h @@ -16,5 +16,6 @@ #include "/EgtDev/Include/EgkBiArcs.h" //----------------------------------------------------------------------------- -ICurve* GetBiArc( const ICurve& Crv, const PolyLine& PL, double& dDist) ; +ICurve* GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg, + const PolyLine& PL, double& dDist) ; diff --git a/CalcDerivate.h b/CalcDerivate.h index db4928b..1ba6904 100644 --- a/CalcDerivate.h +++ b/CalcDerivate.h @@ -17,7 +17,7 @@ //---------------------------------------------------------------------------- -bool +inline bool CalcBesselStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, Vector3d& vtDer) { @@ -33,7 +33,7 @@ CalcBesselStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& } //---------------------------------------------------------------------------- -bool +inline bool CalcBesselMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, Vector3d& vtDer) { @@ -49,7 +49,7 @@ CalcBesselMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& pt } //---------------------------------------------------------------------------- -bool +inline bool CalcBesselEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, Vector3d& vtDer) { @@ -65,7 +65,7 @@ CalcBesselEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& pt } //---------------------------------------------------------------------------- -bool +inline bool CalcCircleStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, Vector3d& vtDer) { @@ -97,7 +97,7 @@ CalcCircleStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& } //---------------------------------------------------------------------------- -bool +inline bool CalcCircleEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, Vector3d& vtDer) { @@ -129,7 +129,7 @@ CalcCircleEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& pt } //---------------------------------------------------------------------------- -bool +inline bool CalcCircleMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, Vector3d& vtDer) { @@ -138,7 +138,7 @@ CalcCircleMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& pt } //---------------------------------------------------------------------------- -bool +inline bool CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, double dU2, const Point3d& ptP2, double dU3, const Point3d& ptP3, double dU4, const Point3d& ptP4, bool bDetectCorner, diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 8c2d5fd..88a94ce 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -25,9 +25,9 @@ #include "NgeReader.h" #include "PolynomialPoint3d.h" #include "/EgtDev/Include/EGkCurveArc.h" -#include "/EgtDev/Include/ENkPolynomial.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" +#include "/EgtDev/Include/ENkPolynomial.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include @@ -1508,8 +1508,19 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo // se la polilinea ha più di 2 punti if ( PL.GetPointNbr() > 2) { + // calcolo punti e direzioni agli estremi della polilinea usando la curva di Bezier + double dU ; + Point3d ptP0, ptP1 ; + Vector3d vtDir ; + double dDir0Deg, dDir1Deg ; + if ( ! PL.GetFirstU( dU) || ! GetPointTang( dU, ICurve::FROM_PLUS, ptP0, vtDir)) + return false ; + vtDir.ToSpherical( nullptr, nullptr, &dDir0Deg) ; + if ( ! PL.GetLastU( dU) || ! GetPointTang( dU, ICurve::FROM_MINUS, ptP1, vtDir)) + return false ; + vtDir.ToSpherical( nullptr, nullptr, &dDir1Deg) ; // costruisco un biarco sulla polilinea (secondo metodo di Z. Sir) - pCrv.Set( GetBiArc( *this, PL, dMaxDist)) ; + pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ; if ( IsNull( pCrv)) return false ; } @@ -1520,7 +1531,7 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo if ( PL.GetLength( dLen) && dLen < EPS_SMALL) return true ; // costruisco la retta che li unisce - PtrOwner pCC( CreateCurveComposite()) ; + PtrOwner pCC( CreateBasicCurveComposite()) ; if ( IsNull( pCC)) return false ; if ( ! pCC->FromPolyLine( PL)) diff --git a/CurveByApprox.cpp b/CurveByApprox.cpp new file mode 100644 index 0000000..803d6e0 --- /dev/null +++ b/CurveByApprox.cpp @@ -0,0 +1,481 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : CurveByApprox.cpp Data : 23.07.15 Versione : 1.6g7 +// Contenuto : Implementazione della classe CurveByApprox, per creare +// una curva mediante approssimazione di punti. +// +// +// Modifiche : 23.07.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveComposite.h" +#include "CalcDerivate.h" +#include "BiArcs.h" +#include "DistPointLine.h" +#include "/EgtDev/Include/EGkCurveByApprox.h" +#include "/EgtDev/Include/EGkPolyLine.h" +#include "/EgtDev/Include/EGkPolyArc.h" +#include "/EgtDev/Include/EgtPointerOwner.h" +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +CurveByApprox::Reset( void) +{ + // pulisco i diversi vettori + m_vPnt.clear() ; + m_vPar.clear() ; + m_vPrevDer.clear() ; + m_vNextDer.clear() ; + m_vSplits.clear() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::AddPoint( const Point3d& ptP) +{ + // se il punto coincide con il precedente, lo salto + if ( ! m_vPnt.empty() && AreSamePointApprox( ptP, m_vPnt.back())) + return false ; + // aggiungo il punto + try { m_vPnt.push_back( ptP) ; } + catch ( ...) { return false ; } + return true ; +} + +//---------------------------------------------------------------------------- +ICurve* +CurveByApprox::GetCurve( int nType, double dLinTol, double dAngTolDeg, double dLinFea) +{ + // calcolo le tangenti + if ( ! CalcAkimaTangents( true)) + return nullptr ; + + // divido in tratti (rettilinei o tra spigoli) + if ( ! CalcSplitPoints( dLinTol, dAngTolDeg, dLinFea)) + return nullptr ; + + // approssimo ogni singolo tratto + PolyArc PA ; + int nPrev = 0 ; + int nSplits = int( m_vSplits.size()) ; + for ( int i = 0 ; i < nSplits ; ++ i) { + // creo la polilinea che unisce i punti + 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)) + return nullptr ; + // salvo fine come prox inizio + nPrev = m_vSplits[i] ; + } + // creo la composita formata da questa approssimazione + PtrOwner pCC( CreateBasicCurveComposite()) ; + if ( ! pCC->FromPolyArc( PA)) + return nullptr ; + // eventuale fusione di curve compatibili + pCC->MergeCurves( dLinTol, dAngTolDeg) ; + + return Release( pCC) ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::CalcAkimaTangents( bool bDetectCorner) +{ + // pulisco i vettori dei parametri e delle tangenti + m_vPar.clear() ; + m_vPrevDer.clear() ; + m_vNextDer.clear() ; + + // numero di punti + int nSize = int( m_vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return false ; + + // calcolo le distanze tra i punti per derivarne i parametri + m_vPar.reserve( nSize) ; + double dPar = 0 ; + m_vPar.push_back( dPar) ; + for ( int i = 1 ; i < nSize ; ++ i) { + double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; + dPar += dDist ; + m_vPar.push_back( dPar) ; + } + + // calcolo le derivate + m_vPrevDer.reserve( nSize) ; + m_vNextDer.reserve( nSize) ; + // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce + if ( nSize == 2) { + // non esiste derivata prima del primo punto + m_vPrevDer.emplace_back( 0, 0, 0) ; + m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; + m_vPrevDer.push_back( m_vNextDer[0]) ; + // non esiste derivata dopo il secondo e ultimo punto + m_vNextDer.emplace_back( 0, 0, 0) ; + return true ; + } + // verifico se curva chiusa (primo e ultimo punto coincidono) + bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; + // calcolo le derivate + for ( int i = 0 ; i < nSize ; ++ i) { + Vector3d vtPrevDer ; + Vector3d vtNextDer ; + // primo punto + if ( i == 0) { + // se curva chiusa, come precedente uso il penultimo punto + if ( bClosed) { + // se non ci sono almeno 5 punti + if ( nSize < 5) { + if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtNextDer)) + return false ; + vtPrevDer = vtNextDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti, uso arco sui primi tre punti + else { + if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], vtNextDer)) + return false ; + vtPrevDer = Vector3d( 0, 0, 0) ; + } + } + // ultimo punto + else if ( i == nSize - 1) { + // se curva chiusa, le tg devono coincidere con quelle del primo + if ( bClosed) { + vtPrevDer = m_vPrevDer[0] ; + vtNextDer = m_vNextDer[0] ; + } + // altrimenti, uso arco sugli ultimi tre punti + else { + if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], vtPrevDer)) + return false ; + vtNextDer = Vector3d( 0, 0, 0) ; + } + } + // punti intermedi + else { + // se secondo punto + if ( i == 1) { + // se curva aperta o non ci sono almeno 5 punti + if ( ! bClosed || nSize < 5) { + if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // se penultimo punto + else if ( i == nSize - 2) { + // se curva aperta o non ci sono almeno 5 punti + if ( ! bClosed || nSize < 5) { + if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // salvo la derivata + m_vPrevDer.push_back( vtPrevDer) ; + m_vNextDer.push_back( vtNextDer) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::CalcBesselTangents( void) +{ + // pulisco i vettori dei parametri e delle tangenti + m_vPar.clear() ; + m_vPrevDer.clear() ; + m_vNextDer.clear() ; + + // numero di punti + int nSize = int( m_vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return false ; + + // calcolo le distanze tra i punti per derivarne i parametri + m_vPar.reserve( nSize) ; + double dPar = 0 ; + m_vPar.push_back( dPar) ; + for ( int i = 1 ; i < nSize ; ++ i) { + double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; + dPar += dDist ; + m_vPar.push_back( dPar) ; + } + + // calcolo le derivate + m_vPrevDer.reserve( nSize) ; + m_vNextDer.reserve( nSize) ; + // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce + if ( nSize == 2) { + // non esiste derivata prima del primo punto + m_vPrevDer.emplace_back( 0, 0, 0) ; + m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; + m_vPrevDer.push_back( m_vNextDer[0]) ; + // non esiste derivata dopo il secondo e ultimo punto + m_vNextDer.emplace_back( 0, 0, 0) ; + return true ; + } + // verifico se curva chiusa (primo e ultimo punto coincidono) + bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; + // calcolo le derivate + for ( int i = 0 ; i < nSize ; ++ i) { + Vector3d vtPrevDer ; + Vector3d vtNextDer ; + // primo punto + if ( i == 0) { + // se curva chiusa, come precedente uso il penultimo punto + if ( bClosed) { + if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtNextDer)) + return false ; + vtPrevDer = vtNextDer ; + } + // altrimenti, uso i primi tre punti + else { + if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], vtNextDer)) + return false ; + vtPrevDer = Vector3d( 0, 0, 0) ; + } + } + // ultimo punto + else if ( i == nSize - 1) { + // se curva chiusa, le tg devono coincidere con quelle del primo + if ( bClosed) { + vtPrevDer = m_vPrevDer[0] ; + vtNextDer = m_vNextDer[0] ; + } + // altrimenti, uso gli ultimi tre punti + else { + if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], vtPrevDer)) + return false ; + vtNextDer = Vector3d( 0, 0, 0) ; + } + } + // punti intermedi + else { + if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // salvo la derivata + m_vPrevDer.push_back( vtPrevDer) ; + m_vNextDer.push_back( vtNextDer) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::CalcSplitPoints( double dLinTol, double dAngTolDeg, double dLinFea) +{ + // precalcolo funzioni dei limiti + double dSqLinTol = dLinTol * dLinTol ; + double dAngTolCos = cos( max( dAngTolDeg, 0.) * DEGTORAD) ; + double dSqLinFea = dLinFea * dLinFea ; + // cerco punti angolosi e punti di separazione di tratti lineari e non + // verifico i punti tranne primo e ultimo + int nSize = int( m_vPnt.size()) ; + for ( int i = 1 ; i < nSize - 1 ; ++ i) { + // se angolo, allora punto di divisione + if ( ( m_vPrevDer[i] * m_vNextDer[i]) < dAngTolCos) { + m_vSplits.push_back(i) ; + continue ; + } + // verifico linearità del tratto precedente + Vector3d vtPrev = m_vPnt[i] - m_vPnt[i-1] ; + bool bPrevLin = vtPrev.SqLen() > dSqLinFea && + ( m_vNextDer[i-1] * m_vPrevDer[i]) > dAngTolCos && + ( vtPrev ^ m_vNextDer[i-1]).SqLen() < dSqLinTol && + ( vtPrev ^ m_vPrevDer[i]).SqLen() < dSqLinTol ; + // verifico linearità del tratto successivo + Vector3d vtNext = m_vPnt[i+1] - m_vPnt[i] ; + bool bNextLin = vtNext.SqLen() > dSqLinFea && + ( m_vNextDer[i] * m_vPrevDer[i+1]) > dAngTolCos && + ( vtNext ^ m_vNextDer[i]).SqLen() < dSqLinTol && + ( vtNext ^ m_vPrevDer[i+1]).SqLen() < dSqLinTol ; + // se uno lineare e l'altro no, allora punto di divisione + if ( ( bPrevLin && ! bNextLin) || ( ! bPrevLin && bNextLin)) { + m_vSplits.push_back(i) ; + continue ; + } + // se entrambi non lineari, vado oltre + if ( ! bPrevLin && ! bNextLin) + continue ; + // sono entrambi tratti lineari, verifico siano allineati + DistPointLine dPL( m_vPnt[i], m_vPnt[i-1], m_vPnt[i+1]) ; + double dSqDist ; + if ( ! dPL.GetSqDist( dSqDist) || dSqDist > dSqLinTol) { + m_vSplits.push_back(i) ; + continue ; + } + } + // in ogni caso ci deve essere l'ultimo punto + m_vSplits.push_back(nSize - 1) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTolDeg, PolyArc& PA) const +{ + const int MAX_LEV = 10 ; + + // se non chiusa + if ( ! PL.IsClosed()) { + + PtrOwner pCrv ; + double dMaxDist ; + + // se la polilinea ha più di 2 punti + if ( PL.GetPointNbr() > 2) { + // calcolo punti e direzioni agli estremi della polilinea usando la curva di Bezier + int nI ; + double dU ; + Point3d ptP0, ptP1 ; + double dDir0Deg, dDir1Deg ; + if ( ! PL.GetFirstU( dU)) + return false ; + nI = int( dU) ; + ptP0 = m_vPnt[nI] ; + m_vNextDer[nI].ToSpherical( nullptr, nullptr, &dDir0Deg) ; + if ( ! PL.GetLastU( dU)) + return false ; + nI = int( dU) ; + ptP1 = m_vPnt[nI] ; + m_vPrevDer[nI].ToSpherical( nullptr, nullptr, &dDir1Deg) ; + // costruisco un biarco sulla polilinea (secondo metodo di Z. Sir) + pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ; + if ( IsNull( pCrv)) + return false ; + } + // se la polilinea è formata da 2 punti + else if ( PL.GetPointNbr() == 2) { + // se molto vicini, esco + double dLen ; + if ( PL.GetLength( dLen) && dLen < EPS_SMALL) + return true ; + // costruisco la retta che li unisce + PtrOwner pCC( CreateBasicCurveComposite()) ; + if ( IsNull( pCC)) + return false ; + if ( ! pCC->FromPolyLine( PL)) + return false ; + pCrv.Set( Release( pCC)) ; + dMaxDist = 0 ; + } + // se la polilinea ha un solo punto, esco + else + return true ; + + // se raggiunto il massimo livello di recursione, forzo l'accettazione del biarco + if ( nLev >= MAX_LEV) { + dMaxDist = 0 ; + // segnalo situazione per debug + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") + } + + // se lunghezza abbastanza picccola, forzo l'accettazione della curva + double dLen ; + if ( PL.GetApproxLength( dLen) && dLen < 10 * EPS_SMALL) + dMaxDist = 0 ; + + // se in tolleranza + if ( dMaxDist <= dLinTol) { + // creo un nuovo poliarco + PolyArc PA2 ; + if ( ! pCrv->ApproxWithArcs( dLinTol, dAngTolDeg, PA2)) + return false ; + // aggiusto la parametrizzazione + double dUStart, dUEnd ; + PL.GetFirstU( dUStart) ; + PL.GetLastU( dUEnd) ; + PA2.ParamLinearTransform( dUStart, dUEnd) ; + // accodo all'esistente + if ( ! PA.Join( PA2)) + return false ; + // esco + return true ; + } + } + + // se raggiunto il massimo livello di recursione, errore + if ( nLev >= MAX_LEV) { + // segnalo situazione per debug + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") + return false ; + } + + // spezzo l'intervallo in due parti a metà + double dParStart, dParEnd ; + if ( ! PL.GetFirstU( dParStart) || ! PL.GetLastU( dParEnd)) + return false ; + double dParMid = 0.5 * ( dParStart + dParEnd) ; + PolyLine PL2 ; + if ( ! PL.Split( dParMid, PL2)) + return false ; + // prima metà + if ( ! BiArcOrSplit( nLev + 1, PL, dLinTol, dAngTolDeg, PA)) + return false ; + // seconda metà + return BiArcOrSplit( nLev + 1, PL2, dLinTol, dAngTolDeg, PA) ; +} diff --git a/CurveByInterp.cpp b/CurveByInterp.cpp index affd52e..f6b0acf 100644 --- a/CurveByInterp.cpp +++ b/CurveByInterp.cpp @@ -23,10 +23,13 @@ //---------------------------------------------------------------------------- bool -CurveByInterp::Start( void) +CurveByInterp::Reset( void) { - // pulisco il vettore dei punti + // pulisco i diversi vettori m_vPnt.clear() ; + m_vPar.clear() ; + m_vPrevDer.clear() ; + m_vNextDer.clear() ; return true ; } @@ -43,20 +46,19 @@ CurveByInterp::AddPoint( const Point3d& ptP) return true ; } -//---------------------------------------------------------------------------- -bool -CurveByInterp::End( void) -{ - return true ; -} - //---------------------------------------------------------------------------- ICurve* CurveByInterp::GetCurve( int nMethod, int nType) { // calcolo le tangenti - if ( ! CalcTangents( nMethod)) - return nullptr ; + if ( nMethod == BESSEL) { + if ( ! CalcBesselTangents()) + return nullptr ; + } + else { + if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER)) + return nullptr ; + } // se richiesti biarchi if ( nType == BIARCS) { @@ -106,7 +108,7 @@ CurveByInterp::GetCurve( int nMethod, int nType) //---------------------------------------------------------------------------- bool -CurveByInterp::CalcTangents( int nMethod) +CurveByInterp::CalcAkimaTangents( bool bDetectCorner) { // pulisco i vettori dei parametri e delle tangenti m_vPar.clear() ; @@ -153,9 +155,9 @@ CurveByInterp::CalcTangents( int nMethod) if ( i == 0) { // se curva chiusa, come precedente uso il penultimo punto if ( bClosed) { - // se richiesto Bessel o non ci sono almeno 5 punti - if ( nMethod == BESSEL || nSize < 5) { - if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], + // se non ci sono almeno 5 punti + if ( nSize < 5) { + if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], vtNextDer)) return false ; vtPrevDer = vtNextDer ; @@ -164,79 +166,41 @@ CurveByInterp::CalcTangents( int nMethod) else { if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], ( nMethod == AKIMA_CORNER), + m_vPar[i+2], m_vPnt[i+2], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } } - // altrimenti, uso i primi tre punti + // altrimenti, uso arco sui primi tre punti else { - // se richiesto Bessel - if ( nMethod == BESSEL) { - if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], vtNextDer)) - return false ; - } - // altrimenti, uso arco - else { - if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], vtNextDer)) - return false ; - } + if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], vtNextDer)) + return false ; vtPrevDer = Vector3d( 0, 0, 0) ; } } // ultimo punto else if ( i == nSize - 1) { - // se curva chiusa, come successivo uso il secondo punto + // se curva chiusa, le tg devono coincidere con quelle del primo if ( bClosed) { - // se richiesto Bessel o non ci sono almeno 5 punti - if ( nMethod == BESSEL || nSize < 5) { - if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[1] + m_vPar[i], m_vPnt[1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[1] + m_vPar[i], m_vPnt[1], - m_vPar[2] + m_vPar[i], m_vPnt[2], ( nMethod == AKIMA_CORNER), - vtPrevDer, vtNextDer)) - return false ; - } + vtPrevDer = m_vPrevDer[0] ; + vtNextDer = m_vNextDer[0] ; } - // altrimenti, uso gli ultimi tre punti + // altrimenti, uso arco sugli ultimi tre punti else { - // se richiesto Bessel - if ( nMethod == BESSEL) { - if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], vtPrevDer)) - return false ; - } - // altrimenti, uso arco - else { - if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], vtPrevDer)) - return false ; - } + if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], vtPrevDer)) + return false ; vtNextDer = Vector3d( 0, 0, 0) ; } } // punti intermedi else { - // se richiesto Bessel - if ( nMethod == BESSEL) { - if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } // se secondo punto - else if ( i == 1) { + if ( i == 1) { // se curva aperta o non ci sono almeno 5 punti if ( ! bClosed || nSize < 5) { - if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) return false ; vtNextDer = vtPrevDer ; @@ -245,7 +209,7 @@ CurveByInterp::CalcTangents( int nMethod) else { if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], ( nMethod == AKIMA_CORNER), + m_vPar[i+2], m_vPnt[i+2], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } @@ -254,7 +218,7 @@ CurveByInterp::CalcTangents( int nMethod) else if ( i == nSize - 2) { // se curva aperta o non ci sono almeno 5 punti if ( ! bClosed || nSize < 5) { - if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) return false ; vtNextDer = vtPrevDer ; @@ -263,7 +227,7 @@ CurveByInterp::CalcTangents( int nMethod) else { if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[1] + m_vPar[i+1], m_vPnt[1], ( nMethod == AKIMA_CORNER), + m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } @@ -272,7 +236,7 @@ CurveByInterp::CalcTangents( int nMethod) else { if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], ( nMethod == AKIMA_CORNER), + m_vPar[i+2], m_vPnt[i+2], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } @@ -284,3 +248,95 @@ CurveByInterp::CalcTangents( int nMethod) return true ; } + +//---------------------------------------------------------------------------- +bool +CurveByInterp::CalcBesselTangents( void) +{ + // pulisco i vettori dei parametri e delle tangenti + m_vPar.clear() ; + m_vPrevDer.clear() ; + m_vNextDer.clear() ; + + // numero di punti + int nSize = int( m_vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return false ; + + // calcolo le distanze tra i punti per derivarne i parametri + m_vPar.reserve( nSize) ; + double dPar = 0 ; + m_vPar.push_back( dPar) ; + for ( int i = 1 ; i < nSize ; ++ i) { + double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; + dPar += dDist ; + m_vPar.push_back( dPar) ; + } + + // calcolo le derivate + m_vPrevDer.reserve( nSize) ; + m_vNextDer.reserve( nSize) ; + // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce + if ( nSize == 2) { + // non esiste derivata prima del primo punto + m_vPrevDer.emplace_back( 0, 0, 0) ; + m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; + m_vPrevDer.push_back( m_vNextDer[0]) ; + // non esiste derivata dopo il secondo e ultimo punto + m_vNextDer.emplace_back( 0, 0, 0) ; + return true ; + } + // verifico se curva chiusa (primo e ultimo punto coincidono) + bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; + // calcolo le derivate + for ( int i = 0 ; i < nSize ; ++ i) { + Vector3d vtPrevDer ; + Vector3d vtNextDer ; + // primo punto + if ( i == 0) { + // se curva chiusa, come precedente uso il penultimo punto + if ( bClosed) { + if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtNextDer)) + return false ; + vtPrevDer = vtNextDer ; + } + // altrimenti, uso i primi tre punti + else { + if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], vtNextDer)) + return false ; + vtPrevDer = Vector3d( 0, 0, 0) ; + } + } + // ultimo punto + else if ( i == nSize - 1) { + // se curva chiusa, le tg devono coincidere con quelle del primo + if ( bClosed) { + vtPrevDer = m_vPrevDer[0] ; + vtNextDer = m_vNextDer[0] ; + } + // altrimenti, uso gli ultimi tre punti + else { + if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], vtPrevDer)) + return false ; + vtNextDer = Vector3d( 0, 0, 0) ; + } + } + // punti intermedi + else { + if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // salvo la derivata + m_vPrevDer.push_back( vtPrevDer) ; + m_vNextDer.push_back( vtNextDer) ; + } + + return true ; +} diff --git a/CurveComposite.cpp b/CurveComposite.cpp index ed61b13..c89a2a2 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -2296,8 +2296,12 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo pArcP->GetEndPoint( ptP2) ; Point3d ptP3 ; pArcC->GetEndPoint( ptP3) ; + // verifico se circonferenza completa + bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ; + if ( bCirc) + pArcC->GetMidPoint( ptP3) ; CurveArc NewArc ; - if ( NewArc.Set3P( ptP1, ptP2, ptP3)) { + if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) { // verifico normale al piano dell'arco if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0) NewArc.InvertN() ; diff --git a/CurveCompositeOffset.cpp b/CurveCompositeOffset.cpp index ebed9f3..9bf06e5 100644 --- a/CurveCompositeOffset.cpp +++ b/CurveCompositeOffset.cpp @@ -65,6 +65,8 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) double dLenVertLast = 0 ; // recupero la prima curva ICurve* pCrv1 = ccCopy.RemoveFirstOrLastCurve( false) ; + if ( pCrv1 == nullptr) + return false ; // se la curva è una linea verticale in Z, passo alla successiva if ( IsVerticalLine( pCrv1, &dLenVertFirst)) { delete pCrv1 ; @@ -73,9 +75,13 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) pCrv1 = ccCopy.RemoveFirstOrLastCurve( false) ; } // offset della prima curva - if ( pCrv1 == nullptr || - ! pCrv1->SimpleOffset( dDist, nType) || - ! ccOffs.AddSimpleCurve( pCrv1)) + if ( pCrv1 == nullptr) + return false ; + if ( ! pCrv1->SimpleOffset( dDist, nType)){ + delete pCrv1 ; + return false ; + } + if ( ! ccOffs.AddSimpleCurve( pCrv1)) return false ; // curve successive ICurve* pCrv2 = ccCopy.RemoveFirstOrLastCurve( false) ; @@ -89,8 +95,10 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) continue ; } // eseguo semplice offset - if ( ! pCrv2->SimpleOffset( dDist, nType)) + if ( ! pCrv2->SimpleOffset( dDist, nType)) { + delete pCrv2 ; return false ; + } // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie CurveComposite ccTemp ; if ( VerifyAndAdjustSamePoint( pCrv1, pCrv2, ccTemp) || diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 03a7989..1c8eec6 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 3f42458..c75cf3d 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -262,6 +262,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index f90fe6f..d29cc3d 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -294,6 +294,9 @@ File di origine\GeoInters + + File di origine\GeoCreate + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 60c275c..ad48a0f 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -1810,13 +1810,11 @@ GdbExecutor::CurveCompoFromPointInterpolation( const STRVECTOR& vsParams) nType = CurveByInterp::CUBIC_BEZIERS ; // oggetto interpolatore CurveByInterp crvByInterp ; - crvByInterp.Start() ; Point3d ptP ; for ( bool bFound = PL.GetFirstPoint( ptP) ; bFound ; bFound = PL.GetNextPoint( ptP)) crvByInterp.AddPoint( ptP) ; - crvByInterp.End() ; PtrOwner pCrv( crvByInterp.GetCurve( nMethod, nType)) ; if ( IsNull( pCrv)) return false ; diff --git a/IntersArcArc.cpp b/IntersArcArc.cpp index 229be2b..a6b4048 100644 --- a/IntersArcArc.cpp +++ b/IntersArcArc.cpp @@ -18,7 +18,7 @@ using namespace std ; //---------------------------------------------------------------------------- -IntersArcArc::IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) +IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2) { // Le intersezioni sono calcolate nel piano XY locale. @@ -41,7 +41,6 @@ IntersArcArc::IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) return ; if ( ! m_Arc2.GetNormVersor().IsZplus() && ! m_Arc2.GetNormVersor().IsZminus()) return ; - // !!! Gestire gli archi proiettati come ellissi // verifico sovrapposizione box BBox3d boxArc1 ; @@ -225,8 +224,16 @@ IntersArcArc::IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) return ; } + // parametri per calcolo intersezioni + // distanza da centro 1 della proiezione delle intersezioni sulla retta congiungente i centri + double dA = ( m_Arc1.GetRadius() * m_Arc1.GetRadius() - m_Arc2.GetRadius() * m_Arc2.GetRadius() + + dDist * dDist) / ( 2 * dDist) ; + // semi-distanza tra i punti di intersezione (al quadrato) + double dSqH = m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA ; + // cerchi tangenti esterni -> una intersezione - if ( fabs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_SMALL) { + if ( dSqH < EPS_SMALL * EPS_SMALL && + fabs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_SMALL) { // calcolo il punto di intersezione Point3d ptInt = m_Arc1.GetCenter() + vtDir * m_Arc1.GetRadius() ; // posizione parametrica dell'intersezione sul primo arco @@ -316,7 +323,8 @@ IntersArcArc::IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) } // cerchi tangenti interni -> una intersezione - if ( fabs( dDist - fabs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_SMALL) { + if ( dSqH < EPS_SMALL * EPS_SMALL && + fabs( dDist - fabs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_SMALL) { // determino quale dei due contiene l'altro bool bBiggest1 = ( m_Arc1.GetRadius() > m_Arc2.GetRadius()) ; // calcolo il punto di intersezione @@ -408,9 +416,7 @@ IntersArcArc::IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) } // due intersezioni - double dA = ( m_Arc1.GetRadius() * m_Arc1.GetRadius() - m_Arc2.GetRadius() * m_Arc2.GetRadius() + - dDist * dDist) / ( 2 * dDist) ; - double dH = sqrt( m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA) ; + double dH = sqrt( dSqH) ; Point3d ptRef = m_Arc1.GetCenter() + dA * vtDir ; Vector3d vtDelta = dH * vtDir ; vtDelta.Rotate( Z_AX, 0, 1) ; diff --git a/IntersArcArc.h b/IntersArcArc.h index 3fb407e..a38a012 100644 --- a/IntersArcArc.h +++ b/IntersArcArc.h @@ -23,7 +23,7 @@ class IntersArcArc friend class IntersCurveCurve ; public : - IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) ; + IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2) ; public : bool GetOverlaps( void) diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index 0c2fb8c..da05cfa 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -121,7 +121,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve) void IntersCurveCurve::LineLineCalculate( const ICurve& CurveA, const ICurve& CurveB, bool bAreSegments) { - IntersLineLine intLnLn( *GetCurveLine( &CurveA), *GetCurveLine( &CurveB), bAreSegments) ; + IntersLineLine intLnLn( *GetBasicCurveLine( &CurveA), *GetBasicCurveLine( &CurveB), bAreSegments) ; if ( intLnLn.m_nNumInters > 0) { m_bOverlaps = intLnLn.m_bOverlaps ; @@ -135,7 +135,7 @@ IntersCurveCurve::LineLineCalculate( const ICurve& CurveA, const ICurve& CurveB, void IntersCurveCurve::LineArcCalculate( const ICurve& CurveA, const ICurve& CurveB) { - IntersLineArc intLnAr( *GetCurveLine( &CurveA), *GetCurveArc( &CurveB)) ; + IntersLineArc intLnAr( *GetBasicCurveLine( &CurveA), *GetBasicCurveArc( &CurveB)) ; if ( intLnAr.m_nNumInters > 0) { m_bOverlaps = false ; @@ -160,7 +160,7 @@ IntersCurveCurve::LineCrvCompoCalculate( const ICurve& CurveA, const ICurve& Cur void IntersCurveCurve::ArcLineCalculate( const ICurve& CurveA, const ICurve& CurveB) { - IntersLineArc intLnAr( *GetCurveLine( &CurveB), *GetCurveArc( &CurveA)) ; + IntersLineArc intLnAr( *GetBasicCurveLine( &CurveB), *GetBasicCurveArc( &CurveA)) ; if ( intLnAr.m_nNumInters > 0) { m_bOverlaps = false ; @@ -176,7 +176,7 @@ IntersCurveCurve::ArcLineCalculate( const ICurve& CurveA, const ICurve& CurveB) void IntersCurveCurve::ArcArcCalculate( const ICurve& CurveA, const ICurve& CurveB) { - IntersArcArc intArAr( *GetCurveArc( &CurveA), *GetCurveArc( &CurveB)) ; + IntersArcArc intArAr( *GetBasicCurveArc( &CurveA), *GetBasicCurveArc( &CurveB)) ; if ( intArAr.m_nNumInters > 0) { m_bOverlaps = intArAr.m_bOverlaps ; diff --git a/IntersLineArc.cpp b/IntersLineArc.cpp index 649ee9c..6d3b4aa 100644 --- a/IntersLineArc.cpp +++ b/IntersLineArc.cpp @@ -18,7 +18,7 @@ using namespace std ; //---------------------------------------------------------------------------- -IntersLineArc::IntersLineArc( const ICurveLine& Line, const ICurveArc& Arc) +IntersLineArc::IntersLineArc( const CurveLine& Line, const CurveArc& Arc) { // Le intersezioni sono calcolate nel piano XY locale. @@ -69,8 +69,9 @@ IntersLineArc::IntersLineArc( const ICurveLine& Line, const ICurveArc& Arc) if ( dSqDelta < - 2 * m_Arc.GetRadius() * EPS_SMALL) return ; - // se distanza uguale al raggio -> una intersezione tangente (è la proiezione) - if ( dSqDelta < 2 * m_Arc.GetRadius() * EPS_SMALL) { + // se distanza uguale al raggio -> una intersezione tangente, è la proiezione + // (verifico che la distanza tra la proiezione e i punti di secanza sia minore di epsilon) + if ( dSqDelta < EPS_SMALL * EPS_SMALL) { // determinazione geometrica dell'intersezione tra le due curve int nPosL, nPosA ; if ( ! CalcIntersGeomData( 0, ptPrjCen, nPosL, nPosA)) diff --git a/IntersLineArc.h b/IntersLineArc.h index 8913f9e..1d0d667 100644 --- a/IntersLineArc.h +++ b/IntersLineArc.h @@ -24,7 +24,7 @@ class IntersLineArc friend class IntersCurveCurve ; public : - IntersLineArc( const ICurveLine& Line, const ICurveArc& Arc) ; + IntersLineArc( const CurveLine& Line, const CurveArc& Arc) ; public : bool GetOverlaps( void) diff --git a/IntersLineLine.cpp b/IntersLineLine.cpp index 041c7bd..d92c882 100644 --- a/IntersLineLine.cpp +++ b/IntersLineLine.cpp @@ -36,7 +36,7 @@ IsPointOutFatSegment( const Point3d& ptP, const Point3d& ptS, const Vector3d& vt } //---------------------------------------------------------------------------- -IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinite) +IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2, bool bFinite) { // Le intersezioni sono calcolate nel piano XY locale. diff --git a/IntersLineLine.h b/IntersLineLine.h index 6f1a802..164856c 100644 --- a/IntersLineLine.h +++ b/IntersLineLine.h @@ -14,7 +14,7 @@ #pragma once #include "/EgtDev/Include/EGkIntersCurves.h" -#include "/EgtDev/Include/EGkCurveLine.h" +#include "CurveLine.h" //----------------------------------------------------------------------------- @@ -23,7 +23,7 @@ class IntersLineLine friend class IntersCurveCurve ; public : - IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinite = true) ; + IntersLineLine( const CurveLine& Line1, const CurveLine& Line2, bool bFinite = true) ; public : bool GetOverlaps( void)