moab
|
00001 00011 #include <vector> 00012 #include <set> 00013 #include <iostream> 00014 #include <map> 00015 #include <algorithm> 00016 #include <bitset> 00017 #include <numeric> 00018 #include <cmath> 00019 #include <tr1/unordered_map> 00020 #include <limits> 00021 #include "common_tree.hpp" 00022 00023 //#define BVH_TREE_DEBUG 00024 #ifndef BVH_TREE_HPP 00025 #define BVH_TREE_HPP 00026 00027 namespace ct = moab::common_tree; 00028 00029 namespace moab { 00030 00031 //forward declarations 00032 template< typename _Entity_handles, 00033 typename _Box, 00034 typename _Moab, 00035 typename _Parametrizer> class Bvh_tree; 00036 00037 //non-exported functionality 00038 namespace { 00039 namespace _bvh { 00040 template< typename Box, typename Entity_handle> 00041 struct _Node{ 00042 typedef typename std::vector< std::pair< Box, Entity_handle> > 00043 Entities; 00044 std::size_t dim; 00045 std::size_t child; 00046 double Lmax, Rmin; 00047 Entities entities; 00048 _Node& operator=( const _Node& f){ 00049 dim = f.dim; 00050 child=f.child; 00051 Lmax=f.Lmax; 00052 Rmin=f.Rmin; 00053 entities=f.entities; 00054 return *this; 00055 } 00056 }; // _Node 00057 00058 00059 template< typename Split> 00060 class Split_comparator : 00061 public std::binary_function< Split, Split, bool> { 00062 inline double objective( const Split & a) const{ 00063 return a.Lmax*a.nl - a.Rmin*a.nr; 00064 } 00065 public: 00066 bool operator()( const Split & a, const Split & b) const{ 00067 return objective( a) < objective( b); 00068 } 00069 }; //Split_comparator 00070 00071 template< typename Iterator> 00072 class Iterator_comparator : 00073 public std::binary_function< Iterator, Iterator, bool> { 00074 public: 00075 bool operator()( const Iterator & a, const Iterator & b) const{ 00076 return a->second.second < b->second.second || 00077 ( !(b->second.second < a->second.second) 00078 && a->first < b->first); 00079 } 00080 }; //Split_comparator 00081 00082 00083 class _Split_data { 00084 public: 00085 typedef ct::Box< double> Box; 00086 _Split_data(): dim( 0), nl( 0), nr( 0), split( 0.0), 00087 Lmax( 0.0), Rmin( 0.0),bounding_box(), 00088 left_box(), right_box(){} 00089 _Split_data( const _Split_data & f): 00090 dim( f.dim), nl( f.nl), nr( f.nr), 00091 split( f.split), Lmax( f.Lmax), Rmin( f.Rmin), 00092 bounding_box( f.bounding_box), 00093 left_box( f.left_box), right_box( f.right_box){} 00094 std::size_t dim; 00095 std::size_t nl; 00096 std::size_t nr; 00097 double split; 00098 double Lmax, Rmin; 00099 Box bounding_box; 00100 Box left_box; 00101 Box right_box; 00102 _Split_data& operator=( const _Split_data & f){ 00103 dim = f.dim; 00104 nl = f.nl; 00105 nr = f.nr; 00106 split = f.split; 00107 Lmax = f.Lmax; 00108 Rmin = f.Rmin; 00109 bounding_box = f.bounding_box; 00110 left_box = f.left_box; 00111 right_box = f.right_box; 00112 return *this; 00113 } 00114 }; //_Split_data 00115 00116 class _Bucket { 00117 public: 00118 _Bucket(): size( 0), bounding_box(){} 00119 _Bucket( const _Bucket & f): 00120 size( f.size), bounding_box(f.bounding_box){} 00121 _Bucket( const std::size_t size_): 00122 size( size_), bounding_box(){} 00123 std::size_t size; 00124 ct::Box< double> bounding_box; 00125 _Bucket& operator=( const _Bucket & f){ 00126 bounding_box = f.bounding_box; 00127 size = f.size; 00128 return *this; 00129 } 00130 }; //_Split_data 00131 } // namespace _bvh 00132 } //private namespace 00133 00134 template< typename _Entity_handles, 00135 typename _Box, 00136 typename _Moab, 00137 typename _Parametrizer> 00138 class Bvh_tree { 00139 //public types 00140 public: 00141 typedef _Entity_handles Entity_handles; 00142 typedef _Box Box; 00143 typedef _Moab Moab; 00144 typedef _Parametrizer Parametrizer; 00145 typedef typename Entity_handles::value_type Entity_handle; 00146 00147 //private types 00148 private: 00149 typedef Bvh_tree< _Entity_handles, 00150 _Box, 00151 _Moab, 00152 _Parametrizer> Self; 00153 typedef typename std::pair< Box, Entity_handle> Leaf_element; 00154 typedef _bvh::_Node< Box, Entity_handle> Node; 00155 typedef typename std::vector< Node> Nodes; 00156 //public methods 00157 public: 00158 //Constructor 00159 Bvh_tree( Entity_handles & _entities, 00160 Moab & _moab, 00161 Box & _bounding_box, 00162 Parametrizer & _entity_contains): entity_handles_( _entities), 00163 tree_(), moab( _moab), 00164 bounding_box( _bounding_box), 00165 entity_contains( _entity_contains){ 00166 typedef typename Entity_handles::iterator Entity_handle_iterator; 00167 typedef ct::_Element_data< const _Box, double > Element_data; 00168 typedef typename std::tr1::unordered_map< Entity_handle, 00169 Element_data> Entity_map; 00170 typedef typename Entity_map::iterator Entity_map_iterator; 00171 typedef std::vector< Entity_map_iterator> Vector; 00172 //a fully balanced tree will have 2*_entities.size() 00173 //which is one doubling away.. 00174 tree_.reserve( entity_handles_.size()); 00175 Entity_map entity_map( entity_handles_.size()); 00176 ct::construct_element_map( entity_handles_, 00177 entity_map, 00178 bounding_box, 00179 moab); 00180 #ifdef BVH_TREE_DEBUG 00181 for(Entity_map_iterator i = entity_map.begin(); 00182 i != entity_map.end(); ++i){ 00183 if( !box_contains_box( bounding_box, i->second.first, 0)){ 00184 std::cerr << "BB:" << bounding_box << "EB:" << 00185 i->second.first << std::endl; 00186 std::exit( -1); 00187 } 00188 } 00189 #endif 00190 //_bounding_box = bounding_box; 00191 Vector entity_ordering; 00192 construct_ordering( entity_map, entity_ordering); 00193 //We only build nonempty trees 00194 if( entity_ordering.size()){ 00195 //initially all bits are set 00196 tree_.push_back( Node()); 00197 const int depth = build_tree( entity_ordering.begin(), 00198 entity_ordering.end(), 0, bounding_box); 00199 #ifdef BVH_TREE_DEBUG 00200 typedef typename Nodes::iterator Node_iterator; 00201 typedef typename Node::Entities::iterator Entity_iterator; 00202 std::set< Entity_handle> entity_handles; 00203 for(Node_iterator i = tree_.begin(); i != tree_.end(); ++i){ 00204 for(Entity_iterator j = i->entities.begin(); 00205 j != i->entities.end(); ++j){ 00206 entity_handles.insert( j->second); 00207 } 00208 00209 } 00210 if( entity_handles.size() != entity_handles_.size()){ 00211 std::cout << "Entity Handle Size Mismatch!" 00212 << std::endl; 00213 } 00214 typedef typename Entity_handles::iterator Entity_iterator_; 00215 for( Entity_iterator_ i = entity_handles_.begin(); 00216 i != entity_handles_.end(); ++i){ 00217 if ( entity_handles.find( *i) == entity_handles.end()){ 00218 std::cout << "Tree is missing an entity! " 00219 << std::endl; 00220 } 00221 } 00222 00223 #endif 00224 std::cout << "max tree depth: " << depth << std::endl; 00225 } 00226 } 00227 00228 //Copy constructor 00229 Bvh_tree( Self & s): entity_handles_( s.entity_handles_), 00230 tree_( s.tree_), moab( s.moab), 00231 bounding_box( s.bounding_box), 00232 entity_contains( s.entity_contains){} 00233 00234 //see FastMemoryEfficientCellLocationinUnstructuredGridsForVisualization.pdf 00235 //around page 9 00236 #define NUM_SPLITS 4 00237 #define NUM_BUCKETS (NUM_SPLITS + 1) //NUM_SPLITS+1 00238 #define SMAX 5 00239 //Paper arithmetic is over-optimized.. this is safer. 00240 template < typename Box> 00241 std::size_t bucket_index( const Box & box, const Box & interval, 00242 const std::size_t dim) const{ 00243 const double min = interval.min[ dim]; 00244 const double length = (interval.max[ dim]-min)/NUM_BUCKETS; 00245 const double center = ((box.max[ dim] + box.min[ dim])/2.0)-min; 00246 #ifdef BVH_TREE_DEBUG 00247 #ifdef BVH_SHOW_INDEX 00248 std::cout << "[ " << min << " , " 00249 << interval.max[ dim] << " ]" <<std::endl; 00250 std::cout << "[ " 00251 << box.min[ dim] << " , " << box.max[ dim] << " ]" <<std::endl; 00252 std::cout << "Length of bucket" << length << std::endl; 00253 std::cout << "Center: " 00254 << (box.max[ dim] + box.min[ dim])/2.0 << std::endl; 00255 std::cout << "Distance of center from min: " << center << std::endl; 00256 std::cout << "ratio: " << center/length << std::endl; 00257 std::cout << "index: " << std::ceil(center/length)-1 << std::endl; 00258 #endif 00259 #endif 00260 return std::ceil(center/length)-1; 00261 } 00262 00263 template< typename Iterator, typename Bounding_box, typename Buckets> 00264 void establish_buckets( const Iterator begin, const Iterator end, 00265 const Bounding_box & interval, 00266 Buckets & buckets) const{ 00267 //put each element into its bucket 00268 for(Iterator i = begin; i != end; ++i){ 00269 const Bounding_box & box = (*i)->second.first; 00270 for (std::size_t dim = 0; dim < NUM_DIM; ++dim){ 00271 const std::size_t index = bucket_index( box, 00272 interval, dim); 00273 _bvh::_Bucket & bucket = buckets[ dim][ index]; 00274 if(bucket.size > 0){ 00275 ct::update_bounding_box( bucket.bounding_box, box); 00276 }else{ 00277 bucket.bounding_box = box; 00278 } 00279 bucket.size++; 00280 } 00281 } 00282 #ifdef BVH_TREE_DEBUG 00283 Bounding_box elt_union = (*begin)->second.first; 00284 for(Iterator i = begin; i != end; ++i){ 00285 const Bounding_box & box = (*i)->second.first; 00286 ct::update_bounding_box( elt_union, box); 00287 for (std::size_t dim = 0; dim < NUM_DIM; ++dim){ 00288 const std::size_t index = bucket_index( box, 00289 interval, dim); 00290 _bvh::_Bucket & bucket = buckets[ dim][ index]; 00291 if(!box_contains_box( bucket.bounding_box, box)){ 00292 std::cerr << "Buckets not covering elements!" 00293 << std::endl; 00294 } 00295 } 00296 } 00297 if( !box_contains_box( elt_union, interval) ){ 00298 std::cout << "element union: " << std::endl << elt_union; 00299 std::cout << "intervals: " << std::endl << interval; 00300 std::cout << "union of elts does not contain original box!" 00301 << std::endl; 00302 } 00303 if ( !box_contains_box( interval, elt_union) ){ 00304 std::cout << "original box does not contain union of elts" 00305 << std::endl; 00306 std::cout << interval << std::endl; 00307 std::cout << elt_union << std::endl; 00308 } 00309 typedef typename Buckets::value_type Bucket_list; 00310 typedef typename Bucket_list::const_iterator Bucket_iterator; 00311 for(std::size_t d = 0; d < NUM_DIM; ++d){ 00312 std::vector< std::size_t> nonempty; 00313 const Bucket_list & buckets_ = buckets[ d]; 00314 std::size_t j = 0; 00315 for( Bucket_iterator i = buckets_.begin(); 00316 i != buckets_.end(); ++i, ++j){ 00317 if( i->size > 0){ nonempty.push_back( j); } 00318 } 00319 Bounding_box test_box = buckets_[ nonempty.front()]. 00320 bounding_box; 00321 for( std::size_t i = 0; i < nonempty.size(); ++i){ 00322 ct::update_bounding_box( test_box, 00323 buckets_[ nonempty[ i]]. 00324 bounding_box); 00325 } 00326 if( !box_contains_box( test_box, interval) ){ 00327 std::cout << "union of buckets in dimension: " << d 00328 << "does not contain original box!" 00329 << std::endl; 00330 } 00331 if ( !box_contains_box( interval, test_box) ){ 00332 std::cout << "original box does " 00333 << "not contain union of buckets" 00334 << "in dimension: " << d 00335 << std::endl; 00336 std::cout << interval << std::endl; 00337 std::cout << test_box << std::endl; 00338 } 00339 } 00340 #endif 00341 } 00342 00343 template< typename Box, typename Iterator> 00344 std::size_t set_interval( Box & interval, const Iterator begin, 00345 const Iterator end) const{ 00346 bool first=true; 00347 std::size_t count = 0; 00348 for( Iterator b = begin; b != end; ++b){ 00349 const Box & box = b->bounding_box; 00350 count += b->size; 00351 if( b->size != 0){ 00352 if( first){ 00353 interval = box; 00354 first=false; 00355 }else{ 00356 ct::update_bounding_box( interval, box); 00357 } 00358 } 00359 } 00360 return count; 00361 } 00362 00363 template< typename Splits, typename Buckets, typename Split_data> 00364 void initialize_splits( Splits & splits, 00365 const Buckets & buckets, 00366 const Split_data & data) const{ 00367 typedef typename Buckets::value_type Bucket_list; 00368 typedef typename Bucket_list::value_type Bucket; 00369 typedef typename Bucket_list::const_iterator Bucket_iterator; 00370 typedef typename Splits::value_type Split_list; 00371 typedef typename Split_list::value_type Split; 00372 typedef typename Split_list::iterator Split_iterator; 00373 for(std::size_t d = 0; d < NUM_DIM; ++d){ 00374 const Split_iterator splits_begin = splits[ d].begin(); 00375 const Split_iterator splits_end = splits[ d].end(); 00376 const Bucket_iterator left_begin = buckets[ d].begin(); 00377 const Bucket_iterator _end = buckets[ d].end(); 00378 Bucket_iterator left_end = buckets[ d].begin()+1; 00379 for( Split_iterator s = splits_begin; 00380 s != splits_end; ++s, ++left_end){ 00381 s->nl = set_interval( s->left_box, 00382 left_begin, left_end); 00383 if( s->nl == 0){ 00384 s->left_box = data.bounding_box; 00385 s->left_box.max[ d] = s->left_box.min[ d]; 00386 } 00387 s->nr = set_interval( s->right_box, 00388 left_end, _end); 00389 if( s->nr == 0){ 00390 s->right_box = data.bounding_box; 00391 s->right_box.min[ d] = s->right_box.max[ d]; 00392 } 00393 s->Lmax = s->left_box.max[ d]; 00394 s->Rmin = s->right_box.min[ d]; 00395 s->split = std::distance( splits_begin, s); 00396 s->dim = d; 00397 } 00398 #ifdef BVH_TREE_DEBUG 00399 for( Split_iterator s = splits_begin; 00400 s != splits_end; ++s, ++left_end){ 00401 typename Split::Box test_box = s->left_box; 00402 ct::update_bounding_box( test_box, s->right_box); 00403 if( !box_contains_box( data.bounding_box, test_box)){ 00404 std::cout << "nr: " << s->nr << std::endl; 00405 std::cout << "Test box: " << std::endl << 00406 test_box; 00407 std::cout << "Left box: " << std::endl << 00408 s->left_box; 00409 std::cout << "Right box: " << std::endl << 00410 s->right_box; 00411 std::cout << "Interval: " << std::endl << 00412 data.bounding_box; 00413 std::cout << "Split boxes larger than bb" 00414 << std::endl; 00415 } 00416 if( !box_contains_box( test_box, data.bounding_box)){ 00417 std::cout << "bb larger than union " 00418 << "of split boxes" 00419 << std::endl; 00420 } 00421 } 00422 #endif 00423 } 00424 } 00425 00426 template< typename Iterator, typename Split_data> 00427 void order_elements( const Iterator & begin, const Iterator & end, 00428 const Split_data & data) const{ 00429 typedef typename Iterator::value_type Map_iterator; 00430 for(Iterator i = begin; i != end; ++i){ 00431 const int index = bucket_index( (*i)->second.first, 00432 data.bounding_box, data.dim); 00433 (*i)->second.second = (index<=data.split)?0:1; 00434 } 00435 std::sort( begin, end, _bvh::Iterator_comparator< Map_iterator>()); 00436 } 00437 00438 template< typename Iterator, typename Split_data> 00439 void median_order( const Iterator & begin, const Iterator & end, 00440 Split_data & data) const{ 00441 typedef typename Iterator::value_type Map_iterator; 00442 for(Iterator i = begin; i != end; ++i){ 00443 const double center = 00444 compute_box_center((*i)->second.first, data.dim); 00445 (*i)->second.second = center; 00446 } 00447 std::sort( begin, end, _bvh::Iterator_comparator< Map_iterator>()); 00448 const std::size_t total = std::distance( begin, end); 00449 Iterator middle = begin+(total/2); 00450 double middle_center = (*middle)->second.second; 00451 middle_center += (*(++middle))->second.second; 00452 middle_center /=2.0; 00453 data.split = middle_center; 00454 data.nl = std::distance( begin, middle)+1; 00455 data.nr = total-data.nl; 00456 middle++; 00457 data.left_box = (*begin)->second.first; 00458 data.right_box = (*middle)->second.first; 00459 for(Iterator i = begin; i != middle; ++i){ 00460 (*i)->second.second = 0; 00461 update_bounding_box( data.left_box, (*i)->second.first); 00462 } 00463 for(Iterator i = middle; i != end; ++i){ 00464 (*i)->second.second = 1; 00465 update_bounding_box( data.right_box, 00466 (*i)->second.first); 00467 } 00468 data.Rmin = data.right_box.min[ data.dim]; 00469 data.Lmax = data.left_box.max[ data.dim]; 00470 #ifdef BVH_TREE_DEBUG 00471 typename Split_data::Box test_box = data.left_box; 00472 ct::update_bounding_box( test_box, data.right_box); 00473 if( !box_contains_box( data.bounding_box, test_box) ){ 00474 std::cerr << "MEDIAN: BB Does not contain splits" << std::endl; 00475 } 00476 if( !box_contains_box( test_box, data.bounding_box) ){ 00477 std::cerr << "MEDIAN: splits do not contain BB" << std::endl; 00478 } 00479 #endif 00480 } 00481 00482 template< typename Splits, typename Split_data> 00483 void choose_best_split( const Splits & splits, Split_data & data) const{ 00484 typedef typename Splits::const_iterator List_iterator; 00485 typedef typename List_iterator::value_type::const_iterator 00486 Split_iterator; 00487 typedef typename Split_iterator::value_type Split; 00488 std::vector< Split> best_splits; 00489 typedef typename _bvh::Split_comparator< Split> Comparator; 00490 Comparator compare; 00491 for( List_iterator i = splits.begin(); i != splits.end(); ++i){ 00492 Split_iterator j = std::min_element( i->begin(), i->end(), 00493 compare); 00494 best_splits.push_back( *j); 00495 } 00496 data = *std::min_element( best_splits.begin(), 00497 best_splits.end(), compare); 00498 } 00499 00500 00501 template< typename Iterator, typename Split_data> 00502 void find_split(const Iterator & begin, 00503 const Iterator & end, Split_data & data) const{ 00504 typedef typename Iterator::value_type Map_iterator; 00505 typedef typename Map_iterator::value_type::second_type Box_data; 00506 typedef typename Box_data::first_type _Bounding_box; // Note, not global typedef moab::common_tree::Box< double> Bounding_box; 00507 typedef typename std::vector< Split_data> Split_list; 00508 typedef typename std::vector< Split_list> Splits; 00509 typedef typename Splits::iterator Split_iterator; 00510 typedef typename std::vector< _bvh::_Bucket> Bucket_list; 00511 typedef typename std::vector< Bucket_list > Buckets; 00512 Buckets buckets( NUM_DIM, Bucket_list( NUM_BUCKETS) ); 00513 Splits splits( NUM_DIM, Split_list( NUM_SPLITS, data)); 00514 00515 const _Bounding_box interval = data.bounding_box; 00516 establish_buckets( begin, end, interval, buckets); 00517 initialize_splits( splits, buckets, data); 00518 choose_best_split( splits, data); 00519 const bool use_median = (0 == data.nl) || (data.nr == 0); 00520 if (!use_median){ order_elements( begin, end, data); } 00521 else{ median_order( begin, end, data); } 00522 #ifdef BVH_TREE_DEBUG 00523 bool seen_one=false,issue=false; 00524 bool first_left=true,first_right=true; 00525 std::size_t count_left=0, count_right=0; 00526 typename Split_data::Box left_box, right_box; 00527 for( Iterator i = begin; i != end; ++i){ 00528 double order = (*i)->second.second; 00529 if( order != 0 && order != 1){ 00530 std::cerr << "Invalid order element !"; 00531 std::cerr << order << std::endl; 00532 std::exit( -1); 00533 } 00534 if(order == 1){ 00535 seen_one=1; 00536 count_right++; 00537 if( first_right){ 00538 right_box = (*i)->second.first; 00539 first_right=false; 00540 }else{ 00541 ct::update_bounding_box( right_box, 00542 (*i)->second.first); 00543 } 00544 if(!box_contains_box( data.right_box, 00545 (*i)->second.first)){ 00546 if(!issue){ 00547 std::cerr << "Bounding right box issue!" 00548 << std::endl; 00549 } 00550 issue=true; 00551 } 00552 } 00553 if(order==0){ 00554 count_left++; 00555 if( first_left){ 00556 left_box = (*i)->second.first; 00557 first_left=false; 00558 }else{ 00559 ct::update_bounding_box( left_box, 00560 (*i)->second.first); 00561 } 00562 if(!box_contains_box( data.left_box, 00563 (*i)->second.first)){ 00564 if(!issue){ 00565 std::cerr << "Bounding left box issue!" 00566 << std::endl; 00567 } 00568 issue=true; 00569 } 00570 if(seen_one){ 00571 std::cerr << "Invalid ordering!" << std::endl; 00572 std::cout << (*(i-1))->second.second 00573 << order << std::endl; 00574 exit( -1); 00575 } 00576 } 00577 } 00578 if( !box_contains_box( left_box, data.left_box)){ 00579 std::cout << "left elts do not contain left box" << std::endl; 00580 } 00581 if( !box_contains_box( data.left_box, left_box)){ 00582 std::cout << "left box does not contain left elts" << std::endl; 00583 } 00584 if( !box_contains_box( right_box, data.right_box)){ 00585 std::cout << "right elts do not contain right box" << std::endl; 00586 } 00587 if( !box_contains_box( data.right_box, right_box)){ 00588 std::cout << "right box do not contain right elts" << std::endl; 00589 } 00590 if( count_left != data.nl || count_right != data.nr) { 00591 std::cerr << "counts are off!" << std::endl; 00592 std::cerr << "total: " 00593 << std::distance( begin, end) << std::endl; 00594 std::cerr << "Dim: " << data.dim << std::endl; 00595 std::cerr << data.Lmax << " , " << data.Rmin << std::endl; 00596 std::cerr << "Right box: " << std::endl << data.right_box 00597 << "Left box: " << std::endl << data.left_box ; 00598 std::cerr << "supposed to be: " << 00599 data.nl << " " << data.nr << std::endl; 00600 std::cerr << "accountant says: " << 00601 count_left << " " << count_right << std::endl; 00602 std::exit( -1); 00603 } 00604 #endif 00605 } 00606 00607 //private functionality 00608 private: 00609 template< typename Iterator> 00610 int build_tree( const Iterator begin, const Iterator end, 00611 const int index, const Box & box, 00612 const int depth=0){ 00613 #ifdef BVH_TREE_DEBUG 00614 for(Iterator i = begin; 00615 i != end; ++i){ 00616 if( !box_contains_box( box, (*i)->second.first, 0)){ 00617 std::cerr << "depth: " << depth << std::endl; 00618 std::cerr << "BB:" << box << "EB:" << 00619 (*i)->second.first << std::endl; 00620 std::exit( -1); 00621 } 00622 } 00623 #endif 00624 00625 const std::size_t total_num_elements = std::distance( begin, end); 00626 Node & node = tree_[ index]; 00627 //logic for splitting conditions 00628 if( total_num_elements > SMAX){ 00629 _bvh::_Split_data data; 00630 data.bounding_box = box; 00631 find_split( begin, end, data); 00632 //assign data to node 00633 node.Lmax = data.Lmax; node.Rmin = data.Rmin; 00634 node.dim = data.dim; node.child = tree_.size(); 00635 //insert left, right children; 00636 tree_.push_back( Node()); tree_.push_back( Node()); 00637 const int left_depth= 00638 build_tree( begin, begin+data.nl, node.child, 00639 data.left_box, depth+1); 00640 const int right_depth= 00641 build_tree( begin+data.nl, end, node.child+1, 00642 data.right_box, depth+1); 00643 return std::max( left_depth, right_depth); 00644 } 00645 node.dim = 3; 00646 ct::assign_entities( node.entities, begin, end); 00647 return depth; 00648 } 00649 00650 template< typename Vector, typename Node_index, typename Result> 00651 Result& _find_point( const Vector & point, 00652 const Node_index & index, 00653 const double tol, 00654 Result& result) const{ 00655 typedef typename Node::Entities::const_iterator Entity_iterator; 00656 const Node & node = tree_[ index]; 00657 if( node.dim == 3){ 00658 for( Entity_iterator i = node.entities.begin(); 00659 i != node.entities.end(); ++i){ 00660 if( ct::box_contains_point( i->first, point, tol)){ 00661 const std::pair< bool, Vector> r = 00662 entity_contains( moab, i->second, point); 00663 if (r.first){ 00664 return result = std::make_pair( i->second, 00665 r.second); 00666 } 00667 } 00668 } 00669 result = Result(0, point); 00670 return result; 00671 } 00672 //the extra tol here considers the case where 00673 //0 < Rmin - Lmax < 2tol 00674 if( (node.Lmax+tol) < (node.Rmin-tol)){ 00675 if( point[ node.dim] <= (node.Lmax + tol)){ 00676 return _find_point( point, node.child, tol, result); 00677 }else if( point[ node.dim] >= (node.Rmin - tol)){ 00678 return _find_point( point, node.child+1, tol, result); 00679 } 00680 result = Result(0, point); 00681 return result; //point lies in empty space. 00682 } 00683 //Boxes overlap 00684 //left of Rmin, you must be on the left 00685 //we can't be sure about the boundaries since the boxes overlap 00686 //this was a typo in the paper which caused pain. 00687 if( point[ node.dim] < (node.Rmin - tol)){ 00688 return _find_point( point, node.child, tol, result); 00689 //if you are on the right Lmax, you must be on the right 00690 }else if( point[ node.dim] > (node.Lmax+tol)){ 00691 return _find_point( point, node.child+1, tol, result); 00692 } 00693 /* pg5 of paper 00694 * However, instead of always traversing either subtree 00695 * first (e.g. left always before right), we first traverse 00696 * the subtree whose bounding plane has the larger distance to the 00697 * sought point. This results in less overall traversal, and the correct 00698 * cell is identified more quickly. 00699 */ 00700 //Sofar all testing confirms that this 'heuristic' is 00701 //significantly slower. 00702 //I conjecture this is because it gets improperly 00703 //branch predicted.. 00704 //bool dir = (point[ node.dim] - node.Rmin) <= 00705 // (node.Lmax - point[ node.dim]); 00706 bool dir=0; 00707 _find_point( point, node.child+dir, tol, result); 00708 if( result.first == 0 ){ 00709 return _find_point( point, node.child+(!dir), tol, result); 00710 } 00711 return result; 00712 } 00713 00714 //public functionality 00715 public: 00716 template< typename Vector, typename Result> 00717 Result& find( const Vector & point, 00718 const double tol, Result & result) const{ 00719 typedef typename Vector::const_iterator Point_iterator; 00720 return _find_point( point, 0, tol, result); 00721 } 00722 00723 //public functionality 00724 public: 00725 template< typename Vector> 00726 Entity_handle bruteforce_find( const Vector & point, const double tol) const{ 00727 typedef typename Vector::const_iterator Point_iterator; 00728 typedef typename Nodes::value_type Node; 00729 typedef typename Nodes::const_iterator Node_iterator; 00730 typedef typename Node::Entities::const_iterator Entity_iterator; 00731 for( Node_iterator i = tree_.begin(); i != tree_.end(); ++i){ 00732 if( i->dim == 3){ 00733 for( Entity_iterator j = i->entities.begin(); 00734 j != i->entities.end(); 00735 ++j){ 00736 if( ct::box_contains_point( j->first, 00737 point, tol)){ 00738 const std::pair< bool, Vector> result = 00739 entity_contains( moab, j->second, point); 00740 if (result.first){ 00741 return j->second; 00742 } 00743 } 00744 } 00745 } 00746 } 00747 return 0; 00748 } 00749 00750 00751 //public accessor methods 00752 public: 00753 00754 //private data members 00755 private: 00756 const Entity_handles & entity_handles_; 00757 Nodes tree_; 00758 Moab & moab; 00759 Box bounding_box; 00760 Parametrizer & entity_contains; 00761 00762 }; //class Bvh_tree 00763 00764 } // namespace moab 00765 00766 #endif //BVH_TREE_HPP