Wm4ParametricSurface.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 "Wm4ParametricSurface.h"
00019 #include "Wm4Matrix2.h"
00020 
00021 namespace Wm4
00022 {
00023 //----------------------------------------------------------------------------
00024 template <class Real>
00025 ParametricSurface<Real>::ParametricSurface (Real fUMin, Real fUMax,
00026    Real fVMin, Real fVMax, bool bRectangular)
00027 {
00028     assert(fUMin < fUMax && fVMin < fVMax);
00029 
00030     m_fUMin = fUMin;
00031     m_fUMax = fUMax;
00032     m_fVMin = fVMin;
00033     m_fVMax = fVMax;
00034     m_bRectangular = bRectangular;
00035 }
00036 //----------------------------------------------------------------------------
00037 template <class Real>
00038 ParametricSurface<Real>::~ParametricSurface ()
00039 {
00040 }
00041 //----------------------------------------------------------------------------
00042 template <class Real>
00043 Real ParametricSurface<Real>::GetUMin () const
00044 {
00045     return m_fUMin;
00046 }
00047 //----------------------------------------------------------------------------
00048 template <class Real>
00049 Real ParametricSurface<Real>::GetUMax () const
00050 {
00051     return m_fUMax;
00052 }
00053 //----------------------------------------------------------------------------
00054 template <class Real>
00055 Real ParametricSurface<Real>::GetVMin () const
00056 {
00057     return m_fVMin;
00058 }
00059 //----------------------------------------------------------------------------
00060 template <class Real>
00061 Real ParametricSurface<Real>::GetVMax () const
00062 {
00063     return m_fVMax;
00064 }
00065 //----------------------------------------------------------------------------
00066 template <class Real>
00067 bool ParametricSurface<Real>::IsRectangular () const
00068 {
00069     return m_bRectangular;
00070 }
00071 //----------------------------------------------------------------------------
00072 template <class Real>
00073 void ParametricSurface<Real>::GetFrame (Real fU, Real fV,
00074     Vector3<Real>& rkPosition, Vector3<Real>& rkTangent0,
00075     Vector3<Real>& rkTangent1, Vector3<Real>& rkNormal) const
00076 {
00077     rkPosition = P(fU,fV);
00078 
00079     rkTangent0 = PU(fU,fV);
00080     rkTangent1 = PV(fU,fV);
00081     rkTangent0.Normalize();  // T0
00082     rkTangent1.Normalize();  // temporary T1 just to compute N
00083     rkNormal = rkTangent0.UnitCross(rkTangent1);  // N
00084 
00085     // The normalized first derivatives are not necessarily orthogonal.
00086     // Recompute T1 so that {T0,T1,N} is an orthonormal set.
00087     rkTangent1 = rkNormal.Cross(rkTangent0);
00088 }
00089 //----------------------------------------------------------------------------
00090 template <class Real>
00091 void ParametricSurface<Real>::ComputePrincipalCurvatureInfo (Real fU, Real fV,
00092     Real& rfCurv0, Real& rfCurv1, Vector3<Real>& rkDir0,
00093     Vector3<Real>& rkDir1)
00094 {
00095     // Tangents:  T0 = (x_u,y_u,z_u), T1 = (x_v,y_v,z_v)
00096     // Normal:    N = Cross(T0,T1)/Length(Cross(T0,T1))
00097     // Metric Tensor:    G = +-                      -+
00098     //                       | Dot(T0,T0)  Dot(T0,T1) |
00099     //                       | Dot(T1,T0)  Dot(T1,T1) |
00100     //                       +-                      -+
00101     //
00102     // Curvature Tensor:  B = +-                          -+
00103     //                        | -Dot(N,T0_u)  -Dot(N,T0_v) |
00104     //                        | -Dot(N,T1_u)  -Dot(N,T1_v) |
00105     //                        +-                          -+
00106     //
00107     // Principal curvatures k are the generalized eigenvalues of
00108     //
00109     //     Bw = kGw
00110     //
00111     // If k is a curvature and w=(a,b) is the corresponding solution to
00112     // Bw = kGw, then the principal direction as a 3D vector is d = a*U+b*V.
00113     //
00114     // Let k1 and k2 be the principal curvatures.  The mean curvature
00115     // is (k1+k2)/2 and the Gaussian curvature is k1*k2.
00116 
00117     // derivatives
00118     Vector3<Real> kDerU = PU(fU,fV);
00119     Vector3<Real> kDerV = PV(fU,fV);
00120     Vector3<Real> kDerUU = PUU(fU,fV);
00121     Vector3<Real> kDerUV = PUV(fU,fV);
00122     Vector3<Real> kDerVV = PVV(fU,fV);
00123 
00124     // metric tensor
00125     Matrix2<Real> kMetricTensor;
00126     kMetricTensor[0][0] = kDerU.Dot(kDerU);
00127     kMetricTensor[0][1] = kDerU.Dot(kDerV);
00128     kMetricTensor[1][0] = kMetricTensor[0][1];
00129     kMetricTensor[1][1] = kDerV.Dot(kDerV);
00130 
00131     // curvature tensor
00132     Vector3<Real> kNormal = kDerU.UnitCross(kDerV);
00133     Matrix2<Real> kCurvatureTensor;
00134     kCurvatureTensor[0][0] = -kNormal.Dot(kDerUU);
00135     kCurvatureTensor[0][1] = -kNormal.Dot(kDerUV);
00136     kCurvatureTensor[1][0] = kCurvatureTensor[0][1];
00137     kCurvatureTensor[1][1] = -kNormal.Dot(kDerVV);
00138 
00139     // characteristic polynomial is 0 = det(B-kG) = c2*k^2+c1*k+c0
00140     Real fC0 = kCurvatureTensor.Determinant();
00141     Real fC1 = ((Real)2.0)*kCurvatureTensor[0][1]* kMetricTensor[0][1] -
00142         kCurvatureTensor[0][0]*kMetricTensor[1][1] -
00143         kCurvatureTensor[1][1]*kMetricTensor[0][0];
00144     Real fC2 = kMetricTensor.Determinant();
00145 
00146     // principal curvatures are roots of characteristic polynomial
00147     Real fTemp = Math<Real>::Sqrt(Math<Real>::FAbs(fC1*fC1 -
00148         ((Real)4.0)*fC0*fC2));
00149     Real fMult = ((Real)0.5)/fC2;
00150     rfCurv0 = -fMult*(fC1+fTemp);
00151     rfCurv1 = fMult*(-fC1+fTemp);
00152 
00153     // principal directions are solutions to (B-kG)w = 0
00154     // w1 = (b12-k1*g12,-(b11-k1*g11)) OR (b22-k1*g22,-(b12-k1*g12))
00155     Real fA0 = kCurvatureTensor[0][1] - rfCurv0*kMetricTensor[0][1];
00156     Real fA1 = rfCurv0*kMetricTensor[0][0] - kCurvatureTensor[0][0];
00157     Real fLength = Math<Real>::Sqrt(fA0*fA0+fA1*fA1);
00158     if (fLength >= Math<Real>::ZERO_TOLERANCE)
00159     {
00160         rkDir0 = fA0*kDerU + fA1*kDerV;
00161     }
00162     else
00163     {
00164         fA0 = kCurvatureTensor[1][1] - rfCurv0*kMetricTensor[1][1];
00165         fA1 = rfCurv0*kMetricTensor[0][1] - kCurvatureTensor[0][1];
00166         fLength = Math<Real>::Sqrt(fA0*fA0+fA1*fA1);
00167         if (fLength >= Math<Real>::ZERO_TOLERANCE)
00168         {
00169             rkDir0 = fA0*kDerU + fA1*kDerV;
00170         }
00171         else
00172         {
00173             // umbilic (surface is locally sphere, any direction principal)
00174             rkDir0 = kDerU;
00175         }
00176     }
00177     rkDir0.Normalize();
00178 
00179     // second tangent is cross product of first tangent and normal
00180     rkDir1 = rkDir0.Cross(kNormal);
00181 }
00182 //----------------------------------------------------------------------------
00183 
00184 //----------------------------------------------------------------------------
00185 // explicit instantiation
00186 //----------------------------------------------------------------------------
00187 template WM4_FOUNDATION_ITEM
00188 class ParametricSurface<float>;
00189 
00190 template WM4_FOUNDATION_ITEM
00191 class ParametricSurface<double>;
00192 //----------------------------------------------------------------------------
00193 }

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