Wm4ApprPlaneFit3.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 "Wm4ApprPlaneFit3.h"
00019 #include "Wm4Eigen.h"
00020 #include "Wm4LinearSystem.h"
00021 
00022 namespace Wm4
00023 {
00024 //----------------------------------------------------------------------------
00025 template <class Real>
00026 bool HeightPlaneFit3 (int iQuantity, const Vector3<Real>* akPoint, Real& rfA,
00027     Real& rfB, Real& rfC)
00028 {
00029     // You need at least three points to determine the plane.  Even so, if
00030     // the points are on a vertical plane, there is no least-squares fit in
00031     // the 'height' sense.  This will be trapped by the determinant of the
00032     // coefficient matrix.
00033 
00034     // compute sums for linear system
00035     Real fSumX = (Real)0.0, fSumY = (Real)0.0, fSumZ = (Real)0.0;
00036     Real fSumXX = (Real)0.0, fSumXY = (Real)0.0, fSumXZ = (Real)0.0;
00037     Real fSumYY = (Real)0.0, fSumYZ = (Real)0.0;
00038     int i;
00039     for (i = 0; i < iQuantity; i++)
00040     {
00041         fSumX += akPoint[i].X();
00042         fSumY += akPoint[i].Y();
00043         fSumZ += akPoint[i].Z();
00044         fSumXX += akPoint[i].X()*akPoint[i].X();
00045         fSumXY += akPoint[i].X()*akPoint[i].Y();
00046         fSumXZ += akPoint[i].X()*akPoint[i].Z();
00047         fSumYY += akPoint[i].Y()*akPoint[i].Y();
00048         fSumYZ += akPoint[i].Y()*akPoint[i].Z();
00049     }
00050 
00051     Real aafA[3][3] =
00052     {
00053         {fSumXX, fSumXY, fSumX},
00054         {fSumXY, fSumYY, fSumY},
00055         {fSumX,  fSumY,  (Real)iQuantity}
00056     };
00057 
00058     Real afB[3] =
00059     {
00060         fSumXZ,
00061         fSumYZ,
00062         fSumZ
00063     };
00064 
00065     Real afX[3];
00066 
00067     bool bNonsingular = LinearSystem<Real>().Solve3(aafA,afB,afX);
00068     if (bNonsingular)
00069     {
00070         rfA = afX[0];
00071         rfB = afX[1];
00072         rfC = afX[2];
00073     }
00074     else
00075     {
00076         rfA = Math<Real>::MAX_REAL;
00077         rfB = Math<Real>::MAX_REAL;
00078         rfC = Math<Real>::MAX_REAL;
00079     }
00080 
00081     return bNonsingular;
00082 }
00083 //----------------------------------------------------------------------------
00084 template <class Real>
00085 Plane3<Real> OrthogonalPlaneFit3 (int iQuantity, const Vector3<Real>* akPoint)
00086 {
00087     // compute the mean of the points
00088     Vector3<Real> kOrigin = Vector3<Real>::ZERO;
00089     int i;
00090     for (i = 0; i < iQuantity; i++)
00091     {
00092         kOrigin += akPoint[i];
00093     }
00094     Real fInvQuantity = ((Real)1.0)/iQuantity;
00095     kOrigin *= fInvQuantity;
00096 
00097     // compute sums of products
00098     Real fSumXX = (Real)0.0, fSumXY = (Real)0.0, fSumXZ = (Real)0.0;
00099     Real fSumYY = (Real)0.0, fSumYZ = (Real)0.0, fSumZZ = (Real)0.0;
00100     for (i = 0; i < iQuantity; i++) 
00101     {
00102         Vector3<Real> kDiff = akPoint[i] - kOrigin;
00103         fSumXX += kDiff.X()*kDiff.X();
00104         fSumXY += kDiff.X()*kDiff.Y();
00105         fSumXZ += kDiff.X()*kDiff.Z();
00106         fSumYY += kDiff.Y()*kDiff.Y();
00107         fSumYZ += kDiff.Y()*kDiff.Z();
00108         fSumZZ += kDiff.Z()*kDiff.Z();
00109     }
00110 
00111     fSumXX *= fInvQuantity;
00112     fSumXY *= fInvQuantity;
00113     fSumXZ *= fInvQuantity;
00114     fSumYY *= fInvQuantity;
00115     fSumYZ *= fInvQuantity;
00116     fSumZZ *= fInvQuantity;
00117 
00118     // setup the eigensolver
00119     Eigen<Real> kES(3);
00120     kES(0,0) = fSumXX;
00121     kES(0,1) = fSumXY;
00122     kES(0,2) = fSumXZ;
00123     kES(1,0) = fSumXY;
00124     kES(1,1) = fSumYY;
00125     kES(1,2) = fSumYZ;
00126     kES(2,0) = fSumXZ;
00127     kES(2,1) = fSumYZ;
00128     kES(2,2) = fSumZZ;
00129 
00130     // compute eigenstuff, smallest eigenvalue is in last position
00131     kES.DecrSortEigenStuff3();
00132 
00133     // get plane normal
00134     Vector3<Real> kNormal;
00135     kES.GetEigenvector(2,kNormal);
00136 
00137     // the minimum energy
00138     return Plane3<Real>(kNormal,kOrigin);
00139 }
00140 //----------------------------------------------------------------------------
00141 
00142 //----------------------------------------------------------------------------
00143 // explicit instantiation
00144 //----------------------------------------------------------------------------
00145 template WM4_FOUNDATION_ITEM
00146 bool HeightPlaneFit3<float> (int, const Vector3<float>*, float&, float&,
00147     float&);
00148 
00149 template WM4_FOUNDATION_ITEM
00150 Plane3<float> OrthogonalPlaneFit3<float> (int, const Vector3<float>*);
00151 
00152 template WM4_FOUNDATION_ITEM
00153 bool HeightPlaneFit3<double> (int, const Vector3<double>*, double&, double&,
00154     double&);
00155 
00156 template WM4_FOUNDATION_ITEM
00157 Plane3<double> OrthogonalPlaneFit3<double> (int, const Vector3<double>*);
00158 //----------------------------------------------------------------------------
00159 }

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