Wm4Vector2.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 Vector2<Real>::Vector2 ()
00022 {
00023     // uninitialized for performance in array construction
00024 }
00025 //----------------------------------------------------------------------------
00026 template <class Real>
00027 Vector2<Real>::Vector2 (Real fX, Real fY)
00028 {
00029     m_afTuple[0] = fX;
00030     m_afTuple[1] = fY;
00031 }
00032 //----------------------------------------------------------------------------
00033 template <class Real>
00034 Vector2<Real>::Vector2 (const Real* afTuple)
00035 {
00036     m_afTuple[0] = afTuple[0];
00037     m_afTuple[1] = afTuple[1];
00038 }
00039 //----------------------------------------------------------------------------
00040 template <class Real>
00041 Vector2<Real>::Vector2 (const Vector2& rkV)
00042 {
00043     m_afTuple[0] = rkV.m_afTuple[0];
00044     m_afTuple[1] = rkV.m_afTuple[1];
00045 }
00046 //----------------------------------------------------------------------------
00047 template <class Real>
00048 Vector2<Real>::operator const Real* () const
00049 {
00050     return m_afTuple;
00051 }
00052 //----------------------------------------------------------------------------
00053 template <class Real>
00054 Vector2<Real>::operator Real* ()
00055 {
00056     return m_afTuple;
00057 }
00058 //----------------------------------------------------------------------------
00059 template <class Real>
00060 Real Vector2<Real>::operator[] (int i) const
00061 {
00062     return m_afTuple[i];
00063 }
00064 //----------------------------------------------------------------------------
00065 template <class Real>
00066 Real& Vector2<Real>::operator[] (int i)
00067 {
00068     return m_afTuple[i];
00069 }
00070 //----------------------------------------------------------------------------
00071 template <class Real>
00072 Real Vector2<Real>::X () const
00073 {
00074     return m_afTuple[0];
00075 }
00076 //----------------------------------------------------------------------------
00077 template <class Real>
00078 Real& Vector2<Real>::X ()
00079 {
00080     return m_afTuple[0];
00081 }
00082 //----------------------------------------------------------------------------
00083 template <class Real>
00084 Real Vector2<Real>::Y () const
00085 {
00086     return m_afTuple[1];
00087 }
00088 //----------------------------------------------------------------------------
00089 template <class Real>
00090 Real& Vector2<Real>::Y ()
00091 {
00092     return m_afTuple[1];
00093 }
00094 //----------------------------------------------------------------------------
00095 template <class Real>
00096 Vector2<Real>& Vector2<Real>::operator= (const Vector2& rkV)
00097 {
00098     m_afTuple[0] = rkV.m_afTuple[0];
00099     m_afTuple[1] = rkV.m_afTuple[1];
00100     return *this;
00101 }
00102 //----------------------------------------------------------------------------
00103 template <class Real>
00104 int Vector2<Real>::CompareArrays (const Vector2& rkV) const
00105 {
00106     return memcmp(m_afTuple,rkV.m_afTuple,2*sizeof(Real));
00107 }
00108 //----------------------------------------------------------------------------
00109 template <class Real>
00110 bool Vector2<Real>::operator== (const Vector2& rkV) const
00111 {
00112     return CompareArrays(rkV) == 0;
00113 }
00114 //----------------------------------------------------------------------------
00115 template <class Real>
00116 bool Vector2<Real>::operator!= (const Vector2& rkV) const
00117 {
00118     return CompareArrays(rkV) != 0;
00119 }
00120 //----------------------------------------------------------------------------
00121 template <class Real>
00122 bool Vector2<Real>::operator< (const Vector2& rkV) const
00123 {
00124     return CompareArrays(rkV) < 0;
00125 }
00126 //----------------------------------------------------------------------------
00127 template <class Real>
00128 bool Vector2<Real>::operator<= (const Vector2& rkV) const
00129 {
00130     return CompareArrays(rkV) <= 0;
00131 }
00132 //----------------------------------------------------------------------------
00133 template <class Real>
00134 bool Vector2<Real>::operator> (const Vector2& rkV) const
00135 {
00136     return CompareArrays(rkV) > 0;
00137 }
00138 //----------------------------------------------------------------------------
00139 template <class Real>
00140 bool Vector2<Real>::operator>= (const Vector2& rkV) const
00141 {
00142     return CompareArrays(rkV) >= 0;
00143 }
00144 //----------------------------------------------------------------------------
00145 template <class Real>
00146 Vector2<Real> Vector2<Real>::operator+ (const Vector2& rkV) const
00147 {
00148     return Vector2(
00149         m_afTuple[0]+rkV.m_afTuple[0],
00150         m_afTuple[1]+rkV.m_afTuple[1]);
00151 }
00152 //----------------------------------------------------------------------------
00153 template <class Real>
00154 Vector2<Real> Vector2<Real>::operator- (const Vector2& rkV) const
00155 {
00156     return Vector2(
00157         m_afTuple[0]-rkV.m_afTuple[0],
00158         m_afTuple[1]-rkV.m_afTuple[1]);
00159 }
00160 //----------------------------------------------------------------------------
00161 template <class Real>
00162 Vector2<Real> Vector2<Real>::operator* (Real fScalar) const
00163 {
00164     return Vector2(
00165         fScalar*m_afTuple[0],
00166         fScalar*m_afTuple[1]);
00167 }
00168 //----------------------------------------------------------------------------
00169 template <class Real>
00170 Vector2<Real> Vector2<Real>::operator/ (Real fScalar) const
00171 {
00172     Vector2 kQuot;
00173 
00174     if (fScalar != (Real)0.0)
00175     {
00176         Real fInvScalar = ((Real)1.0)/fScalar;
00177         kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
00178         kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
00179     }
00180     else
00181     {
00182         kQuot.m_afTuple[0] = Math<Real>::MAX_REAL;
00183         kQuot.m_afTuple[1] = Math<Real>::MAX_REAL;
00184     }
00185 
00186     return kQuot;
00187 }
00188 //----------------------------------------------------------------------------
00189 template <class Real>
00190 Vector2<Real> Vector2<Real>::operator- () const
00191 {
00192     return Vector2(
00193         -m_afTuple[0],
00194         -m_afTuple[1]);
00195 }
00196 //----------------------------------------------------------------------------
00197 template <class Real>
00198 Vector2<Real> operator* (Real fScalar, const Vector2<Real>& rkV)
00199 {
00200     return Vector2<Real>(
00201         fScalar*rkV[0],
00202         fScalar*rkV[1]);
00203 }
00204 //----------------------------------------------------------------------------
00205 template <class Real>
00206 Vector2<Real>& Vector2<Real>::operator+= (const Vector2& rkV)
00207 {
00208     m_afTuple[0] += rkV.m_afTuple[0];
00209     m_afTuple[1] += rkV.m_afTuple[1];
00210     return *this;
00211 }
00212 //----------------------------------------------------------------------------
00213 template <class Real>
00214 Vector2<Real>& Vector2<Real>::operator-= (const Vector2& rkV)
00215 {
00216     m_afTuple[0] -= rkV.m_afTuple[0];
00217     m_afTuple[1] -= rkV.m_afTuple[1];
00218     return *this;
00219 }
00220 //----------------------------------------------------------------------------
00221 template <class Real>
00222 Vector2<Real>& Vector2<Real>::operator*= (Real fScalar)
00223 {
00224     m_afTuple[0] *= fScalar;
00225     m_afTuple[1] *= fScalar;
00226     return *this;
00227 }
00228 //----------------------------------------------------------------------------
00229 template <class Real>
00230 Vector2<Real>& Vector2<Real>::operator/= (Real fScalar)
00231 {
00232     if (fScalar != (Real)0.0)
00233     {
00234         Real fInvScalar = ((Real)1.0)/fScalar;
00235         m_afTuple[0] *= fInvScalar;
00236         m_afTuple[1] *= fInvScalar;
00237     }
00238     else
00239     {
00240         m_afTuple[0] = Math<Real>::MAX_REAL;
00241         m_afTuple[1] = Math<Real>::MAX_REAL;
00242     }
00243 
00244     return *this;
00245 }
00246 //----------------------------------------------------------------------------
00247 template <class Real>
00248 Real Vector2<Real>::Length () const
00249 {
00250     return Math<Real>::Sqrt(
00251         m_afTuple[0]*m_afTuple[0] +
00252         m_afTuple[1]*m_afTuple[1]);
00253 }
00254 //----------------------------------------------------------------------------
00255 template <class Real>
00256 Real Vector2<Real>::SquaredLength () const
00257 {
00258     return
00259         m_afTuple[0]*m_afTuple[0] +
00260         m_afTuple[1]*m_afTuple[1];
00261 }
00262 //----------------------------------------------------------------------------
00263 template <class Real>
00264 Real Vector2<Real>::Dot (const Vector2& rkV) const
00265 {
00266     return
00267         m_afTuple[0]*rkV.m_afTuple[0] +
00268         m_afTuple[1]*rkV.m_afTuple[1];
00269 }
00270 //----------------------------------------------------------------------------
00271 template <class Real>
00272 Real Vector2<Real>::Normalize ()
00273 {
00274     Real fLength = Length();
00275 
00276     if (fLength > Math<Real>::ZERO_TOLERANCE)
00277     {
00278         Real fInvLength = ((Real)1.0)/fLength;
00279         m_afTuple[0] *= fInvLength;
00280         m_afTuple[1] *= fInvLength;
00281     }
00282     else
00283     {
00284         fLength = (Real)0.0;
00285         m_afTuple[0] = (Real)0.0;
00286         m_afTuple[1] = (Real)0.0;
00287     }
00288 
00289     return fLength;
00290 }
00291 //----------------------------------------------------------------------------
00292 template <class Real>
00293 Vector2<Real> Vector2<Real>::Perp () const
00294 {
00295     return Vector2(m_afTuple[1],-m_afTuple[0]);
00296 }
00297 //----------------------------------------------------------------------------
00298 template <class Real>
00299 Vector2<Real> Vector2<Real>::UnitPerp () const
00300 {
00301     Vector2 kPerp(m_afTuple[1],-m_afTuple[0]);
00302     kPerp.Normalize();
00303     return kPerp;
00304 }
00305 //----------------------------------------------------------------------------
00306 template <class Real>
00307 Real Vector2<Real>::DotPerp (const Vector2& rkV) const
00308 {
00309     return m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0];
00310 }
00311 //----------------------------------------------------------------------------
00312 template <class Real>
00313 void Vector2<Real>::GetBarycentrics (const Vector2& rkV0, const Vector2& rkV1,
00314     const Vector2& rkV2, Real afBary[3]) const
00315 {
00316     // compute the vectors relative to V2 of the triangle
00317     Vector2 akDiff[3] =
00318     {
00319         rkV0 - rkV2,
00320         rkV1 - rkV2,
00321         *this - rkV2
00322     };
00323 
00324     // If the vertices have large magnitude, the linear system of equations
00325     // for computing barycentric coordinates can be ill-conditioned.  To avoid
00326     // this, uniformly scale the triangle edges to be of order 1.  The scaling
00327     // of all differences does not change the barycentric coordinates.
00328     Real fMax = (Real)0.0;
00329     int i;
00330     for (i = 0; i < 2; i++)
00331     {
00332         for (int j = 0; j < 2; j++)
00333         {
00334             Real fValue = Math<Real>::FAbs(akDiff[i][j]);
00335             if (fValue > fMax)
00336             {
00337                 fMax = fValue;
00338             }
00339         }
00340     }
00341 
00342     // scale down only large data
00343     if (fMax > (Real)1.0)
00344     {
00345         Real fInvMax = ((Real)1.0)/fMax;
00346         for (i = 0; i < 3; i++)
00347         {
00348             akDiff[i] *= fInvMax;
00349         }
00350     }
00351 
00352     Real fDet = akDiff[0].DotPerp(akDiff[1]);
00353     if (Math<Real>::FAbs(fDet) > Math<Real>::ZERO_TOLERANCE)
00354     {
00355         Real fInvDet = ((Real)1.0)/fDet;
00356         afBary[0] = akDiff[2].DotPerp(akDiff[1])*fInvDet;
00357         afBary[1] = akDiff[0].DotPerp(akDiff[2])*fInvDet;
00358         afBary[2] = (Real)1.0 - afBary[0] - afBary[1];
00359     }
00360     else
00361     {
00362         // The triangle is a sliver.  Determine the longest edge and
00363         // compute barycentric coordinates with respect to that edge.
00364         Vector2 kE2 = rkV0 - rkV1;
00365         Real fMaxSqrLength = kE2.SquaredLength();
00366         int iMaxIndex = 2;
00367         Real fSqrLength = akDiff[1].SquaredLength();
00368         if (fSqrLength > fMaxSqrLength)
00369         {
00370             iMaxIndex = 1;
00371             fMaxSqrLength = fSqrLength;
00372         }
00373         fSqrLength = akDiff[0].SquaredLength();
00374         if (fSqrLength > fMaxSqrLength)
00375         {
00376             iMaxIndex = 0;
00377             fMaxSqrLength = fSqrLength;
00378         }
00379 
00380         if (fMaxSqrLength > Math<Real>::ZERO_TOLERANCE)
00381         {
00382             Real fInvSqrLength = ((Real)1.0)/fMaxSqrLength;
00383             if (iMaxIndex == 0)
00384             {
00385                 // P-V2 = t(V0-V2)
00386                 afBary[0] = akDiff[2].Dot(akDiff[0])*fInvSqrLength;
00387                 afBary[1] = (Real)0.0;
00388                 afBary[2] = (Real)1.0 - afBary[0];
00389             }
00390             else if (iMaxIndex == 1)
00391             {
00392                 // P-V2 = t(V1-V2)
00393                 afBary[0] = (Real)0.0;
00394                 afBary[1] = akDiff[2].Dot(akDiff[1])*fInvSqrLength;
00395                 afBary[2] = (Real)1.0 - afBary[1];
00396             }
00397             else
00398             {
00399                 // P-V1 = t(V0-V1)
00400                 akDiff[2] = *this - rkV1;
00401                 afBary[0] = akDiff[2].Dot(kE2)*fInvSqrLength;
00402                 afBary[1] = (Real)1.0 - afBary[0];
00403                 afBary[2] = (Real)0.0;
00404             }
00405         }
00406         else
00407         {
00408             // triangle is a nearly a point, just return equal weights
00409             afBary[0] = ((Real)1.0)/(Real)3.0;
00410             afBary[1] = afBary[0];
00411             afBary[2] = afBary[0];
00412         }
00413     }
00414 }
00415 //----------------------------------------------------------------------------
00416 template <class Real>
00417 void Vector2<Real>::Orthonormalize (Vector2& rkU, Vector2& rkV)
00418 {
00419     // If the input vectors are v0 and v1, then the Gram-Schmidt
00420     // orthonormalization produces vectors u0 and u1 as follows,
00421     //
00422     //   u0 = v0/|v0|
00423     //   u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
00424     //
00425     // where |A| indicates length of vector A and A*B indicates dot
00426     // product of vectors A and B.
00427 
00428     // compute u0
00429     rkU.Normalize();
00430 
00431     // compute u1
00432     Real fDot0 = rkU.Dot(rkV); 
00433     rkV -= rkU*fDot0;
00434     rkV.Normalize();
00435 }
00436 //----------------------------------------------------------------------------
00437 template <class Real>
00438 void Vector2<Real>::GenerateOrthonormalBasis (Vector2& rkU, Vector2& rkV)
00439 {
00440     rkV.Normalize();
00441     rkU = rkV.Perp();
00442 }
00443 //----------------------------------------------------------------------------
00444 template <class Real>
00445 void Vector2<Real>::ComputeExtremes (int iVQuantity, const Vector2* akPoint,
00446     Vector2& rkMin, Vector2& rkMax)
00447 {
00448     assert(iVQuantity > 0 && akPoint);
00449 
00450     rkMin = akPoint[0];
00451     rkMax = rkMin;
00452     for (int i = 1; i < iVQuantity; i++)
00453     {
00454         const Vector2<Real>& rkPoint = akPoint[i];
00455         for (int j = 0; j < 2; j++)
00456         {
00457             if (rkPoint[j] < rkMin[j])
00458             {
00459                 rkMin[j] = rkPoint[j];
00460             }
00461             else if (rkPoint[j] > rkMax[j])
00462             {
00463                 rkMax[j] = rkPoint[j];
00464             }
00465         }
00466     }
00467 }
00468 //----------------------------------------------------------------------------
00469 template <class Real>
00470 std::ostream& operator<< (std::ostream& rkOStr, const Vector2<Real>& rkV)
00471 {
00472      return rkOStr << rkV.X() << ' ' << rkV.Y();
00473 }
00474 //----------------------------------------------------------------------------
00475 } //namespace Wm4

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