Wm4DistLine3Segment3.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 "Wm4DistLine3Segment3.h"
00019 
00020 namespace Wm4
00021 {
00022 //----------------------------------------------------------------------------
00023 template <class Real>
00024 DistLine3Segment3<Real>::DistLine3Segment3 (const Line3<Real>& rkLine,
00025     const Segment3<Real>& rkSegment)
00026     :
00027     m_rkLine(rkLine),
00028     m_rkSegment(rkSegment)
00029 {
00030 }
00031 //----------------------------------------------------------------------------
00032 template <class Real>
00033 const Line3<Real>& DistLine3Segment3<Real>::GetLine () const
00034 {
00035     return m_rkLine;
00036 }
00037 //----------------------------------------------------------------------------
00038 template <class Real>
00039 const Segment3<Real>& DistLine3Segment3<Real>::GetSegment () const
00040 {
00041     return m_rkSegment;
00042 }
00043 //----------------------------------------------------------------------------
00044 template <class Real>
00045 Real DistLine3Segment3<Real>::Get ()
00046 {
00047     Real fSqrDist = GetSquared();
00048     return Math<Real>::Sqrt(fSqrDist);
00049 }
00050 //----------------------------------------------------------------------------
00051 template <class Real>
00052 Real DistLine3Segment3<Real>::GetSquared ()
00053 {
00054     Vector3<Real> kDiff = m_rkLine.Origin - m_rkSegment.Origin;
00055     Real fA01 = -m_rkLine.Direction.Dot(m_rkSegment.Direction);
00056     Real fB0 = kDiff.Dot(m_rkLine.Direction);
00057     Real fC = kDiff.SquaredLength();
00058     Real fDet = Math<Real>::FAbs((Real)1.0 - fA01*fA01);
00059     Real fB1, fS0, fS1, fSqrDist, fExtDet;
00060 
00061     if (fDet >= Math<Real>::ZERO_TOLERANCE)
00062     {
00063         // The line and segment are not parallel.
00064         fB1 = -kDiff.Dot(m_rkSegment.Direction);
00065         fS1 = fA01*fB0-fB1;
00066         fExtDet = m_rkSegment.Extent*fDet;
00067 
00068         if (fS1 >= -fExtDet)
00069         {
00070             if (fS1 <= fExtDet)
00071             {
00072                 // Two interior points are closest, one on the line and one
00073                 // on the segment.
00074                 Real fInvDet = ((Real)1.0)/fDet;
00075                 fS0 = (fA01*fB1-fB0)*fInvDet;
00076                 fS1 *= fInvDet;
00077                 fSqrDist = fS0*(fS0+fA01*fS1+((Real)2.0)*fB0) +
00078                     fS1*(fA01*fS0+fS1+((Real)2.0)*fB1)+fC;
00079             }
00080             else
00081             {
00082                 // The end point e1 of the segment and an interior point of
00083                 // the line are closest.
00084                 fS1 = m_rkSegment.Extent;
00085                 fS0 = -(fA01*fS1+fB0);
00086                 fSqrDist = -fS0*fS0+fS1*(fS1+((Real)2.0)*fB1)+fC;
00087             }
00088         }
00089         else
00090         {
00091             // The end point e0 of the segment and an interior point of the
00092             // line are closest.
00093             fS1 = -m_rkSegment.Extent;
00094             fS0 = -(fA01*fS1+fB0);
00095             fSqrDist = -fS0*fS0+fS1*(fS1+((Real)2.0)*fB1)+fC;
00096         }
00097     }
00098     else
00099     {
00100         // The line and segment are parallel.  Choose the closest pair so that
00101         // one point is at segment origin.
00102         fS1 = (Real)0.0;
00103         fS0 = -fB0;
00104         fSqrDist = fB0*fS0+fC;
00105     }
00106 
00107     m_kClosestPoint0 = m_rkLine.Origin + fS0*m_rkLine.Direction;
00108     m_kClosestPoint1 = m_rkSegment.Origin + fS1*m_rkSegment.Direction;
00109     m_fLineParameter = fS0;
00110     m_fSegmentParameter = fS1;
00111     return Math<Real>::FAbs(fSqrDist);
00112 }
00113 //----------------------------------------------------------------------------
00114 template <class Real>
00115 Real DistLine3Segment3<Real>::Get (Real fT, const Vector3<Real>& rkVelocity0,
00116     const Vector3<Real>& rkVelocity1)
00117 {
00118     Vector3<Real> kMOrigin0 = m_rkLine.Origin + fT*rkVelocity0;
00119     Vector3<Real> kMOrigin1 = m_rkSegment.Origin + fT*rkVelocity1;
00120     Line3<Real> kMLine(kMOrigin0,m_rkLine.Direction);
00121     Segment3<Real> kMSegment(kMOrigin1,m_rkSegment.Direction,
00122         m_rkSegment.Extent);
00123     return DistLine3Segment3<Real>(kMLine,kMSegment).Get();
00124 }
00125 //----------------------------------------------------------------------------
00126 template <class Real>
00127 Real DistLine3Segment3<Real>::GetSquared (Real fT,
00128     const Vector3<Real>& rkVelocity0, const Vector3<Real>& rkVelocity1)
00129 {
00130     Vector3<Real> kMOrigin0 = m_rkLine.Origin + fT*rkVelocity0;
00131     Vector3<Real> kMOrigin1 = m_rkSegment.Origin + fT*rkVelocity1;
00132     Line3<Real> kMLine(kMOrigin0,m_rkLine.Direction);
00133     Segment3<Real> kMSegment(kMOrigin1,m_rkSegment.Direction,
00134         m_rkSegment.Extent);
00135     return DistLine3Segment3<Real>(kMLine,kMSegment).GetSquared();
00136 }
00137 //----------------------------------------------------------------------------
00138 template <class Real>
00139 Real DistLine3Segment3<Real>::GetLineParameter () const
00140 {
00141     return m_fLineParameter;
00142 }
00143 //----------------------------------------------------------------------------
00144 template <class Real>
00145 Real DistLine3Segment3<Real>::GetSegmentParameter () const
00146 {
00147     return m_fSegmentParameter;
00148 }
00149 //----------------------------------------------------------------------------
00150 
00151 //----------------------------------------------------------------------------
00152 // explicit instantiation
00153 //----------------------------------------------------------------------------
00154 template WM4_FOUNDATION_ITEM
00155 class DistLine3Segment3<float>;
00156 
00157 template WM4_FOUNDATION_ITEM
00158 class DistLine3Segment3<double>;
00159 //----------------------------------------------------------------------------
00160 }

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