📄 rtree.h
字号:
return foundCount;}RTREE_TEMPLATEint RTREE_QUAL::Count(){ int count = 0; CountRec(m_root, count); return count;}RTREE_TEMPLATEvoid 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_TEMPLATEbool 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_TEMPLATEbool 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_TEMPLATEbool 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_TEMPLATEbool 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_TEMPLATEbool 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_TEMPLATEbool 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_TEMPLATEvoid RTREE_QUAL::RemoveAll(){ // Delete all existing nodes Reset(); m_root = AllocNode(); m_root->m_level = 0;}RTREE_TEMPLATEvoid 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_TEMPLATEvoid 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_TEMPLATEtypename 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_TEMPLATEvoid 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_TEMPLATEtypename 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_TEMPLATEvoid 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_TEMPLATEvoid RTREE_QUAL::InitNode(Node* a_node){ a_node->m_count = 0; a_node->m_level = -1;}RTREE_TEMPLATEvoid 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_TEMPLATEbool 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.//RTREE_TEMPLATEbool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root, int a_level){ ASSERT(a_rect && a_root); ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);#ifdef _DEBUG for(int index=0; index < NUMDIMS; ++index) { ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]); }#endif //_DEBUG Node* newRoot; Node* newNode; Branch branch; if(InsertRectRec(a_rect, a_id, *a_root, &newNode, a_level)) // Root split { newRoot = AllocNode(); // Grow tree taller and new root newRoot->m_level = (*a_root)->m_level + 1; branch.m_rect = NodeCover(*a_root); branch.m_child = *a_root; AddBranch(&branch, newRoot, NULL); branch.m_rect = NodeCover(newNode); branch.m_child = newNode; AddBranch(&branch, newRoot, NULL); *a_root = newRoot; return true; } return false;}// Find the smallest rectangle that includes all rectangles in branches of a node.RTREE_TEMPLATEtypename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node){ ASSERT(a_node); int firstTime = true; Rect rect; InitRect(&rect); for(int index = 0; index < a_node->m_count; ++index) { if(firstTime) { rect = a_node->m_branch[index].m_rect; firstTime = false; } else { rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect)); } } return rect;}// Add a branch to a node. Split the node if necessary.// Returns 0 if node not split. Old node updated.// Returns 1 if node split, sets *new_node to address of new node.// Old node updated, becomes one of two.RTREE_TEMPLATEbool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode){ ASSERT(a_branch); ASSERT(a_node); if(a_node->m_count < MAXNODES) // Split won't be necessary { a_node->m_branch[a_node->m_count] = *a_branch; ++a_node->m_count; return false; } else { ASSERT(a_newNode); SplitNode(a_node, a_branch, a_newNode); return true; }}// Disconnect a dependent node.// Caller must return (or stop using iteration index) after this as count has changedRTREE_TEMPLATEvoid RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index){ ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES)); ASSERT(a_node->m_count > 0); // Remove element by swapping with the last element to prevent gaps in array a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1]; --a_node->m_count;}// Pick a branch. Pick the one that will need the smallest increase// in area to accomodate the new rectangle. This will result in the// least total area for the covering rectangles in the current node.// In case of a tie, pick the one which was smaller before, to get// the best resolution when searching.RTREE_TEMPLATEint RTREE_QUAL::PickBranch(Rect* a_rect, Node* a_node){ ASSERT(a_rect && a_node); bool firstTime = true; ELEMTYPEREAL increase; ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1; ELEMTYPEREAL area; ELEMTYPEREAL bestArea; int best; Rect tempRect; for(int index=0; index < a_node->m_count; ++index) { Rect* curRect = &a_node->m_branch[index].m_rect; area = CalcRectVolume(curRect); tempRect = CombineRect(a_rect, curRect); increase = CalcRectVolume(&tempRect) - area; if((increase < bestIncr) || firstTime) { best = index; bestArea = area; bestIncr = increase; firstTime = false; } else if((increase == bestIncr) && (area < bestArea)) { best = index; bestArea = area; bestIncr = increase;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -