33 #ifndef __H__UG__ntree_impl__
34 #define __H__UG__ntree_impl__
41 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
44 m_warningsEnabled (true)
50 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
60 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
66 m_numDelayedElements = 0;
70 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
77 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
84 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
88 m_commonData = commonData;
91 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
98 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
106 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
110 return m_entries.size() - m_numDelayedElements;
114 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
118 return m_numDelayedElements;
122 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
127 m_entries.push_back(
Entry(elem));
129 ++m_numDelayedElements;
159 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
166 Node& root = m_nodes.back();
167 if(!m_entries.empty()){
171 for(
size_t i = 0; i < m_entries.size(); ++i)
172 m_entries[i].nextEntryInd = i+1;
173 m_entries.back().nextEntryInd = s_invalidIndex;
177 update_loose_bounding_box(root);
186 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
191 if(m_nodes[nodeIndex].numEntries <= 1)
194 if(m_nodes[nodeIndex].level >= m_desc.maxDepth){
195 if(m_warningsEnabled){
196 UG_LOG(
"WARNING in ntree::split_leaf_node(): maximum tree depth "
197 << m_desc.maxDepth <<
" reached. No further splits are performed for "
198 " this node. Note that too many elements per node may lead to performance issues.\n"
199 <<
" Number of elements in this node: " << m_nodes[nodeIndex].numEntries << std::endl
200 <<
" Corner coordinates of this node: " << m_nodes[nodeIndex].tightBox << std::endl);
205 if(m_nodes[nodeIndex].childNodeInd[0] != s_invalidIndex)
208 const size_t firstChild = m_nodes.size();
209 m_nodes.resize(firstChild + s_numChildren);
212 Node& node = m_nodes[nodeIndex];
217 vector_t centerOfMass = calculate_center_of_mass(node);
218 box_t childBoxes[s_numChildren];
219 traits::split_box(childBoxes, node.tightBox, centerOfMass);
222 size_t numEntriesAssigned = 0;
223 for(
size_t entryInd = node.firstEntryInd; entryInd != s_invalidIndex;){
224 Entry& entry = m_entries[entryInd];
225 size_t nextEntryInd = entry.nextEntryInd;
229 traits::calculate_center(center, entry.elem, m_commonData);
230 for(i_child = 0; i_child < s_numChildren; ++i_child){
231 if(traits::box_contains_point(childBoxes[i_child], center)){
232 add_entry_to_node(m_nodes[firstChild + i_child], entryInd);
233 ++numEntriesAssigned;
244 entryInd = nextEntryInd;
249 UG_COND_THROW(numEntriesAssigned != node.numEntries,
"Couldn't find a matching "
250 "child node for some elements during split_leaf_node in "
251 "ntree::split_leaf_node");
253 node.firstEntryInd = node.lastEntryInd = s_invalidIndex;
256 for(
size_t i_child = 0; i_child < s_numChildren; ++i_child){
257 node.childNodeInd[i_child] = firstChild + i_child;
258 Node& childNode = m_nodes[firstChild + i_child];
259 childNode.level = node.level + 1;
260 childNode.tightBox = childBoxes[i_child];
261 update_loose_bounding_box(childNode);
266 for(
size_t i_child = 0; i_child < s_numChildren; ++i_child){
267 size_t childNodeInd = firstChild + i_child;
268 if(m_nodes[childNodeInd].numEntries >= m_desc.splitThreshold)
269 split_leaf_node(childNodeInd);
274 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
278 Node& n = m_nodes[curNode];
279 if(traits::box_contains_point(n.
tightBox, point)){
281 for(
size_t i = 0; i < s_numChildren; ++i){
282 size_t result = find_leaf_node(point, n.
childNodeInd[i]);
283 if(result != s_invalidIndex)
291 return s_invalidIndex;
295 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
308 m_entries[entryInd].nextEntryInd = s_invalidIndex;
313 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
318 if(entryInd == s_invalidIndex){
323 Entry& entry = m_entries[entryInd];
324 traits::calculate_bounding_box(node.
looseBox, entry.elem, m_commonData);
326 entryInd = entry.nextEntryInd;
327 while(entryInd != s_invalidIndex){
328 Entry& entry = m_entries[entryInd];
330 traits::calculate_bounding_box(nbox, entry.elem, m_commonData);
332 entryInd = entry.nextEntryInd;
336 typename traits::vector_t offset;
342 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
350 for(
size_t entryInd = node.
firstEntryInd; entryInd != s_invalidIndex;){
351 Entry& entry = m_entries[entryInd];
354 traits::calculate_center(center, entry.
elem, m_commonData);
355 VecAdd(centerOfMass, centerOfMass, center);
366 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
370 return m_nodes.size();
374 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
378 assert(nodeId < m_nodes.size());
379 if(m_nodes[nodeId].childNodeInd[0] == s_invalidIndex)
381 return s_numChildren;
385 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
389 assert(nodeId < m_nodes.size());
390 return m_nodes[nodeId].childNodeInd;
394 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
399 assert(nodeId < m_nodes.size());
400 if(m_entries.empty())
402 return elem_iterator_t(&m_entries.front(), m_nodes[nodeId].firstEntryInd);
406 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
415 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
419 assert(nodeId < m_nodes.size());
420 return m_nodes[nodeId].numEntries;
423 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
425 level(
size_t nodeId)
const
427 assert(nodeId < m_nodes.size());
428 return m_nodes[nodeId].level;
431 template <
int tree_dim,
int world_dim,
class elem_t,
class common_data_t>
436 assert(nodeId < m_nodes.size());
437 return m_nodes[nodeId].looseBox;
this iterator is used by the ntree class to provide access to the elements of a given node
Definition: ntree_iterator.h:43
void add_entry_to_node(Node &node, size_t entryInd)
adds an entry to the given node
Definition: ntree_impl.hpp:297
traits::vector_t vector_t
Definition: ntree.h:172
size_t num_elements(size_t nodeId) const
returns the number of elements that the given node contains
Definition: ntree_impl.hpp:417
size_t num_delayed_elements() const
returns the number of elements which have been added but are not yet accessible in the tree.
Definition: ntree_impl.hpp:116
void add_element(const elem_t &elem)
adds an element to the tree.
Definition: ntree_impl.hpp:124
elem_iterator_t elems_end(size_t nodeId) const
returns an iterator to the end of the element-sequence of a given node
Definition: ntree_impl.hpp:409
void clear()
Definition: ntree_impl.hpp:62
const NTreeDesc & desc() const
returns the balancing-parameters of the tree.
Definition: ntree_impl.hpp:79
void split_leaf_node(size_t nodeIndex)
splits a node into 2^tree_dim child nodes and assigns entries to those children.
Definition: ntree_impl.hpp:188
size_t num_child_nodes(size_t nodeId) const
returns the number of children of a node
Definition: ntree_impl.hpp:376
size_t num_nodes() const
returns the total number of nodes in the tree
Definition: ntree_impl.hpp:368
size_t size() const
returns the number of entries in the tree (delayed entries excluded)
Definition: ntree_impl.hpp:108
void clear_nodes()
clear only the nodes
Definition: ntree_impl.hpp:52
TCommonData common_data_t
Definition: ntree.h:169
TElem elem_t
Definition: ntree.h:165
bool empty() const
returns true if the tree is empty
Definition: ntree_impl.hpp:100
ntree()
Definition: ntree_impl.hpp:43
vector_t calculate_center_of_mass(Node &node)
calculates the center of mass of a given node
Definition: ntree_impl.hpp:345
const box_t & bounding_box(size_t nodeId) const
returns the smallest box which contains all elements of the given node
Definition: ntree_impl.hpp:434
void rebalance()
rebalances the whole tree
Definition: ntree_impl.hpp:161
const common_data_t & common_data() const
returns the common-data stored in the tree
Definition: ntree_impl.hpp:93
size_t level(size_t nodeId) const
returns the number tree-level in which the node is located
Definition: ntree_impl.hpp:425
size_t find_leaf_node(const vector_t &point, size_t curNode=0)
returns an index to the leaf-node which contains the given point
Definition: ntree_impl.hpp:276
void update_loose_bounding_box(Node &node)
updates the loose bounding box of the given node
Definition: ntree_impl.hpp:315
traits::box_t box_t
Definition: ntree.h:173
void set_desc(const NTreeDesc &desc)
sets the balancing-parameters of the tree.
Definition: ntree_impl.hpp:72
elem_iterator_t elems_begin(size_t nodeId) const
returns an iterator to the first element of a given node
Definition: ntree_impl.hpp:397
void set_common_data(const common_data_t &commonData)
sets the common-data which the tree passes on to callback methods
Definition: ntree_impl.hpp:86
const size_t * child_node_ids(size_t nodeId) const
returns an array of child-id's for the given node
Definition: ntree_impl.hpp:387
traits::real_t real_t
Definition: ntree.h:171
std::vector< Node > m_nodes
m_nodes[0] is always considered to be the root node.
Definition: ntree.h:334
#define UG_LOG(msg)
Definition: log.h:367
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition: error.h:61
void VecSet(vector_t &vInOut, typename vector_t::value_type s)
Set each vector component to scalar (componentwise)
Definition: math_vector_functions_common_impl.hpp:539
void VecAdd(vector_t &vOut, const vector_t &v1, const vector_t &v2)
adds two MathVector<N>s and stores the result in a third one
Definition: math_vector_functions_common_impl.hpp:185
void VecScale(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
scales a MathVector<N>
Definition: math_vector_functions_common_impl.hpp:252
const number SMALL
Definition: math_constants.h:41
An Entry combines an element with the index to the next entry in a leaf-node's entry list.
Definition: ntree.h:273
elem_t elem
Definition: ntree.h:274
size_t nextEntryInd
Definition: ntree.h:277
size_t numEntries
number of entries in the node
Definition: ntree.h:290
size_t lastEntryInd
index into m_entries. s_invalidIndex: no entry
Definition: ntree.h:289
box_t tightBox
tight bounding box - disjunct partition of the root box
Definition: ntree.h:292
box_t looseBox
loose bounding box - contains all bounding boxes of its entries
Definition: ntree.h:293
size_t firstEntryInd
< index into m_nodes. s_invalidIndex: no child node.
Definition: ntree.h:288
size_t childNodeInd[s_numChildren]
Definition: ntree.h:287