Wm4ApprQuadraticFit3.cpp

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.0 (2006/06/28)
00016 
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4ApprQuadraticFit3.h"
00019 #include "Wm4Eigen.h"
00020 
00021 namespace Wm4
00022 {
00023 //----------------------------------------------------------------------------
00024 template <class Real>
00025 Real QuadraticFit3 (int iQuantity, const Vector3<Real>* akPoint,
00026     Real afCoeff[10])
00027 {
00028     Eigen<Real> kES(10);
00029     int iRow, iCol;
00030     for (iRow = 0; iRow < 10; iRow++)
00031     {
00032         for (iCol = 0; iCol < 10; iCol++)
00033         {
00034             kES(iRow,iCol) = (Real)0.0;
00035         }
00036     }
00037 
00038     for (int i = 0; i < iQuantity; i++)
00039     {
00040         Real fX = akPoint[i].X();
00041         Real fY = akPoint[i].Y();
00042         Real fZ = akPoint[i].Z();
00043         Real fX2 = fX*fX;
00044         Real fY2 = fY*fY;
00045         Real fZ2 = fZ*fZ;
00046         Real fXY = fX*fY;
00047         Real fXZ = fX*fZ;
00048         Real fYZ = fY*fZ;
00049         Real fX3 = fX*fX2;
00050         Real fXY2 = fX*fY2;
00051         Real fXZ2 = fX*fZ2;
00052         Real fX2Y = fX*fXY;
00053         Real fX2Z = fX*fXZ;
00054         Real fXYZ = fX*fY*fZ;
00055         Real fY3 = fY*fY2;
00056         Real fYZ2 = fY*fZ2;
00057         Real fY2Z = fY*fYZ;
00058         Real fZ3 = fZ*fZ2;
00059         Real fX4 = fX*fX3;
00060         Real fX2Y2 = fX*fXY2;
00061         Real fX2Z2 = fX*fXZ2;
00062         Real fX3Y = fX*fX2Y;
00063         Real fX3Z = fX*fX2Z;
00064         Real fX2YZ = fX*fXYZ;
00065         Real fY4 = fY*fY3;
00066         Real fY2Z2 = fY*fYZ2;
00067         Real fXY3 = fX*fY3;
00068         Real fXY2Z = fX*fY2Z;
00069         Real fY3Z = fY*fY2Z;
00070         Real fZ4 = fZ*fZ3;
00071         Real fXYZ2 = fX*fYZ2;
00072         Real fXZ3 = fX*fZ3;
00073         Real fYZ3 = fY*fZ3;
00074 
00075         kES(0,1) += fX;
00076         kES(0,2) += fY;
00077         kES(0,3) += fZ;
00078         kES(0,4) += fX2;
00079         kES(0,5) += fY2;
00080         kES(0,6) += fZ2;
00081         kES(0,7) += fXY;
00082         kES(0,8) += fXZ;
00083         kES(0,9) += fYZ;
00084         kES(1,4) += fX3;
00085         kES(1,5) += fXY2;
00086         kES(1,6) += fXZ2;
00087         kES(1,7) += fX2Y;
00088         kES(1,8) += fX2Z;
00089         kES(1,9) += fXYZ;
00090         kES(2,5) += fY3;
00091         kES(2,6) += fYZ2;
00092         kES(2,9) += fY2Z;
00093         kES(3,6) += fZ3;
00094         kES(4,4) += fX4;
00095         kES(4,5) += fX2Y2;
00096         kES(4,6) += fX2Z2;
00097         kES(4,7) += fX3Y;
00098         kES(4,8) += fX3Z;
00099         kES(4,9) += fX2YZ;
00100         kES(5,5) += fY4;
00101         kES(5,6) += fY2Z2;
00102         kES(5,7) += fXY3;
00103         kES(5,8) += fXY2Z;
00104         kES(5,9) += fY3Z;
00105         kES(6,6) += fZ4;
00106         kES(6,7) += fXYZ2;
00107         kES(6,8) += fXZ3;
00108         kES(6,9) += fYZ3;
00109         kES(9,9) += fY2Z2;
00110     }
00111 
00112     kES(0,0) = (Real)iQuantity;
00113     kES(1,1) = kES(0,4);
00114     kES(1,2) = kES(0,7);
00115     kES(1,3) = kES(0,8);
00116     kES(2,2) = kES(0,5);
00117     kES(2,3) = kES(0,9);
00118     kES(2,4) = kES(1,7);
00119     kES(2,7) = kES(1,5);
00120     kES(2,8) = kES(1,9);
00121     kES(3,3) = kES(0,6);
00122     kES(3,4) = kES(1,8);
00123     kES(3,5) = kES(2,9);
00124     kES(3,7) = kES(1,9);
00125     kES(3,8) = kES(1,6);
00126     kES(3,9) = kES(2,6);
00127     kES(7,7) = kES(4,5);
00128     kES(7,8) = kES(4,9);
00129     kES(7,9) = kES(5,8);
00130     kES(8,8) = kES(4,6);
00131     kES(8,9) = kES(6,7);
00132     kES(9,9) = kES(5,6);
00133 
00134     for (iRow = 0; iRow < 10; iRow++)
00135     {
00136         for (iCol = 0; iCol < iRow; iCol++)
00137         {
00138             kES(iRow,iCol) = kES(iCol,iRow);
00139         }
00140     }
00141 
00142     Real fInvQuantity = ((Real)1.0)/(Real)iQuantity;
00143     for (iRow = 0; iRow < 10; iRow++)
00144     {
00145         for (iCol = 0; iCol < 10; iCol++)
00146         {
00147             kES(iRow,iCol) *= fInvQuantity;
00148         }
00149     }
00150 
00151     kES.IncrSortEigenStuffN();
00152 
00153     GVector<Real> kEVector = kES.GetEigenvector(0);
00154     size_t uiSize = 10*sizeof(Real);
00155     System::Memcpy(afCoeff,uiSize,(Real*)kEVector,uiSize);
00156 
00157     // For exact fit, numeric round-off errors may make the minimum
00158     // eigenvalue just slightly negative.  Return absolute value since
00159     // application may rely on the return value being nonnegative.
00160     return Math<Real>::FAbs(kES.GetEigenvalue(0));
00161 }
00162 //----------------------------------------------------------------------------
00163 template <class Real>
00164 Real QuadraticSphereFit3 (int iQuantity, const Vector3<Real>* akPoint,
00165     Vector3<Real>& rkCenter, Real& rfRadius)
00166 {
00167     Eigen<Real> kES(5);
00168     int iRow, iCol;
00169     for (iRow = 0; iRow < 5; iRow++)
00170     {
00171         for (iCol = 0; iCol < 5; iCol++)
00172         {
00173             kES(iRow,iCol) = (Real)0.0;
00174         }
00175     }
00176 
00177     for (int i = 0; i < iQuantity; i++)
00178     {
00179         Real fX = akPoint[i].X();
00180         Real fY = akPoint[i].Y();
00181         Real fZ = akPoint[i].Z();
00182         Real fX2 = fX*fX;
00183         Real fY2 = fY*fY;
00184         Real fZ2 = fZ*fZ;
00185         Real fXY = fX*fY;
00186         Real fXZ = fX*fZ;
00187         Real fYZ = fY*fZ;
00188         Real fR2 = fX2+fY2+fZ2;
00189         Real fXR2 = fX*fR2;
00190         Real fYR2 = fY*fR2;
00191         Real fZR2 = fZ*fR2;
00192         Real fR4 = fR2*fR2;
00193 
00194         kES(0,1) += fX;
00195         kES(0,2) += fY;
00196         kES(0,3) += fZ;
00197         kES(0,4) += fR2;
00198         kES(1,1) += fX2;
00199         kES(1,2) += fXY;
00200         kES(1,3) += fXZ;
00201         kES(1,4) += fXR2;
00202         kES(2,2) += fY2;
00203         kES(2,3) += fYZ;
00204         kES(2,4) += fYR2;
00205         kES(3,3) += fZ2;
00206         kES(3,4) += fZR2;
00207         kES(4,4) += fR4;
00208     }
00209 
00210     kES(0,0) = (Real)iQuantity;
00211 
00212     for (iRow = 0; iRow < 5; iRow++)
00213     {
00214         for (iCol = 0; iCol < iRow; iCol++)
00215         {
00216             kES(iRow,iCol) = kES(iCol,iRow);
00217         }
00218     }
00219 
00220     Real fInvQuantity = ((Real)1.0)/(Real)iQuantity;
00221     for (iRow = 0; iRow < 5; iRow++)
00222     {
00223         for (iCol = 0; iCol < 5; iCol++)
00224         {
00225             kES(iRow,iCol) *= fInvQuantity;
00226         }
00227     }
00228 
00229     kES.IncrSortEigenStuffN();
00230 
00231     GVector<Real> kEVector = kES.GetEigenvector(0);
00232     Real fInv = ((Real)1.0)/kEVector[4];  // beware zero divide
00233     Real afCoeff[4];
00234     for (iRow = 0; iRow < 4; iRow++)
00235     {
00236         afCoeff[iRow] = fInv*kEVector[iRow];
00237     }
00238 
00239     rkCenter.X() = -((Real)0.5)*afCoeff[1];
00240     rkCenter.Y() = -((Real)0.5)*afCoeff[2];
00241     rkCenter.Z() = -((Real)0.5)*afCoeff[3];
00242     rfRadius = Math<Real>::Sqrt(Math<Real>::FAbs(rkCenter.X()*rkCenter.X() +
00243         rkCenter.Y()*rkCenter.Y() + rkCenter.Z()*rkCenter.Z() - afCoeff[0]));
00244 
00245     // For exact fit, numeric round-off errors may make the minimum
00246     // eigenvalue just slightly negative.  Return absolute value since
00247     // application may rely on the return value being nonnegative.
00248     return Math<Real>::FAbs(kES.GetEigenvalue(0));
00249 }
00250 //----------------------------------------------------------------------------
00251 
00252 //----------------------------------------------------------------------------
00253 // explicit instantiation
00254 //----------------------------------------------------------------------------
00255 template WM4_FOUNDATION_ITEM
00256 float QuadraticFit3<float> (int, const Vector3<float>*, float[10]);
00257 
00258 template WM4_FOUNDATION_ITEM
00259 float QuadraticSphereFit3<float> (int, const Vector3<float>*,
00260     Vector3<float>&, float&);
00261 
00262 template WM4_FOUNDATION_ITEM
00263 double QuadraticFit3<double> (int, const Vector3<double>*, double[10]);
00264 
00265 template WM4_FOUNDATION_ITEM
00266 double QuadraticSphereFit3<double> (int, const Vector3<double>*,
00267     Vector3<double>&, double&);
00268 //----------------------------------------------------------------------------
00269 }

Generated on Wed Nov 23 19:01:02 2011 for FreeCAD by  doxygen 1.6.1