Wm4DistLine3Triangle3.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.1 (2006/07/23)
00016 
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4DistLine3Triangle3.h"
00019 #include "Wm4DistLine3Segment3.h"
00020 
00021 namespace Wm4
00022 {
00023 //----------------------------------------------------------------------------
00024 template <class Real>
00025 DistLine3Triangle3<Real>::DistLine3Triangle3 (const Line3<Real>& rkLine,
00026     const Triangle3<Real>& rkTriangle)
00027     :
00028     m_rkLine(rkLine),
00029     m_rkTriangle(rkTriangle)
00030 {
00031 }
00032 //----------------------------------------------------------------------------
00033 template <class Real>
00034 const Line3<Real>& DistLine3Triangle3<Real>::GetLine () const
00035 {
00036     return m_rkLine;
00037 }
00038 //----------------------------------------------------------------------------
00039 template <class Real>
00040 const Triangle3<Real>& DistLine3Triangle3<Real>::GetTriangle () const
00041 {
00042     return m_rkTriangle;
00043 }
00044 //----------------------------------------------------------------------------
00045 template <class Real>
00046 Real DistLine3Triangle3<Real>::Get ()
00047 {
00048     Real fSqrDist = GetSquared();
00049     return Math<Real>::Sqrt(fSqrDist);
00050 }
00051 //----------------------------------------------------------------------------
00052 template <class Real>
00053 Real DistLine3Triangle3<Real>::GetSquared ()
00054 {
00055     // Test if line intersects triangle.  If so, the squared distance is zero.
00056     Vector3<Real> kEdge0 = m_rkTriangle.V[1] - m_rkTriangle.V[0];
00057     Vector3<Real> kEdge1 = m_rkTriangle.V[2] - m_rkTriangle.V[0];
00058     Vector3<Real> kNormal = kEdge0.UnitCross(kEdge1);
00059     Real fNdD = kNormal.Dot(m_rkLine.Direction);
00060     if (Math<Real>::FAbs(fNdD) > Math<Real>::ZERO_TOLERANCE)
00061     {
00062         // The line and triangle are not parallel, so the line intersects
00063         // the plane of the triangle.
00064         Vector3<Real> kDiff = m_rkLine.Origin - m_rkTriangle.V[0];
00065         Vector3<Real>& rkD = (Vector3<Real>&) m_rkLine.Direction;
00066         Vector3<Real> kU, kV;
00067         Vector3<Real>::GenerateComplementBasis(kU,kV,rkD);
00068         Real fUdE0 = kU.Dot(kEdge0);
00069         Real fUdE1 = kU.Dot(kEdge0);
00070         Real fUdDiff = kU.Dot(kDiff);
00071         Real fVdE0 = kV.Dot(kEdge0);
00072         Real fVdE1 = kV.Dot(kEdge0);
00073         Real fVdDiff = kV.Dot(kDiff);
00074         Real fInvDet = ((Real)1.0)/(fUdE0*fVdE1 - fUdE1*fVdE0);
00075 
00076         // Barycentric coordinates for the point of intersection.
00077         Real fB1 = (fVdE1*fUdDiff - fUdE1*fVdDiff)*fInvDet;
00078         Real fB2 = (fUdE0*fVdDiff - fVdE0*fUdDiff)*fInvDet;
00079         Real fB0 = (Real)1.0 - fB1 - fB2;
00080 
00081         if (fB0 >= (Real)0.0 && fB1 >= (Real)0.0 && fB2 >= (Real)0.0)
00082         {
00083             // Line parameter for the point of intersection.
00084             Real fDdE0 = rkD.Dot(kEdge0);
00085             Real fDdE1 = rkD.Dot(kEdge1);
00086             Real fDdDiff = m_rkLine.Direction.Dot(kDiff);
00087             m_fLineParameter = fB1*fDdE0 + fB2*fDdE1 - fDdDiff;
00088 
00089             // Barycentric coordinates for the point of intersection.
00090             m_afTriangleBary[0] = fB0;
00091             m_afTriangleBary[1] = fB1;
00092             m_afTriangleBary[2] = fB2;
00093 
00094             // The intersection point is inside or on the triangle.
00095             m_kClosestPoint0 = m_rkLine.Origin +
00096                 m_fLineParameter*m_rkLine.Direction;
00097 
00098             m_kClosestPoint1 = m_rkTriangle.V[0] + fB1*kEdge0 + fB2*kEdge1;
00099             return (Real)0.0;
00100         }
00101     }
00102 
00103     // Either (1) the line is not parallel to the triangle and the point of
00104     // intersection of the line and the plane of the triangle is outside the
00105     // triangle or (2) the line and triangle are parallel.  Regardless, the
00106     // closest point on the triangle is on an edge of the triangle.  Compare
00107     // the line to all three edges of the triangle.
00108     Real fSqrDist = Math<Real>::MAX_REAL;
00109     for (int i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
00110     {
00111         Segment3<Real> kSeg;
00112         kSeg.Origin = ((Real)0.5)*(m_rkTriangle.V[i0] + m_rkTriangle.V[i1]);
00113         kSeg.Direction = m_rkTriangle.V[i1] - m_rkTriangle.V[i0];
00114         kSeg.Extent = ((Real)0.5)*kSeg.Direction.Normalize();
00115         DistLine3Segment3<Real> kLSDist(m_rkLine,kSeg);
00116         Real fSqrDistTmp = kLSDist.GetSquared();
00117         if (fSqrDistTmp < fSqrDist)
00118         {
00119             m_kClosestPoint0 = kLSDist.GetClosestPoint0();
00120             m_kClosestPoint1 = kLSDist.GetClosestPoint1();
00121             fSqrDist = fSqrDistTmp;
00122 
00123             m_fLineParameter = kLSDist.GetLineParameter();
00124             Real fRatio = kLSDist.GetSegmentParameter()/kSeg.Extent;
00125             m_afTriangleBary[i0] = ((Real)0.5)*((Real)1.0 - fRatio);
00126             m_afTriangleBary[i1] = (Real)1.0 - m_afTriangleBary[i0];
00127             m_afTriangleBary[3-i0-i1] = (Real)0.0;
00128         }
00129     }
00130     return fSqrDist;
00131 }
00132 //----------------------------------------------------------------------------
00133 template <class Real>
00134 Real DistLine3Triangle3<Real>::Get (Real fT, const Vector3<Real>& rkVelocity0,
00135     const Vector3<Real>& rkVelocity1)
00136 {
00137     Vector3<Real> kMOrigin = m_rkLine.Origin + fT*rkVelocity0;
00138     Vector3<Real> kMV0 = m_rkTriangle.V[0] + fT*rkVelocity1;
00139     Vector3<Real> kMV1 = m_rkTriangle.V[1] + fT*rkVelocity1;
00140     Vector3<Real> kMV2 = m_rkTriangle.V[2] + fT*rkVelocity1;
00141     Line3<Real> kMLine(kMOrigin,m_rkLine.Direction);
00142     Triangle3<Real> kMTriangle(kMV0,kMV1,kMV2);
00143     return DistLine3Triangle3<Real>(kMLine,kMTriangle).Get();
00144 }
00145 //----------------------------------------------------------------------------
00146 template <class Real>
00147 Real DistLine3Triangle3<Real>::GetSquared (Real fT,
00148     const Vector3<Real>& rkVelocity0, const Vector3<Real>& rkVelocity1)
00149 {
00150     Vector3<Real> kMOrigin = m_rkLine.Origin + fT*rkVelocity0;
00151     Vector3<Real> kMV0 = m_rkTriangle.V[0] + fT*rkVelocity1;
00152     Vector3<Real> kMV1 = m_rkTriangle.V[1] + fT*rkVelocity1;
00153     Vector3<Real> kMV2 = m_rkTriangle.V[2] + fT*rkVelocity1;
00154     Line3<Real> kMLine(kMOrigin,m_rkLine.Direction);
00155     Triangle3<Real> kMTriangle(kMV0,kMV1,kMV2);
00156     return DistLine3Triangle3<Real>(kMLine,kMTriangle).GetSquared();
00157 }
00158 //----------------------------------------------------------------------------
00159 template <class Real>
00160 Real DistLine3Triangle3<Real>::GetLineParameter () const
00161 {
00162     return m_fLineParameter;
00163 }
00164 //----------------------------------------------------------------------------
00165 template <class Real>
00166 Real DistLine3Triangle3<Real>::GetTriangleBary (int i) const
00167 {
00168     assert(0 <= i && i < 3);
00169     return m_afTriangleBary[i];
00170 }
00171 //----------------------------------------------------------------------------
00172 
00173 //----------------------------------------------------------------------------
00174 // explicit instantiation
00175 //----------------------------------------------------------------------------
00176 template WM4_FOUNDATION_ITEM
00177 class DistLine3Triangle3<float>;
00178 
00179 template WM4_FOUNDATION_ITEM
00180 class DistLine3Triangle3<double>;
00181 //----------------------------------------------------------------------------
00182 }

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