Approximation.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Imetric 3D GmbH                                    *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <algorithm>
00028 #endif
00029 
00030 #include "Approximation.h"
00031 
00032 #include <boost/math/special_functions/fpclassify.hpp>
00033 #include <Mod/Mesh/App/WildMagic4/Wm4ApprQuadraticFit3.h>
00034 #include <Mod/Mesh/App/WildMagic4/Wm4ApprPlaneFit3.h>
00035 #include <Mod/Mesh/App/WildMagic4/Wm4DistVector3Plane3.h>
00036 #include <Mod/Mesh/App/WildMagic4/Wm4Matrix3.h>
00037 #include <Mod/Mesh/App/WildMagic4/Wm4ApprPolyFit3.h>
00038 
00039 //#define FC_USE_EIGEN
00040 #if defined(FC_USE_BOOST)
00041 #include <boost/numeric/ublas/io.hpp>
00042 #include <boost/numeric/bindings/traits/ublas_matrix.hpp>
00043 #include <boost/numeric/bindings/traits/ublas_vector.hpp>
00044 
00045 #define BOOST_NUMERIC_BINDINGS_USE_CLAPACK
00046 #include <boost/numeric/bindings/lapack/syev.hpp>
00047 #include <boost/numeric/bindings/lapack/heev.hpp>
00048 #include <boost/numeric/bindings/lapack/gesv.hpp> 
00049 
00050 namespace ublas = boost::numeric::ublas; 
00051 extern "C" void LAPACK_DGESV (int const* n, int const* nrhs, 
00052                      double* a, int const* lda, int* ipiv, 
00053                      double* b, int const* ldb, int* info);
00054 #elif defined(FC_USE_EIGEN)
00055 # include <Eigen/LeastSquares>
00056 #endif
00057 
00058 using namespace MeshCore;
00059 
00060 
00061 void Approximation::Convert( const Wm4::Vector3<float>& Wm4, Base::Vector3f& pt)
00062 {
00063     pt.Set( Wm4.X(), Wm4.Y(), Wm4.Z() );
00064 }
00065 
00066 void Approximation::Convert( const Base::Vector3f& pt, Wm4::Vector3<float>& Wm4)
00067 {
00068     Wm4.X() = pt.x; Wm4.Y() = pt.y; Wm4.Z() = pt.z;
00069 }
00070 
00071 void Approximation::GetMgcVectorArray(std::vector< Wm4::Vector3<float> >& rcPts) const
00072 {
00073     std::list< Base::Vector3f >::const_iterator It;
00074     for (It = _vPoints.begin(); It != _vPoints.end(); ++It) {
00075         Wm4::Vector3<float> pt( (*It).x, (*It).y, (*It).z );
00076         rcPts.push_back( pt );
00077     }
00078 }
00079 
00080 void Approximation::AddPoint(const Base::Vector3f &rcVector)
00081 {
00082     _vPoints.push_back(rcVector);
00083     _bIsFitted = false;
00084 }
00085 
00086 void Approximation::AddPoints(const std::vector<Base::Vector3f> &rvPointVect)
00087 {
00088     std::vector<Base::Vector3f>::const_iterator cIt;
00089     for (cIt = rvPointVect.begin(); cIt != rvPointVect.end(); ++cIt)
00090         _vPoints.push_back(*cIt);
00091     _bIsFitted = false;
00092 }
00093 
00094 void Approximation::AddPoints(const std::set<Base::Vector3f> &rsPointSet)
00095 {
00096     std::set<Base::Vector3f>::const_iterator cIt;
00097     for (cIt = rsPointSet.begin(); cIt != rsPointSet.end(); ++cIt)
00098         _vPoints.push_back(*cIt);
00099     _bIsFitted = false;
00100 }
00101 
00102 void Approximation::AddPoints(const std::list<Base::Vector3f> &rsPointList)
00103 {
00104     std::list<Base::Vector3f>::const_iterator cIt;
00105     for (cIt = rsPointList.begin(); cIt != rsPointList.end(); ++cIt)
00106         _vPoints.push_back(*cIt);
00107     _bIsFitted = false;
00108 }
00109 
00110 Base::Vector3f Approximation::GetGravity() const
00111 {
00112     Base::Vector3f clGravity;
00113     for (std::list<Base::Vector3f>::const_iterator it = _vPoints.begin(); it!=_vPoints.end(); ++it)
00114         clGravity += *it;
00115     clGravity *= 1.0f / float(_vPoints.size());
00116     return clGravity;
00117 }
00118 
00119 unsigned long Approximation::CountPoints() const
00120 { 
00121     return _vPoints.size();
00122 }
00123 
00124 void Approximation::Clear()
00125 {
00126     _vPoints.clear();
00127     _bIsFitted = false;
00128 }
00129 
00130 float Approximation::GetLastResult() const
00131 {
00132     return _fLastResult;
00133 }
00134 
00135 bool Approximation::Done() const
00136 {
00137     return _bIsFitted;
00138 }
00139 
00140 // -------------------------------------------------------------------------------
00141 
00142 float PlaneFit::Fit()
00143 {
00144     _bIsFitted = true;
00145     if (CountPoints() < 3)
00146         return FLOAT_MAX;
00147 
00148     double sxx,sxy,sxz,syy,syz,szz,mx,my,mz;
00149     sxx=sxy=sxz=syy=syz=szz=mx=my=mz=0.0f;
00150 
00151     for (std::list<Base::Vector3f>::iterator it = _vPoints.begin(); it!=_vPoints.end(); ++it) {
00152         sxx += it->x * it->x; sxy += it->x * it->y;
00153         sxz += it->x * it->z; syy += it->y * it->y;
00154         syz += it->y * it->z; szz += it->z * it->z;
00155         mx  += it->x;   my += it->y;   mz += it->z;
00156     }
00157 
00158     unsigned int nSize = _vPoints.size();
00159     sxx = sxx - mx*mx/((double)nSize);
00160     sxy = sxy - mx*my/((double)nSize);
00161     sxz = sxz - mx*mz/((double)nSize);
00162     syy = syy - my*my/((double)nSize);
00163     syz = syz - my*mz/((double)nSize);
00164     szz = szz - mz*mz/((double)nSize);
00165 
00166 #if defined(FC_USE_BOOST)
00167     ublas::matrix<double> A(3,3);
00168     A(0,0) = sxx;
00169     A(1,1) = syy;
00170     A(2,2) = szz;
00171     A(0,1) = sxy; A(1,0) = sxy;
00172     A(0,2) = sxz; A(2,0) = sxz;
00173     A(1,2) = syz; A(2,1) = syz;
00174     namespace lapack= boost::numeric::bindings::lapack;
00175     ublas::vector<double> eigenval(3);
00176     int r = lapack::syev('V','U',A,eigenval,lapack::optimal_workspace());
00177     if (r) {
00178     }
00179     float sigma;
00180 #elif defined(FC_USE_EIGEN)
00181     Eigen::Matrix3d covMat = Eigen::Matrix3d::Zero();
00182     covMat(0,0) = sxx;
00183     covMat(1,1) = syy;
00184     covMat(2,2) = szz;
00185     covMat(0,1) = sxy; covMat(1,0) = sxy;
00186     covMat(0,2) = sxz; covMat(2,0) = sxz;
00187     covMat(1,2) = syz; covMat(2,1) = syz;
00188     Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(covMat);
00189 
00190     Eigen::Vector3d u = eig.eigenvectors().col(1);
00191     Eigen::Vector3d v = eig.eigenvectors().col(2);
00192     Eigen::Vector3d w = eig.eigenvectors().col(0);
00193 
00194     _vDirU.Set(u.x(), u.y(), u.z());
00195     _vDirV.Set(v.x(), v.y(), v.z());
00196     _vDirW.Set(w.x(), w.y(), w.z());
00197     _vBase.Set(mx/(float)nSize, my/(float)nSize, mz/(float)nSize);
00198 
00199     float sigma = w.dot(covMat * w);
00200 #else
00201     // Covariance matrix
00202     Wm4::Matrix3<double> akMat(sxx,sxy,sxz,sxy,syy,syz,sxz,syz,szz);
00203     Wm4::Matrix3<double> rkRot, rkDiag;
00204     try {
00205         akMat.EigenDecomposition(rkRot, rkDiag);
00206     }
00207     catch (const std::exception&) {
00208         return FLOAT_MAX;
00209     }
00210 
00211     Wm4::Vector3<double> U = rkRot.GetColumn(1);
00212     Wm4::Vector3<double> V = rkRot.GetColumn(2);
00213     Wm4::Vector3<double> W = rkRot.GetColumn(0);
00214 
00215     // It may happen that the result have nan values
00216     for (int i=0; i<3; i++) {
00217         if (boost::math::isnan(U[i]) || 
00218             boost::math::isnan(V[i]) ||
00219             boost::math::isnan(W[i]))
00220             return FLOAT_MAX;
00221     }
00222 
00223     _vDirU.Set((float)U.X(), (float)U.Y(), (float)U.Z());
00224     _vDirV.Set((float)V.X(), (float)V.Y(), (float)V.Z());
00225     _vDirW.Set((float)W.X(), (float)W.Y(), (float)W.Z());
00226     _vBase.Set((float)(mx/nSize), (float)(my/nSize), (float)(mz/nSize));
00227     float sigma = (float)W.Dot(akMat * W);
00228 #endif
00229 
00230     // make a right-handed system
00231     if ((_vDirU % _vDirV) * _vDirW < 0.0f) {
00232         Base::Vector3f tmp = _vDirU;
00233         _vDirU = _vDirV;
00234         _vDirV = tmp;
00235     }
00236 
00237     if (nSize > 3)
00238         sigma = sqrt(sigma/(nSize-3));
00239     _fLastResult = sigma;
00240     return _fLastResult;
00241 }
00242 
00243 Base::Vector3f PlaneFit::GetBase() const
00244 {
00245     if (_bIsFitted)
00246         return _vBase;
00247     else
00248         return Base::Vector3f();
00249 }
00250 
00251 Base::Vector3f PlaneFit::GetDirU() const
00252 {
00253     if (_bIsFitted)
00254         return _vDirU;
00255     else
00256         return Base::Vector3f();
00257 }
00258 
00259 Base::Vector3f PlaneFit::GetDirV() const
00260 {
00261     if (_bIsFitted)
00262         return _vDirV;
00263     else
00264         return Base::Vector3f();
00265 }
00266 
00267 Base::Vector3f PlaneFit::GetNormal() const
00268 {
00269     if (_bIsFitted)
00270         return _vDirW;
00271     else
00272         return Base::Vector3f();
00273 }
00274 
00275 float PlaneFit::GetDistanceToPlane(const Base::Vector3f &rcPoint) const
00276 {
00277     float fResult = FLOAT_MAX;
00278     if (_bIsFitted)
00279         fResult = (rcPoint - _vBase) * _vDirW;
00280     return fResult;
00281 }
00282 
00283 float PlaneFit::GetStdDeviation() const
00284 {
00285     // Mean: M=(1/N)*SUM Xi
00286     // Variance: VAR=(N/N-3)*[(1/N)*SUM(Xi^2)-M^2]
00287     // Standard deviation: SD=SQRT(VAR)
00288     // Standard error of the mean: SE=SD/SQRT(N)
00289     if (!_bIsFitted)
00290         return FLOAT_MAX;
00291 
00292     float fSumXi = 0.0f, fSumXi2 = 0.0f,
00293           fMean  = 0.0f, fDist   = 0.0f;
00294 
00295     float ulPtCt = (float)CountPoints();
00296     std::list< Base::Vector3f >::const_iterator cIt;
00297 
00298     for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt) {
00299         fDist = GetDistanceToPlane( *cIt );
00300         fSumXi  += fDist;
00301         fSumXi2 += ( fDist * fDist );
00302     }
00303 
00304     fMean = (1.0f / ulPtCt) * fSumXi;
00305     return (float)sqrt((ulPtCt / (ulPtCt - 3.0)) * ((1.0 / ulPtCt) * fSumXi2 - fMean * fMean));
00306 }
00307 
00308 float PlaneFit::GetSignedStdDeviation() const
00309 {
00310     // if the nearest point to the gravity is at the side 
00311     // of normal direction the value will be 
00312     // positive otherwise negative
00313     if (!_bIsFitted)
00314         return FLOAT_MAX;
00315 
00316     float fSumXi = 0.0f, fSumXi2 = 0.0f,
00317           fMean  = 0.0f, fDist   = 0.0f;
00318     float fMinDist = FLOAT_MAX;
00319     float fFactor;
00320 
00321     float ulPtCt = (float)CountPoints();
00322     Base::Vector3f clGravity, clPt;
00323     std::list<Base::Vector3f>::const_iterator cIt;
00324     for (cIt = _vPoints.begin(); cIt != _vPoints.end(); cIt++)
00325         clGravity += *cIt;
00326     clGravity *= (1.0f / ulPtCt);
00327 
00328     for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt) {
00329         if ((clGravity - *cIt).Length() < fMinDist) {
00330             fMinDist = (clGravity - *cIt).Length();
00331             clPt = *cIt;
00332         }
00333         fDist = GetDistanceToPlane(*cIt);
00334         fSumXi  += fDist;
00335         fSumXi2 += (fDist * fDist);
00336     }
00337 
00338     // which side
00339     if ((clPt-clGravity)*GetNormal() > 0)
00340         fFactor = 1.0f;
00341     else
00342         fFactor = -1.0f;
00343 
00344     fMean = 1.0f / ulPtCt * fSumXi;
00345 
00346     return fFactor * (float)sqrt((ulPtCt / (ulPtCt - 3.0)) * ((1.0 / ulPtCt) * fSumXi2 - fMean * fMean));
00347 }
00348 
00349 void PlaneFit::ProjectToPlane ()
00350 {
00351     Base::Vector3f cGravity(GetGravity());
00352     Base::Vector3f cNormal (GetNormal ());
00353 
00354     for (std::list< Base::Vector3f >::iterator it = _vPoints.begin(); it != _vPoints.end(); ++it) {
00355         Base::Vector3f& cPnt = *it;
00356         float fD = (cPnt - cGravity) * cNormal;
00357         cPnt = cPnt - fD * cNormal;
00358     }
00359 }
00360 
00361 // -------------------------------------------------------------------------------
00362 
00363 float FunctionContainer::dKoeff[]; // Koeffizienten der Quadrik
00364 
00365 bool QuadraticFit::GetCurvatureInfo(float x, float y, float z,
00366                                     float &rfCurv0, float &rfCurv1,
00367                                     Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance)
00368 {
00369     assert( _bIsFitted );
00370     bool bResult = false;
00371 
00372     if (_bIsFitted) {
00373         Wm4::Vector3<float> Dir0, Dir1;
00374         FunctionContainer  clFuncCont( _fCoeff );
00375         bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1, Dir0, Dir1, dDistance );
00376 
00377         dDistance = clFuncCont.GetGradient( x, y, z ).Length();
00378         Convert( Dir0, rkDir0 );
00379         Convert( Dir1, rkDir1 );
00380     }
00381 
00382     return bResult;
00383 }
00384 
00385 bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1)
00386 {
00387     bool bResult = false;
00388 
00389     if (_bIsFitted) {
00390         FunctionContainer clFuncCont( _fCoeff );
00391         bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1 );
00392     }
00393 
00394     return bResult;
00395 }
00396 
00397 const float& QuadraticFit::GetCoeffArray() const
00398 {
00399     return _fCoeff[0];
00400 }
00401 
00402 float QuadraticFit::GetCoeff(unsigned long ulIndex) const
00403 {
00404     assert( ulIndex >= 0 && ulIndex < 10 );
00405 
00406     if( _bIsFitted )
00407         return _fCoeff[ ulIndex ];
00408     else
00409         return FLOAT_MAX;
00410 }
00411 
00412 float QuadraticFit::Fit()
00413 {
00414     float fResult = FLOAT_MAX;
00415 
00416     if (CountPoints() > 0) {
00417         std::vector< Wm4::Vector3<float> > cPts;
00418         GetMgcVectorArray( cPts );
00419         fResult = Wm4::QuadraticFit3<float>( CountPoints(), &(cPts[0]), _fCoeff );
00420         _fLastResult = fResult;
00421 
00422         _bIsFitted = true;
00423     }
00424 
00425     return fResult;
00426 }
00427 
00428 void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLambda3,
00429                                    Base::Vector3f &clEV1, Base::Vector3f &clEV2, Base::Vector3f &clEV3) const
00430 {
00431     assert( _bIsFitted );
00432 
00433     /*
00434      * F(x,y,z) = a11*x*x + a22*y*y + a33*z*z +2*a12*x*y + 2*a13*x*z + 2*a23*y*z + 2*a10*x + 2*a20*y + 2*a30*z * a00 = 0
00435      *
00436      * Formenmatrix:
00437      *
00438      *      ( a11   a12   a13 )
00439      * A =  ( a21   a22   a23 )       wobei gilt a[i,j] = a[j,i]
00440      *      ( a31   a32   a33 )
00441      *
00442      * Koeffizienten des Quadrik-Fits bezogen auf die hier verwendete Schreibweise:
00443      * 
00444      *   0 = C[0] + C[1]*X + C[2]*Y + C[3]*Z + C[4]*X^2 + C[5]*Y^2
00445      *     + C[6]*Z^2 + C[7]*X*Y + C[8]*X*Z + C[9]*Y*Z
00446      *
00447      * Quadratisch:   a11 := c[4],    a22 := c[5],    a33 := c[6]
00448      * Gemischt:      a12 := c[7]/2,  a13 := c[8]/2,  a23 := c[9]/2
00449      * Linear:        a10 := c[1]/2,  a20 := c[2]/2,  a30 := c[3]/2
00450      * Konstant:      a00 := c[0]
00451      *
00452      */
00453 
00454     Wm4::Matrix3<float>  akMat(_fCoeff[4],       _fCoeff[7]/2.0f, _fCoeff[8]/2.0f,
00455                                _fCoeff[7]/2.0f,  _fCoeff[5],      _fCoeff[9]/2.0f,
00456                                _fCoeff[8]/2.0f,  _fCoeff[9]/2.0f, _fCoeff[6]       );
00457 
00458     Wm4::Matrix3<float> rkRot, rkDiag;
00459     akMat.EigenDecomposition( rkRot, rkDiag );
00460 
00461     Wm4::Vector3<float> vEigenU = rkRot.GetColumn(0);
00462     Wm4::Vector3<float> vEigenV = rkRot.GetColumn(1);
00463     Wm4::Vector3<float> vEigenW = rkRot.GetColumn(2);
00464 
00465     Convert( vEigenU, clEV1 );
00466     Convert( vEigenV, clEV2 );
00467     Convert( vEigenW, clEV3 );
00468 
00469     dLambda1 = rkDiag[0][0];
00470     dLambda2 = rkDiag[1][1];
00471     dLambda3 = rkDiag[2][2];
00472 }
00473 
00474 void QuadraticFit::CalcZValues( float x, float y, float &dZ1, float &dZ2 ) const
00475 {
00476     assert( _bIsFitted );
00477 
00478     float dDisk = _fCoeff[3]*_fCoeff[3]+2*_fCoeff[3]*_fCoeff[8]*x+2*_fCoeff[3]*_fCoeff[9]*y+
00479                   _fCoeff[8]*_fCoeff[8]*x*x+2*_fCoeff[8]*x*_fCoeff[9]*y+_fCoeff[9]*_fCoeff[9]*y*y-
00480                   4*_fCoeff[6]*_fCoeff[0]-4*_fCoeff[6]*_fCoeff[1]*x-4*_fCoeff[6]*_fCoeff[2]*y-
00481                   4*_fCoeff[6]*_fCoeff[7]*x*y-4*_fCoeff[6]*_fCoeff[4]*x*x-4*_fCoeff[6]*_fCoeff[5]*y*y;
00482 
00483     if (fabs( _fCoeff[6] ) < 0.000005) {
00484         dZ1 = FLOAT_MAX; 
00485         dZ2 = FLOAT_MAX; 
00486         return;
00487     }
00488 
00489     if (dDisk < 0.0f) {
00490         dZ1 = FLOAT_MAX; 
00491         dZ2 = FLOAT_MAX; 
00492         return;
00493     }
00494     else
00495         dDisk = sqrt( dDisk );
00496 
00497     dZ1 = 0.5f * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y + dDisk ) / _fCoeff[6] );
00498     dZ2 = 0.5f * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y - dDisk ) / _fCoeff[6] );
00499 }
00500 
00501 // -------------------------------------------------------------------------------
00502 
00503 SurfaceFit::SurfaceFit()
00504    : PlaneFit()
00505 {
00506     _fCoeff[0] = 0.0f;
00507     _fCoeff[1] = 0.0f;
00508     _fCoeff[2] = 0.0f;
00509     _fCoeff[3] = 0.0f;
00510     _fCoeff[4] = 0.0f;
00511     _fCoeff[5] = 0.0f;
00512     _fCoeff[6] = 0.0f;
00513     _fCoeff[7] = 0.0f;
00514     _fCoeff[8] = 0.0f;
00515     _fCoeff[9] = 0.0f;
00516 }
00517 
00518 float SurfaceFit::Fit()
00519 {
00520     float fResult = FLOAT_MAX;
00521 
00522     if (CountPoints() > 0) {
00523         fResult = PolynomFit();
00524         _fLastResult = fResult;
00525 
00526         _bIsFitted = true;
00527     }
00528 
00529     return fResult;
00530 }
00531 
00532 bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1,
00533                                   Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance )
00534 {
00535     bool bResult = false;
00536 
00537     if (_bIsFitted) {
00538         Wm4::Vector3<float> Dir0, Dir1;
00539         FunctionContainer  clFuncCont( _fCoeff );
00540         bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1, Dir0, Dir1, dDistance );
00541 
00542         dDistance = clFuncCont.GetGradient( x, y, z ).Length();
00543         Convert( Dir0, rkDir0 );
00544         Convert( Dir1, rkDir1 );
00545     }
00546 
00547     return bResult;
00548 }
00549 
00550 bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1)
00551 {
00552     assert( _bIsFitted );
00553     bool bResult = false;
00554 
00555     if (_bIsFitted) {
00556         FunctionContainer clFuncCont( _fCoeff );
00557         bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1 );
00558     }
00559 
00560     return bResult;
00561 }
00562 
00563 float SurfaceFit::PolynomFit()
00564 {
00565     if (PlaneFit::Fit() == FLOAT_MAX)
00566         return FLOAT_MAX;
00567 
00568 #if 0
00569 #if defined(FC_USE_BOOST)
00570     Base::Vector3d bs(this->_vBase.x,this->_vBase.y,this->_vBase.z);
00571     Base::Vector3d ex(this->_vDirU.x,this->_vDirU.y,this->_vDirU.z);
00572     Base::Vector3d ey(this->_vDirV.x,this->_vDirV.y,this->_vDirV.z);
00573     Base::Vector3d ez(this->_vDirW.x,this->_vDirW.y,this->_vDirW.z);
00574 
00575     ublas::matrix<double> A(6,6);
00576     ublas::vector<double> b(6);
00577     for (int i=0; i<6; i++) {
00578         for (int j=0; j<6; j++) {
00579             A(i,j) = 0.0;
00580         }
00581         b(i) = 0.0;
00582     }
00583 
00584     for (std::list<Base::Vector3f>::const_iterator it = _vPoints.begin(); it != _vPoints.end(); it++) {
00585         Base::Vector3d clPoint(it->x,it->y,it->z);
00586         clPoint.TransformToCoordinateSystem(bs, ex, ey);
00587         double dU = clPoint.x;
00588         double dV = clPoint.y;
00589         double dW = clPoint.z;
00590 
00591         double dU2 = dU*dU;
00592         double dV2 = dV*dV;
00593         double dUV = dU*dV;
00594 
00595         A(0,0) = A(0,0) + dU2*dU2;
00596         A(0,1) = A(0,1) + dU2*dV2;
00597         A(0,2) = A(0,2) + dU2*dUV;
00598         A(0,3) = A(0,3) + dU2*dU ;
00599         A(0,4) = A(0,4) + dU2*dV ;
00600         A(0,5) = A(0,5) + dU2    ;
00601         b(0)   = b(0)   + dU2*dW ;
00602 
00603         A(1,1) = A(1,1) + dV2*dV2;
00604         A(1,2) = A(1,2) + dV2*dUV;
00605         A(1,3) = A(1,3) + dV2*dU ;
00606         A(1,4) = A(1,4) + dV2*dV ;
00607         A(1,5) = A(1,5) + dV2    ;
00608         b(1)   = b(1)   + dV2*dW ;
00609 
00610         A(2,2) = A(2,2) + dUV*dUV;
00611         A(2,3) = A(2,3) + dUV*dU ;
00612         A(2,4) = A(2,4) + dUV*dV ;
00613         A(2,5) = A(2,5) + dUV    ;
00614         b(3)   = b(3)   + dUV*dW ;
00615 
00616         A(3,3) = A(3,3) + dU *dU ;
00617         A(3,4) = A(3,4) + dU *dV ;
00618         A(3,5) = A(3,5) + dU     ;
00619         b(3)   = b(3)   + dU *dW ;
00620 
00621         A(4,4) = A(4,4) + dV *dV ;
00622         A(4,5) = A(4,5) + dV     ;
00623         b(5)   = b(5)   + dV *dW ;
00624 
00625         A(5,5) = A(5,5) + 1      ;
00626         b(5)   = b(5)   + 1  *dW ;
00627     }
00628 
00629     // Mat is symmetric
00630     //
00631     A(1,0) = A(0,1);
00632     A(2,0) = A(0,2);
00633     A(3,0) = A(0,3);
00634     A(4,0) = A(0,4);
00635     A(5,0) = A(0,5);
00636 
00637     A(2,1) = A(1,2);
00638     A(3,1) = A(1,3);
00639     A(4,1) = A(1,4);
00640     A(5,1) = A(1,5);
00641 
00642     A(3,2) = A(2,3);
00643     A(4,2) = A(2,4);
00644     A(5,2) = A(2,5);
00645 
00646     A(4,3) = A(3,4);
00647     A(5,3) = A(3,5);
00648 
00649     A(5,4) = A(4,5);
00650 
00651 
00652     namespace lapack= boost::numeric::bindings::lapack;
00653     //std::clog << A << std::endl;
00654     //std::clog << b << std::endl;
00655     lapack::gesv(A,b);
00656     //std::clog << b << std::endl;
00657 
00658     _fCoeff[0] = (float)(-b(5));
00659     _fCoeff[1] = (float)(-b(3));
00660     _fCoeff[2] = (float)(-b(4));
00661     _fCoeff[3] = 1.0f;
00662     _fCoeff[4] = (float)(-b(0));
00663     _fCoeff[5] = (float)(-b(1));
00664     _fCoeff[6] = 0.0f;
00665     _fCoeff[7] = (float)(-b(2));
00666     _fCoeff[8] = 0.0f;
00667     _fCoeff[9] = 0.0f;
00668 #endif
00669 #endif
00670     return 0.0f;
00671 }
00672 
00673 float SurfaceFit::Value(float x, float y) const
00674 {
00675     float z = 0.0f;
00676     if (_bIsFitted) {
00677         FunctionContainer clFuncCont(_fCoeff);
00678         z = clFuncCont.F(x, y, 0.0f);
00679     }
00680 
00681     return z;
00682 }
00683 
00684 // -----------------------------------------------------------------------------
00685 
00686 PolynomialFit::PolynomialFit()
00687 {
00688     for (int i=0; i<9; i++)
00689         _fCoeff[i] = 0.0f;
00690 }
00691 
00692 PolynomialFit::~PolynomialFit()
00693 {
00694 }
00695 
00696 float PolynomialFit::Fit()
00697 {
00698     std::vector<float> x, y, z;
00699     x.reserve(_vPoints.size());
00700     y.reserve(_vPoints.size());
00701     z.reserve(_vPoints.size());
00702     for (std::list<Base::Vector3f>::const_iterator it = _vPoints.begin(); it != _vPoints.end(); ++it) {
00703         x.push_back(it->x);
00704         y.push_back(it->y);
00705         z.push_back(it->z);
00706     }
00707 
00708     try {
00709         float* coeff = Wm4::PolyFit3<float>(_vPoints.size(), &(x[0]), &(y[0]), &(z[0]), 2 , 2);
00710         for (int i=0; i<9; i++)
00711             _fCoeff[i] = coeff[i];
00712     }
00713     catch (const std::exception&) {
00714         return FLOAT_MAX;
00715     }
00716 
00717     return 0.0f;
00718 }
00719 
00720 float PolynomialFit::Value(float x, float y) const
00721 {
00722     float fValue = 
00723     _fCoeff[0]                   +
00724     _fCoeff[1] * x               +
00725     _fCoeff[2] * x * x           +
00726     _fCoeff[3]         * y       +
00727     _fCoeff[4] * x     * y       +
00728     _fCoeff[5] * x * x * y       +
00729     _fCoeff[6]         * y * y   +      
00730     _fCoeff[7] * x     * y * y   +
00731     _fCoeff[8] * x * x * y * y;
00732     return fValue;
00733 }

Generated on Wed Nov 23 18:59:57 2011 for FreeCAD by  doxygen 1.6.1