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 #ifndef WM4APPRCYLINDERFIT3_H 00018 #define WM4APPRCYLINDERFIT3_H 00019 00020 // Least-squares fit of a finite cylinder to (x,y,z) data. The cylinder has 00021 // center C, unit-length axis direction U, radius r, and height h. The end 00022 // disks of the cylinder are at C+(h/2)*U and C-(h/2)*U. A point X is on the 00023 // cylinder wall if (X-C)^T*(I-U*U^T)*(X-C) = r^2. A point X is on the end 00024 // disk at C+(h/2)*U if Dot(U,X-C) = h/2 and (X-C)^T*(I-U*U^T)*(X-C) <= r^2. 00025 // A point X is on the end disk at C-(h/2)*U if Dot(U,X-C) = -h/2 and 00026 // (X-C)^T*(I-U*U^T)*(X-C) <= r^2. 00027 00028 // The inputs are the quantity of points and the point array. The outputs 00029 // are the center C, unit-length axis direction U, radius R, and height H. 00030 // You can supply initial guesses for C and U. In this case you need to set 00031 // bInputsAreInitialGuess to 'true'. Otherwise set it to 'false' and the 00032 // function will select C and U by first fitting the data with a least-squares 00033 // line. The return function value is the error for the least-squares fit, 00034 // e >= 0. If all the points lie exactly on a cylinder, then e = 0. 00035 // 00036 // You can examine the error e and iterate the calls yourself. The outputs 00037 // C, U, R, and H can be fed back into the function call as initial guesses. 00038 // 00039 // Real fError0 = CylinderFit3<Real>(iQuantity,akPoint,kC,kU,fR,fH,false); 00040 // for (i = 1; i <= iMax; i++) 00041 // { 00042 // Real fError1 = CylinderFit3<Real>(iQuantity,akPoint,kC,kU,fR,fH,true); 00043 // if ( fError1 not changed much from fError0 ) 00044 // break; 00045 // } 00046 00047 #include "Wm4FoundationLIB.h" 00048 #include "Wm4Vector3.h" 00049 00050 namespace Wm4 00051 { 00052 00053 template <class Real> 00054 class WM4_FOUNDATION_ITEM CylinderFit3 00055 { 00056 public: 00057 CylinderFit3 (int iQuantity, const Vector3<Real>* akPoint, 00058 Vector3<Real>& rkC, Vector3<Real>& rkU, Real& rfR, Real& rfH, 00059 bool bInputsAreInitialGuess); 00060 00061 // return the error value 00062 operator Real (); 00063 00064 private: 00065 static Real UpdateInvRSqr (int iQuantity, const Vector3<Real>* akPoint, 00066 const Vector3<Real>& rkC, const Vector3<Real>& rkU, Real& rfInvRSqr); 00067 00068 static Real UpdateDirection (int iQuantity, const Vector3<Real>* akPoint, 00069 const Vector3<Real>& rkC, Vector3<Real>& rkU, Real& rfInvRSqr); 00070 00071 static Real UpdateCenter (int iQuantity, const Vector3<Real>* akPoint, 00072 Vector3<Real>& rkC, const Vector3<Real>& rkU, const Real& rfInvRSqr); 00073 00074 Real m_fError; 00075 }; 00076 00077 typedef CylinderFit3<float> CylinderFit3f; 00078 typedef CylinderFit3<double> CylinderFit3d; 00079 00080 } 00081 00082 #endif