|
cgma
|
#include <OctTree.hpp>
Public Member Functions | |
| OctTree (DLIList< X * > &nodes, double tolerance, int min_nodes_per_box=-1, double min_box_dimension=-1.0) | |
| ~OctTree () | |
| void | nodes_near (const CubitVector &position, DLIList< X * > &result_list) |
| void | tree_size (DLIList< int > &count_at_each_level, DLIList< int > &leaves_at_each_level) |
Private Member Functions | |
| void | split_node (OctTreeCell< X, E > *node, const CubitVector &min, const CubitVector &max) |
| OctTreeCell< X, E > * | allocate_8 () |
| void | push_search_box (int quadrant_flags) |
| void | pop_to_current () |
| void | tree_size (OctTreeCell< X, E > *box, DLIList< int > &boxes, DLIList< int > &leaves) |
Private Attributes | |
| double | tolerance_ |
| double | min_box_size_ |
| int | min_nodes_ |
| OctTreeCell< X, E > * | root_ |
| CubitVector | min_ |
| CubitVector | max_ |
| OctTreeEntry< X, E > * | node_memory_ |
| DLIList< OctTreeCell< X, E > * > | mem_pages_ |
| OctTreeCell< X, E > * | curr_page_end_ |
| OctTreeCell< X, E > * | box_list [64] |
| CubitVector | box_min [64] |
| CubitVector | box_max [64] |
| int | box_count |
| DLIList< X * > | search_results |
| CubitVector | current_min |
| CubitVector | current_max |
| CubitVector | center |
| OctTreeCell< X, E > * | current_box |
Definition at line 29 of file OctTree.hpp.
| OctTree< X, E >::OctTree | ( | DLIList< X * > & | nodes, |
| double | tolerance, | ||
| int | min_nodes_per_box = -1, |
||
| double | min_box_dimension = -1.0 |
||
| ) |
Definition at line 54 of file OctTree.cpp.
{
// Check and store constructor arguments
tolerance_ = tolerance < GEOMETRY_RESABS ? GEOMETRY_RESABS : tolerance;
min_nodes_ = min_nodes_per_box < 0 ? DEFAULT_MIN_NODES_PER_BOX : min_nodes_per_box;
double tol3 = 3 * tolerance_;
min_box_size_ = min_box_dimension < tol3 ? tol3 : min_box_dimension;
// Note: min_box_size must be greater than twice the tolerance
// or the internal stack used for searching the tree will
// overflow (more than 8 boxes may be within the tolerance
// of a passed position).
// set up data for memory pool of oct-tree nodes
mem_pages_.append( new OctTreeCell<X,E>[OCT_TREE_ALLOC_COUNT] );
curr_page_end_ = mem_pages_.get() + OCT_TREE_ALLOC_COUNT;
// construct root node
node_memory_ = new OctTreeEntry<X,E>[nodes.size()];
nodes.reset();
OctTreeEntry<X,E>* ptr = node_memory_;
for( int i = nodes.size(); i--; )
{
ptr->node = nodes.get_and_step();
ptr->next = 0;
ptr++;
}
root_ = new OctTreeCell<X,E>( node_memory_, nodes.size() );
// get bounding box of all nodes
CubitVector junk;
root_->node_locations( min_, max_, junk );
// create the oct-tree
split_node(root_, min_, max_ );
}
Definition at line 103 of file OctTree.cpp.
{
// Release all memory
// Note that the oct-tree is not deleted except for the root node.
// Only the root node was allocated directly from the heap. All
// other nodes were allocated from our internal memory bool by
// the allocate_8() method. We just release the whole pool.
delete root_;
delete [] node_memory_;
while( mem_pages_.size() )
delete [] mem_pages_.pop();
// Reinitialize to catch stale pointer to this object.
node_memory_ = 0;
root_ = 0;
}
| OctTreeCell< X, E > * OctTree< X, E >::allocate_8 | ( | ) | [private] |
Definition at line 354 of file OctTree.cpp.
{
// Want to pop from end of page
curr_page_end_ -= 8;
// Any blocks available in current page?
mem_pages_.last();
if( curr_page_end_ < mem_pages_.get() )
{
// Allocate new page
mem_pages_.append( new OctTreeCell<X,E>[OCT_TREE_ALLOC_COUNT] );
// Pop last block from new page
mem_pages_.last();
curr_page_end_ = mem_pages_.get() + OCT_TREE_ALLOC_COUNT - 8;
}
return curr_page_end_;
}
| void OctTree< X, E >::nodes_near | ( | const CubitVector & | position, |
| DLIList< X * > & | result_list | ||
| ) |
Definition at line 131 of file OctTree.cpp.
{
if( position.x() - min_.x() < -tolerance_ ||
position.y() - min_.y() < -tolerance_ ||
position.z() - min_.z() < -tolerance_ ||
position.x() - max_.x() > tolerance_ ||
position.y() - max_.y() > tolerance_ ||
position.z() - max_.z() > tolerance_ )
return;
// Initialize search stack
if( root_->leaf() )
{
// Done searching already -- that was easy
root_->append_nodes( search_results );
box_count = 0;
}
else
{
search_results.clean_out();
// Start with root node on stack of nodes to search
box_count = 1;
box_list[0] = root_;
box_min[0] = min_;
box_max[0] = max_;
}
// While there are still boxes on the search stack
while( box_count )
{
// Pop the 'current' box from the stack
pop_to_current();
// Push appropriate child box(es) to stack
CubitVector diff = position - center;
if( diff.x() <= tolerance_ )
{
if( diff.y() <= tolerance_ )
{
if( diff.z() <= tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MIN |
OctTreeCell<X,E>::Y_MIN |
OctTreeCell<X,E>::Z_MIN );
}
if( diff.z() >= -tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MIN |
OctTreeCell<X,E>::Y_MIN |
OctTreeCell<X,E>::Z_MAX );
}
}
if( diff.y() >= -tolerance_ )
{
if( diff.z() <= tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MIN |
OctTreeCell<X,E>::Y_MAX |
OctTreeCell<X,E>::Z_MIN );
}
if( diff.z() >= -tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MIN |
OctTreeCell<X,E>::Y_MAX |
OctTreeCell<X,E>::Z_MAX );
}
}
}
if( diff.x() >= -tolerance_ )
{
if( diff.y() <= tolerance_ )
{
if( diff.z() <= tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MAX |
OctTreeCell<X,E>::Y_MIN |
OctTreeCell<X,E>::Z_MIN );
}
if( diff.z() >= -tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MAX |
OctTreeCell<X,E>::Y_MIN |
OctTreeCell<X,E>::Z_MAX );
}
}
if( diff.y() >= -tolerance_ )
{
if( diff.z() <= tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MAX |
OctTreeCell<X,E>::Y_MAX |
OctTreeCell<X,E>::Z_MIN );
}
if( diff.z() >= -tolerance_ )
{
push_search_box( OctTreeCell<X,E>::X_MAX |
OctTreeCell<X,E>::Y_MAX |
OctTreeCell<X,E>::Z_MAX );
}
}
}
}
// append to result list all nodes within tolerance
// of passed position
search_results.reset();
const double tol_sqr = tolerance_ * tolerance_;
for( int i = search_results.size(); i--; )
{
X* node = search_results.get_and_step();
CubitVector coords = E::coordinates(node);
double x = position.x() - coords.x();
double y = position.y() - coords.y();
double z = position.z() - coords.z();
double dist_sqr = x * x + y * y + z * z;
if( dist_sqr <= tol_sqr )
result_list.append( node );
}
}
| void OctTree< X, E >::pop_to_current | ( | ) | [private] |
Definition at line 333 of file OctTree.cpp.
{
assert( box_count );
box_count--;
current_min = box_min[box_count];
current_max = box_max[box_count];
current_box = box_list[box_count];
center = (current_min + current_max) * 0.5;
}
| void OctTree< X, E >::push_search_box | ( | int | quadrant_flags | ) | [private] |
Definition at line 266 of file OctTree.cpp.
{
OctTreeCell<X,E>* box = current_box->child( quadrant_flags );
if( box->leaf() )
{
// If a leaf node, get its nodes
box->append_nodes( search_results );
}
else
{
assert( box_count < 64 );
// Get appropriate min and max corners of child box
CubitVector& oldmin = current_min;
CubitVector& oldmax = current_max;
CubitVector& newmin = box_min[box_count];
CubitVector& newmax = box_max[box_count];
if( quadrant_flags & OctTreeCell<X,E>::X_MAX )
{
newmin.x( center.x() );
newmax.x( oldmax.x() );
}
else
{
newmin.x( oldmin.x() );
newmax.x( center.x() );
}
if( quadrant_flags & OctTreeCell<X,E>::Y_MAX )
{
newmin.y( center.y() );
newmax.y( oldmax.y() );
}
else
{
newmin.y( oldmin.y() );
newmax.y( center.y() );
}
if( quadrant_flags & OctTreeCell<X,E>::Z_MAX )
{
newmin.z( center.z() );
newmax.z( oldmax.z() );
}
else
{
newmin.z( oldmin.z() );
newmax.z( center.z() );
}
// Put the box on the stack
box_list[box_count++] = box;
}
}
| void OctTree< X, E >::split_node | ( | OctTreeCell< X, E > * | node, |
| const CubitVector & | min, | ||
| const CubitVector & | max | ||
| ) | [private] |
Definition at line 391 of file OctTree.cpp.
{
assert( box->leaf() );
CubitVector diag = max - min;
diag *= 0.5; // diagonal size of child boxes
if( (box->node_count() <= min_nodes_) || // must have more than min_nodes_
(diag.x() < min_box_size_ && // child boxes will be smaller
diag.y() < min_box_size_ && // than min_box_size_ in all
diag.z() < min_box_size_ ) ) // three dimensions.
return;
// Check if all nodes are currently within 2*tolerance_
// of each other.
double tol2 = 2 * tolerance_;
CubitVector node_min, node_max, junk;
box->node_locations( node_min, node_max, junk );
diag = node_max - node_min;
if( diag.x() < tol2 &&
diag.y() < tol2 &&
diag.z() < tol2 )
return;
// Split the box
CubitVector mid = (min + max) * 0.5;
if( !box->split( mid, allocate_8() ) )
return;
// Recursively call split_node on all 8 new child boxes
split_node(
box->child(OctTreeCell<X,E>::X_MIN|OctTreeCell<X,E>::Y_MIN|OctTreeCell<X,E>::Z_MIN),
CubitVector( min.x(), min.y(), min.z() ),
CubitVector( mid.x(), mid.y(), mid.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MIN|OctTreeCell<X,E>::Y_MIN|OctTreeCell<X,E>::Z_MAX),
CubitVector( min.x(), min.y(), mid.z() ),
CubitVector( mid.x(), mid.y(), max.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MIN|OctTreeCell<X,E>::Y_MAX|OctTreeCell<X,E>::Z_MIN),
CubitVector( min.x(), mid.y(), min.z() ),
CubitVector( mid.x(), max.y(), mid.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MIN|OctTreeCell<X,E>::Y_MAX|OctTreeCell<X,E>::Z_MAX),
CubitVector( min.x(), mid.y(), mid.z() ),
CubitVector( mid.x(), max.y(), max.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MAX|OctTreeCell<X,E>::Y_MIN|OctTreeCell<X,E>::Z_MIN),
CubitVector( mid.x(), min.y(), min.z() ),
CubitVector( max.x(), mid.y(), mid.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MAX|OctTreeCell<X,E>::Y_MIN|OctTreeCell<X,E>::Z_MAX),
CubitVector( mid.x(), min.y(), mid.z() ),
CubitVector( max.x(), mid.y(), max.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MAX|OctTreeCell<X,E>::Y_MAX|OctTreeCell<X,E>::Z_MIN),
CubitVector( mid.x(), mid.y(), min.z() ),
CubitVector( max.x(), max.y(), mid.z() ) );
split_node(
box->child(OctTreeCell<X,E>::X_MAX|OctTreeCell<X,E>::Y_MAX|OctTreeCell<X,E>::Z_MAX),
CubitVector( mid.x(), mid.y(), mid.z() ),
CubitVector( max.x(), max.y(), max.z() ) );
}
| void OctTree< X, E >::tree_size | ( | DLIList< int > & | count_at_each_level, |
| DLIList< int > & | leaves_at_each_level | ||
| ) |
Definition at line 457 of file OctTree.cpp.
| void OctTree< X, E >::tree_size | ( | OctTreeCell< X, E > * | box, |
| DLIList< int > & | boxes, | ||
| DLIList< int > & | leaves | ||
| ) | [private] |
Definition at line 469 of file OctTree.cpp.
{
if( boxes.is_at_end() )
{
boxes.append(1);
boxes.step();
}
else
{
boxes.step();
boxes.change_to( boxes.get() + 1 );
}
if( box->leaf() )
{
if( leaves.is_at_end() )
{
leaves.append(1);
leaves.step();
}
else
{
leaves.step();
leaves.change_to( leaves.get() + 1 );
}
}
else
{
if( leaves.is_at_end() )
leaves.append(0);
leaves.step();
for( int i = 0; i < 8; i++ )
tree_size( box->child(i), boxes, leaves );
}
boxes.back();
leaves.back();
}
Definition at line 106 of file OctTree.hpp.
OctTreeCell<X,E>* OctTree< X, E >::box_list[64] [private] |
Definition at line 103 of file OctTree.hpp.
CubitVector OctTree< X, E >::box_max[64] [private] |
Definition at line 105 of file OctTree.hpp.
CubitVector OctTree< X, E >::box_min[64] [private] |
Definition at line 104 of file OctTree.hpp.
CubitVector OctTree< X, E >::center [private] |
Definition at line 112 of file OctTree.hpp.
OctTreeCell<X,E>* OctTree< X, E >::curr_page_end_ [private] |
Definition at line 90 of file OctTree.hpp.
OctTreeCell<X,E>* OctTree< X, E >::current_box [private] |
Definition at line 113 of file OctTree.hpp.
CubitVector OctTree< X, E >::current_max [private] |
Definition at line 111 of file OctTree.hpp.
CubitVector OctTree< X, E >::current_min [private] |
Definition at line 110 of file OctTree.hpp.
CubitVector OctTree< X, E >::max_ [private] |
Definition at line 70 of file OctTree.hpp.
DLIList<OctTreeCell<X,E>*> OctTree< X, E >::mem_pages_ [private] |
Definition at line 89 of file OctTree.hpp.
CubitVector OctTree< X, E >::min_ [private] |
Definition at line 69 of file OctTree.hpp.
double OctTree< X, E >::min_box_size_ [private] |
Definition at line 62 of file OctTree.hpp.
int OctTree< X, E >::min_nodes_ [private] |
Definition at line 63 of file OctTree.hpp.
OctTreeEntry<X,E>* OctTree< X, E >::node_memory_ [private] |
Definition at line 73 of file OctTree.hpp.
OctTreeCell<X,E>* OctTree< X, E >::root_ [private] |
Definition at line 66 of file OctTree.hpp.
DLIList<X*> OctTree< X, E >::search_results [private] |
Definition at line 107 of file OctTree.hpp.
double OctTree< X, E >::tolerance_ [private] |
Definition at line 61 of file OctTree.hpp.