00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4Distance.h"
00019
00020 namespace Wm4
00021 {
00022
00023 template <class Real, class TVector>
00024 Distance<Real,TVector>::Distance ()
00025 {
00026 MaximumIterations = 8;
00027 ZeroThreshold = Math<Real>::ZERO_TOLERANCE;
00028 SetDifferenceStep((Real)1e-03);
00029
00030 m_fContactTime = Math<Real>::MAX_REAL;
00031 m_bHasMultipleClosestPoints0 = false;
00032 m_bHasMultipleClosestPoints1 = false;
00033 }
00034
00035 template <class Real, class TVector>
00036 Distance<Real,TVector>::~Distance ()
00037 {
00038 }
00039
00040 template <class Real, class TVector>
00041 Real Distance<Real,TVector>::GetDifferenceStep () const
00042 {
00043 return m_fDifferenceStep;
00044 }
00045
00046 template <class Real, class TVector>
00047 Real Distance<Real,TVector>::GetContactTime () const
00048 {
00049 return m_fContactTime;
00050 }
00051
00052 template <class Real, class TVector>
00053 const TVector& Distance<Real,TVector>::GetClosestPoint0 () const
00054 {
00055 return m_kClosestPoint0;
00056 }
00057
00058 template <class Real, class TVector>
00059 const TVector& Distance<Real,TVector>::GetClosestPoint1 () const
00060 {
00061 return m_kClosestPoint1;
00062 }
00063
00064 template <class Real, class TVector>
00065 bool Distance<Real,TVector>::HasMultipleClosestPoints0 () const
00066 {
00067 return m_bHasMultipleClosestPoints0;
00068 }
00069
00070 template <class Real, class TVector>
00071 bool Distance<Real,TVector>::HasMultipleClosestPoints1 () const
00072 {
00073 return m_bHasMultipleClosestPoints1;
00074 }
00075
00076 template <class Real, class TVector>
00077 void Distance<Real,TVector>::SetDifferenceStep (Real fDifferenceStep)
00078 {
00079 assert(fDifferenceStep > (Real)0.0);
00080 if (fDifferenceStep > (Real)0.0)
00081 {
00082 m_fDifferenceStep = fDifferenceStep;
00083 }
00084 else
00085 {
00086 m_fDifferenceStep = (Real)1e-03;
00087 }
00088
00089 m_fInvTwoDifferenceStep = ((Real)0.5)/m_fDifferenceStep;
00090 }
00091
00092 template <class Real, class TVector>
00093 Real Distance<Real,TVector>::GetDerivative (Real fT,
00094 const TVector& rkVelocity0, const TVector& rkVelocity1)
00095 {
00096
00097 Real fFp = Get(fT+m_fDifferenceStep,rkVelocity0,rkVelocity1);
00098 Real fFm = Get(fT-m_fDifferenceStep,rkVelocity0,rkVelocity1);
00099 Real fDFApprox = m_fInvTwoDifferenceStep*(fFp-fFm);
00100 return fDFApprox;
00101 }
00102
00103 template <class Real, class TVector>
00104 Real Distance<Real,TVector>::GetDerivativeSquared (Real fT,
00105 const TVector& rkVelocity0, const TVector& rkVelocity1)
00106 {
00107
00108
00109
00110 Real fDistance = Get(fT,rkVelocity0,rkVelocity1);
00111 Real fDerivative = GetDerivative(fT,rkVelocity0,rkVelocity1);
00112 return ((Real)2.0)*fDistance*fDerivative;
00113 }
00114
00115 template <class Real, class TVector>
00116 Real Distance<Real,TVector>::Get (Real fTMin, Real fTMax,
00117 const TVector& rkVelocity0, const TVector& rkVelocity1)
00118 {
00119
00120
00121
00122
00123
00124 Real fT0 = fTMin;
00125 Real fF0 = Get(fT0,rkVelocity0,rkVelocity1);
00126 if (fF0 <= ZeroThreshold)
00127 {
00128
00129
00130 m_fContactTime = fT0;
00131 return (Real)0.0;
00132 }
00133 Real fDF0 = GetDerivative(fT0,rkVelocity0,rkVelocity1);
00134 if (fDF0 >= (Real)0.0)
00135 {
00136
00137 m_fContactTime = fT0;
00138 return fF0;
00139 }
00140
00141 Real fT1 = fTMax;
00142 Real fF1 = Get(fT1,rkVelocity0,rkVelocity1);
00143 if (fF1 <= ZeroThreshold)
00144 {
00145
00146 m_fContactTime = fT1;
00147 return (Real)0.0;
00148 }
00149 Real fDF1 = GetDerivative(fT1,rkVelocity0,rkVelocity1);
00150 if (fDF1 <= (Real)0.0)
00151 {
00152
00153 m_fContactTime = fT1;
00154 return fF1;
00155 }
00156
00157
00158
00159
00160 int i;
00161 for (i = 0; i < MaximumIterations; i++)
00162 {
00163
00164 Real fT = fT0 - fF0/fDF0;
00165 if (fT >= fTMax)
00166 {
00167
00168
00169
00170 break;
00171 }
00172
00173 Real fF = Get(fT,rkVelocity0,rkVelocity1);
00174 if (fF <= ZeroThreshold)
00175 {
00176
00177 m_fContactTime = fT;
00178 return (Real)0.0;
00179 }
00180
00181 Real fDF = GetDerivative(fT,rkVelocity0,rkVelocity1);
00182 if (fDF >= (Real)0.0)
00183 {
00184
00185
00186
00187 break;
00188 }
00189
00190 fT0 = fT;
00191 fF0 = fF;
00192 fDF0 = fDF;
00193 }
00194
00195 if (i == MaximumIterations)
00196 {
00197
00198
00199
00200 m_fContactTime = fT0;
00201 return fF0;
00202 }
00203
00204
00205
00206 Real fTm = fT0;
00207 for (i = 0; i < MaximumIterations; i++)
00208 {
00209 fTm = ((Real)0.5)*(fT0 + fT1);
00210 Real fDFm = GetDerivative(fTm,rkVelocity0,rkVelocity1);
00211 Real fProduct = fDFm*fDF0;
00212 if (fProduct < -ZeroThreshold)
00213 {
00214 fT1 = fTm;
00215 fDF1 = fDFm;
00216 }
00217 else if (fProduct > ZeroThreshold)
00218 {
00219 fT0 = fTm;
00220 fDF0 = fDFm;
00221 }
00222 else
00223 {
00224 break;
00225 }
00226 }
00227
00228
00229
00230 m_fContactTime = fTm;
00231 Real fFm = Get(fTm,rkVelocity0,rkVelocity1);
00232 return fFm;
00233 }
00234
00235 template <class Real, class TVector>
00236 Real Distance<Real,TVector>::GetSquared (Real fTMin, Real fTMax,
00237 const TVector& rkVelocity0, const TVector& rkVelocity1)
00238 {
00239
00240
00241
00242
00243
00244 Real fT0 = fTMin;
00245 Real fF0 = GetSquared(fT0,rkVelocity0,rkVelocity1);
00246 if (fF0 <= ZeroThreshold)
00247 {
00248
00249
00250 m_fContactTime = fT0;
00251 return (Real)0.0;
00252 }
00253 Real fDF0 = GetDerivativeSquared(fT0,rkVelocity0,rkVelocity1);
00254 if (fDF0 >= (Real)0.0)
00255 {
00256
00257 m_fContactTime = fT0;
00258 return fF0;
00259 }
00260
00261 Real fT1 = fTMax;
00262 Real fF1 = GetSquared(fT1,rkVelocity0,rkVelocity1);
00263 if (fF1 <= ZeroThreshold)
00264 {
00265
00266 m_fContactTime = fT1;
00267 return (Real)0.0;
00268 }
00269 Real fDF1 = GetDerivativeSquared(fT1,rkVelocity0,rkVelocity1);
00270 if (fDF1 <= (Real)0.0)
00271 {
00272
00273 m_fContactTime = fT1;
00274 return fF1;
00275 }
00276
00277
00278
00279
00280 int i;
00281 for (i = 0; i < MaximumIterations; i++)
00282 {
00283
00284 Real fT = fT0 - fF0/fDF0;
00285 if (fT >= fTMax)
00286 {
00287
00288
00289
00290 break;
00291 }
00292
00293 Real fF = GetSquared(fT,rkVelocity0,rkVelocity1);
00294 if (fF <= ZeroThreshold)
00295 {
00296
00297 m_fContactTime = fT;
00298 return (Real)0.0;
00299 }
00300
00301 Real fDF = GetDerivativeSquared(fT,rkVelocity0,rkVelocity1);
00302 if (fDF >= (Real)0.0)
00303 {
00304
00305
00306
00307 break;
00308 }
00309
00310 fT0 = fT;
00311 fF0 = fF;
00312 fDF0 = fDF;
00313 }
00314
00315 if (i == MaximumIterations)
00316 {
00317
00318
00319
00320 m_fContactTime = fT0;
00321 return fF0;
00322 }
00323
00324
00325
00326 Real fTm = fT0;
00327 for (i = 0; i < MaximumIterations; i++)
00328 {
00329 fTm = ((Real)0.5)*(fT0 + fT1);
00330 Real fDFm = GetDerivativeSquared(fTm,rkVelocity0,rkVelocity1);
00331 Real fProduct = fDFm*fDF0;
00332 if (fProduct < -ZeroThreshold)
00333 {
00334 fT1 = fTm;
00335 fDF1 = fDFm;
00336 }
00337 else if (fProduct > ZeroThreshold)
00338 {
00339 fT0 = fTm;
00340 fDF0 = fDFm;
00341 }
00342 else
00343 {
00344 break;
00345 }
00346 }
00347
00348
00349
00350 m_fContactTime = fTm;
00351 Real fFm = GetSquared(fTm,rkVelocity0,rkVelocity1);
00352 return fFm;
00353 }
00354
00355
00356
00357
00358
00359 template class Distance<float,Vector2f>;
00360 template class Distance<float,Vector3f>;
00361
00362 template class Distance<double,Vector2d>;
00363 template class Distance<double,Vector3d>;
00364
00365 }