math/Segment.cpp

Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <math.h>
00003 #include "Segment.h"
00004 
00005 //=============================================================================
00006 // Constructor
00007 //
00008 // Description: Constructor
00009 //=============================================================================
00010 Segment::Segment( const Vector4& p0, const Vector4& p1 )
00011 :
00012     p0( p0 ),
00013     p1( p1 )
00014 {
00015     //nothing
00016 }
00017 
00018 //=============================================================================
00019 // Distance
00020 //
00021 // Description: distance between point and this segment
00022 //=============================================================================
00023 double Segment::Distance( const Vector4& p ) const
00024 {
00025     return sqrt( DistanceSquared( p ) );
00026 }
00027 
00028 //=============================================================================
00029 // Distance
00030 //
00031 // Description: distance between segment and this segment
00032 //=============================================================================
00033 double Segment::Distance( const Segment& s ) const
00034 {
00035     return sqrt( DistanceSquared( s ) );
00036 }
00037 
00038 //=============================================================================
00039 // DistanceSquared
00040 //
00041 // Description: distance between segment and this segment
00042 //=============================================================================
00043 double Segment::DistanceSquared( const Segment& s ) const
00044 {
00045     Vector4 kDiff = this->p0 - s.p0;
00046     Vector4 d0 = p1 - p0;
00047     Vector4 d1 = s.p1 - s.p0;
00048     double fA00 = d0.MagSquared();
00049     double fA01 = -d0.Dot( d1 );
00050     double fA11 = d1.MagSquared();
00051     double fB0 = kDiff.Dot( d0 );
00052     double fC = kDiff.MagSquared();
00053     double fDet = fabs( fA00 * fA11 - fA01 * fA01 );
00054     double fB1, fS, fT, fSqrDist, fTmp;
00055 
00056     //HACK: what is this value really?
00057     double gs_fTolerance = 0.00000001;
00058     if ( fDet >= gs_fTolerance )
00059     {
00060         // line segments are not parallel
00061         fB1 = -kDiff.Dot( d1 );
00062         fS = fA01*fB1-fA11*fB0;
00063         fT = fA01*fB0-fA00*fB1;
00064         
00065         if ( fS >= 0.0f )
00066         {
00067             if ( fS <= fDet )
00068             {
00069                 if ( fT >= 0.0f )
00070                 {
00071                     if ( fT <= fDet )  // region 0 (interior)
00072                     {
00073                         // minimum at two interior points of 3D lines
00074                         double fInvDet = 1.0f/fDet;
00075                         fS *= fInvDet;
00076                         fT *= fInvDet;
00077                         fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) +
00078                             fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
00079                     }
00080                     else  // region 3 (side)
00081                     {
00082                         fT = 1.0f;
00083                         fTmp = fA01+fB0;
00084                         if ( fTmp >= 0.0f )
00085                         {
00086                             fS = 0.0f;
00087                             fSqrDist = fA11+2.0f*fB1+fC;
00088                         }
00089                         else if ( -fTmp >= fA00 )
00090                         {
00091                             fS = 1.0f;
00092                             fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp);
00093                         }
00094                         else
00095                         {
00096                             fS = -fTmp/fA00;
00097                             fSqrDist = fTmp*fS+fA11+2.0f*fB1+fC;
00098                         }
00099                     }
00100                 }
00101                 else  // region 7 (side)
00102                 {
00103                     fT = 0.0f;
00104                     if ( fB0 >= 0.0f )
00105                     {
00106                         fS = 0.0f;
00107                         fSqrDist = fC;
00108                     }
00109                     else if ( -fB0 >= fA00 )
00110                     {
00111                         fS = 1.0f;
00112                         fSqrDist = fA00+2.0f*fB0+fC;
00113                     }
00114                     else
00115                     {
00116                         fS = -fB0/fA00;
00117                         fSqrDist = fB0*fS+fC;
00118                     }
00119                 }
00120             }
00121             else
00122             {
00123                 if ( fT >= 0.0 )
00124                 {
00125                     if ( fT <= fDet )  // region 1 (side)
00126                     {
00127                         fS = 1.0f;
00128                         fTmp = fA01+fB1;
00129                         if ( fTmp >= 0.0f )
00130                         {
00131                             fT = 0.0f;
00132                             fSqrDist = fA00+2.0f*fB0+fC;
00133                         }
00134                         else if ( -fTmp >= fA11 )
00135                         {
00136                             fT = 1.0f;
00137                             fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
00138                         }
00139                         else
00140                         {
00141                             fT = -fTmp/fA11;
00142                             fSqrDist = fTmp*fT+fA00+2.0f*fB0+fC;
00143                         }
00144                     }
00145                     else  // region 2 (corner)
00146                     {
00147                         fTmp = fA01+fB0;
00148                         if ( -fTmp <= fA00 )
00149                         {
00150                             fT = 1.0f;
00151                             if ( fTmp >= 0.0f )
00152                             {
00153                                 fS = 0.0f;
00154                                 fSqrDist = fA11+2.0f*fB1+fC;
00155                             }
00156                             else
00157                             {
00158                                  fS = -fTmp/fA00;
00159                                  fSqrDist = fTmp*fS+fA11+2.0f*fB1+fC;
00160                             }
00161                         }
00162                         else
00163                         {
00164                             fS = 1.0f;
00165                             fTmp = fA01+fB1;
00166                             if ( fTmp >= 0.0f )
00167                             {
00168                                 fT = 0.0f;
00169                                 fSqrDist = fA00+2.0f*fB0+fC;
00170                             }
00171                             else if ( -fTmp >= fA11 )
00172                             {
00173                                 fT = 1.0f;
00174                                 fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
00175                             }
00176                             else
00177                             {
00178                                 fT = -fTmp/fA11;
00179                                 fSqrDist = fTmp*fT+fA00+2.0f*fB0+fC;
00180                             }
00181                         }
00182                     }
00183                 }
00184                 else  // region 8 (corner)
00185                 {
00186                     if ( -fB0 < fA00 )
00187                     {
00188                         fT = 0.0f;
00189                         if ( fB0 >= 0.0f )
00190                         {
00191                             fS = 0.0f;
00192                             fSqrDist = fC;
00193                         }
00194                         else
00195                         {
00196                             fS = -fB0/fA00;
00197                             fSqrDist = fB0*fS+fC;
00198                         }
00199                     }
00200                     else
00201                     {
00202                         fS = 1.0f;
00203                         fTmp = fA01+fB1;
00204                         if ( fTmp >= 0.0f )
00205                         {
00206                             fT = 0.0f;
00207                             fSqrDist = fA00+2.0f*fB0+fC;
00208                         }
00209                         else if ( -fTmp >= fA11 )
00210                         {
00211                             fT = 1.0f;
00212                             fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
00213                         }
00214                         else
00215                         {
00216                             fT = -fTmp/fA11;
00217                             fSqrDist = fTmp*fT+fA00+2.0f*fB0+fC;
00218                         }
00219                     }
00220                 }
00221             }
00222         }
00223         else 
00224         {
00225             if ( fT >= 0.0f )
00226             {
00227                 if ( fT <= fDet )  // region 5 (side)
00228                 {
00229                     fS = 0.0f;
00230                     if ( fB1 >= 0.0f )
00231                     {
00232                         fT = 0.0f;
00233                         fSqrDist = fC;
00234                     }
00235                     else if ( -fB1 >= fA11 )
00236                     {
00237                         fT = 1.0f;
00238                         fSqrDist = fA11+2.0f*fB1+fC;
00239                     }
00240                     else
00241                     {
00242                         fT = -fB1/fA11;
00243                         fSqrDist = fB1*fT+fC;
00244                     }
00245                 }
00246                 else  // region 4 (corner)
00247                 {
00248                     fTmp = fA01+fB0;
00249                     if ( fTmp < 0.0f )
00250                     {
00251                         fT = 1.0f;
00252                         if ( -fTmp >= fA00 )
00253                         {
00254                             fS = 1.0f;
00255                             fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp);
00256                         }
00257                         else
00258                         {
00259                             fS = -fTmp/fA00;
00260                             fSqrDist = fTmp*fS+fA11+2.0f*fB1+fC;
00261                         }
00262                     }
00263                     else
00264                     {
00265                         fS = 0.0f;
00266                         if ( fB1 >= 0.0f )
00267                         {
00268                             fT = 0.0f;
00269                             fSqrDist = fC;
00270                         }
00271                         else if ( -fB1 >= fA11 )
00272                         {
00273                             fT = 1.0f;
00274                             fSqrDist = fA11+2.0f*fB1+fC;
00275                         }
00276                         else
00277                         {
00278                             fT = -fB1/fA11;
00279                             fSqrDist = fB1*fT+fC;
00280                         }
00281                     }
00282                 }
00283             }
00284             else   // region 6 (corner)
00285             {
00286                 if ( fB0 < 0.0f )
00287                 {
00288                     fT = 0.0f;
00289                     if ( -fB0 >= fA00 )
00290                     {
00291                         fS = 1.0f;
00292                         fSqrDist = fA00+2.0f*fB0+fC;
00293                     }
00294                     else
00295                     {
00296                         fS = -fB0/fA00;
00297                         fSqrDist = fB0*fS+fC;
00298                     }
00299                 }
00300                 else
00301                 {
00302                     fS = 0.0f;
00303                     if ( fB1 >= 0.0f )
00304                     {
00305                         fT = 0.0f;
00306                         fSqrDist = fC;
00307                     }
00308                     else if ( -fB1 >= fA11 )
00309                     {
00310                         fT = 1.0f;
00311                         fSqrDist = fA11+2.0f*fB1+fC;
00312                     }
00313                     else
00314                     {
00315                         fT = -fB1/fA11;
00316                         fSqrDist = fB1*fT+fC;
00317                     }
00318                 }
00319             }
00320         }
00321     }
00322     else
00323     {
00324         // line segments are parallel
00325         if ( fA01 > 0.0f )
00326         {
00327             // direction vectors form an obtuse angle
00328             if ( fB0 >= 0.0f )
00329             {
00330                 fS = 0.0f;
00331                 fT = 0.0f;
00332                 fSqrDist = fC;
00333             }
00334             else if ( -fB0 <= fA00 )
00335             {
00336                 fS = -fB0/fA00;
00337                 fT = 0.0f;
00338                 fSqrDist = fB0*fS+fC;
00339             }
00340             else
00341             {
00342                 fB1 = -kDiff.Dot( d1 );
00343                 fS = 1.0f;
00344                 fTmp = fA00+fB0;
00345                 if ( -fTmp >= fA01 )
00346                 {
00347                     fT = 1.0f;
00348                     fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1);
00349                 }
00350                 else
00351                 {
00352                     fT = -fTmp/fA01;
00353                     fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1));
00354                 }
00355             }
00356         }
00357         else
00358         {
00359             // direction vectors form an acute angle
00360             if ( -fB0 >= fA00 )
00361             {
00362                 fS = 1.0f;
00363                 fT = 0.0f;
00364                 fSqrDist = fA00+2.0f*fB0+fC;
00365             }
00366             else if ( fB0 <= 0.0f )
00367             {
00368                 fS = -fB0/fA00;
00369                 fT = 0.0f;
00370                 fSqrDist = fB0*fS+fC;
00371             }
00372             else
00373             {
00374                 fB1 = -kDiff.Dot( d1 );
00375                 fS = 0.0f;
00376                 if ( fB0 >= -fA01 )
00377                 {
00378                     fT = 1.0f;
00379                     fSqrDist = fA11+2.0f*fB1+fC;
00380                 }
00381                 else
00382                 {
00383                     fT = -fB0/fA01;
00384                     fSqrDist = fC+fT*(2.0f*fB1+fA11*fT);
00385                 }
00386             }
00387         }
00388     }
00389 
00390     return fabs( fSqrDist );
00391 }
00392 
00393 //=============================================================================
00394 // Distance
00395 //
00396 // Description: distance between point and this segment
00397 //=============================================================================
00398 double Segment::DistanceSquared( const Vector4& p ) const
00399 {
00400     //debug checking code
00401 #ifndef NDEBUG
00402     Segment s( p, p );
00403     double checkSegmentDistance = DistanceSquared( s );
00404 #endif
00405 
00406     Vector4 segmentDirection = p1 - p0;
00407     Vector4 pointDirection = p - p0;
00408     double dot = segmentDirection.Dot( pointDirection );
00409     if( dot <= 0.0 )
00410     {
00411         //
00412         // Point is behind the origin
00413         //
00414         double returnMe = pointDirection.MagSquared();
00415         assert( returnMe == checkSegmentDistance );
00416         return returnMe;
00417     }
00418 
00419     double segmentLengthSqr = segmentDirection.MagSquared();
00420     if( dot >= segmentLengthSqr )
00421     {
00422         //
00423         // Point is behind the other target
00424         //
00425         pointDirection -= segmentDirection;
00426         double returnMe = pointDirection.MagSquared();
00427         assert( ( checkSegmentDistance - returnMe ) < 0.00000001 );
00428         return returnMe;
00429     }
00430     else
00431     {
00432         //
00433         // Point is closest to somewhere in the middle of the line
00434         //
00435         dot /= segmentLengthSqr;
00436         pointDirection -= segmentDirection * dot;
00437         double returnMe = pointDirection.MagSquared();
00438         assert( ( checkSegmentDistance - returnMe ) < 0.00000001 );
00439         return returnMe;
00440     }
00441 }
00442 

Generated on Sat Apr 1 21:30:38 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO