Files
EgtGeomKernel/CurveByInterp.cpp
T
Daniele Bariletti 7cdc1ba5a3 EgtGeomKernel :
- implementazione dell'approsimazione tramite curve di bezier.
2026-02-05 16:54:09 +01:00

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) ;
}