• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

/home/hauberg/Dokumenter/Capture/humim-tracker-0.1/src/OpenTissue/OpenTissue/collision/gjk/gjk_compute_closest_points.h

Go to the documentation of this file.
00001 #ifndef OPENTISSUE_COLLISION_GJK_GJK_COMPUTE_CLOSEST_POINTS_H
00002 #define OPENTISSUE_COLLISION_GJK_GJK_COMPUTE_CLOSEST_POINTS_H
00003 //
00004 // OpenTissue Template Library
00005 // - A generic toolbox for physics-based modeling and simulation.
00006 // Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
00007 //
00008 // OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
00009 //
00010 #include <OpenTissue/configuration.h>
00011 
00012 #include <OpenTissue/collision/gjk/gjk_constants.h>
00013 #include <OpenTissue/collision/gjk/gjk_simplex.h>
00014 #include <OpenTissue/collision/gjk/gjk_voronoi_simplex_solver_policy.h>
00015 
00016 #include <cmath>
00017 #include <stdexcept>
00018 #include <cassert>
00019 
00020 namespace OpenTissue
00021 {
00022   namespace gjk
00023   {
00024 
00127     template<
00128       typename transform_type
00129       , typename support_functor1
00130       , typename support_functor2
00131       , typename simplex_solver_policy
00132     >
00133     inline void compute_closest_points( 
00134       transform_type const & transform_A
00135     , support_functor1 const & support_function_A
00136     , transform_type const & transform_B
00137     , support_functor2 const & support_function_B
00138     , typename transform_type::vector3_type & p_a
00139     , typename transform_type::vector3_type & p_b
00140     , typename transform_type::value_type & distance
00141     , size_t & iterations
00142     , size_t & status
00143     , typename transform_type::value_type const & absolute_tolerance
00144     , typename transform_type::value_type const & relative_tolerance
00145     , typename transform_type::value_type const & stagnation_tolerance
00146     , size_t const & max_iterations
00147     , simplex_solver_policy const & /*solver_policy*/
00148     )
00149     {
00150       using std::sqrt;
00151       using std::fabs;
00152       using std::max;
00153 
00154       typedef typename transform_type::vector3_type  V;
00155       typedef typename transform_type::value_type    T;
00156       typedef typename transform_type::value_traits  value_traits;
00157       typedef          Simplex<V>                    simplex_type;
00158 
00159       if( absolute_tolerance < value_traits::zero() ) 
00160         throw std::invalid_argument( "absolute tolerance must be non-negative" );
00161       if( relative_tolerance < value_traits::zero() ) 
00162         throw std::invalid_argument( "relative tolerance must be non-negative" );
00163       if( stagnation_tolerance < value_traits::zero() ) 
00164         throw std::invalid_argument( "stagnation tolerance must be non-negative" );
00165       if( max_iterations <= 0u ) 
00166         throw std::invalid_argument( "max_iterations must be positive" );
00167 
00168       distance   = value_traits::infinity();
00169       status     = ITERATING;
00170       iterations = 0u;
00171 
00172       T    const squared_absolute_tolerance = absolute_tolerance*absolute_tolerance;
00173       T          squared_distance           = value_traits::infinity();
00174 
00175       // Simplex approximation to convex set C
00176       simplex_type sigma;
00177 
00178       // Initially we use a 0-simplex corresponding to some point
00179       // in C. We do this by seeding the initial closest point to
00180       // be the zero-vector.
00181       V v = V( value_traits::zero(), value_traits::zero(), value_traits::zero() );
00182 
00183 
00184       // Lower error bound on distance from origin to closest point 
00185       T mu = value_traits::zero();
00186 
00187       // We use a maximum iteration count to guard against infinite loops.
00188       for(iterations=1u; iterations<=max_iterations; ++iterations)
00189       {
00190         // Find another point w that is hopefully closer to the origin.
00191         //
00192         // That means the search direction should point towards the origin, ie. s = -v
00193         //
00194         //   S_{ T_A(A) - T_B(B) }(s) = S_{ T_A(A) } (-v) - S_{ T_B(B) }(v)
00195         //                            = T_A( S_A(- R_A^T v) ) - T_B( S_B(R_B^T v)
00196         //
00197         V s_a = conj( transform_A.Q() ).rotate( - v );
00198         V s_b = conj( transform_B.Q() ).rotate(   v );
00199 
00200         V w_a = support_function_A( s_a );
00201         V w_b = support_function_B( s_b );
00202 
00203         w_a = transform_A.Q().rotate( w_a ) + transform_A.T();
00204         w_b = transform_B.Q().rotate( w_b ) + transform_B.T();
00205 
00206         assert( is_number( w_a(0) ) || !"compute_closest_points(): NaN encountered");
00207         assert( is_number( w_a(1) ) || !"compute_closest_points(): NaN encountered");
00208         assert( is_number( w_a(2) ) || !"compute_closest_points(): NaN encountered");
00209 
00210         assert( is_number( w_b(0) ) || !"compute_closest_points(): NaN encountered");
00211         assert( is_number( w_b(1) ) || !"compute_closest_points(): NaN encountered");
00212         assert( is_number( w_b(2) ) || !"compute_closest_points(): NaN encountered");
00213 
00214         V w    = w_a - w_b;
00215 
00216         assert( is_number( w(0) ) || !"compute_closest_points(): NaN encountered");
00217         assert( is_number( w(1) ) || !"compute_closest_points(): NaN encountered");
00218         assert( is_number( w(2) ) || !"compute_closest_points(): NaN encountered");
00219 
00220         // Test if the new point is already part of the current simplex
00221         if ( is_point_in_simplex ( w, sigma ) )
00222         {
00223           assert( iterations > 1u || !"compute_closest_points(): simplex should be empty in first iteration?");
00224           // if so it means we can not find any points in C that is
00225           // closer to p and we are done
00226           distance = sqrt( squared_distance );
00227           status = SIMPLEX_EXPANSION_FAILED;
00228           return;
00229         }
00230 
00231         // Update lower error bound
00232         distance = sqrt(squared_distance);
00233         mu = max( mu, ( dot(v,w) / distance) );
00234         // Test relative stopping criteria proposed by Gino van den Bergen!
00235         if(distance - mu <= distance * relative_tolerance)
00236         {
00237           status = LOWER_ERROR_BOUND_CONVERGENCE;
00238           return;
00239         }
00240 
00241         // Extend the simplex with a new vertex
00242         add_point_to_simplex(w, w_a, w_b, sigma);
00243 
00244         // Compute the point, v, on the simplex that is closest to the origin and
00245         // Reduce simplex to lowest dimensional face on the boundary
00246         // containing the closest point.
00247         v = simplex_solver_policy::reduce_simplex( sigma, p_a, p_b );
00248 
00249         assert( is_number( v(0) ) || !"compute_closest_points(): NaN encountered");
00250         assert( is_number( v(1) ) || !"compute_closest_points(): NaN encountered");
00251         assert( is_number( v(2) ) || !"compute_closest_points(): NaN encountered");
00252 
00253         assert( is_number( p_a(0) ) || !"compute_closest_points(): NaN encountered");
00254         assert( is_number( p_a(1) ) || !"compute_closest_points(): NaN encountered");
00255         assert( is_number( p_a(2) ) || !"compute_closest_points(): NaN encountered");
00256 
00257         assert( is_number( p_b(0) ) || !"compute_closest_points(): NaN encountered");
00258         assert( is_number( p_b(1) ) || !"compute_closest_points(): NaN encountered");
00259         assert( is_number( p_b(2) ) || !"compute_closest_points(): NaN encountered");
00260 
00261         // Test if simplex is a full tetrahedron. In this case the closest
00262         // point must be inside the tetrahedron and equal to the origin. Thus
00263         // we clearly have an intersection.
00264         if( is_full_simplex( sigma) )
00265         {
00266           distance = value_traits::zero();
00267           status = INTERSECTION;
00268           return;
00269         }
00270 
00271         T const old_squared_distance = squared_distance;
00272         squared_distance = dot( v, v);
00273 
00274         assert( is_number( squared_distance ) || !"compute_closest_points(): NaN encountered");
00275 
00276         // Test that closest distance are non-increasing
00277         if(squared_distance > old_squared_distance)
00278         {
00279           // This means that the closest distance is increasing
00280           distance = sqrt( squared_distance );
00281           status = NON_DESCEND_DIRECTION;
00282           return;
00283         }
00284 
00285         // Test absolute stopping criteria
00286         if( squared_distance <= squared_absolute_tolerance )
00287         {
00288           // This basically means that p are so close to the
00289           // convex set that we consider the distance to be zero.
00290           distance = sqrt( squared_distance );
00291           status = ABSOLUTE_CONVERGENCE;
00292           return;
00293         }
00294 
00295         // Test relative stopping criteria, so see if we do not make enough
00296         // progress toward the ``solution''
00297         if( (old_squared_distance - squared_distance) <= (relative_tolerance*old_squared_distance) )
00298         {
00299           // If relative test succedes then it means that this is as good as it
00300           // gets and we consider the algorithm to have converged.
00301           distance = sqrt( squared_distance );
00302           status = RELATIVE_CONVERGENCE;
00303           return;
00304         }
00305 
00306         // Test for stagnation of the solution
00307         if(fabs( old_squared_distance - squared_distance ) <= stagnation_tolerance )
00308         {
00309           distance = sqrt( squared_distance );
00310           status = STAGNATION;
00311           return;
00312         }
00313 
00314       }
00315 
00316       // If this point of the code is reached it means that we did
00317       // not converge with the maximum number of iterations.
00318       distance = sqrt( squared_distance );
00319       status = EXCEEDED_MAX_ITERATIONS_LIMIT;
00320     }
00321 
00326     template<
00327       typename transform_type
00328       , typename support_functor1
00329       , typename support_functor2
00330     >
00331     inline void compute_closest_points( 
00332       transform_type const & transform_A
00333     , support_functor1 const & A
00334     , transform_type const & transform_B
00335     , support_functor2 const & B
00336     , typename transform_type::vector3_type & p_a
00337     , typename transform_type::vector3_type & p_b
00338     , typename transform_type::value_type & distance
00339     , size_t & status
00340     )
00341     {
00342       typedef typename transform_type::value_type  T;
00343 
00344       OpenTissue::gjk::VoronoiSimplexSolverPolicy const simplex_solver_policy  = OpenTissue::gjk::VoronoiSimplexSolverPolicy();
00345 
00346       size_t       iterations           = 0u;
00347       size_t const max_iterations       = 100u;
00348       T      const absolute_tolerance   = boost::numeric_cast<T>(10e-6);
00349       T      const relative_tolerance   = boost::numeric_cast<T>(10e-10); // Don't be too greedy!
00350       T      const stagnation_tolerance = boost::numeric_cast<T>(10e-16);
00351 
00352       compute_closest_points( 
00353         transform_A
00354         , A
00355         , transform_B
00356         , B
00357         , p_a
00358         , p_b
00359         , distance
00360         , iterations
00361         , status
00362         , absolute_tolerance
00363         , relative_tolerance
00364         , stagnation_tolerance
00365         , max_iterations
00366         , simplex_solver_policy
00367         );
00368     }
00369 
00370   } // namespace gjk
00371 
00372 } // namespace OpenTissue
00373 
00374 // OPENTISSUE_COLLISION_GJK_GJK_COMPUTE_CLOSEST_POINTS_H
00375 #endif

Generated on Thu Dec 1 2011 12:50:47 for HUMIM Tracker by  doxygen 1.7.1