Wm4DistVector3Triangle3.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 "Wm4DistVector3Triangle3.h"
00019 
00020 namespace Wm4
00021 {
00022 //----------------------------------------------------------------------------
00023 template <class Real>
00024 DistVector3Triangle3<Real>::DistVector3Triangle3 (
00025     const Vector3<Real>& rkVector, const Triangle3<Real>& rkTriangle)
00026     :
00027     m_rkVector(rkVector),
00028     m_rkTriangle(rkTriangle)
00029 {
00030 }
00031 //----------------------------------------------------------------------------
00032 template <class Real>
00033 const Vector3<Real>& DistVector3Triangle3<Real>::GetVector () const
00034 {
00035     return m_rkVector;
00036 }
00037 //----------------------------------------------------------------------------
00038 template <class Real>
00039 const Triangle3<Real>& DistVector3Triangle3<Real>::GetTriangle () const
00040 {
00041     return m_rkTriangle;
00042 }
00043 //----------------------------------------------------------------------------
00044 template <class Real>
00045 Real DistVector3Triangle3<Real>::Get ()
00046 {
00047     Real fSqrDist = GetSquared();
00048     return Math<Real>::Sqrt(fSqrDist);
00049 }
00050 //----------------------------------------------------------------------------
00051 template <class Real>
00052 Real DistVector3Triangle3<Real>::GetSquared ()
00053 {
00054     Vector3<Real> kDiff = m_rkTriangle.V[0] - m_rkVector;
00055     Vector3<Real> kEdge0 = m_rkTriangle.V[1] - m_rkTriangle.V[0];
00056     Vector3<Real> kEdge1 = m_rkTriangle.V[2] - m_rkTriangle.V[0];
00057     Real fA00 = kEdge0.SquaredLength();
00058     Real fA01 = kEdge0.Dot(kEdge1);
00059     Real fA11 = kEdge1.SquaredLength();
00060     Real fB0 = kDiff.Dot(kEdge0);
00061     Real fB1 = kDiff.Dot(kEdge1);
00062     Real fC = kDiff.SquaredLength();
00063     Real fDet = Math<Real>::FAbs(fA00*fA11-fA01*fA01);
00064     Real fS = fA01*fB1-fA11*fB0;
00065     Real fT = fA01*fB0-fA00*fB1;
00066     Real fSqrDistance;
00067 
00068     if (fS + fT <= fDet)
00069     {
00070         if (fS < (Real)0.0)
00071         {
00072             if (fT < (Real)0.0)  // region 4
00073             {
00074                 if (fB0 < (Real)0.0)
00075                 {
00076                     fT = (Real)0.0;
00077                     if (-fB0 >= fA00)
00078                     {
00079                         fS = (Real)1.0;
00080                         fSqrDistance = fA00+((Real)2.0)*fB0+fC;
00081                     }
00082                     else
00083                     {
00084                         fS = -fB0/fA00;
00085                         fSqrDistance = fB0*fS+fC;
00086                     }
00087                 }
00088                 else
00089                 {
00090                     fS = (Real)0.0;
00091                     if (fB1 >= (Real)0.0)
00092                     {
00093                         fT = (Real)0.0;
00094                         fSqrDistance = fC;
00095                     }
00096                     else if (-fB1 >= fA11)
00097                     {
00098                         fT = (Real)1.0;
00099                         fSqrDistance = fA11+((Real)2.0)*fB1+fC;
00100                     }
00101                     else
00102                     {
00103                         fT = -fB1/fA11;
00104                         fSqrDistance = fB1*fT+fC;
00105                     }
00106                 }
00107             }
00108             else  // region 3
00109             {
00110                 fS = (Real)0.0;
00111                 if (fB1 >= (Real)0.0)
00112                 {
00113                     fT = (Real)0.0;
00114                     fSqrDistance = fC;
00115                 }
00116                 else if (-fB1 >= fA11)
00117                 {
00118                     fT = (Real)1.0;
00119                     fSqrDistance = fA11+((Real)2.0)*fB1+fC;
00120                 }
00121                 else
00122                 {
00123                     fT = -fB1/fA11;
00124                     fSqrDistance = fB1*fT+fC;
00125                 }
00126             }
00127         }
00128         else if (fT < (Real)0.0)  // region 5
00129         {
00130             fT = (Real)0.0;
00131             if (fB0 >= (Real)0.0)
00132             {
00133                 fS = (Real)0.0;
00134                 fSqrDistance = fC;
00135             }
00136             else if (-fB0 >= fA00)
00137             {
00138                 fS = (Real)1.0;
00139                 fSqrDistance = fA00+((Real)2.0)*fB0+fC;
00140             }
00141             else
00142             {
00143                 fS = -fB0/fA00;
00144                 fSqrDistance = fB0*fS+fC;
00145             }
00146         }
00147         else  // region 0
00148         {
00149             // minimum at interior point
00150             Real fInvDet = ((Real)1.0)/fDet;
00151             fS *= fInvDet;
00152             fT *= fInvDet;
00153             fSqrDistance = fS*(fA00*fS+fA01*fT+((Real)2.0)*fB0) +
00154                 fT*(fA01*fS+fA11*fT+((Real)2.0)*fB1)+fC;
00155         }
00156     }
00157     else
00158     {
00159         Real fTmp0, fTmp1, fNumer, fDenom;
00160 
00161         if (fS < (Real)0.0)  // region 2
00162         {
00163             fTmp0 = fA01 + fB0;
00164             fTmp1 = fA11 + fB1;
00165             if (fTmp1 > fTmp0)
00166             {
00167                 fNumer = fTmp1 - fTmp0;
00168                 fDenom = fA00-2.0f*fA01+fA11;
00169                 if (fNumer >= fDenom)
00170                 {
00171                     fS = (Real)1.0;
00172                     fT = (Real)0.0;
00173                     fSqrDistance = fA00+((Real)2.0)*fB0+fC;
00174                 }
00175                 else
00176                 {
00177                     fS = fNumer/fDenom;
00178                     fT = (Real)1.0 - fS;
00179                     fSqrDistance = fS*(fA00*fS+fA01*fT+2.0f*fB0) +
00180                         fT*(fA01*fS+fA11*fT+((Real)2.0)*fB1)+fC;
00181                 }
00182             }
00183             else
00184             {
00185                 fS = (Real)0.0;
00186                 if (fTmp1 <= (Real)0.0)
00187                 {
00188                     fT = (Real)1.0;
00189                     fSqrDistance = fA11+((Real)2.0)*fB1+fC;
00190                 }
00191                 else if (fB1 >= (Real)0.0)
00192                 {
00193                     fT = (Real)0.0;
00194                     fSqrDistance = fC;
00195                 }
00196                 else
00197                 {
00198                     fT = -fB1/fA11;
00199                     fSqrDistance = fB1*fT+fC;
00200                 }
00201             }
00202         }
00203         else if (fT < (Real)0.0)  // region 6
00204         {
00205             fTmp0 = fA01 + fB1;
00206             fTmp1 = fA00 + fB0;
00207             if (fTmp1 > fTmp0)
00208             {
00209                 fNumer = fTmp1 - fTmp0;
00210                 fDenom = fA00-((Real)2.0)*fA01+fA11;
00211                 if (fNumer >= fDenom)
00212                 {
00213                     fT = (Real)1.0;
00214                     fS = (Real)0.0;
00215                     fSqrDistance = fA11+((Real)2.0)*fB1+fC;
00216                 }
00217                 else
00218                 {
00219                     fT = fNumer/fDenom;
00220                     fS = (Real)1.0 - fT;
00221                     fSqrDistance = fS*(fA00*fS+fA01*fT+((Real)2.0)*fB0) +
00222                         fT*(fA01*fS+fA11*fT+((Real)2.0)*fB1)+fC;
00223                 }
00224             }
00225             else
00226             {
00227                 fT = (Real)0.0;
00228                 if (fTmp1 <= (Real)0.0)
00229                 {
00230                     fS = (Real)1.0;
00231                     fSqrDistance = fA00+((Real)2.0)*fB0+fC;
00232                 }
00233                 else if (fB0 >= (Real)0.0)
00234                 {
00235                     fS = (Real)0.0;
00236                     fSqrDistance = fC;
00237                 }
00238                 else
00239                 {
00240                     fS = -fB0/fA00;
00241                     fSqrDistance = fB0*fS+fC;
00242                 }
00243             }
00244         }
00245         else  // region 1
00246         {
00247             fNumer = fA11 + fB1 - fA01 - fB0;
00248             if (fNumer <= (Real)0.0)
00249             {
00250                 fS = (Real)0.0;
00251                 fT = (Real)1.0;
00252                 fSqrDistance = fA11+((Real)2.0)*fB1+fC;
00253             }
00254             else
00255             {
00256                 fDenom = fA00-2.0f*fA01+fA11;
00257                 if (fNumer >= fDenom)
00258                 {
00259                     fS = (Real)1.0;
00260                     fT = (Real)0.0;
00261                     fSqrDistance = fA00+((Real)2.0)*fB0+fC;
00262                 }
00263                 else
00264                 {
00265                     fS = fNumer/fDenom;
00266                     fT = (Real)1.0 - fS;
00267                     fSqrDistance = fS*(fA00*fS+fA01*fT+((Real)2.0)*fB0) +
00268                         fT*(fA01*fS+fA11*fT+((Real)2.0)*fB1)+fC;
00269                 }
00270             }
00271         }
00272     }
00273 
00274     // account for numerical round-off error
00275     if (fSqrDistance < (Real)0.0)
00276     {
00277         fSqrDistance = (Real)0.0;
00278     }
00279 
00280     m_kClosestPoint0 = m_rkVector;
00281     m_kClosestPoint1 = m_rkTriangle.V[0] + fS*kEdge0 + fT*kEdge1;
00282     m_afTriangleBary[1] = fS;
00283     m_afTriangleBary[2] = fT;
00284     m_afTriangleBary[0] = (Real)1.0 - fS - fT;
00285     return fSqrDistance;
00286 }
00287 //----------------------------------------------------------------------------
00288 template <class Real>
00289 Real DistVector3Triangle3<Real>::Get (Real fT,
00290     const Vector3<Real>& rkVelocity0, const Vector3<Real>& rkVelocity1)
00291 {
00292     Vector3<Real> kMVector = m_rkVector + fT*rkVelocity0;
00293     Vector3<Real> kMV0 = m_rkTriangle.V[0] + fT*rkVelocity1;
00294     Vector3<Real> kMV1 = m_rkTriangle.V[1] + fT*rkVelocity1;
00295     Vector3<Real> kMV2 = m_rkTriangle.V[2] + fT*rkVelocity1;
00296     Triangle3<Real> kMTriangle(kMV0,kMV1,kMV2);
00297     return DistVector3Triangle3<Real>(kMVector,kMTriangle).Get();
00298 }
00299 //----------------------------------------------------------------------------
00300 template <class Real>
00301 Real DistVector3Triangle3<Real>::GetSquared (Real fT,
00302     const Vector3<Real>& rkVelocity0, const Vector3<Real>& rkVelocity1)
00303 {
00304     Vector3<Real> kMVector = m_rkVector + fT*rkVelocity0;
00305     Vector3<Real> kMV0 = m_rkTriangle.V[0] + fT*rkVelocity1;
00306     Vector3<Real> kMV1 = m_rkTriangle.V[1] + fT*rkVelocity1;
00307     Vector3<Real> kMV2 = m_rkTriangle.V[2] + fT*rkVelocity1;
00308     Triangle3<Real> kMTriangle(kMV0,kMV1,kMV2);
00309     return DistVector3Triangle3<Real>(kMVector,kMTriangle).GetSquared();
00310 }
00311 //----------------------------------------------------------------------------
00312 template <class Real>
00313 Real DistVector3Triangle3<Real>::GetTriangleBary (int i) const
00314 {
00315     assert(0 <= i && i < 3);
00316     return m_afTriangleBary[i];
00317 }
00318 //----------------------------------------------------------------------------
00319 
00320 //----------------------------------------------------------------------------
00321 // explicit instantiation
00322 //----------------------------------------------------------------------------
00323 template WM4_FOUNDATION_ITEM
00324 class DistVector3Triangle3<float>;
00325 
00326 template WM4_FOUNDATION_ITEM
00327 class DistVector3Triangle3<double>;
00328 //----------------------------------------------------------------------------
00329 }

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