00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00160
00161
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
00196
00197 template WM4_FOUNDATION_ITEM
00198 class IntrLine3Box3<float>;
00199
00200 template WM4_FOUNDATION_ITEM
00201 class IntrLine3Box3<double>;
00202
00203 }