📄 rtree.h
字号:
m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
}
RTREE_TEMPLATE
RTREE_QUAL::~RTree()
{
Reset(); // Free, or reset node memory
}
RTREE_TEMPLATE
void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
{
#ifdef _DEBUG
for(int index=0; index<NUMDIMS; ++index)
{
ASSERT(a_min[index] <= a_max[index]);
}
#endif //_DEBUG
Rect rect;
for(int axis=0; axis<NUMDIMS; ++axis)
{
rect.m_min[axis] = a_min[axis];
rect.m_max[axis] = a_max[axis];
}
InsertRect(&rect, a_dataId, &m_root, 0);
}
RTREE_TEMPLATE
void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
{
#ifdef _DEBUG
for(int index=0; index<NUMDIMS; ++index)
{
ASSERT(a_min[index] <= a_max[index]);
}
#endif //_DEBUG
Rect rect;
for(int axis=0; axis<NUMDIMS; ++axis)
{
rect.m_min[axis] = a_min[axis];
rect.m_max[axis] = a_max[axis];
}
RemoveRect(&rect, a_dataId, &m_root);
}
RTREE_TEMPLATE
int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], bool __cdecl a_resultCallback(DATATYPE a_data, void* a_context), void* a_context)
{
#ifdef _DEBUG
for(int index=0; index<NUMDIMS; ++index)
{
ASSERT(a_min[index] <= a_max[index]);
}
#endif //_DEBUG
Rect rect;
for(int axis=0; axis<NUMDIMS; ++axis)
{
rect.m_min[axis] = a_min[axis];
rect.m_max[axis] = a_max[axis];
}
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
int foundCount = 0;
Search(m_root, &rect, foundCount, a_resultCallback, a_context);
return foundCount;
}
RTREE_TEMPLATE
int RTREE_QUAL::Count()
{
int count = 0;
CountRec(m_root, count);
return count;
}
RTREE_TEMPLATE
void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
{
if(a_node->IsInternalNode()) // not a leaf node
{
for(int index = 0; index < a_node->m_count; ++index)
{
CountRec(a_node->m_branch[index].m_child, a_count);
}
}
else // A leaf node
{
a_count += a_node->m_count;
}
}
RTREE_TEMPLATE
bool RTREE_QUAL::Load(const char* a_fileName)
{
RemoveAll(); // Clear existing tree
RTFileStream stream;
if(!stream.OpenRead(a_fileName))
{
return false;
}
bool result = Load(stream);
stream.Close();
return result;
};
RTREE_TEMPLATE
bool RTREE_QUAL::Load(RTFileStream& a_stream)
{
// Write some kind of header
int _dataFileId = ('R'<<0)|('T'<<8)|('R'<<16)|('E'<<24);
int _dataSize = sizeof(DATATYPE);
int _dataNumDims = NUMDIMS;
int _dataElemSize = sizeof(ELEMTYPE);
int _dataElemRealSize = sizeof(ELEMTYPEREAL);
int _dataMaxNodes = TMAXNODES;
int _dataMinNodes = TMINNODES;
int dataFileId = 0;
int dataSize = 0;
int dataNumDims = 0;
int dataElemSize = 0;
int dataElemRealSize = 0;
int dataMaxNodes = 0;
int dataMinNodes = 0;
a_stream.Read(dataFileId);
a_stream.Read(dataSize);
a_stream.Read(dataNumDims);
a_stream.Read(dataElemSize);
a_stream.Read(dataElemRealSize);
a_stream.Read(dataMaxNodes);
a_stream.Read(dataMinNodes);
bool result = false;
// Test if header was valid and compatible
if( (dataFileId == _dataFileId)
&& (dataSize == _dataSize)
&& (dataNumDims == _dataNumDims)
&& (dataElemSize == _dataElemSize)
&& (dataElemRealSize == _dataElemRealSize)
&& (dataMaxNodes == _dataMaxNodes)
&& (dataMinNodes == _dataMinNodes)
)
{
// Recursively load tree
result = LoadRec(m_root, a_stream);
}
return result;
}
RTREE_TEMPLATE
bool RTREE_QUAL::LoadRec(Node* a_node, RTFileStream& a_stream)
{
a_stream.Read(a_node->m_level);
a_stream.Read(a_node->m_count);
if(a_node->IsInternalNode()) // not a leaf node
{
for(int index = 0; index < a_node->m_count; ++index)
{
Branch* curBranch = &a_node->m_branch[index];
a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
curBranch->m_child = AllocNode();
LoadRec(curBranch->m_child, a_stream);
}
}
else // A leaf node
{
for(int index = 0; index < a_node->m_count; ++index)
{
Branch* curBranch = &a_node->m_branch[index];
a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
a_stream.Read(curBranch->m_data);
}
}
return true; // Should do more error checking on I/O operations
}
RTREE_TEMPLATE
bool RTREE_QUAL::Save(const char* a_fileName)
{
RTFileStream stream;
if(!stream.OpenWrite(a_fileName))
{
return false;
}
bool result = Save(stream);
stream.Close();
return result;
}
RTREE_TEMPLATE
bool RTREE_QUAL::Save(RTFileStream& a_stream)
{
// Write some kind of header
int dataFileId = ('R'<<0)|('T'<<8)|('R'<<16)|('E'<<24);
int dataSize = sizeof(DATATYPE);
int dataNumDims = NUMDIMS;
int dataElemSize = sizeof(ELEMTYPE);
int dataElemRealSize = sizeof(ELEMTYPEREAL);
int dataMaxNodes = TMAXNODES;
int dataMinNodes = TMINNODES;
a_stream.Write(dataFileId);
a_stream.Write(dataSize);
a_stream.Write(dataNumDims);
a_stream.Write(dataElemSize);
a_stream.Write(dataElemRealSize);
a_stream.Write(dataMaxNodes);
a_stream.Write(dataMinNodes);
// Recursively save tree
bool result = SaveRec(m_root, a_stream);
return result;
}
RTREE_TEMPLATE
bool RTREE_QUAL::SaveRec(Node* a_node, RTFileStream& a_stream)
{
a_stream.Write(a_node->m_level);
a_stream.Write(a_node->m_count);
if(a_node->IsInternalNode()) // not a leaf node
{
for(int index = 0; index < a_node->m_count; ++index)
{
Branch* curBranch = &a_node->m_branch[index];
a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
SaveRec(curBranch->m_child, a_stream);
}
}
else // A leaf node
{
for(int index = 0; index < a_node->m_count; ++index)
{
Branch* curBranch = &a_node->m_branch[index];
a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
a_stream.Write(curBranch->m_data);
}
}
return true; // Should do more error checking on I/O operations
}
RTREE_TEMPLATE
void RTREE_QUAL::RemoveAll()
{
// Delete all existing nodes
Reset();
m_root = AllocNode();
m_root->m_level = 0;
}
RTREE_TEMPLATE
void RTREE_QUAL::Reset()
{
#ifdef RTREE_DONT_USE_MEMPOOLS
// Delete all existing nodes
RemoveAllRec(m_root);
#else // RTREE_DONT_USE_MEMPOOLS
// Just reset memory pools. We are not using complex types
// EXAMPLE
#endif // RTREE_DONT_USE_MEMPOOLS
}
RTREE_TEMPLATE
void RTREE_QUAL::RemoveAllRec(Node* a_node)
{
ASSERT(a_node);
ASSERT(a_node->m_level >= 0);
if(a_node->IsInternalNode()) // This is an internal node in the tree
{
for(int index=0; index < a_node->m_count; ++index)
{
RemoveAllRec(a_node->m_branch[index].m_child);
}
}
FreeNode(a_node);
}
RTREE_TEMPLATE
typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
{
Node* newNode;
#ifdef RTREE_DONT_USE_MEMPOOLS
newNode = new Node;
#else // RTREE_DONT_USE_MEMPOOLS
// EXAMPLE
#endif // RTREE_DONT_USE_MEMPOOLS
InitNode(newNode);
return newNode;
}
RTREE_TEMPLATE
void RTREE_QUAL::FreeNode(Node* a_node)
{
ASSERT(a_node);
#ifdef RTREE_DONT_USE_MEMPOOLS
delete a_node;
#else // RTREE_DONT_USE_MEMPOOLS
// EXAMPLE
#endif // RTREE_DONT_USE_MEMPOOLS
}
// Allocate space for a node in the list used in DeletRect to
// store Nodes that are too empty.
RTREE_TEMPLATE
typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
{
#ifdef RTREE_DONT_USE_MEMPOOLS
return new ListNode;
#else // RTREE_DONT_USE_MEMPOOLS
// EXAMPLE
#endif // RTREE_DONT_USE_MEMPOOLS
}
RTREE_TEMPLATE
void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
{
#ifdef RTREE_DONT_USE_MEMPOOLS
delete a_listNode;
#else // RTREE_DONT_USE_MEMPOOLS
// EXAMPLE
#endif // RTREE_DONT_USE_MEMPOOLS
}
RTREE_TEMPLATE
void RTREE_QUAL::InitNode(Node* a_node)
{
a_node->m_count = 0;
a_node->m_level = -1;
}
RTREE_TEMPLATE
void RTREE_QUAL::InitRect(Rect* a_rect)
{
for(int index = 0; index < NUMDIMS; ++index)
{
a_rect->m_min[index] = (ELEMTYPE)0;
a_rect->m_max[index] = (ELEMTYPE)0;
}
}
// Inserts a new data rectangle into the index structure.
// Recursively descends tree, propagates splits back up.
// Returns 0 if node was not split. Old node updated.
// If node was split, returns 1 and sets the pointer pointed to by
// new_node to point to the new node. Old node updated to become one of two.
// The level argument specifies the number of steps up from the leaf
// level to insert; e.g. a data rectangle goes in at level = 0.
RTREE_TEMPLATE
bool RTREE_QUAL::InsertRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, Node** a_newNode, int a_level)
{
ASSERT(a_rect && a_node && a_newNode);
ASSERT(a_level >= 0 && a_level <= a_node->m_level);
int index;
Branch branch;
Node* otherNode;
// Still above level for insertion, go down tree recursively
if(a_node->m_level > a_level)
{
index = PickBranch(a_rect, a_node);
if (!InsertRectRec(a_rect, a_id, a_node->m_branch[index].m_child, &otherNode, a_level))
{
// Child was not split
a_node->m_branch[index].m_rect = CombineRect(a_rect, &(a_node->m_branch[index].m_rect));
return false;
}
else // Child was split
{
a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
branch.m_child = otherNode;
branch.m_rect = NodeCover(otherNode);
return AddBranch(&branch, a_node, a_newNode);
}
}
else if(a_node->m_level == a_level) // Have reached level for insertion. Add rect, split if necessary
{
branch.m_rect = *a_rect;
branch.m_child = (Node*) a_id;
// Child field of leaves contains id of data record
return AddBranch(&branch, a_node, a_newNode);
}
else
{
// Should never occur
ASSERT(0);
return false;
}
}
// Insert a data rectangle into an index structure.
// InsertRect provides for splitting the root;
// returns 1 if root was split, 0 if it was not.
// The level argument specifies the number of steps up from the leaf
// level to insert; e.g. a data rectangle goes in at level = 0.
// InsertRect2 does the recursion.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -