7cdc1ba5a3
- implementazione dell'approsimazione tramite curve di bezier.
151 lines
5.0 KiB
C++
151 lines
5.0 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : CurveByInterp.cpp Data : 05.08.14 Versione : 1.5h1
|
|
// Contenuto : Implementazione della classe CurveByInterp, per creare
|
|
// una curva mediante interpolazione di punti.
|
|
//
|
|
//
|
|
// Modifiche : 05.08.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "CalcDerivate.h"
|
|
#include "CurveBezier.h"
|
|
#include "CurveComposite.h"
|
|
#include "/EgtDev/Include/EGkCurveByInterp.h"
|
|
#include "/EgtDev/Include/EGkBiArcs.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveByInterp::Reset( void)
|
|
{
|
|
// pulisco i diversi vettori
|
|
m_vPnt.clear() ;
|
|
m_vPar.clear() ;
|
|
m_vPrevDer.clear() ;
|
|
m_vNextDer.clear() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveByInterp::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*
|
|
CurveByInterp::GetCurve( int nMethod, int nType)
|
|
{
|
|
// se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs)
|
|
if ( nType == CUBIC_BEZIERS_LONG) {
|
|
// creo la curva composita
|
|
PtrOwner<ICurve> pCrv ;
|
|
//pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ;
|
|
//debug
|
|
pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 0.1, 100)) ;
|
|
if ( IsNull(pCrv) || ! pCrv->IsValid())
|
|
return nullptr ;
|
|
return Release( pCrv) ;
|
|
}
|
|
|
|
// numero di punti
|
|
int nSize = int( m_vPnt.size()) ;
|
|
|
|
// sono necessari almeno due punti
|
|
if ( nSize < 2)
|
|
return nullptr ;
|
|
|
|
// 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 tangenti
|
|
if ( nMethod == BESSEL) {
|
|
if ( ! CalcBesselTangents())
|
|
return nullptr ;
|
|
}
|
|
else {
|
|
if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER))
|
|
return nullptr ;
|
|
}
|
|
|
|
// se richiesti biarchi
|
|
if ( nType == BIARCS) {
|
|
// creo la curva composita
|
|
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
|
|
if ( IsNull( pCrvCompo))
|
|
return nullptr ;
|
|
// ciclo sugli intervalli
|
|
for ( int i = 1 ; i < int( m_vPnt.size()) ; ++ i) {
|
|
// creo un biarco per ogni intervallo
|
|
double dDirStartDeg ;
|
|
m_vNextDer[i-1].ToSpherical( nullptr, nullptr, &dDirStartDeg) ;
|
|
double dDirEndDeg ;
|
|
m_vPrevDer[i].ToSpherical( nullptr, nullptr, &dDirEndDeg) ;
|
|
ICurve* pCrv = GetBiArc( m_vPnt[i-1], dDirStartDeg, m_vPnt[i], dDirEndDeg, 0.5) ;
|
|
if ( ! pCrvCompo->AddCurve( pCrv))
|
|
return nullptr ;
|
|
}
|
|
return ::Release( pCrvCompo) ;
|
|
}
|
|
|
|
// se richieste curve di Bezier cubiche
|
|
if ( nType == CUBIC_BEZIERS) {
|
|
// creo la curva composita
|
|
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
|
|
if ( IsNull( pCrvCompo))
|
|
return nullptr ;
|
|
// ciclo sugli intervalli
|
|
for ( int i = 1 ; i < int( m_vPnt.size()) ; ++ i) {
|
|
// creo una curva di Bezier cubica per ogni intervallo
|
|
PtrOwner<CurveBezier> pCBez( CreateBasicCurveBezier()) ;
|
|
if ( IsNull( pCBez))
|
|
return nullptr ;
|
|
pCBez->Init( 3, false) ;
|
|
pCBez->SetControlPoint( 0, m_vPnt[i-1]) ;
|
|
pCBez->SetControlPoint( 1, m_vPnt[i-1] + ( m_vPar[i] - m_vPar[i-1]) / 3 * m_vNextDer[i-1]) ;
|
|
pCBez->SetControlPoint( 2, m_vPnt[i] - ( m_vPar[i] - m_vPar[i-1]) / 3 * m_vPrevDer[i]) ;
|
|
pCBez->SetControlPoint( 3, m_vPnt[i]) ;
|
|
if ( ! pCrvCompo->AddCurve( ::Release( pCBez)))
|
|
return nullptr ;
|
|
}
|
|
return ::Release( pCrvCompo) ;
|
|
}
|
|
|
|
return nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
|
|
{
|
|
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveByInterp::CalcBesselTangents( void)
|
|
{
|
|
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
|
} |