1
11 #include <vector>
12 #include <set>
13 #include <iostream>
14 #include <map>
15 #include <algorithm>
16 #include <bitset>
17 #include <numeric>
18 #include <cmath>
19 #include <tr1/unordered_map>
20 #include <limits>
21
22 #include "common_tree.hpp"
23
24 #ifndef ELEMENT_TREE_HPP
25 #define ELEMENT_TREE_HPP
26 namespace moab
27 {
28
29
30 template < typename _Entity_handles, typename _Box, typename _Moab, typename _Parametrizer >
31 class Element_tree;
32
33
34 namespace
35 {
36 namespace _element_tree
37 {
38 template < typename Iterator >
39 struct Iterator_comparator
40 {
41 typedef typename Iterator::value_type Value;
42 bool operator()( const Value& a, const Value& b )
43 {
44 return a->second.second.to_ulong() < b->second.second.to_ulong();
45 }
46 };
47
48 template < typename Data >
49 struct Split_comparator
50 {
51
52 double split_objective( const Data& a ) const
53 {
54 if( a.second.sizes[2] == 0 || a.second.sizes[0] == 0 )
55 {
56 return std::numeric_limits< std::size_t >::max();
57 }
58 const double total = a.second.sizes[0] + a.second.sizes[2];
59 const int max = 2 * ( a.second.sizes[2] > a.second.sizes[0] );
60
61 return ( a.second.sizes[max] - a.second.sizes[2 * ( 1 - ( max == 2 ) )] ) / total;
62 }
63 bool operator()( const Data& a, const Data& b ) const
64 {
65 return split_objective( a ) < split_objective( b );
66 }
67 };
68
69 template < typename Partition_data, typename Box >
70 void correct_bounding_box( const Partition_data& data, Box& box, const int child )
71 {
72 const int dim = data.dim;
73 switch( child )
74 {
75 case 0:
76 box.max[dim] = data.left_rightline;
77 break;
78 case 1:
79 box.max[dim] = data.right_line;
80 box.min[dim] = data.left_line;
81 break;
82 case 2:
83 box.min[dim] = data.right_leftline;
84 break;
85 }
86 #ifdef ELEMENT_TREE_DEBUG
87 print_vector( data.bounding_box.max );
88 print_vector( data.bounding_box.min );
89 print_vector( box.max );
90 print_vector( box.min );
91 #endif
92 }
93
94 template < typename Box >
95 struct _Partition_data
96 {
97 typedef _Partition_data< Box > Self;
98
99 _Partition_data() : sizes( 3, 0 ), dim( 0 ) {}
100 _Partition_data( const Self& f )
101 {
102 *this = f;
103 }
104 _Partition_data( const Box& _box, int _dim )
105 : sizes( 3, 0 ), bounding_box( _box ), split( ( _box.max[_dim] + _box.min[_dim] ) / 2.0 ),
106 left_line( split ), right_line( split ), dim( _dim )
107 {
108 }
109 _Partition_data& operator=( const Self& f )
110 {
111 sizes = f.sizes;
112 bounding_box = f.bounding_box;
113 split = f.split;
114 left_line = f.left_line;
115 right_line = f.right_line;
116 right_leftline = f.right_leftline;
117 left_rightline = f.left_rightline;
118 dim = f.dim;
119 return *this;
120 }
121 std::vector< std::size_t > sizes;
122 Box bounding_box;
123 double split;
124 double left_line;
125 double right_line;
126 double right_leftline;
127 double left_rightline;
128 int dim;
129 std::size_t left() const
130 {
131 return sizes[0];
132 }
133 std::size_t middle() const
134 {
135 return sizes[1];
136 }
137 std::size_t right() const
138 {
139 return sizes[2];
140 }
141 };
142
143 template < typename _Entity_handles, typename _Entities >
144 class _Node
145 {
146
147 public:
148 typedef _Entity_handles Entity_handles;
149 typedef _Entities Entities;
150
151
152 private:
153 typedef _Node< _Entity_handles, _Entities > Self;
154
155
156 public:
157
158 _Node()
159 : children( 3, -1 ), left_( children[0] ), middle_( children[1] ), right_( children[2] ), dim( -1 ),
160 split( 0 ), left_line( 0 ), right_line( 0 ), entities( 0 )
161 {
162 }
163
164
165 _Node( const Self& from )
166 : children( from.children ), left_( children[0] ), middle_( children[1] ), right_( children[2] ),
167 dim( from.dim ), split( from.split ), left_line( from.left_line ), right_line( from.right_line ),
168 entities( from.entities )
169 {
170 }
171
172 public:
173 template < typename Iterator >
174 void assign_entities( const Iterator& begin, const Iterator& end )
175 {
176 entities.reserve( std::distance( begin, end ) );
177 for( Iterator i = begin; i != end; ++i )
178 {
179 entities.push_back( std::make_pair( ( *i )->second.first, ( *i )->first ) );
180 }
181 }
182
183
184 public:
185 bool leaf() const
186 {
187 return children[0] == -1 && children[1] == -1 && children[2] == -1;
188 }
189 Self& operator=( const Self& from )
190 {
191 children = from.children;
192 dim = from.dim;
193 left_ = from.left_;
194 middle_ = from.middle_;
195 right_ = from.right_;
196 split = from.split;
197 left_line = from.left_line;
198 right_line = from.right_line;
199 entities = from.entities;
200 return *this;
201 }
202 template < typename Box >
203 Self& operator=( const _Partition_data< Box >& from )
204 {
205 dim = from.dim;
206 split = from.split;
207 left_line = from.left_line;
208 right_line = from.right_line;
209 return *this;
210 }
211
212 private:
213
214 std::vector< int > children;
215 int &left_, middle_, right_;
216 int dim;
217 double split;
218 double left_line;
219 double right_line;
220 Entities entities;
221
222
223 template < Entity_handles, typename B >
224 friend class moab::Element_tree;
225 };
226
227 }
228 }
229
230 template < typename _Entity_handles, typename _Box, typename _Moab, typename _Parametrizer >
231 class Element_tree
232 {
233
234
235 public:
236 typedef _Entity_handles Entity_handles;
237 typedef _Box Box;
238 typedef _Moab Moab;
239 typedef _Parametrizer Parametrizer;
240 typedef typename Entity_handles::value_type Entity_handle;
241
242
243 private:
244 typedef Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer > Self;
245 typedef std::pair< Box, Entity_handle > Leaf_element;
246 typedef _element_tree::_Node< Entity_handles, std::vector< Leaf_element > > Node;
247
248 #define MAX_ITERATIONS 2
249 typedef common_tree::_Element_data< Box, std::bitset< NUM_DIM * MAX_ITERATIONS * 2 > > Element_data;
250 typedef std::vector< Node > Nodes;
251
252 typedef std::tr1::unordered_map< Entity_handle, Element_data > Element_map;
253 typedef typename std::vector< typename Element_map::iterator > Element_list;
254 typedef _element_tree::_Partition_data< Box > Partition_data;
255
256 public:
257
258 Element_tree( Entity_handles& _entities, Moab& _moab, Box& _bounding_box, Parametrizer& _entity_contains )
259 : entity_handles_( _entities ), tree_(), moab( _moab ), bounding_box( _bounding_box ),
260 entity_contains( _entity_contains )
261 {
262 tree_.reserve( _entities.size() );
263 Element_map element_map( _entities.size() );
264 Partition_data _data;
265 common_tree::construct_element_map( entity_handles_, element_map, _data.bounding_box, moab );
266 bounding_box = _data.bounding_box;
267 _bounding_box = bounding_box;
268 Element_list element_ordering( element_map.size() );
269 std::size_t index = 0;
270 for( typename Element_map::iterator i = element_map.begin(); i != element_map.end(); ++i, ++index )
271 {
272 element_ordering[index] = i;
273 }
274
275 if( element_ordering.size() )
276 {
277
278 std::bitset< 3 > directions( 7 );
279 tree_.push_back( Node() );
280 int depth = 0;
281 build_tree( element_ordering.begin(), element_ordering.end(), 0, directions, _data, depth );
282 std::cout << "depth: " << depth << std::endl;
283 }
284 }
285
286
287 Element_tree( Self& s )
288 : entity_handles_( s.entity_handles_ ), tree_( s.tree_ ), moab( s.moab ), bounding_box( s.bounding_box )
289 {
290 }
291
292
293 private:
294 template < typename Iterator, typename Split_data >
295 void compute_split( Iterator& begin, Iterator& end, Split_data& split_data, bool iteration = false )
296 {
297 typedef typename Iterator::value_type::value_type Map_value_type;
298 typedef typename Map_value_type::second_type::second_type Bitset;
299
300 double& left_line = split_data.left_line;
301 double& right_line = split_data.right_line;
302 double& split = split_data.split;
303 const int& dim = split_data.dim;
304 #ifdef ELEMENT_TREE_DEBUG
305 std::cout << std::endl;
306 std::cout << "-------------------" << std::endl;
307 std::cout << "dim: " << dim << " split: " << split << std::endl;
308 std::cout << "bounding_box min: ";
309 print_vector( split_data.bounding_box.min );
310 std::cout << "bounding_box max: ";
311 print_vector( split_data.bounding_box.max );
312 #endif
313
314 for( Iterator i = begin; i != end; ++i )
315 {
316 const Box& box = ( *i )->second.first;
317 Bitset& bits = ( *i )->second.second;
318
319
320 const bool on_left = ( box.max[dim] < split );
321 const bool on_right = ( box.min[dim] > split );
322 const bool in_middle = !on_left && !on_right;
323
324
325
326 const int index = 4 * dim + 2 * iteration;
327 if( on_left )
328 {
329 split_data.sizes[0]++;
330 }
331 else if( in_middle )
332 {
333 split_data.sizes[1]++;
334 bits.set( index, 1 );
335 left_line = std::min( left_line, box.min[dim] );
336 right_line = std::max( right_line, box.max[dim] );
337 }
338 else if( on_right )
339 {
340 bits.set( index + 1, 1 );
341 split_data.sizes[2]++;
342 }
343 }
344 #ifdef ELEMENT_TREE_DEBUG
345 std::size_t _count = std::accumulate( split_data.sizes.begin(), split_data.sizes.end(), 0 );
346 std::size_t total = std::distance( begin, end );
347 if( total != _count )
348 {
349 std::cout << total << "vs. " << _count << std::endl;
350 }
351 std::cout << " left_line: " << left_line;
352 std::cout << " right_line: " << right_line << std::endl;
353 std::cout << "co/mputed partition size: ";
354 print_vector( split_data.sizes );
355 std::cout << "-------------------" << std::endl;
356 #endif
357 }
358
359 template < typename Split_data >
360 bool update_split_line( Split_data& data ) const
361 {
362 const int max = 2 * ( data.sizes[2] > data.sizes[0] );
363 const int min = 2 * ( 1 - ( max == 2 ) );
364 bool one_side_empty = data.sizes[max] == 0 || data.sizes[min] == 0;
365 double balance_ratio = data.sizes[max] - data.sizes[min];
366
367 if( !one_side_empty )
368 {
369
370
371 balance_ratio /= data.sizes[max];
372 data.split += ( max - 1 ) * balance_ratio * ( data.split / 2.0 );
373 }
374 else
375 {
376
377
378
379
380 const double left_distance = std::abs( data.left_line - data.split );
381 const double right_distance = std::abs( data.right_line - data.split );
382 if( ( data.sizes[0] == 0 ) && ( data.sizes[2] != 0 ) )
383 {
384 data.split += right_distance;
385 }
386 else if( data.sizes[2] == 0 && data.sizes[0] != 0 )
387 {
388 data.split -= left_distance;
389 }
390 else
391 {
392 data.split *= 1.05;
393 }
394 }
395 data.left_line = data.right_line = data.split;
396 data.sizes.assign( data.sizes.size(), 0 );
397 return true;
398 }
399
400 template < typename Iterator, typename Split_data, typename Directions >
401 void determine_split( Iterator& begin, Iterator& end, Split_data& data, const Directions& directions )
402 {
403 typedef typename Iterator::value_type Pair;
404 typedef typename Pair::value_type Map_value_type;
405 typedef typename Map_value_type::second_type::second_type Bitset;
406 typedef typename Map_value_type::second_type::first_type Box;
407 typedef typename std::map< std::size_t, Split_data > Splits;
408 typedef typename Splits::value_type Split;
409 typedef _element_tree::Split_comparator< Split > Comparator;
410 Splits splits;
411 for( std::size_t dir = 0; dir < directions.size(); ++dir )
412 {
413 if( directions.test( dir ) )
414 {
415 Split_data split_data( data.bounding_box, dir );
416 compute_split( begin, end, split_data );
417 splits.insert( std::make_pair( 2 * dir, split_data ) );
418 if( update_split_line( split_data ) )
419 {
420 compute_split( begin, end, split_data, true );
421 splits.insert( std::make_pair( 2 * dir + 1, split_data ) );
422 }
423 }
424 }
425 Split best = *std::min_element( splits.begin(), splits.end(), Comparator() );
426 #ifdef ELEMENT_TREE_DEBUG
427 std::cout << "best: " << Comparator().split_objective( best ) << " ";
428 print_vector( best.second.sizes );
429 #endif
430 const int dir = best.first / 2;
431 const int iter = best.first % 2;
432 double& left_rightline = best.second.left_rightline = best.second.bounding_box.min[dir];
433 double& right_leftline = best.second.right_leftline = best.second.bounding_box.max[dir];
434 Bitset mask( 0 );
435 mask.flip( 4 * dir + 2 * iter ).flip( 4 * dir + 2 * iter + 1 );
436 for( Iterator i = begin; i != end; ++i )
437 {
438 Bitset& bits = ( *i )->second.second;
439 const Box& box = ( *i )->second.first;
440
441 bits &= mask;
442 bits >>= 4 * dir + 2 * iter;
443
444
445
446 switch( bits.to_ulong() )
447 {
448 case 0:
449 if( box.max[dir] > best.second.left_line )
450 {
451 left_rightline = std::max( left_rightline, box.max[dir] );
452 }
453 break;
454 case 2:
455 if( box.min[dir] < best.second.right_line )
456 {
457 right_leftline = std::min( right_leftline, box.max[dir] );
458 }
459 break;
460 }
461 }
462 data = best.second;
463 }
464
465
466 #define ELEMENTS_PER_LEAF 30
467 #define MAX_DEPTH 30
468 #define EPSILON 1e-1
469 template < typename Iterator, typename Node_index, typename Directions, typename Partition_data >
470 void build_tree( Iterator begin,
471 Iterator end,
472 const Node_index node,
473 const Directions& directions,
474 Partition_data& _data,
475 int& depth,
476 const bool is_middle = false )
477 {
478 std::size_t number_elements = std::distance( begin, end );
479 if( depth < MAX_DEPTH && number_elements > ELEMENTS_PER_LEAF && ( !is_middle || directions.any() ) )
480 {
481 determine_split( begin, end, _data, directions );
482
483 std::sort( begin, end, _element_tree::Iterator_comparator< Iterator >() );
484
485 tree_[node] = _data;
486 Iterator middle_begin( begin + _data.left() );
487 Iterator middle_end( middle_begin + _data.middle() );
488 std::vector< int > depths( 3, depth );
489
490 if( _data.left() > 0 )
491 {
492 Partition_data data( _data );
493 tree_.push_back( Node() );
494 tree_[node].children[0] = tree_.size() - 1;
495 correct_bounding_box( _data, data.bounding_box, 0 );
496 Directions new_directions( directions );
497 const bool axis_is_very_small =
498 ( data.bounding_box.max[_data.dim] - data.bounding_box.min[_data.dim] < EPSILON );
499 new_directions.set( _data.dim, axis_is_very_small );
500 build_tree( begin, middle_begin, tree_[node].children[0], new_directions, data, ++depths[0],
501 is_middle );
502 }
503
504 if( _data.middle() > 0 )
505 {
506 Partition_data data( _data );
507 tree_.push_back( Node() );
508 tree_[node].children[1] = tree_.size() - 1;
509 correct_bounding_box( _data, data.bounding_box, 1 );
510
511
512 Directions new_directions( directions );
513 new_directions.flip( tree_[node].dim );
514 bool axis_is_very_small =
515 ( data.bounding_box.max[_data.dim] - data.bounding_box.min[_data.dim] < EPSILON );
516 new_directions.set( _data.dim, axis_is_very_small );
517 build_tree( middle_begin, middle_end, tree_[node].children[1], new_directions, data, ++depths[1],
518 true );
519 }
520
521 if( _data.right() > 0 )
522 {
523 Partition_data data( _data );
524 tree_.push_back( Node() );
525 tree_[node].children[2] = tree_.size() - 1;
526 correct_bounding_box( _data, data.bounding_box, 2 );
527 Directions new_directions( directions );
528 const bool axis_is_very_small =
529 ( data.bounding_box.max[_data.dim] - data.bounding_box.min[_data.dim] < EPSILON );
530 new_directions.set( _data.dim, axis_is_very_small );
531
532 build_tree( middle_end, end, tree_[node].children[2], directions, data, ++depths[2], is_middle );
533 }
534 depth = *std::max_element( depths.begin(), depths.end() );
535 }
536 if( tree_[node].leaf() )
537 {
538 common_tree::assign_entities( tree_[node].entities, begin, end );
539 }
540 }
541
542 template < typename Vector, typename Node_index, typename Result >
543 Result& _find_point( const Vector& point, const Node_index& index, Result& result ) const
544 {
545 typedef typename Node::Entities::const_iterator Entity_iterator;
546 typedef typename std::pair< bool, Vector > Return_type;
547 const Node& node = tree_[index];
548 if( node.leaf() )
549 {
550
551 for( Entity_iterator i = node.entities.begin(); i != node.entities.end(); ++i )
552 {
553 if( common_tree::box_contains_point( i->first, point ) )
554 {
555 Return_type r = entity_contains( moab, i->second, point );
556 if( r.first )
557 {
558 result = std::make_pair( i->second, r.second );
559 }
560 return result;
561 }
562 }
563 return Result( 0, point );
564 }
565 if( point[node.dim] < node.left_line )
566 {
567 return _find_point( point, node.left_, result );
568 }
569 else if( point[node.dim] > node.right_line )
570 {
571 return _find_point( point, node.right_, result );
572 }
573 else
574 {
575 Entity_handle middle = _find_point( point, node.middle_, result );
576 if( middle != 0 )
577 {
578 return result;
579 }
580 if( point[node.dim] < node.split )
581 {
582 return _find_point( point, node.left_, result );
583 }
584 return _find_point( point, node.right_, result );
585 }
586 }
587
588
589 public:
590 template < typename Vector, typename Result >
591 Result& find( const Vector& point, Result& result ) const
592 {
593 typedef typename Vector::const_iterator Point_iterator;
594 typedef typename Box::Pair Pair;
595 typedef typename Pair::first_type Box_iterator;
596 return _find_point( point, 0, result );
597 }
598
599
600 public:
601
602 private:
603 const Entity_handles& entity_handles_;
604 Nodes tree_;
605 Moab& moab;
606 Box bounding_box;
607 Parametrizer entity_contains;
608
609 };
610
611 }
612
613 #endif