Go to the documentation of this file.00001 #ifndef OPENTISSUE_BVH_BVH_SELF_COLLISION_QUERY_H
00002 #define OPENTISSUE_BVH_BVH_SELF_COLLISION_QUERY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <boost/shared_ptr.hpp>
00013
00014 #include <list>
00015
00016 namespace OpenTissue
00017 {
00018 namespace bvh
00019 {
00040 template <typename collision_policy>
00041 class SelfCollisionQuery : public collision_policy
00042 {
00043 public:
00044
00045
00046 typedef typename collision_policy::bvh_type bvh_type;
00047 typedef typename bvh_type::bv_ptr bv_ptr;
00048 typedef typename bvh_type::bv_ptr_container bv_ptr_container;
00049 typedef typename bvh_type::bv_type bv_type;
00050 typedef typename bv_type::bv_ptr_iterator bv_ptr_iterator;
00051
00052 public:
00053
00061 template<typename results_container>
00062 void run( bvh_type const & bvh, results_container & results )
00063 {
00064 this->reset(results);
00065
00066 bv_ptr root = boost::const_pointer_cast<bv_type>( bvh.root() );
00067
00068 self_test( root, results );
00069 }
00070
00071 protected:
00072
00080 template<typename results_container>
00081 void self_test( bv_ptr bv, results_container & results )
00082 {
00083 if( bv->is_leaf() )
00084 return;
00085 if( this->curvature_test( bv ) )
00086 return;
00087
00088 bv_ptr_iterator a = bv->child_ptr_begin();
00089 bv_ptr_iterator end = bv->child_ptr_end();
00090 for(;a!=end;++a)
00091 {
00092 bv_ptr ptr1( *a );
00093 self_test( ptr1, results );
00094 bv_ptr_iterator b = a;
00095 ++b;
00096 for ( ;b != end; ++b )
00097 {
00098 bv_ptr ptr2( *b );
00099 tandem_test( ptr1, ptr2, results );
00100 }
00101 }
00102 }
00103
00112 template<typename results_container>
00113 void tandem_test( bv_ptr bv_A, bv_ptr bv_B, results_container & results )
00114 {
00115 std::list<bool> adj_queue;
00116 adj_queue.push_back( bool(true) );
00117 bv_ptr_container Q;
00118 Q.push_back( bv_A );
00119 Q.push_back( bv_B );
00120 while ( !Q.empty() )
00121 {
00122 bv_ptr A( Q.front() );
00123 Q.pop_front();
00124 bv_ptr B( Q.front() );
00125 Q.pop_front();
00126 bool adj = adj_queue.front(); adj_queue.pop_front();
00127
00128 if( !this->overlap( A, B ) )
00129 continue;
00130
00131 if ( adj )
00132 {
00133 adj = this->adjacent(A,B);
00134 if( adj && this->curvature_test( A, B ) )
00135 continue;
00136 }
00137 if ( A->is_leaf() && B->is_leaf() )
00138 {
00139 this->report( A, B, results);
00140 continue;
00141 }
00142 if ( B->is_leaf() || ( !A->is_leaf() && ( A->volume().volume() > B->volume().volume() ) ) )
00143 {
00144 bv_ptr_iterator a = A->child_ptr_begin();
00145 bv_ptr_iterator end = A->child_ptr_end();
00146 for(;a!=end;++a)
00147 {
00148 bv_ptr ptr( *a );
00149 Q.push_back( ptr );
00150 Q.push_back( B );
00151 adj_queue.push_back( adj );
00152 }
00153 }
00154 else
00155 {
00156 bv_ptr_iterator b = B->child_ptr_begin();
00157 bv_ptr_iterator end = B->child_ptr_end();
00158 for(;b!=end;++b)
00159 {
00160 bv_ptr ptr( *b );
00161 Q.push_back( A );
00162 Q.push_back( ptr );
00163 adj_queue.push_back( adj );
00164 }
00165 }
00166 }
00167 }
00168
00169 };
00170
00171 }
00172
00173 }
00174
00175
00176 #endif