Wm4IntrLine3Box3.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 "Wm4IntrLine3Box3.h"
00019 
00020 namespace Wm4
00021 {
00022 //----------------------------------------------------------------------------
00023 template <class Real>
00024 IntrLine3Box3<Real>::IntrLine3Box3 (const Line3<Real>& rkLine,
00025     const Box3<Real>& rkBox)
00026     :
00027     m_rkLine(rkLine),
00028     m_rkBox(rkBox)
00029 {
00030 }
00031 //----------------------------------------------------------------------------
00032 template <class Real>
00033 const Line3<Real>& IntrLine3Box3<Real>::GetLine () const
00034 {
00035     return m_rkLine;
00036 }
00037 //----------------------------------------------------------------------------
00038 template <class Real>
00039 const Box3<Real>& IntrLine3Box3<Real>::GetBox () const
00040 {
00041     return m_rkBox;
00042 }
00043 //----------------------------------------------------------------------------
00044 template <class Real>
00045 bool IntrLine3Box3<Real>::Test ()
00046 {
00047     Real afAWdU[3], afAWxDdU[3], fRhs;
00048 
00049     Vector3<Real> kDiff = m_rkLine.Origin - m_rkBox.Center;
00050     Vector3<Real> kWxD = m_rkLine.Direction.Cross(kDiff);
00051 
00052     afAWdU[1] = Math<Real>::FAbs(m_rkLine.Direction.Dot(m_rkBox.Axis[1]));
00053     afAWdU[2] = Math<Real>::FAbs(m_rkLine.Direction.Dot(m_rkBox.Axis[2]));
00054     afAWxDdU[0] = Math<Real>::FAbs(kWxD.Dot(m_rkBox.Axis[0]));
00055     fRhs = m_rkBox.Extent[1]*afAWdU[2] + m_rkBox.Extent[2]*afAWdU[1];
00056     if (afAWxDdU[0] > fRhs)
00057     {
00058         return false;
00059     }
00060 
00061     afAWdU[0] = Math<Real>::FAbs(m_rkLine.Direction.Dot(m_rkBox.Axis[0]));
00062     afAWxDdU[1] = Math<Real>::FAbs(kWxD.Dot(m_rkBox.Axis[1]));
00063     fRhs = m_rkBox.Extent[0]*afAWdU[2] + m_rkBox.Extent[2]*afAWdU[0];
00064     if (afAWxDdU[1] > fRhs)
00065     {
00066         return false;
00067     }
00068 
00069     afAWxDdU[2] = Math<Real>::FAbs(kWxD.Dot(m_rkBox.Axis[2]));
00070     fRhs = m_rkBox.Extent[0]*afAWdU[1] + m_rkBox.Extent[1]*afAWdU[0];
00071     if (afAWxDdU[2] > fRhs)
00072     {
00073         return false;
00074     }
00075 
00076     return true;
00077 }
00078 //----------------------------------------------------------------------------
00079 template <class Real>
00080 bool IntrLine3Box3<Real>::Find ()
00081 {
00082     Real fT0 = -Math<Real>::MAX_REAL, fT1 = Math<Real>::MAX_REAL;
00083     return DoClipping(fT0,fT1,m_rkLine.Origin,m_rkLine.Direction,m_rkBox,
00084         true,m_iQuantity,m_akPoint,m_iIntersectionType);
00085 }
00086 //----------------------------------------------------------------------------
00087 template <class Real>
00088 int IntrLine3Box3<Real>::GetQuantity () const
00089 {
00090     return m_iQuantity;
00091 }
00092 //----------------------------------------------------------------------------
00093 template <class Real>
00094 const Vector3<Real>& IntrLine3Box3<Real>::GetPoint (int i) const
00095 {
00096     assert(0 <= i && i < m_iQuantity);
00097     return m_akPoint[i];
00098 }
00099 //----------------------------------------------------------------------------
00100 template <class Real>
00101 bool IntrLine3Box3<Real>::DoClipping (Real fT0, Real fT1,
00102     const Vector3<Real>& rkOrigin, const Vector3<Real>& rkDirection,
00103     const Box3<Real>& rkBox, bool bSolid, int& riQuantity,
00104     Vector3<Real> akPoint[2], int& riIntrType)
00105 {
00106     assert(fT0 < fT1);
00107 
00108     // convert linear component to box coordinates
00109     Vector3<Real> kDiff = rkOrigin - rkBox.Center;
00110     Vector3<Real> kBOrigin(
00111         kDiff.Dot(rkBox.Axis[0]),
00112         kDiff.Dot(rkBox.Axis[1]),
00113         kDiff.Dot(rkBox.Axis[2])
00114     );
00115     Vector3<Real> kBDirection(
00116         rkDirection.Dot(rkBox.Axis[0]),
00117         rkDirection.Dot(rkBox.Axis[1]),
00118         rkDirection.Dot(rkBox.Axis[2])
00119     );
00120 
00121     Real fSaveT0 = fT0, fSaveT1 = fT1;
00122     bool bNotAllClipped =
00123         Clip(+kBDirection.X(),-kBOrigin.X()-rkBox.Extent[0],fT0,fT1) &&
00124         Clip(-kBDirection.X(),+kBOrigin.X()-rkBox.Extent[0],fT0,fT1) &&
00125         Clip(+kBDirection.Y(),-kBOrigin.Y()-rkBox.Extent[1],fT0,fT1) &&
00126         Clip(-kBDirection.Y(),+kBOrigin.Y()-rkBox.Extent[1],fT0,fT1) &&
00127         Clip(+kBDirection.Z(),-kBOrigin.Z()-rkBox.Extent[2],fT0,fT1) &&
00128         Clip(-kBDirection.Z(),+kBOrigin.Z()-rkBox.Extent[2],fT0,fT1);
00129 
00130     if (bNotAllClipped && (bSolid || fT0 != fSaveT0 || fT1 != fSaveT1))
00131     {
00132         if (fT1 > fT0)
00133         {
00134             riIntrType = IT_SEGMENT;
00135             riQuantity = 2;
00136             akPoint[0] = rkOrigin + fT0*rkDirection;
00137             akPoint[1] = rkOrigin + fT1*rkDirection;
00138         }
00139         else
00140         {
00141             riIntrType = IT_POINT;
00142             riQuantity = 1;
00143             akPoint[0] = rkOrigin + fT0*rkDirection;
00144         }
00145     }
00146     else
00147     {
00148         riQuantity = 0;
00149         riIntrType = IT_EMPTY;
00150     }
00151 
00152     return riIntrType != IT_EMPTY;
00153 }
00154 //----------------------------------------------------------------------------
00155 template <class Real>
00156 bool IntrLine3Box3<Real>::Clip (Real fDenom, Real fNumer, Real& rfT0,
00157     Real& rfT1)
00158 {
00159     // Return value is 'true' if line segment intersects the current test
00160     // plane.  Otherwise 'false' is returned in which case the line segment
00161     // is entirely clipped.
00162 
00163     if (fDenom > (Real)0.0)
00164     {
00165         if (fNumer > fDenom*rfT1)
00166         {
00167             return false;
00168         }
00169         if (fNumer > fDenom*rfT0)
00170         {
00171             rfT0 = fNumer/fDenom;
00172         }
00173         return true;
00174     }
00175     else if (fDenom < (Real)0.0)
00176     {
00177         if (fNumer > fDenom*rfT0)
00178         {
00179             return false;
00180         }
00181         if (fNumer > fDenom*rfT1)
00182         {
00183             rfT1 = fNumer/fDenom;
00184         }
00185         return true;
00186     }
00187     else
00188     {
00189         return fNumer <= (Real)0.0;
00190     }
00191 }
00192 //----------------------------------------------------------------------------
00193 
00194 //----------------------------------------------------------------------------
00195 // explicit instantiation
00196 //----------------------------------------------------------------------------
00197 template WM4_FOUNDATION_ITEM
00198 class IntrLine3Box3<float>;
00199 
00200 template WM4_FOUNDATION_ITEM
00201 class IntrLine3Box3<double>;
00202 //----------------------------------------------------------------------------
00203 }

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