Exemple #1
0
void ntree<tree_dim, world_dim, elem_t, common_data_t>::
rebalance()
{
//	push all elements into the root node, calculate its bounding box
//	and call split_leaf_node if the element threshold is surpassed.
	clear_nodes();
	Node& root = m_nodes.back();
	if(!m_entries.empty()){
		root.firstEntryInd = 0;
		root.lastEntryInd = m_entries.size() - 1;
		root.numEntries = m_entries.size();
		for(size_t i = 0; i < m_entries.size(); ++i)
			m_entries[i].nextEntryInd = i+1;
		m_entries.back().nextEntryInd = s_invalidIndex;

	//	the tight bounding box and the loose bounding box of the root node
	//	should be the same.
		update_loose_bounding_box(root);
		root.tightBox = root.looseBox;

		if(root.numEntries >= m_desc.splitThreshold)
			split_leaf_node(0);
	}
}
Exemple #2
0
void ntree<tree_dim, world_dim, elem_t, common_data_t>::
split_leaf_node(size_t nodeIndex)
{

	assert((m_nodes[nodeIndex].numEntries >= 2)
		   && "Not enough elements in a node during split_leaf_node");


	if(m_nodes[nodeIndex].childNodeInd[0] != s_invalidIndex)
		return;

	const size_t firstChild = m_nodes.size();
	m_nodes.resize(firstChild + s_numChildren);

//	ATTENTION: Be careful not to resize m_nodes while using node, since this would invalidate the reference!
	Node& node = m_nodes[nodeIndex];

	vector_t centerOfMass = calculate_center_of_mass(node);
	box_t childBoxes[s_numChildren];
	traits::split_box(childBoxes, node.tightBox, centerOfMass);

	size_t numEntriesAssigned = 0;
	for(size_t entryInd = node.firstEntryInd; entryInd != s_invalidIndex;){
		Entry& entry = m_entries[entryInd];
		size_t nextEntryInd = entry.nextEntryInd;

		vector_t center;
		traits::calculate_center(center, entry.elem, m_commonData);
		for(size_t i_child = 0; i_child < s_numChildren; ++i_child){
			if(traits::box_contains_point(childBoxes[i_child], center)){
				add_entry_to_node(m_nodes[firstChild + i_child], entryInd);
				++numEntriesAssigned;
				break;
			}
		}

		entryInd = nextEntryInd;
	}

	assert((numEntriesAssigned == node.numEntries)
		   && "Couldn't find a matching child node for some elements during split_leaf_node:");

	node.firstEntryInd = node.lastEntryInd = s_invalidIndex;
	node.numEntries = 0;

	for(size_t i_child = 0; i_child < s_numChildren; ++i_child){
		node.childNodeInd[i_child] = firstChild + i_child;
		Node& childNode = m_nodes[firstChild + i_child];
		childNode.level = node.level + 1;
		childNode.tightBox = childBoxes[i_child];
		update_loose_bounding_box(childNode);
	}

//	since split_leaf_node resizes m_nodes and since this invalidates any references
//	to m_nodes, we perform the recursion in a last step
	for(size_t i_child = 0; i_child < s_numChildren; ++i_child){
		size_t childNodeInd = firstChild + i_child;
		if(m_nodes[childNodeInd].numEntries >= m_desc.splitThreshold)
			split_leaf_node(childNodeInd);
	}
}
Exemple #3
0
void ntree<tree_dim, world_dim, elem_t, common_data_t>::
split_leaf_node(size_t nodeIndex)
{

	if(m_nodes[nodeIndex].numEntries <= 1)
		return;

	if(m_nodes[nodeIndex].level >= m_desc.maxDepth){
		if(m_warningsEnabled){
			UG_LOG("WARNING in ntree::split_leaf_node(): maximum tree depth "
				<< m_desc.maxDepth << " reached. No further splits are performed for "
				" this node. Note that too many elements per node may lead to performance issues.\n"
				<< "  Number of elements in this node: " << m_nodes[nodeIndex].numEntries << std::endl
				<< "  Corner coordinates of this node: " << m_nodes[nodeIndex].tightBox << std::endl);
		}
		return;
	}

	if(m_nodes[nodeIndex].childNodeInd[0] != s_invalidIndex)
		return;

	const size_t firstChild = m_nodes.size();
	m_nodes.resize(firstChild + s_numChildren);

//	ATTENTION: Be careful not to resize m_nodes while using node, since this would invalidate the reference!
	Node& node = m_nodes[nodeIndex];

//	calculate center of mass and use the traits class to split the box of
//	the current node into 's_numChildren' child boxes. Each child box thereby
//	spanned by one of the corners of the original box and 'centerOfMass'.
	vector_t centerOfMass = calculate_center_of_mass(node);
	box_t childBoxes[s_numChildren];
	traits::split_box(childBoxes, node.tightBox, centerOfMass);

//	iterate over all entries in the current node and assign them to child nodes.
	size_t numEntriesAssigned = 0;
	for(size_t entryInd = node.firstEntryInd; entryInd != s_invalidIndex;){
		Entry& entry = m_entries[entryInd];
		size_t nextEntryInd = entry.nextEntryInd;

		size_t i_child;
		vector_t center;
		traits::calculate_center(center, entry.elem, m_commonData);
		for(i_child = 0; i_child < s_numChildren; ++i_child){
			if(traits::box_contains_point(childBoxes[i_child], center)){
				add_entry_to_node(m_nodes[firstChild + i_child], entryInd);
				++numEntriesAssigned;
				break;
			}
		}
		/*-- For debugging only: --*
		if(i_child == s_numChildren){
			UG_LOG ("ERROR in ntree::split_leaf_node(): Element with center @ " << center
				<< " does not belong to any child of the box " << node.tightBox << std::endl);
		}
		 *--*/

		entryInd = nextEntryInd;
	}

//	all elements of the current box now should be assigned to child boxes.
//	we thus clear element lists and entry-count from the current node.
	UG_COND_THROW(numEntriesAssigned != node.numEntries, "Couldn't find a matching "
				  "child node for some elements during split_leaf_node in "
				  "ntree::split_leaf_node");

	node.firstEntryInd = node.lastEntryInd = s_invalidIndex;
	node.numEntries = 0;

	for(size_t i_child = 0; i_child < s_numChildren; ++i_child){
		node.childNodeInd[i_child] = firstChild + i_child;
		Node& childNode = m_nodes[firstChild + i_child];
		childNode.level = node.level + 1;
		childNode.tightBox = childBoxes[i_child];
		update_loose_bounding_box(childNode);
	}

//	since split_leaf_node resizes m_nodes and since this invalidates any references
//	to m_nodes, we perform the recursion in a last step
	for(size_t i_child = 0; i_child < s_numChildren; ++i_child){
		size_t childNodeInd = firstChild + i_child;
		if(m_nodes[childNodeInd].numEntries >= m_desc.splitThreshold)
			split_leaf_node(childNodeInd);
	}
}