//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : PolynomialPoint3d.cpp Data : 12.01.14 Versione : 1.5a2 // Contenuto : Implementazione classe polinomio con coefficienti Point3d. // // // // Modifiche : 12.01.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "PolynomialPoint3d.h" //---------------------------------------------------------------------------- bool PolynomialPoint3d::SetDegree( int nDegree) { // gradi negativi non hanno senso if ( nDegree < 0) return false ; // pulisco, alloco e inizializzo a 0 try { m_Coeff.clear() ; m_Coeff.reserve( nDegree + 1) ; m_nDegree = nDegree ; for ( int i = 0 ; i <= m_nDegree ; ++ i) m_Coeff.emplace_back( 0, 0, 0) ; return true ; } catch (...) { return false ; } } //---------------------------------------------------------------------------- bool PolynomialPoint3d::EnsureDegree( int nDegree) { // se il grado è già adeguato non devo fare alcunché if ( nDegree <= m_nDegree) return true ; // alloco e inizializzo a 0 i nuovi coefficienti try { m_Coeff.reserve( nDegree + 1) ; for ( int i = m_nDegree + 1 ; i <= nDegree ; ++ i) m_Coeff.emplace_back() ; m_nDegree = nDegree ; return true ; } catch (...) { return false ; } } //---------------------------------------------------------------------------- bool PolynomialPoint3d::SetCoeff( int nPower, Point3d& ptP) { if ( nPower < 0 || nPower > m_nDegree) return false ; m_Coeff[nPower] = ptP ; return true ; } //---------------------------------------------------------------------------- bool PolynomialPoint3d::Set( int nDegree, const PNTVECTOR& vP) { if ( ! SetDegree( nDegree)) return false ; for ( int i = 0 ; i <= nDegree ; i ++) m_Coeff[i] = vP[i] ; return true ; } //---------------------------------------------------------------------------- bool PolynomialPoint3d::SetToConstant( const Point3d& ptP) { if ( ! SetDegree( 0)) return false ; m_Coeff[0] = ptP ; return true ; } //---------------------------------------------------------------------------- PolynomialPoint3d& PolynomialPoint3d::operator +=( const PolynomialPoint3d& pol3P) { // mi assicuro che il polinomio risultante abbia grado sufficiente EnsureDegree( pol3P.GetDegree()) ; // eseguo la somma for ( int i = 0 ; i <= pol3P.GetDegree() ; ++ i) m_Coeff[i] += pol3P.m_Coeff[i] ; return *this ; } //---------------------------------------------------------------------------- PolynomialPoint3d& PolynomialPoint3d::operator -=( const PolynomialPoint3d& pol3P) { // mi assicuro che il polinomio risultante abbia grado sufficiente EnsureDegree( pol3P.GetDegree()) ; // eseguo la somma for ( int i = 0 ; i <= pol3P.GetDegree() ; ++ i) m_Coeff[i] += ( - pol3P.m_Coeff[i]) ; return *this ; } //---------------------------------------------------------------------------- PolynomialPoint3d& PolynomialPoint3d::operator *=( const Polynomial& polP) { // copio il polinomio corrente PolynomialPoint3d pol3C = *this ; // pulisco e imposto il grado del polinomio risultante SetDegree( pol3C.GetDegree() + polP.GetDegree()) ; // eseguo il prodotto for ( int i = 0 ; i <= pol3C.GetDegree() ; ++ i) { for ( int j = 0 ; j <= polP.GetDegree() ; ++ j) m_Coeff[i+j] += pol3C.m_Coeff[i] * polP.GetCoeff(j) ; } return *this ; } //---------------------------------------------------------------------------- void PolynomialPoint3d::Derive( void) { // polinomio non inizializzato if ( m_nDegree < 0) return ; // polinomio costante if ( m_nDegree == 0) { m_Coeff[0] = Point3d( 0, 0, 0) ; return ; } // caso normale for ( int i = 0 ; i < m_nDegree ; ++ i) m_Coeff[i] = ( i + 1) * m_Coeff[i+1] ; m_Coeff.pop_back() ; -- m_nDegree ; } //---------------------------------------------------------------------------- void PolynomialPoint3d::Derive( const PolynomialPoint3d& pol3P) { operator=( pol3P) ; Derive() ; } //---------------------------------------------------------------------------- void PolynomialPoint3d::AdjustDegree( void) { // se il coefficiente del grado più alto è zero, diminuisco il grado while ( m_nDegree >= 0 && abs( m_Coeff[m_nDegree].x) < DBL_EPSILON && abs( m_Coeff[m_nDegree].y) < DBL_EPSILON && abs( m_Coeff[m_nDegree].z) < DBL_EPSILON) { m_Coeff.pop_back() ; -- m_nDegree ; } } //---------------------------------------------------------------------------- Point3d PolynomialPoint3d::Evaluate( double dVal) { // polinomio non inizializzato if ( m_nDegree < 0) return Point3d( 0, 0, 0) ; // caso normale Point3d ptRes = m_Coeff[m_nDegree] ; for ( int i = m_nDegree - 1 ; i >= 0 ; -- i) ptRes = ptRes * dVal + m_Coeff[i] ; return ptRes ; } //---------------------------------------------------------------------------- int PolynomialPoint3d::FindMainComponentRoots( DBLVECTOR& vdRoot) { // cerco la componente più significativa tra x, y e z Point3d ptSumm ; for ( int i = 0 ; i <= m_nDegree ; ++ i) { ptSumm.x += abs( m_Coeff[i].x) ; ptSumm.y += abs( m_Coeff[i].y) ; ptSumm.z += abs( m_Coeff[i].z) ; } // la copio in un polinomio numerico Polynomial polP ; if ( ! polP.SetDegree( m_nDegree)) return 0 ; if ( ptSumm.x > ptSumm.y && ptSumm.x > ptSumm.z) { for ( int i = 0 ; i <= m_nDegree ; ++ i) polP.SetCoeff( i, m_Coeff[i].x) ; } else if ( ptSumm.y > ptSumm.z) { for ( int i = 0 ; i <= m_nDegree ; ++ i) polP.SetCoeff( i, m_Coeff[i].y) ; } else { for ( int i = 0 ; i <= m_nDegree ; ++ i) polP.SetCoeff( i, m_Coeff[i].z) ; } // calcolo le radici reali di questo polinomio numerico return polP.FindRoots( vdRoot) ; }