00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
00286
00287
00288
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
00311
00312
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
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[];
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
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
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
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
00654
00655 lapack::gesv(A,b);
00656
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 }