moab
|
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