EgtGeomKernel 1.6g7 :
- aggiunta approssimazione di punti con archi e rette (CurveByApprox) - fatte correzioni ad intersezioni rette/archi e archi/archi quasi tangenti - correzioni ad offset di curve composite che non liberava memoria in caso di errore.
This commit is contained in:
+4
-13
@@ -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<ICurve> 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)) ;
|
||||
}
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
|
||||
+7
-7
@@ -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,
|
||||
|
||||
+14
-3
@@ -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 <new>
|
||||
|
||||
@@ -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<ICurveComposite> pCC( CreateCurveComposite()) ;
|
||||
PtrOwner<CurveComposite> pCC( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCC))
|
||||
return false ;
|
||||
if ( ! pCC->FromPolyLine( PL))
|
||||
|
||||
@@ -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 <algorithm>
|
||||
|
||||
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<CurveComposite> 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<ICurve> 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<CurveComposite> 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) ;
|
||||
}
|
||||
+127
-71
@@ -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 ;
|
||||
}
|
||||
|
||||
+5
-1
@@ -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() ;
|
||||
|
||||
@@ -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) ||
|
||||
|
||||
Binary file not shown.
@@ -262,6 +262,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CircleCenTgCurve.cpp" />
|
||||
<ClCompile Include="Color.cpp" />
|
||||
<ClCompile Include="CreateCurveAux.cpp" />
|
||||
<ClCompile Include="CurveByApprox.cpp" />
|
||||
<ClCompile Include="CurveByInterp.cpp" />
|
||||
<ClCompile Include="CurveCompositeOffset.cpp" />
|
||||
<ClCompile Include="DistPointArc.cpp" />
|
||||
|
||||
@@ -294,6 +294,9 @@
|
||||
<ClCompile Include="SelfIntersCurve.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CurveByApprox.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
||||
@@ -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<ICurve> pCrv( crvByInterp.GetCurve( nMethod, nType)) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
|
||||
+13
-7
@@ -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) ;
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
+4
-3
@@ -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))
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user