moab
bvh_tree.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines