moab
BVHTree.hpp
Go to the documentation of this file.
00001 
00006 #ifndef BVH_TREE_HPP
00007 #define BVH_TREE_HPP
00008 
00009 #include "moab/Interface.hpp"
00010 #include "moab/CartVect.hpp"
00011 #include "moab/BoundBox.hpp"
00012 #include "moab/Tree.hpp"
00013 #include "moab/Range.hpp"
00014 #include "moab/CN.hpp"
00015 
00016 #include <vector>
00017 #include <cfloat>
00018 #include <climits>
00019 #include <map>
00020 #include <set>
00021 #include <iostream>
00022 
00023 namespace moab {
00024 
00025     class ElemEvaluator;
00026     
00027     class BVHTree : public Tree {
00028   public:
00029       BVHTree(Interface *impl);
00030 
00031       ~BVHTree() {reset_tree();}
00032       
00036       virtual ErrorCode reset_tree();
00037 
00038       virtual ErrorCode parse_options(FileOptions &opts);
00039       
00048       virtual ErrorCode get_bounding_box(BoundBox &box, EntityHandle *tree_node = NULL) const;
00049   
00063       virtual ErrorCode build_tree(const Range& entities,
00064                                    EntityHandle *tree_root_set = NULL,
00065                                    FileOptions *options = NULL);
00066 
00085       virtual ErrorCode point_search(const double *point,
00086                                      EntityHandle& leaf_out,
00087                                      const double iter_tol = 1.0e-10,
00088                                      const double inside_tol = 1.0e-6,
00089                                      bool *multiple_leaves = NULL,
00090                                      EntityHandle *start_node = NULL,
00091                                      CartVect *params = NULL);
00092 
00108       virtual ErrorCode distance_search(const double from_point[3],
00109                                         const double distance,
00110                                         std::vector<EntityHandle>& result_list,
00111                                         const double iter_tol = 1.0e-10,
00112                                         const double inside_tol = 1.0e-6,
00113                                         std::vector<double> *result_dists = NULL,
00114                                         std::vector<CartVect> *result_params = NULL,
00115                                         EntityHandle *tree_root = NULL);
00116 
00118       virtual ErrorCode print();
00119 
00120       
00121   private:
00122         // don't allow copy constructor, too complicated
00123       BVHTree(const BVHTree &s);
00124 
00125       class HandleData 
00126       {
00127     public:
00128         HandleData(EntityHandle h, const BoundBox &bx, const double dp) : myHandle(h), myBox(bx), myDim(dp) {}
00129         HandleData() : myHandle(0), myDim(-1) {}
00130         EntityHandle myHandle;
00131         BoundBox myBox;
00132         double myDim;
00133       };
00134       typedef std::vector<HandleData> HandleDataVec;
00135     
00136       class SplitData {
00137     public:
00138         SplitData(): dim(UINT_MAX), nl(UINT_MAX), nr(UINT_MAX), split(DBL_MAX), 
00139                      Lmax(-DBL_MAX), Rmin(DBL_MAX) {}
00140         SplitData( const SplitData &f): 
00141         dim(f.dim), nl(f.nl), nr(f.nr), split(f.split), Lmax(f.Lmax), Rmin(f.Rmin), 
00142         boundingBox(f.boundingBox), leftBox(f.leftBox), rightBox(f.rightBox){}
00143         unsigned int dim, nl, nr;
00144         double split;
00145         double Lmax, Rmin;
00146         BoundBox boundingBox, leftBox, rightBox;
00147         SplitData& operator=(const SplitData & f){
00148           dim = f.dim; nl = f.nl; nr = f.nr;
00149           split = f.split; Lmax = f.Lmax; Rmin = f.Rmin;
00150           boundingBox = f.boundingBox; leftBox = f.leftBox; rightBox = f.rightBox;
00151           return *this;
00152         }
00153       }; //SplitData
00154 
00155       class Split_comparator : 
00156           public std::binary_function< SplitData, SplitData, bool> {
00157         inline double objective(const SplitData & a) const{
00158           return a.Lmax*a.nl - a.Rmin*a.nr;
00159         }
00160     public:
00161         bool operator()(const SplitData &a, const SplitData &b) const {
00162           return  objective( a) < objective( b);
00163         }
00164       }; //Split_comparator
00165 
00166       class HandleData_comparator : 
00167           public std::binary_function<HandleData, HandleData, bool> {
00168     public:
00169         bool operator()(const HandleData &a, const HandleData &b) {
00170           return a.myDim < b.myDim ||
00171               (a.myDim == b.myDim && 
00172                a.myHandle < b.myHandle);
00173         }
00174       }; //Iterator_comparator
00175 
00176       class Bucket {
00177     public:
00178         Bucket() : mySize(0) {}
00179         Bucket( const Bucket &f): mySize(f.mySize), boundingBox(f.boundingBox) {}
00180         Bucket(const unsigned int sz): mySize(sz) {}
00181         static unsigned int bucket_index(int num_splits, const BoundBox &box, const BoundBox &interval, const unsigned int dim);
00182         unsigned int mySize;
00183         BoundBox boundingBox;
00184         Bucket &operator=(const Bucket & f){
00185           boundingBox = f.boundingBox; mySize = f.mySize;
00186           return *this;
00187         }
00188       }; //Bucket
00189 
00190       class Node {
00191     public:
00192         HandleDataVec entities;
00193         unsigned int dim, child;
00194         double Lmax, Rmin;
00195         BoundBox box;
00196         Node() : dim(-2), child(-1), Lmax(-DBL_MAX), Rmin(DBL_MAX) {}        
00197         Node &operator=(const Node& f) {
00198           dim = f.dim; child = f.child;
00199           Lmax = f.Lmax; Rmin = f.Rmin;
00200           entities = f.entities;
00201           return *this;
00202         }
00203       }; // Node
00204 
00205       class TreeNode {
00206     public:
00207         unsigned int dim, child;
00208         double Lmax, Rmin;
00209         BoundBox box;
00210         TreeNode(int dm, int chld, double lmx, double rmn, BoundBox &bx) 
00211                 : dim(dm), child(chld), Lmax(lmx), Rmin(rmn), box(bx) {}
00212         TreeNode &operator=(const TreeNode& f) {
00213           dim = f.dim; child = f.child;
00214           Lmax = f.Lmax; Rmin = f.Rmin;
00215           return *this;
00216         }
00217       }; // TreeNode
00218 
00219       void establish_buckets(HandleDataVec::const_iterator begin, 
00220                              HandleDataVec::const_iterator end, 
00221                              const BoundBox &interval, std::vector<std::vector<Bucket> > &buckets) const;
00222 
00223       unsigned int set_interval(BoundBox & interval, 
00224                                 std::vector<Bucket>::const_iterator begin, 
00225                                 std::vector<Bucket>::const_iterator end) const;
00226 
00227       void initialize_splits(std::vector<std::vector<SplitData> > &splits, 
00228                              const std::vector<std::vector<Bucket> > &buckets, 
00229                              const SplitData &data) const;
00230 
00231       void order_elements(HandleDataVec::iterator &begin, 
00232                           HandleDataVec::iterator &end, 
00233                           SplitData &data) const;
00234 
00235       void median_order(HandleDataVec::iterator &begin, 
00236                         HandleDataVec::iterator &end, 
00237                         SplitData & data) const;
00238 
00239       void choose_best_split(const std::vector<std::vector<SplitData> > &splits,
00240                              SplitData & data) const;
00241 
00242 
00243       void find_split(HandleDataVec::iterator &begin, 
00244                       HandleDataVec::iterator &end, 
00245                       SplitData &data) const;
00246 
00247       ErrorCode find_point(const std::vector<double> &point, 
00248                            const unsigned int &index,
00249                            const double iter_tol,
00250                            const double inside_tol,
00251                            std::pair<EntityHandle, CartVect> &result);
00252       
00253       EntityHandle bruteforce_find(const double *point, 
00254                                    const double iter_tol = 1.0e-10,
00255                                    const double inside_tol = 1.0e-6);
00256 
00257       int local_build_tree(std::vector<Node> &tree_nodes,
00258                            HandleDataVec::iterator begin, 
00259                            HandleDataVec::iterator end,
00260                            const int index, const BoundBox &box, 
00261                            const int depth=0);
00262 
00263         // builds up vector of HandleData, which caches elements' bounding boxes
00264       ErrorCode construct_element_vec(std::vector<HandleData> &handle_data_vec,
00265                                       const Range &elements, 
00266                                       BoundBox & bounding_box);
00267       
00268         // convert the std::vector<Node> to myTree and a bunch of entity sets
00269       ErrorCode convert_tree(std::vector<Node> &tree_nodes);
00270 
00271         // print tree nodes
00272       ErrorCode print_nodes(std::vector<Node> &nodes);
00273       
00274       Range entityHandles;
00275       std::vector<TreeNode> myTree;
00276       int splitsPerDir;
00277       EntityHandle startSetHandle;
00278       static const char *treeName;
00279     }; //class Bvh_tree
00280 
00281     inline unsigned int BVHTree::Bucket::bucket_index(int num_splits, const BoundBox &box, const BoundBox & interval, const unsigned int dim)
00282     {
00283 //see FastMemoryEfficientCellLocationinUnstructuredGridsForVisualization.pdf 
00284 //around page 9
00285       
00286 //Paper arithmetic is over-optimized.. this is safer.
00287       const double min = interval.bMin[dim];
00288       const double length = (interval.bMax[dim]-min)/(num_splits+1);
00289       const double center = ((box.bMax[dim] + box.bMin[dim])/2.0)-min;
00290 #ifndef NDEBUG
00291 #ifdef BVH_SHOW_INDEX
00292       std::cout << "[" << min << " , " 
00293                 << interval.max[dim] << " ]" <<std::endl;
00294       std::cout << "[" 
00295                 << box.bMin[dim] << " , " << box.bMax[dim] << " ]" <<std::endl;
00296       std::cout << "Length of bucket" << length << std::endl;
00297       std::cout << "Center: " 
00298                 << (box.bMax[dim] + box.bMin[dim])/2.0 << std::endl;
00299       std::cout << "Distance of center from min:  " << center << std::endl;
00300       std::cout << "ratio: " << center/length << std::endl;
00301       std::cout << "index: " << std::ceil(center/length)-1 << std::endl;
00302 #endif
00303 #endif
00304       unsigned int cl = std::ceil(center/length);
00305       return (cl > 0 ? cl-1 : 0);
00306     }
00307 
00308     inline BVHTree::BVHTree(Interface *impl) : 
00309             Tree(impl), splitsPerDir(3), startSetHandle(0) {boxTagName = treeName;}
00310 
00311     inline unsigned int BVHTree::set_interval(BoundBox &interval, 
00312                                               std::vector<Bucket>::const_iterator begin, 
00313                                               std::vector<Bucket>::const_iterator end) const
00314     {
00315       bool first=true;
00316       unsigned int count = 0;
00317       for(std::vector<Bucket>::const_iterator b = begin; b != end; ++b) {
00318         const BoundBox &box = b->boundingBox;
00319         count += b->mySize;
00320         if(b->mySize != 0){
00321           if(first){
00322             interval = box;
00323             first=false;
00324           }
00325           else
00326             interval.update(box);
00327         }
00328       }
00329       return count;
00330     }
00331 
00332     inline void BVHTree::order_elements(HandleDataVec::iterator &begin, 
00333                                         HandleDataVec::iterator &end, 
00334                                         SplitData &data) const  
00335     {
00336       for(HandleDataVec::iterator i = begin; i != end; ++i) 
00337       {
00338         const int index = Bucket::bucket_index(splitsPerDir, i->myBox, data.boundingBox, data.dim);
00339         i->myDim = (index<=data.split)?0:1;
00340       }
00341       std::sort(begin, end, HandleData_comparator());
00342     }
00343 
00344     inline void BVHTree::choose_best_split(const std::vector<std::vector<SplitData> > &splits,
00345                                            SplitData &data) const
00346     {
00347       std::vector<SplitData> best_splits;
00348       for(std::vector<std::vector<SplitData> >::const_iterator i = splits.begin(); i != splits.end(); ++i){
00349         std::vector<SplitData>::const_iterator j = std::min_element((*i).begin(), (*i).end(), 
00350                                                                     Split_comparator());
00351         best_splits.push_back(*j);
00352       }
00353       data = *std::min_element(best_splits.begin(), best_splits.end(), Split_comparator());
00354     }
00355 
00356     inline ErrorCode BVHTree::construct_element_vec(std::vector<HandleData> &handle_data_vec,
00357                                                     const Range &elements, 
00358                                                     BoundBox & bounding_box) 
00359     {
00360       std::vector<double> coordinate(3*CN::MAX_NODES_PER_ELEMENT);
00361       int num_conn;
00362       ErrorCode rval = MB_SUCCESS;
00363       std::vector<EntityHandle> storage;
00364       for(Range::iterator i = elements.begin(); i != elements.end(); ++i) {
00365           //TODO: not generic enough. Why dim != 3
00366           //Commence un-necessary deep copying.
00367         const EntityHandle* connect;
00368         rval = mbImpl->get_connectivity(*i, connect, num_conn, false, &storage);
00369         if (MB_SUCCESS != rval) return rval;
00370         rval = mbImpl->get_coords(connect, num_conn, &coordinate[0]);
00371         if (MB_SUCCESS != rval) return rval;
00372         BoundBox box;
00373         for(int j = 0; j < num_conn; j++)
00374           box.update(&coordinate[3*j]);
00375         if(i == elements.begin())
00376           bounding_box = box;
00377         else bounding_box.update(box);
00378         handle_data_vec.push_back(HandleData(*i, box, 0.0));
00379       }
00380 
00381       return rval;
00382     }
00383 
00384     inline ErrorCode BVHTree::reset_tree()
00385     {
00386       return delete_tree_sets();
00387     }
00388 
00389 } // namespace moab
00390 
00391 #endif //BVH_TREE_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines