Algorithms.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 7028 $                                                       *
00038  *   $Author: bommes $                                                      *
00039  *   $Date: 2009-09-09 13:37:04 +0200 (Mi, 09. Sep 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 //=============================================================================
00047 //
00048 //  CLASS Geometry - IMPLEMENTATION
00049 //
00050 //=============================================================================
00051 
00052 #define GEO_ALGORITHMS_C
00053 
00054 //== INCLUDES =================================================================
00055 
00056 #include "Algorithms.hh"
00057 #include "../Utils/NumLimitsT.hh"
00058 #include <math.h>
00059 
00060 #ifdef max
00061 #  undef max
00062 #endif
00063 
00064 #ifdef min
00065 #  undef min
00066 #endif
00067 
00068 
00069 //----------------------------------------------------------------------------
00070 
00071 
00072 namespace ACG {
00073 namespace Geometry {
00074 
00075 
00076 //== IMPLEMENTATION ========================================================== 
00077 
00078 
00079 //== 3D STUFF ================================================================ 
00080 
00081   
00082 template<typename Scalar>
00083 bool
00084 baryCoord( const VectorT<Scalar,3> & _p,
00085            const VectorT<Scalar,3> & _u,
00086            const VectorT<Scalar,3> & _v,
00087            const VectorT<Scalar,3> & _w,
00088            VectorT<Scalar,3> & _result )
00089 {
00090   VectorT<Scalar,3>  vu = _v - _u,
00091                           wu = _w - _u,
00092                           pu = _p - _u;
00093 
00094   
00095   // find largest absolute coodinate of normal
00096   Scalar nx = vu[1]*wu[2] - vu[2]*wu[1],
00097          ny = vu[2]*wu[0] - vu[0]*wu[2],
00098          nz = vu[0]*wu[1] - vu[1]*wu[0],
00099          ax = fabs(nx),
00100          ay = fabs(ny),
00101          az = fabs(nz);
00102 
00103 
00104   unsigned char max_coord;
00105 
00106   if ( ax > ay ) {
00107     if ( ax > az ) {
00108       max_coord = 0;
00109     }
00110     else {
00111       max_coord = 2;
00112     }
00113   }
00114   else {
00115     if ( ay > az ) {
00116       max_coord = 1;
00117     }
00118     else {
00119       max_coord = 2;
00120     }
00121   }
00122 
00123 
00124   // solve 2D problem
00125   switch (max_coord) {
00126 
00127     case 0:
00128     {      
00129       if (1.0+ax == 1.0) return false;
00130       _result[1] = 1.0 + (pu[1]*wu[2]-pu[2]*wu[1])/nx - 1.0;
00131       _result[2] = 1.0 + (vu[1]*pu[2]-vu[2]*pu[1])/nx - 1.0;
00132       _result[0] = 1.0 - _result[1] - _result[2];
00133     }
00134     break;
00135       
00136     case 1:
00137     {
00138       if (1.0+ay == 1.0) return false;
00139       _result[1] = 1.0 + (pu[2]*wu[0]-pu[0]*wu[2])/ny - 1.0;
00140       _result[2] = 1.0 + (vu[2]*pu[0]-vu[0]*pu[2])/ny - 1.0;
00141       _result[0] = 1.0 - _result[1] - _result[2];
00142     }
00143     break;
00144       
00145     case 2:
00146     {
00147       if (1.0+az == 1.0) return false;
00148       _result[1] = 1.0 + (pu[0]*wu[1]-pu[1]*wu[0])/nz - 1.0;
00149       _result[2] = 1.0 + (vu[0]*pu[1]-vu[1]*pu[0])/nz - 1.0;
00150       _result[0] = 1.0 - _result[1] - _result[2];
00151     }
00152     break;    
00153   }
00154 
00155   return true;
00156 }
00157 
00158 
00159 //-----------------------------------------------------------------------------
00160 
00161 
00162 template <class Vec>
00163 typename Vec::value_type
00164 triangleAreaSquared( const Vec& _v0,
00165                      const Vec& _v1,
00166                      const Vec& _v2 )
00167 {
00168   return 0.25 * ((_v1-_v0)%(_v2-_v0)).sqrnorm();
00169 }
00170 
00171 
00172 //-----------------------------------------------------------------------------
00173 
00174 
00175 template<class Vec>
00176 typename Vec::value_type
00177 distPointLineSquared( const Vec& _p,
00178                       const Vec& _v0,
00179                       const Vec& _v1,
00180                       Vec*       _min_v )
00181 {
00182   Vec d1(_p-_v0), d2(_v1-_v0), min_v(_v0);
00183   typename Vec::value_type t = (d1|d2)/(d2|d2);
00184 
00185   if (t >  1.0)       d1 = _p - (min_v = _v1);
00186   else if (t > 0.0)   d1 = _p - (min_v = _v0 + d2*t);
00187 
00188   if (_min_v) *_min_v = min_v;
00189   return d1.sqrnorm();
00190 }    
00191 
00192 
00193 //-----------------------------------------------------------------------------
00194 
00195 
00196 template <class Vec>
00197 typename Vec::value_type
00198 distPointTriangleSquared( const Vec& _p,
00199                           const Vec& _v0,
00200                           const Vec& _v1,
00201                           const Vec& _v2,
00202                           Vec& _nearestPoint )
00203 {
00204   Vec v0v1 = _v1 - _v0;
00205   Vec v0v2 = _v2 - _v0;
00206   Vec n = v0v1 % v0v2; // not normalized !
00207   double d = n.sqrnorm();
00208 
00209   
00210   // Check if the triangle is degenerated
00211   if (d < FLT_MIN && d > -FLT_MIN) {
00212     std::cerr << "distPointTriangleSquared: Degenerated triangle !\n";
00213     return -1.0;
00214   }
00215   double invD = 1.0 / d;
00216 
00217   
00218   // these are not needed for every point, should still perform
00219   // better with many points against one triangle
00220   Vec v1v2 = _v2 - _v1;
00221   double inv_v0v2_2 = 1.0 / v0v2.sqrnorm();
00222   double inv_v0v1_2 = 1.0 / v0v1.sqrnorm();
00223   double inv_v1v2_2 = 1.0 / v1v2.sqrnorm();
00224 
00225   
00226   Vec v0p = _p - _v0;
00227   Vec t = v0p % n;
00228   double  s01, s02, s12;
00229   double a = (t | v0v2) * -invD;
00230   double b = (t | v0v1) * invD;
00231 
00232   
00233   if (a < 0)
00234   {
00235     // Calculate the distance to an edge or a corner vertex
00236     s02 = ( v0v2 | v0p ) * inv_v0v2_2;
00237     if (s02 < 0.0)
00238     {
00239       s01 = ( v0v1 | v0p ) * inv_v0v1_2;
00240       if (s01 <= 0.0) {
00241         v0p = _v0;
00242       } else if (s01 >= 1.0) {
00243         v0p = _v1;
00244       } else {
00245         v0p = _v0 + v0v1 * s01;
00246       }
00247     } else if (s02 > 1.0) {
00248       s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
00249       if (s12 >= 1.0) {
00250         v0p = _v2;
00251       } else if (s12 <= 0.0) {
00252         v0p = _v1;
00253       } else {
00254         v0p = _v1 + v1v2 * s12;
00255       }
00256     } else {
00257       v0p = _v0 + v0v2 * s02;
00258     }
00259   } else if (b < 0.0) {
00260     // Calculate the distance to an edge or a corner vertex
00261     s01 = ( v0v1 | v0p ) * inv_v0v1_2;
00262     if (s01 < 0.0)
00263     {
00264       s02 = ( v0v2 |  v0p ) * inv_v0v2_2;
00265       if (s02 <= 0.0) {
00266         v0p = _v0;
00267       } else if (s02 >= 1.0) {
00268         v0p = _v2;
00269       } else {
00270         v0p = _v0 + v0v2 * s02;
00271       }
00272     } else if (s01 > 1.0) {
00273       s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
00274       if (s12 >= 1.0) {
00275         v0p = _v2;
00276       } else if (s12 <= 0.0) {
00277         v0p = _v1;
00278       } else {
00279         v0p = _v1 + v1v2 * s12;
00280       }
00281     } else {
00282       v0p = _v0 + v0v1 * s01;
00283     }
00284   } else if (a+b > 1.0) {
00285     // Calculate the distance to an edge or a corner vertex
00286     s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
00287     if (s12 >= 1.0) {
00288       s02 = ( v0v2 | v0p ) * inv_v0v2_2;
00289       if (s02 <= 0.0) {
00290         v0p = _v0;
00291       } else if (s02 >= 1.0) {
00292         v0p = _v2;
00293       } else {
00294         v0p = _v0 + v0v2*s02;
00295       }
00296     } else if (s12 <= 0.0) {
00297       s01 = ( v0v1 |  v0p ) * inv_v0v1_2;
00298       if (s01 <= 0.0) {
00299         v0p = _v0;
00300       } else if (s01 >= 1.0) {
00301         v0p = _v1;
00302       } else {
00303         v0p = _v0 + v0v1 * s01;
00304       }
00305     } else {
00306       v0p = _v1 + v1v2 * s12;
00307     }
00308   } else {
00309     // Calculate the distance to an interior point of the triangle
00310     _nearestPoint = _p - n*((n|v0p) * invD);
00311     return (_nearestPoint - _p).sqrnorm();
00312   }
00313   
00314   _nearestPoint = v0p;
00315 
00316   return (_nearestPoint - _p).sqrnorm();
00317 }
00318 
00319 
00320 //-----------------------------------------------------------------------------
00321 
00322 
00323 //
00324 // Modified code of Dave Eberly (www.magic-software.com)
00325 //
00326 
00327 template<typename Scalar>
00328 Scalar
00329 distLineLineSquared( const VectorT<Scalar,3>& _v00,
00330                      const VectorT<Scalar,3>& _v01,
00331                      const VectorT<Scalar,3>& _v10,
00332                      const VectorT<Scalar,3>& _v11,
00333                      VectorT<Scalar,3>*       _min_v0,
00334                      VectorT<Scalar,3>*       _min_v1,
00335                      bool                          _fastApprox )
00336 {
00337   VectorT<Scalar,3> kDiff = _v00 - _v10;
00338   VectorT<Scalar,3> d0 = _v01-_v00;
00339   VectorT<Scalar,3> d1 = _v11-_v10;
00340 
00341   Scalar fA00 = d0.sqrnorm();
00342   Scalar fA01 = -(d0|d1);
00343   Scalar fA11 = d1.sqrnorm();
00344   Scalar fB0  = (kDiff|d0);
00345   Scalar fC   = kDiff.sqrnorm();
00346   Scalar fDet = fabs(fA00*fA11-fA01*fA01);
00347   Scalar fB1, fS, fT, fSqrDist, fTmp;
00348 
00349   
00350   if ( fDet >= FLT_MIN )
00351   {
00352     // line segments are not parallel
00353     fB1 = -(kDiff|d1);
00354     fS = fA01*fB1-fA11*fB0;
00355     fT = fA01*fB0-fA00*fB1;
00356 
00357     
00358     // conservative approximation only?
00359     if (_fastApprox)
00360     {
00361       if      ( fS < 0.0 )  fS = 0.0;
00362       else if ( fS > fDet ) fS = fDet;
00363       if      ( fT < 0.0 )  fT = 0.0;
00364       else if ( fT > fDet ) fT = fDet;
00365     }
00366 
00367     
00368     if ( fS >= 0.0 )
00369     {
00370       if ( fS <= fDet )
00371       {
00372         if ( fT >= 0.0 )
00373         {
00374           if ( fT <= fDet )  // region 0 (interior)
00375           {
00376             // minimum at two interior points of 3D lines
00377             Scalar fInvDet = 1.0/fDet;
00378             fS *= fInvDet;
00379             fT *= fInvDet;
00380             fSqrDist = fS*(fA00*fS+fA01*fT+2.0*fB0) +
00381                        fT*(fA01*fS+fA11*fT+2.0*fB1)+fC;
00382           }
00383           else  // region 3 (side)
00384           {
00385             fT = 1.0;
00386             fTmp = fA01+fB0;
00387             if ( fTmp >= 0.0 )
00388             {
00389               fS = 0.0;
00390               fSqrDist = fA11+2.0*fB1+fC;
00391             }
00392             else if ( -fTmp >= fA00 )
00393             {
00394               fS = 1.0;
00395               fSqrDist = fA00+fA11+fC+2.0*(fB1+fTmp);
00396             }
00397             else
00398             {
00399               fS = -fTmp/fA00;
00400               fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
00401             }
00402           }
00403         }
00404         else  // region 7 (side)
00405         {
00406           fT = 0.0;
00407           if ( fB0 >= 0.0 )
00408           {
00409             fS = 0.0;
00410             fSqrDist = fC;
00411           }
00412           else if ( -fB0 >= fA00 )
00413           {
00414             fS = 1.0;
00415             fSqrDist = fA00+2.0*fB0+fC;
00416           }
00417           else
00418           {
00419             fS = -fB0/fA00;
00420             fSqrDist = fB0*fS+fC;
00421           }
00422         }
00423       }
00424       else
00425       {
00426         if ( fT >= 0.0 )
00427         {
00428           if ( fT <= fDet )  // region 1 (side)
00429           {
00430             fS = 1.0;
00431             fTmp = fA01+fB1;
00432             if ( fTmp >= 0.0 )
00433             {
00434               fT = 0.0;
00435               fSqrDist = fA00+2.0*fB0+fC;
00436             }
00437             else if ( -fTmp >= fA11 )
00438             {
00439               fT = 1.0;
00440               fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
00441             }
00442             else
00443             {
00444               fT = -fTmp/fA11;
00445               fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
00446             }
00447           }
00448           else  // region 2 (corner)
00449           {
00450             fTmp = fA01+fB0;
00451             if ( -fTmp <= fA00 )
00452             {
00453               fT = 1.0;
00454               if ( fTmp >= 0.0 )
00455               {
00456                 fS = 0.0;
00457                 fSqrDist = fA11+2.0*fB1+fC;
00458               }
00459               else
00460               {
00461                 fS = -fTmp/fA00;
00462                 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
00463               }
00464             }
00465             else
00466             {
00467               fS = 1.0;
00468               fTmp = fA01+fB1;
00469               if ( fTmp >= 0.0 )
00470               {
00471                 fT = 0.0;
00472                 fSqrDist = fA00+2.0*fB0+fC;
00473               }
00474               else if ( -fTmp >= fA11 )
00475               {
00476                 fT = 1.0;
00477                 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
00478               }
00479               else
00480               {
00481                 fT = -fTmp/fA11;
00482                 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
00483               }
00484             }
00485           }
00486         }
00487         else  // region 8 (corner)
00488         {
00489           if ( -fB0 < fA00 )
00490           {
00491             fT = 0.0;
00492             if ( fB0 >= 0.0 )
00493             {
00494               fS = 0.0;
00495               fSqrDist = fC;
00496             }
00497             else
00498             {
00499               fS = -fB0/fA00;
00500               fSqrDist = fB0*fS+fC;
00501             }
00502           }
00503           else
00504           {
00505             fS = 1.0;
00506             fTmp = fA01+fB1;
00507             if ( fTmp >= 0.0 )
00508             {
00509               fT = 0.0;
00510               fSqrDist = fA00+2.0*fB0+fC;
00511             }
00512             else if ( -fTmp >= fA11 )
00513             {
00514               fT = 1.0;
00515               fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
00516             }
00517             else
00518             {
00519               fT = -fTmp/fA11;
00520               fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
00521             }
00522           }
00523         }
00524       }
00525     }
00526     else 
00527     {
00528       if ( fT >= 0.0 )
00529       {
00530         if ( fT <= fDet )  // region 5 (side)
00531         {
00532           fS = 0.0;
00533           if ( fB1 >= 0.0 )
00534           {
00535             fT = 0.0;
00536             fSqrDist = fC;
00537           }
00538           else if ( -fB1 >= fA11 )
00539           {
00540             fT = 1.0;
00541             fSqrDist = fA11+2.0*fB1+fC;
00542           }
00543           else
00544           {
00545             fT = -fB1/fA11;
00546             fSqrDist = fB1*fT+fC;
00547           }
00548         }
00549         else  // region 4 (corner)
00550         {
00551           fTmp = fA01+fB0;
00552           if ( fTmp < 0.0 )
00553           {
00554             fT = 1.0;
00555             if ( -fTmp >= fA00 )
00556             {
00557               fS = 1.0;
00558               fSqrDist = fA00+fA11+fC+2.0*(fB1+fTmp);
00559             }
00560             else
00561             {
00562               fS = -fTmp/fA00;
00563               fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
00564             }
00565           }
00566           else
00567           {
00568             fS = 0.0;
00569             if ( fB1 >= 0.0 )
00570             {
00571               fT = 0.0;
00572               fSqrDist = fC;
00573             }
00574             else if ( -fB1 >= fA11 )
00575             {
00576               fT = 1.0;
00577               fSqrDist = fA11+2.0*fB1+fC;
00578             }
00579             else
00580             {
00581               fT = -fB1/fA11;
00582               fSqrDist = fB1*fT+fC;
00583             }
00584           }
00585         }
00586       }
00587       else   // region 6 (corner)
00588       {
00589         if ( fB0 < 0.0 )
00590         {
00591           fT = 0.0;
00592           if ( -fB0 >= fA00 )
00593           {
00594             fS = 1.0;
00595             fSqrDist = fA00+2.0*fB0+fC;
00596           }
00597           else
00598           {
00599             fS = -fB0/fA00;
00600             fSqrDist = fB0*fS+fC;
00601           }
00602         }
00603         else
00604         {
00605           fS = 0.0;
00606           if ( fB1 >= 0.0 )
00607           {
00608             fT = 0.0;
00609             fSqrDist = fC;
00610           }
00611           else if ( -fB1 >= fA11 )
00612           {
00613             fT = 1.0;
00614             fSqrDist = fA11+2.0*fB1+fC;
00615           }
00616           else
00617           {
00618             fT = -fB1/fA11;
00619             fSqrDist = fB1*fT+fC;
00620           }
00621         }
00622       }
00623     }
00624   }
00625   else
00626   {
00627     // line segments are parallel
00628     if ( fA01 > 0.0 )
00629     {
00630       // direction vectors form an obtuse angle
00631       if ( fB0 >= 0.0 )
00632       {
00633         fS = 0.0;
00634         fT = 0.0;
00635         fSqrDist = fC;
00636       }
00637       else if ( -fB0 <= fA00 )
00638       {
00639         fS = -fB0/fA00;
00640         fT = 0.0;
00641         fSqrDist = fB0*fS+fC;
00642       }
00643       else
00644       {
00645         fB1 = -(kDiff|d1);
00646         fS = 1.0;
00647         fTmp = fA00+fB0;
00648         if ( -fTmp >= fA01 )
00649         {
00650           fT = 1.0;
00651           fSqrDist = fA00+fA11+fC+2.0*(fA01+fB0+fB1);
00652         }
00653         else
00654         {
00655           fT = -fTmp/fA01;
00656           fSqrDist = fA00+2.0*fB0+fC+fT*(fA11*fT+2.0*(fA01+fB1));
00657         }
00658       }
00659     }
00660     else
00661     {
00662       // direction vectors form an acute angle
00663       if ( -fB0 >= fA00 )
00664       {
00665         fS = 1.0;
00666         fT = 0.0;
00667         fSqrDist = fA00+2.0*fB0+fC;
00668       }
00669       else if ( fB0 <= 0.0 )
00670       {
00671         fS = -fB0/fA00;
00672         fT = 0.0;
00673         fSqrDist = fB0*fS+fC;
00674       }
00675       else
00676       {
00677         fB1 = -(kDiff|d1);
00678         fS = 0.0;
00679         if ( fB0 >= -fA01 )
00680         {
00681           fT = 1.0;
00682           fSqrDist = fA11+2.0*fB1+fC;
00683         }
00684         else
00685         {
00686           fT = -fB0/fA01;
00687           fSqrDist = fC+fT*(2.0*fB1+fA11*fT);
00688         }
00689       }
00690     }
00691   }
00692 
00693 
00694   if (_min_v0)  *_min_v0 = _v00 + fS*d0;
00695   if (_min_v1)  *_min_v1 = _v10 + fT*d1;
00696 
00697   return fabs(fSqrDist);
00698 }
00699 
00700 
00701 //-----------------------------------------------------------------------------
00702 
00703 
00704 template<typename Scalar>
00705 bool
00706 circumCenter( const VectorT<Scalar,3>&  _v0,
00707               const VectorT<Scalar,3>&  _v1,
00708               const VectorT<Scalar,3>&  _v2,
00709               VectorT<Scalar,3>&        _result )
00710 {
00711   VectorT<Scalar,3>   a(_v1-_v2),
00712                            b(_v2-_v0),
00713                            c(_v0-_v1),
00714                            G((_v0+_v1+_v2)/3.0);
00715   
00716   Scalar d0 = -(b|c),
00717          d1 = -(c|a),
00718          d2 = -(a|b),
00719          e0 = d1*d2,
00720          e1 = d2*d0,
00721          e2 = d0*d1,
00722          e  = e0+e1+e2;
00723 
00724   if (e <= NumLimitsT<Scalar>::min())  return false;
00725 
00726   VectorT<Scalar,3>   H((e0*_v0 + e1*_v1 + e2*_v2)/e);
00727 
00728   _result = (Scalar)0.5 * ((Scalar)3.0*G - H);
00729 
00730   return true;
00731 }
00732 
00733 
00734 
00735 //-----------------------------------------------------------------------------
00736 
00737 
00738 template<typename Scalar>
00739 Scalar
00740 circumRadiusSquared( const VectorT<Scalar,3>&  _v0,
00741                      const VectorT<Scalar,3>&  _v1,
00742                      const VectorT<Scalar,3>&  _v2 )
00743 {
00744   VectorT<Scalar,3>  v0v1(_v1-_v0),
00745                           v0v2(_v2-_v0),
00746                           v1v2(_v2-_v1);
00747 
00748   Scalar denom = 4.0*((v0v1%v0v2).sqrnorm());
00749   if (denom < NumLimitsT<Scalar>::min()  && 
00750       denom > -NumLimitsT<Scalar>::min())  
00751     return NumLimitsT<Scalar>::max();
00752 
00753   return ( v0v1.sqrnorm() *
00754            v0v2.sqrnorm() *
00755            v1v2.sqrnorm() /
00756            denom );
00757 }
00758 
00759 
00760 //-----------------------------------------------------------------------------
00761 
00762 
00763 template<typename Scalar>
00764 bool
00765 minSphere(const VectorT<Scalar,3>&  _v0,
00766           const VectorT<Scalar,3>&  _v1,
00767           const VectorT<Scalar,3>&  _v2,
00768           VectorT<Scalar,3>&        _center,
00769           Scalar&                        _radius)
00770 {
00771   VectorT<Scalar,3>   a(_v1-_v2),
00772                            b(_v2-_v0),
00773                            c(_v0-_v1);
00774 
00775   Scalar d0 = -(b|c),
00776          d1 = -(c|a),
00777          d2 = -(a|b);
00778 
00779   
00780   // obtuse angle ?
00781   if (d2 < NumLimitsT<Scalar>::min())
00782   {
00783     _center = (_v0+_v1)*0.5;
00784     _radius = 0.5 * c.norm();
00785     return true;
00786   }
00787   if (d0 < NumLimitsT<Scalar>::min())
00788   {
00789     _center = (_v1+_v2)*0.5;
00790     _radius = 0.5 * a.norm();
00791     return true;
00792   }
00793   if (d1 < NumLimitsT<Scalar>::min())
00794   {
00795     _center = (_v2+_v0)*0.5;
00796     _radius = 0.5 * b.norm();
00797     return true;
00798   }
00799   
00800 
00801   // acute angle
00802   VectorT<Scalar,3>   G((_v0+_v1+_v2)/3.0);
00803   
00804   Scalar e0 = d1*d2,
00805          e1 = d2*d0,
00806          e2 = d0*d1,
00807          e  = e0+e1+e2;
00808 
00809   if ( e <= NumLimitsT<Scalar>::min() )  return false;
00810 
00811   VectorT<Scalar,3>   H((e0*_v0 + e1*_v1 + e2*_v2)/e);
00812 
00813   _center = (Scalar)0.5 * ((Scalar)3.0*G - H);
00814   _radius = (_center-_v0).norm();
00815   
00816   return true;
00817 }
00818 
00819 
00820 //-----------------------------------------------------------------------------
00821 
00822 
00823 template<typename Scalar>
00824 Scalar
00825 minRadiusSquared( const VectorT<Scalar,3>&  _v0,
00826                   const VectorT<Scalar,3>&  _v1,
00827                   const VectorT<Scalar,3>&  _v2 )
00828 {
00829   VectorT<Scalar,3>  v0v1(_v1-_v0),
00830                           v0v2(_v2-_v0),
00831                           v1v2(_v2-_v1);
00832 
00833   Scalar denom = 4.0*((v0v1%v0v2).sqrnorm());
00834   if (denom < NumLimitsT<Scalar>::min() && 
00835       denom > -NumLimitsT<Scalar>::min())  
00836     return NumLimitsT<Scalar>::max();
00837 
00838   Scalar  l0 = v0v1.sqrnorm(),
00839           l1 = v0v2.sqrnorm(),
00840           l2 = v1v2.sqrnorm(),
00841           l3 = l0*l1*l2/denom;
00842   
00843   return  std::max(std::max(l0, l1), std::max(l2, l3));
00844 }
00845 
00846 
00847 //-----------------------------------------------------------------------------
00848 
00849 
00850 template<typename Scalar>
00851 bool
00852 circumCenter( const VectorT<Scalar,3>&  _v0,
00853               const VectorT<Scalar,3>&  _v1,
00854               const VectorT<Scalar,3>&  _v2,
00855               const VectorT<Scalar,3>&  _v3,
00856               VectorT<Scalar,3>&        _result )
00857 {
00858   VectorT<Scalar,3>
00859     v0v1(_v1-_v0),
00860     v0v2(_v2-_v0),
00861     v0v3(_v3-_v0);
00862 
00863   Scalar  denom = ((v0v1[0]*v0v2[1]*v0v3[2] +
00864                     v0v1[1]*v0v2[2]*v0v3[0] +
00865                     v0v1[2]*v0v2[0]*v0v3[1]) -
00866                    (v0v1[0]*v0v2[2]*v0v3[1] +
00867                     v0v1[1]*v0v2[0]*v0v3[2] +
00868                     v0v1[2]*v0v2[1]*v0v3[0])) * 2.0;
00869 
00870   if (denom < NumLimitsT<Scalar>::min() && 
00871       denom > -NumLimitsT<Scalar>::min())  return false;
00872 
00873   
00874   _result = _v0 + (( v0v3.sqrnorm()*(v0v1%v0v2) +
00875                      v0v2.sqrnorm()*(v0v3%v0v1) +
00876                      v0v1.sqrnorm()*(v0v2%v0v3) ) / denom);
00877   
00878   return true;
00879 }
00880 
00881 
00882 //-----------------------------------------------------------------------------
00883 
00884 
00885 template <typename Scalar>
00886 VectorT<Scalar,3>
00887 perpendicular( const VectorT<Scalar,3>&  v )
00888 {
00889   if (fabs(v[0]) < fabs(v[1]))
00890   {
00891     if (fabs(v[0]) < fabs(v[2]))
00892       return VectorT<Scalar,3>( Scalar(1.0) - v[0]*v[0], -v[0]*v[1], -v[0]*v[2]).normalize();
00893   }
00894   else
00895     {
00896       if (fabs(v[1]) < fabs(v[2]))
00897         return VectorT<Scalar,3>(-v[1]*v[0], Scalar(1.0) - v[1]*v[1], -v[1]*v[2]).normalize();
00898     }
00899   
00900   return VectorT<Scalar,3>(-v[2]*v[0], -v[2]*v[1], Scalar(1.0) - v[2]*v[2]).normalize();
00901 }
00902 
00903 
00904 
00905 //== 2D STUFF ================================================================ 
00906 
00907 
00908 
00909 template<typename Scalar>
00910 bool
00911 baryCoord( const VectorT<Scalar,2> & _p,
00912            const VectorT<Scalar,2> & _u,
00913            const VectorT<Scalar,2> & _v,
00914            const VectorT<Scalar,2> & _w,
00915            VectorT<Scalar,3> & _result )
00916 {
00917   Scalar  v0(_v[0]-_u[0]), v1(_v[1]-_u[1]),
00918           w0(_w[0]-_u[0]), w1(_w[1]-_u[1]),
00919           p0(_p[0]-_u[0]), p1(_p[1]-_u[1]),
00920           denom = v0*w1-v1*w0;
00921 
00922   if (1.0+fabs(denom) == 1.0) {
00923     std::cerr << "degen tri: ("
00924               << _u << "), ("
00925               << _v << "), ("
00926               << _w << ")\n";
00927     return false;
00928   }
00929   
00930   _result[1] = 1.0 + ((p0*w1-p1*w0)/denom) - 1.0;
00931   _result[2] = 1.0 + ((v0*p1-v1*p0)/denom) - 1.0;
00932   _result[0] = 1.0 - _result[1] - _result[2];
00933 
00934   return true;
00935 }
00936 
00937 
00938 //-----------------------------------------------------------------------------
00939 
00940 
00941 template<typename Scalar>
00942 bool
00943 lineIntersection( const VectorT<Scalar,2>&  _v0,
00944                   const VectorT<Scalar,2>&  _v1,
00945                   const VectorT<Scalar,2>&  _v2,
00946                   const VectorT<Scalar,2>&  _v3,
00947                   Scalar& _t1,
00948                   Scalar& _t2 )
00949 {      
00950   _t1 = ((_v0[1]-_v2[1])*(_v3[0]-_v2[0])-(_v0[0]-_v2[0])*(_v3[1]-_v2[1])) /
00951         ((_v1[0]-_v0[0])*(_v3[1]-_v2[1])-(_v1[1]-_v0[1])*(_v3[0]-_v2[0]));
00952       
00953   _t2 = ((_v0[1]-_v2[1])*(_v1[0]-_v0[0])-(_v0[0]-_v2[0])*(_v1[1]-_v0[1])) /
00954     ((_v1[0]-_v0[0])*(_v3[1]-_v2[1])-(_v1[1]-_v0[1])*(_v3[0]-_v2[0]));
00955       
00956   return ((_t1>0.0) && (_t1<1.0) && (_t2>0.0) && (_t2<1.0));
00957 }
00958 
00959 
00960 //-----------------------------------------------------------------------------
00961 
00962 template<typename Scalar>
00963 bool
00964 circumCenter( const VectorT<Scalar,2>&  _v0,
00965               const VectorT<Scalar,2>&  _v1,
00966               const VectorT<Scalar,2>&  _v2,
00967               VectorT<Scalar,2>&        _result )
00968 {
00969   Scalar x0(_v0[0]), y0(_v0[1]), xy0(x0*x0+y0*y0),
00970          x1(_v1[0]), y1(_v1[1]), xy1(x1*x1+y1*y1),
00971          x2(_v2[0]), y2(_v2[1]), xy2(x2*x2+y2*y2),
00972          a(x0*y1 - x0*y2 - x1*y0 + x1*y2 + x2*y0 - x2*y1),
00973          b(xy0*y1 - xy0*y2 - xy1*y0 + xy1*y2 + xy2*y0 - xy2*y1),
00974          c(xy0*x1 - xy0*x2 - xy1*x0 + xy1*x2 + xy2*x0 - xy2*x1);
00975 
00976   if (Scalar(1.0)+a == Scalar(1.0)) {
00977     std::cerr << "circumcircle: colinear points\n";
00978     return false;
00979   }
00980 
00981   _result[0] = 0.5*b/a;
00982   _result[1] = -0.5*c/a;
00983   
00984   return true;
00985 }
00986 
00987 
00988 
00989 //== N-DIM STUFF ============================================================== 
00990 
00991 
00992 template <typename Scalar, int N>
00993 Scalar
00994 aspectRatio( const VectorT<Scalar, N>& _v0,
00995              const VectorT<Scalar, N>& _v1,
00996              const VectorT<Scalar, N>& _v2 )
00997 {
00998   Scalar d0 = (_v0-_v1).sqrnorm(),
00999          d1 = (_v1-_v2).sqrnorm(),
01000          d2 = (_v2-_v0).sqrnorm();
01001 
01002   if (d0 < d1) {
01003     if (d0 < d2) {
01004       if (d1 < d2) return sqrt(d2/d0);
01005       else         return sqrt(d1/d0);
01006     }
01007     else           return sqrt(d1/d2);
01008   }
01009   else {
01010     if (d1 < d2) {
01011       if (d0 < d2) return sqrt(d2/d1);
01012       else         return sqrt(d0/d1);
01013     }
01014     else           return sqrt(d0/d2);
01015   }    
01016 }
01017 
01018 
01019 //-----------------------------------------------------------------------------
01020 
01021 
01022 template <typename Scalar, int N>
01023 Scalar
01024 roundness( const VectorT<Scalar, N>& _v0,
01025            const VectorT<Scalar, N>& _v1,
01026            const VectorT<Scalar, N>& _v2 )
01027 {
01028   const double FOUR_ROOT3 = 6.928203230275509;
01029 
01030   double area = 0.5*((_v1-_v0)%(_v2-_v0)).norm();
01031 
01032   return (Scalar) (FOUR_ROOT3 * area / ((_v0-_v1).sqrnorm() +
01033                                         (_v1-_v2).sqrnorm() +
01034                                         (_v2-_v0).sqrnorm() ));
01035 }
01036 
01037 
01038 //=============================================================================
01039 } // namespace Geometry
01040 } // namespace ACG
01041 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .