19 #include <tr1/unordered_map>
24 #ifndef ELEMENT_TREE_HPP
25 #define ELEMENT_TREE_HPP
30 template <
typename _Entity_handles,
typename _Box,
typename _Moab,
typename _Parametrizer >
36 namespace _element_tree
38 template <
typename Iterator >
39 struct Iterator_comparator
41 typedef typename Iterator::value_type Value;
42 bool operator()(
const Value& a,
const Value& b )
44 return a->second.second.to_ulong() < b->second.second.to_ulong();
48 template <
typename Data >
49 struct Split_comparator
52 double split_objective(
const Data& a )
const
54 if( a.second.sizes[2] == 0 || a.second.sizes[0] == 0 )
56 return std::numeric_limits< std::size_t >::max();
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] );
61 return ( a.second.sizes[max] - a.second.sizes[2 * ( 1 - ( max == 2 ) )] ) / total;
63 bool operator()(
const Data& a,
const Data& b )
const
65 return split_objective( a ) < split_objective( b );
69 template <
typename Partition_data,
typename Box >
70 void correct_bounding_box(
const Partition_data& data, Box& box,
const int child )
72 const int dim = data.dim;
76 box.max[
dim] = data.left_rightline;
79 box.max[
dim] = data.right_line;
80 box.min[
dim] = data.left_line;
83 box.min[
dim] = data.right_leftline;
86 #ifdef ELEMENT_TREE_DEBUG
94 template <
typename Box >
95 struct _Partition_data
97 typedef _Partition_data< Box > Self;
99 _Partition_data() :
sizes( 3, 0 ),
dim( 0 ) {}
100 _Partition_data(
const Self& f )
104 _Partition_data(
const Box& _box,
int _dim )
109 _Partition_data& operator=(
const Self& f )
129 std::size_t left()
const
133 std::size_t middle()
const
137 std::size_t right()
const
143 template <
typename _Entity_handles,
typename _Entities >
148 typedef _Entity_handles Entity_handles;
149 typedef _Entities Entities;
153 typedef _Node< _Entity_handles, _Entities > Self;
165 _Node(
const Self& from )
173 template <
typename Iterator >
176 entities.reserve( std::distance( begin, end ) );
177 for( Iterator i = begin; i != end; ++i )
179 entities.push_back( std::make_pair( ( *i )->second.first, ( *i )->first ) );
189 Self& operator=(
const Self& from )
202 template <
typename Box >
203 Self& operator=(
const _Partition_data< Box >& from )
223 template < Entity_handles,
typename B >
230 template <
typename _Entity_handles,
typename _Box,
typename _Moab,
typename _Parametrizer >
246 typedef _element_tree::_Node< Entity_handles, std::vector< Leaf_element > >
Node;
248 #define MAX_ITERATIONS 2
252 typedef std::tr1::unordered_map< Entity_handle, Element_data >
Element_map;
253 typedef typename std::vector< typename Element_map::iterator >
Element_list;
262 tree_.reserve( _entities.size() );
269 std::size_t index = 0;
270 for(
typename Element_map::iterator i = element_map.begin(); i != element_map.end(); ++i, ++index )
272 element_ordering[index] = i;
275 if( element_ordering.size() )
278 std::bitset< 3 > directions( 7 );
281 build_tree( element_ordering.begin(), element_ordering.end(), 0, directions, _data, depth );
282 std::cout <<
"depth: " << depth << std::endl;
294 template <
typename Iterator,
typename Split_data >
295 void compute_split( Iterator& begin, Iterator& end, Split_data& split_data,
bool iteration =
false )
297 typedef typename Iterator::value_type::value_type Map_value_type;
298 typedef typename Map_value_type::second_type::second_type Bitset;
300 double&
left_line = split_data.left_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: ";
310 std::cout <<
"bounding_box max: ";
314 for( Iterator i = begin; i != end; ++i )
316 const Box& box = ( *i )->second.first;
317 Bitset& bits = ( *i )->second.second;
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;
326 const int index = 4 *
dim + 2 * iteration;
329 split_data.sizes[0]++;
333 split_data.sizes[1]++;
334 bits.set( index, 1 );
340 bits.set( index + 1, 1 );
341 split_data.sizes[2]++;
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 )
349 std::cout << total <<
"vs. " << _count << std::endl;
351 std::cout <<
" left_line: " <<
left_line;
352 std::cout <<
" right_line: " <<
right_line << std::endl;
353 std::cout <<
"co/mputed partition size: ";
355 std::cout <<
"-------------------" << std::endl;
359 template <
typename Split_data >
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];
367 if( !one_side_empty )
371 balance_ratio /= data.sizes[max];
372 data.split += ( max - 1 ) * balance_ratio * ( data.split / 2.0 );
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 ) )
384 data.split += right_distance;
386 else if( data.sizes[2] == 0 && data.sizes[0] != 0 )
388 data.split -= left_distance;
395 data.left_line = data.right_line = data.split;
396 data.sizes.assign( data.sizes.size(), 0 );
400 template <
typename Iterator,
typename Split_data,
typename Directions >
401 void determine_split( Iterator& begin, Iterator& end, Split_data& data,
const Directions& directions )
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;
411 for( std::size_t dir = 0; dir < directions.size(); ++dir )
413 if( directions.test( dir ) )
415 Split_data split_data( data.bounding_box, dir );
417 splits.insert( std::make_pair( 2 * dir, split_data ) );
421 splits.insert( std::make_pair( 2 * dir + 1, split_data ) );
425 Split best = *std::min_element( splits.begin(), splits.end(), Comparator() );
426 #ifdef ELEMENT_TREE_DEBUG
427 std::cout <<
"best: " << Comparator().split_objective( best ) <<
" ";
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];
435 mask.flip( 4 * dir + 2 * iter ).flip( 4 * dir + 2 * iter + 1 );
436 for( Iterator i = begin; i != end; ++i )
438 Bitset& bits = ( *i )->second.second;
439 const Box& box = ( *i )->second.first;
442 bits >>= 4 * dir + 2 * iter;
446 switch( bits.to_ulong() )
449 if( box.max[dir] > best.second.left_line )
455 if( box.min[dir] < best.second.right_line )
466 #define ELEMENTS_PER_LEAF 30
469 template <
typename Iterator,
typename Node_index,
typename Directions,
typename Partition_data >
472 const Node_index node,
473 const Directions& directions,
476 const bool is_middle =
false )
478 std::size_t number_elements = std::distance( begin, end );
479 if( depth < MAX_DEPTH && number_elements >
ELEMENTS_PER_LEAF && ( !is_middle || directions.any() ) )
483 std::sort( begin, end, _element_tree::Iterator_comparator< Iterator >() );
486 Iterator middle_begin( begin + _data.left() );
487 Iterator middle_end( middle_begin + _data.middle() );
488 std::vector< int > depths( 3, depth );
490 if( _data.left() > 0 )
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 );
504 if( _data.middle() > 0 )
509 correct_bounding_box( _data, data.bounding_box, 1 );
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 );
521 if( _data.right() > 0 )
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 );
534 depth = *std::max_element( depths.begin(), depths.end() );
536 if(
tree_[node].leaf() )
542 template <
typename Vector,
typename Node_index,
typename Result >
543 Result&
_find_point(
const Vector& point,
const Node_index& index, Result& result )
const
545 typedef typename Node::Entities::const_iterator Entity_iterator;
546 typedef typename std::pair< bool, Vector > Return_type;
551 for( Entity_iterator i = node.entities.begin(); i != node.entities.end(); ++i )
558 result = std::make_pair( i->second, r.second );
563 return Result( 0, point );
565 if( point[node.dim] < node.left_line )
569 else if( point[node.dim] > node.right_line )
580 if( point[node.dim] < node.split )
590 template <
typename Vector,
typename Result >
591 Result&
find(
const Vector& point, Result& result )
const
593 typedef typename Vector::const_iterator Point_iterator;
594 typedef typename Box::Pair Pair;
595 typedef typename Pair::first_type Box_iterator;