Wm4Vector3.inl

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.2 (2006/08/19)
00016 
00017 namespace Wm4
00018 {
00019 //----------------------------------------------------------------------------
00020 template <class Real>
00021 Vector3<Real>::Vector3 ()
00022 {
00023     // uninitialized for performance in array construction
00024 }
00025 //----------------------------------------------------------------------------
00026 template <class Real>
00027 Vector3<Real>::Vector3 (Real fX, Real fY, Real fZ)
00028 {
00029     m_afTuple[0] = fX;
00030     m_afTuple[1] = fY;
00031     m_afTuple[2] = fZ;
00032 }
00033 //----------------------------------------------------------------------------
00034 template <class Real>
00035 Vector3<Real>::Vector3 (const Real* afTuple)
00036 {
00037     m_afTuple[0] = afTuple[0];
00038     m_afTuple[1] = afTuple[1];
00039     m_afTuple[2] = afTuple[2];
00040 }
00041 //----------------------------------------------------------------------------
00042 template <class Real>
00043 Vector3<Real>::Vector3 (const Vector3& rkV)
00044 {
00045     m_afTuple[0] = rkV.m_afTuple[0];
00046     m_afTuple[1] = rkV.m_afTuple[1];
00047     m_afTuple[2] = rkV.m_afTuple[2];
00048 }
00049 //----------------------------------------------------------------------------
00050 template <class Real>
00051 Vector3<Real>::operator const Real* () const
00052 {
00053     return m_afTuple;
00054 }
00055 //----------------------------------------------------------------------------
00056 template <class Real>
00057 Vector3<Real>::operator Real* ()
00058 {
00059     return m_afTuple;
00060 }
00061 //----------------------------------------------------------------------------
00062 template <class Real>
00063 Real Vector3<Real>::operator[] (int i) const
00064 {
00065     return m_afTuple[i];
00066 }
00067 //----------------------------------------------------------------------------
00068 template <class Real>
00069 Real& Vector3<Real>::operator[] (int i)
00070 {
00071     return m_afTuple[i];
00072 }
00073 //----------------------------------------------------------------------------
00074 template <class Real>
00075 Real Vector3<Real>::X () const
00076 {
00077     return m_afTuple[0];
00078 }
00079 //----------------------------------------------------------------------------
00080 template <class Real>
00081 Real& Vector3<Real>::X ()
00082 {
00083     return m_afTuple[0];
00084 }
00085 //----------------------------------------------------------------------------
00086 template <class Real>
00087 Real Vector3<Real>::Y () const
00088 {
00089     return m_afTuple[1];
00090 }
00091 //----------------------------------------------------------------------------
00092 template <class Real>
00093 Real& Vector3<Real>::Y ()
00094 {
00095     return m_afTuple[1];
00096 }
00097 //----------------------------------------------------------------------------
00098 template <class Real>
00099 Real Vector3<Real>::Z () const
00100 {
00101     return m_afTuple[2];
00102 }
00103 //----------------------------------------------------------------------------
00104 template <class Real>
00105 Real& Vector3<Real>::Z ()
00106 {
00107     return m_afTuple[2];
00108 }
00109 //----------------------------------------------------------------------------
00110 template <class Real>
00111 Vector3<Real>& Vector3<Real>::operator= (const Vector3& rkV)
00112 {
00113     m_afTuple[0] = rkV.m_afTuple[0];
00114     m_afTuple[1] = rkV.m_afTuple[1];
00115     m_afTuple[2] = rkV.m_afTuple[2];
00116     return *this;
00117 }
00118 //----------------------------------------------------------------------------
00119 template <class Real>
00120 int Vector3<Real>::CompareArrays (const Vector3& rkV) const
00121 {
00122     return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(Real));
00123 }
00124 //----------------------------------------------------------------------------
00125 template <class Real>
00126 bool Vector3<Real>::operator== (const Vector3& rkV) const
00127 {
00128     return CompareArrays(rkV) == 0;
00129 }
00130 //----------------------------------------------------------------------------
00131 template <class Real>
00132 bool Vector3<Real>::operator!= (const Vector3& rkV) const
00133 {
00134     return CompareArrays(rkV) != 0;
00135 }
00136 //----------------------------------------------------------------------------
00137 template <class Real>
00138 bool Vector3<Real>::operator< (const Vector3& rkV) const
00139 {
00140     return CompareArrays(rkV) < 0;
00141 }
00142 //----------------------------------------------------------------------------
00143 template <class Real>
00144 bool Vector3<Real>::operator<= (const Vector3& rkV) const
00145 {
00146     return CompareArrays(rkV) <= 0;
00147 }
00148 //----------------------------------------------------------------------------
00149 template <class Real>
00150 bool Vector3<Real>::operator> (const Vector3& rkV) const
00151 {
00152     return CompareArrays(rkV) > 0;
00153 }
00154 //----------------------------------------------------------------------------
00155 template <class Real>
00156 bool Vector3<Real>::operator>= (const Vector3& rkV) const
00157 {
00158     return CompareArrays(rkV) >= 0;
00159 }
00160 //----------------------------------------------------------------------------
00161 template <class Real>
00162 Vector3<Real> Vector3<Real>::operator+ (const Vector3& rkV) const
00163 {
00164     return Vector3(
00165         m_afTuple[0]+rkV.m_afTuple[0],
00166         m_afTuple[1]+rkV.m_afTuple[1],
00167         m_afTuple[2]+rkV.m_afTuple[2]);
00168 }
00169 //----------------------------------------------------------------------------
00170 template <class Real>
00171 Vector3<Real> Vector3<Real>::operator- (const Vector3& rkV) const
00172 {
00173     return Vector3(
00174         m_afTuple[0]-rkV.m_afTuple[0],
00175         m_afTuple[1]-rkV.m_afTuple[1],
00176         m_afTuple[2]-rkV.m_afTuple[2]);
00177 }
00178 //----------------------------------------------------------------------------
00179 template <class Real>
00180 Vector3<Real> Vector3<Real>::operator* (Real fScalar) const
00181 {
00182     return Vector3(
00183         fScalar*m_afTuple[0],
00184         fScalar*m_afTuple[1],
00185         fScalar*m_afTuple[2]);
00186 }
00187 //----------------------------------------------------------------------------
00188 template <class Real>
00189 Vector3<Real> Vector3<Real>::operator/ (Real fScalar) const
00190 {
00191     Vector3 kQuot;
00192 
00193     if (fScalar != (Real)0.0)
00194     {
00195         Real fInvScalar = ((Real)1.0)/fScalar;
00196         kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
00197         kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
00198         kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2];
00199     }
00200     else
00201     {
00202         kQuot.m_afTuple[0] = Math<Real>::MAX_REAL;
00203         kQuot.m_afTuple[1] = Math<Real>::MAX_REAL;
00204         kQuot.m_afTuple[2] = Math<Real>::MAX_REAL;
00205     }
00206 
00207     return kQuot;
00208 }
00209 //----------------------------------------------------------------------------
00210 template <class Real>
00211 Vector3<Real> Vector3<Real>::operator- () const
00212 {
00213     return Vector3(
00214         -m_afTuple[0],
00215         -m_afTuple[1],
00216         -m_afTuple[2]);
00217 }
00218 //----------------------------------------------------------------------------
00219 template <class Real>
00220 Vector3<Real> operator* (Real fScalar, const Vector3<Real>& rkV)
00221 {
00222     return Vector3<Real>(
00223         fScalar*rkV[0],
00224         fScalar*rkV[1],
00225         fScalar*rkV[2]);
00226 }
00227 //----------------------------------------------------------------------------
00228 template <class Real>
00229 Vector3<Real>& Vector3<Real>::operator+= (const Vector3& rkV)
00230 {
00231     m_afTuple[0] += rkV.m_afTuple[0];
00232     m_afTuple[1] += rkV.m_afTuple[1];
00233     m_afTuple[2] += rkV.m_afTuple[2];
00234     return *this;
00235 }
00236 //----------------------------------------------------------------------------
00237 template <class Real>
00238 Vector3<Real>& Vector3<Real>::operator-= (const Vector3& rkV)
00239 {
00240     m_afTuple[0] -= rkV.m_afTuple[0];
00241     m_afTuple[1] -= rkV.m_afTuple[1];
00242     m_afTuple[2] -= rkV.m_afTuple[2];
00243     return *this;
00244 }
00245 //----------------------------------------------------------------------------
00246 template <class Real>
00247 Vector3<Real>& Vector3<Real>::operator*= (Real fScalar)
00248 {
00249     m_afTuple[0] *= fScalar;
00250     m_afTuple[1] *= fScalar;
00251     m_afTuple[2] *= fScalar;
00252     return *this;
00253 }
00254 //----------------------------------------------------------------------------
00255 template <class Real>
00256 Vector3<Real>& Vector3<Real>::operator/= (Real fScalar)
00257 {
00258     if (fScalar != (Real)0.0)
00259     {
00260         Real fInvScalar = ((Real)1.0)/fScalar;
00261         m_afTuple[0] *= fInvScalar;
00262         m_afTuple[1] *= fInvScalar;
00263         m_afTuple[2] *= fInvScalar;
00264     }
00265     else
00266     {
00267         m_afTuple[0] = Math<Real>::MAX_REAL;
00268         m_afTuple[1] = Math<Real>::MAX_REAL;
00269         m_afTuple[2] = Math<Real>::MAX_REAL;
00270     }
00271 
00272     return *this;
00273 }
00274 //----------------------------------------------------------------------------
00275 template <class Real>
00276 Real Vector3<Real>::Length () const
00277 {
00278     return Math<Real>::Sqrt(
00279         m_afTuple[0]*m_afTuple[0] +
00280         m_afTuple[1]*m_afTuple[1] +
00281         m_afTuple[2]*m_afTuple[2]);
00282 }
00283 //----------------------------------------------------------------------------
00284 template <class Real>
00285 Real Vector3<Real>::SquaredLength () const
00286 {
00287     return
00288         m_afTuple[0]*m_afTuple[0] +
00289         m_afTuple[1]*m_afTuple[1] +
00290         m_afTuple[2]*m_afTuple[2];
00291 }
00292 //----------------------------------------------------------------------------
00293 template <class Real>
00294 Real Vector3<Real>::Dot (const Vector3& rkV) const
00295 {
00296     return
00297         m_afTuple[0]*rkV.m_afTuple[0] +
00298         m_afTuple[1]*rkV.m_afTuple[1] +
00299         m_afTuple[2]*rkV.m_afTuple[2];
00300 }
00301 //----------------------------------------------------------------------------
00302 template <class Real>
00303 Real Vector3<Real>::Normalize ()
00304 {
00305     Real fLength = Length();
00306 
00307     if (fLength > Math<Real>::ZERO_TOLERANCE)
00308     {
00309         Real fInvLength = ((Real)1.0)/fLength;
00310         m_afTuple[0] *= fInvLength;
00311         m_afTuple[1] *= fInvLength;
00312         m_afTuple[2] *= fInvLength;
00313     }
00314     else
00315     {
00316         fLength = (Real)0.0;
00317         m_afTuple[0] = (Real)0.0;
00318         m_afTuple[1] = (Real)0.0;
00319         m_afTuple[2] = (Real)0.0;
00320     }
00321 
00322     return fLength;
00323 }
00324 //----------------------------------------------------------------------------
00325 template <class Real>
00326 Vector3<Real> Vector3<Real>::Cross (const Vector3& rkV) const
00327 {
00328     return Vector3(
00329         m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
00330         m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
00331         m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
00332 }
00333 //----------------------------------------------------------------------------
00334 template <class Real>
00335 Vector3<Real> Vector3<Real>::UnitCross (const Vector3& rkV) const
00336 {
00337     Vector3 kCross(
00338         m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
00339         m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
00340         m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
00341     kCross.Normalize();
00342     return kCross;
00343 }
00344 //----------------------------------------------------------------------------
00345 template <class Real>
00346 void Vector3<Real>::GetBarycentrics (const Vector3<Real>& rkV0,
00347     const Vector3<Real>& rkV1, const Vector3<Real>& rkV2,
00348     const Vector3<Real>& rkV3, Real afBary[4]) const
00349 {
00350     // compute the vectors relative to V3 of the tetrahedron
00351     Vector3<Real> akDiff[4] =
00352     {
00353         rkV0 - rkV3,
00354         rkV1 - rkV3,
00355         rkV2 - rkV3,
00356         *this - rkV3
00357     };
00358 
00359     // If the vertices have large magnitude, the linear system of
00360     // equations for computing barycentric coordinates can be
00361     // ill-conditioned.  To avoid this, uniformly scale the tetrahedron
00362     // edges to be of order 1.  The scaling of all differences does not
00363     // change the barycentric coordinates.
00364     Real fMax = (Real)0.0;
00365     int i;
00366     for (i = 0; i < 3; i++)
00367     {
00368         for (int j = 0; j < 3; j++)
00369         {
00370             Real fValue = Math<Real>::FAbs(akDiff[i][j]);
00371             if (fValue > fMax)
00372             {
00373                 fMax = fValue;
00374             }
00375         }
00376     }
00377 
00378     // scale down only large data
00379     if (fMax > (Real)1.0)
00380     {
00381         Real fInvMax = ((Real)1.0)/fMax;
00382         for (i = 0; i < 4; i++)
00383         {
00384             akDiff[i] *= fInvMax;
00385         }
00386     }
00387 
00388     Real fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2]));
00389     Vector3<Real> kE1cE2 = akDiff[1].Cross(akDiff[2]);
00390     Vector3<Real> kE2cE0 = akDiff[2].Cross(akDiff[0]);
00391     Vector3<Real> kE0cE1 = akDiff[0].Cross(akDiff[1]);
00392     if (Math<Real>::FAbs(fDet) > Math<Real>::ZERO_TOLERANCE)
00393     {
00394         Real fInvDet = ((Real)1.0)/fDet;
00395         afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet;
00396         afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet;
00397         afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet;
00398         afBary[3] = (Real)1.0 - afBary[0] - afBary[1] - afBary[2];
00399     }
00400     else
00401     {
00402         // The tetrahedron is potentially flat.  Determine the face of
00403         // maximum area and compute barycentric coordinates with respect
00404         // to that face.
00405         Vector3<Real> kE02 = rkV0 - rkV2;
00406         Vector3<Real> kE12 = rkV1 - rkV2;
00407         Vector3<Real> kE02cE12 = kE02.Cross(kE12);
00408         Real fMaxSqrArea = kE02cE12.SquaredLength();
00409         int iMaxIndex = 3;
00410         Real fSqrArea = kE0cE1.SquaredLength();
00411         if (fSqrArea > fMaxSqrArea)
00412         {
00413             iMaxIndex = 0;
00414             fMaxSqrArea = fSqrArea;
00415         }
00416         fSqrArea = kE1cE2.SquaredLength();
00417         if (fSqrArea > fMaxSqrArea)
00418         {
00419             iMaxIndex = 1;
00420             fMaxSqrArea = fSqrArea;
00421         }
00422         fSqrArea = kE2cE0.SquaredLength();
00423         if (fSqrArea > fMaxSqrArea)
00424         {
00425             iMaxIndex = 2;
00426             fMaxSqrArea = fSqrArea;
00427         }
00428 
00429         if (fMaxSqrArea > Math<Real>::ZERO_TOLERANCE)
00430         {
00431             Real fInvSqrArea = ((Real)1.0)/fMaxSqrArea;
00432             Vector3<Real> kTmp;
00433             if (iMaxIndex == 0)
00434             {
00435                 kTmp = akDiff[3].Cross(akDiff[1]);
00436                 afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea;
00437                 kTmp = akDiff[0].Cross(akDiff[3]);
00438                 afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea;
00439                 afBary[2] = (Real)0.0;
00440                 afBary[3] = (Real)1.0 - afBary[0] - afBary[1];
00441             }
00442             else if (iMaxIndex == 1)
00443             {
00444                 afBary[0] = (Real)0.0;
00445                 kTmp = akDiff[3].Cross(akDiff[2]);
00446                 afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea;
00447                 kTmp = akDiff[1].Cross(akDiff[3]);
00448                 afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea;
00449                 afBary[3] = (Real)1.0 - afBary[1] - afBary[2];
00450             }
00451             else if (iMaxIndex == 2)
00452             {
00453                 kTmp = akDiff[2].Cross(akDiff[3]);
00454                 afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea;
00455                 afBary[1] = (Real)0.0;
00456                 kTmp = akDiff[3].Cross(akDiff[0]);
00457                 afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea;
00458                 afBary[3] = (Real)1.0 - afBary[0] - afBary[2];
00459             }
00460             else
00461             {
00462                 akDiff[3] = *this - rkV2;
00463                 kTmp = akDiff[3].Cross(kE12);
00464                 afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea;
00465                 kTmp = kE02.Cross(akDiff[3]);
00466                 afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea;
00467                 afBary[2] = (Real)1.0 - afBary[0] - afBary[1];
00468                 afBary[3] = (Real)0.0;
00469             }
00470         }
00471         else
00472         {
00473             // The tetrahedron is potentially a sliver.  Determine the edge of
00474             // maximum length and compute barycentric coordinates with respect
00475             // to that edge.
00476             Real fMaxSqrLength = akDiff[0].SquaredLength();
00477             iMaxIndex = 0;  // <V0,V3>
00478             Real fSqrLength = akDiff[1].SquaredLength();
00479             if (fSqrLength > fMaxSqrLength)
00480             {
00481                 iMaxIndex = 1;  // <V1,V3>
00482                 fMaxSqrLength = fSqrLength;
00483             }
00484             fSqrLength = akDiff[2].SquaredLength();
00485             if (fSqrLength > fMaxSqrLength)
00486             {
00487                 iMaxIndex = 2;  // <V2,V3>
00488                 fMaxSqrLength = fSqrLength;
00489             }
00490             fSqrLength = kE02.SquaredLength();
00491             if (fSqrLength > fMaxSqrLength)
00492             {
00493                 iMaxIndex = 3;  // <V0,V2>
00494                 fMaxSqrLength = fSqrLength;
00495             }
00496             fSqrLength = kE12.SquaredLength();
00497             if (fSqrLength > fMaxSqrLength)
00498             {
00499                 iMaxIndex = 4;  // <V1,V2>
00500                 fMaxSqrLength = fSqrLength;
00501             }
00502             Vector3<Real> kE01 = rkV0 - rkV1;
00503             fSqrLength = kE01.SquaredLength();
00504             if (fSqrLength > fMaxSqrLength)
00505             {
00506                 iMaxIndex = 5;  // <V0,V1>
00507                 fMaxSqrLength = fSqrLength;
00508             }
00509 
00510             if (fMaxSqrLength > Math<Real>::ZERO_TOLERANCE)
00511             {
00512                 Real fInvSqrLength = ((Real)1.0)/fMaxSqrLength;
00513                 if (iMaxIndex == 0)
00514                 {
00515                     // P-V3 = t*(V0-V3)
00516                     afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength;
00517                     afBary[1] = (Real)0.0;
00518                     afBary[2] = (Real)0.0;
00519                     afBary[3] = (Real)1.0 - afBary[0];
00520                 }
00521                 else if (iMaxIndex == 1)
00522                 {
00523                     // P-V3 = t*(V1-V3)
00524                     afBary[0] = (Real)0.0;
00525                     afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength;
00526                     afBary[2] = (Real)0.0;
00527                     afBary[3] = (Real)1.0 - afBary[1];
00528                 }
00529                 else if (iMaxIndex == 2)
00530                 {
00531                     // P-V3 = t*(V2-V3)
00532                     afBary[0] = (Real)0.0;
00533                     afBary[1] = (Real)0.0;
00534                     afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength;
00535                     afBary[3] = (Real)1.0 - afBary[2];
00536                 }
00537                 else if (iMaxIndex == 3)
00538                 {
00539                     // P-V2 = t*(V0-V2)
00540                     akDiff[3] = *this - rkV2;
00541                     afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength;
00542                     afBary[1] = (Real)0.0;
00543                     afBary[2] = (Real)1.0 - afBary[0];
00544                     afBary[3] = (Real)0.0;
00545                 }
00546                 else if (iMaxIndex == 4)
00547                 {
00548                     // P-V2 = t*(V1-V2)
00549                     akDiff[3] = *this - rkV2;
00550                     afBary[0] = (Real)0.0;
00551                     afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength;
00552                     afBary[2] = (Real)1.0 - afBary[1];
00553                     afBary[3] = (Real)0.0;
00554                 }
00555                 else
00556                 {
00557                     // P-V1 = t*(V0-V1)
00558                     akDiff[3] = *this - rkV1;
00559                     afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength;
00560                     afBary[1] = (Real)1.0 - afBary[0];
00561                     afBary[2] = (Real)0.0;
00562                     afBary[3] = (Real)0.0;
00563                 }
00564             }
00565             else
00566             {
00567                 // tetrahedron is a nearly a point, just return equal weights
00568                 afBary[0] = (Real)0.25;
00569                 afBary[1] = afBary[0];
00570                 afBary[2] = afBary[0];
00571                 afBary[3] = afBary[0];
00572             }
00573         }
00574     }
00575 }
00576 //----------------------------------------------------------------------------
00577 template <class Real>
00578 void Vector3<Real>::Orthonormalize (Vector3& rkU, Vector3& rkV, Vector3& rkW)
00579 {
00580     // If the input vectors are v0, v1, and v2, then the Gram-Schmidt
00581     // orthonormalization produces vectors u0, u1, and u2 as follows,
00582     //
00583     //   u0 = v0/|v0|
00584     //   u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
00585     //   u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
00586     //
00587     // where |A| indicates length of vector A and A*B indicates dot
00588     // product of vectors A and B.
00589 
00590     // compute u0
00591     rkU.Normalize();
00592 
00593     // compute u1
00594     Real fDot0 = rkU.Dot(rkV); 
00595     rkV -= fDot0*rkU;
00596     rkV.Normalize();
00597 
00598     // compute u2
00599     Real fDot1 = rkV.Dot(rkW);
00600     fDot0 = rkU.Dot(rkW);
00601     rkW -= fDot0*rkU + fDot1*rkV;
00602     rkW.Normalize();
00603 }
00604 //----------------------------------------------------------------------------
00605 template <class Real>
00606 void Vector3<Real>::Orthonormalize (Vector3* akV)
00607 {
00608     Orthonormalize(akV[0],akV[1],akV[2]);
00609 }
00610 //----------------------------------------------------------------------------
00611 template <class Real>
00612 void Vector3<Real>::GenerateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
00613     Vector3& rkW)
00614 {
00615     rkW.Normalize();
00616     GenerateComplementBasis(rkU,rkV,rkW);
00617 }
00618 //----------------------------------------------------------------------------
00619 template <class Real>
00620 void Vector3<Real>::GenerateComplementBasis (Vector3& rkU, Vector3& rkV,
00621     const Vector3& rkW)
00622 {
00623     Real fInvLength;
00624 
00625     if (Math<Real>::FAbs(rkW.m_afTuple[0]) >=
00626         Math<Real>::FAbs(rkW.m_afTuple[1]) )
00627     {
00628         // W.x or W.z is the largest magnitude component, swap them
00629         fInvLength = Math<Real>::InvSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] +
00630             rkW.m_afTuple[2]*rkW.m_afTuple[2]);
00631         rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength;
00632         rkU.m_afTuple[1] = (Real)0.0;
00633         rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength;
00634         rkV.m_afTuple[0] = rkW.m_afTuple[1]*rkU.m_afTuple[2];
00635         rkV.m_afTuple[1] = rkW.m_afTuple[2]*rkU.m_afTuple[0] -
00636             rkW.m_afTuple[0]*rkU.m_afTuple[2];
00637         rkV.m_afTuple[2] = -rkW.m_afTuple[1]*rkU.m_afTuple[0];
00638     }
00639     else
00640     {
00641         // W.y or W.z is the largest magnitude component, swap them
00642         fInvLength = Math<Real>::InvSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] +
00643             rkW.m_afTuple[2]*rkW.m_afTuple[2]);
00644         rkU.m_afTuple[0] = (Real)0.0;
00645         rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength;
00646         rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength;
00647         rkV.m_afTuple[0] = rkW.m_afTuple[1]*rkU.m_afTuple[2] -
00648             rkW.m_afTuple[2]*rkU.m_afTuple[1];
00649         rkV.m_afTuple[1] = -rkW.m_afTuple[0]*rkU.m_afTuple[2];
00650         rkV.m_afTuple[2] = rkW.m_afTuple[0]*rkU.m_afTuple[1];
00651     }
00652 }
00653 //----------------------------------------------------------------------------
00654 template <class Real>
00655 void Vector3<Real>::ComputeExtremes (int iVQuantity, const Vector3* akPoint,
00656     Vector3& rkMin, Vector3& rkMax)
00657 {
00658     assert(iVQuantity > 0 && akPoint);
00659 
00660     rkMin = akPoint[0];
00661     rkMax = rkMin;
00662     for (int i = 1; i < iVQuantity; i++)
00663     {
00664         const Vector3<Real>& rkPoint = akPoint[i];
00665         for (int j = 0; j < 3; j++)
00666         {
00667             if (rkPoint[j] < rkMin[j])
00668             {
00669                 rkMin[j] = rkPoint[j];
00670             }
00671             else if (rkPoint[j] > rkMax[j])
00672             {
00673                 rkMax[j] = rkPoint[j];
00674             }
00675         }
00676     }
00677 }
00678 //----------------------------------------------------------------------------
00679 template <class Real>
00680 std::ostream& operator<< (std::ostream& rkOStr, const Vector3<Real>& rkV)
00681 {
00682      return rkOStr << rkV.X() << ' ' << rkV.Y() << ' ' << rkV.Z();
00683 }
00684 //----------------------------------------------------------------------------
00685 } //namespace Wm4

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