/* class representing nodes in an R Tree */ #include "RTreeNode.h" #include #include #include "BPTree/BPTree.h" #include "WinUnix.h" #include #include #include #include #include "RTree.h" #include "Algebras/Rectangle/RectangleAlgebra.h" using std::out_of_range; using std::runtime_error; //#define RTreeNodeMax 2 namespace fialgebra{ template size_t RTreeNode::constantSize = sizeof(bool) + sizeof(size_t); template size_t RTreeNode::typeSize = SizeOfRectangle(); template RTreeNode::RTreeNode(size_t pageSize, size_t id, bool isLeaf) : m_box(NULL){ if (pageSize < typeSize + sizeof(size_t) + constantSize){ throw out_of_range("RTreeNode::RTreeNode(size_t, size_t, bool): " "page size too small for a entry"); } m_box = NULL; nodeID = id; m_pageSize = pageSize; m_max = GetMax(pageSize); m_bytes = new char[pageSize]; m_isLeaf = (bool*)m_bytes; m_numberOfEntries = (size_t *)(m_isLeaf + 1); m_values = (char*)(m_numberOfEntries + 1); m_ids = (size_t*)(m_values + (m_max * typeSize)); *m_isLeaf = isLeaf; *m_numberOfEntries = 0; } template RTreeNode::RTreeNode(char* bytes, size_t pageSize, size_t id) : m_box(NULL){ if (pageSize < typeSize + sizeof(size_t) + constantSize){ throw out_of_range("RTreeNode::RTreeNode(size_t, size_t, bool): " "page size too small for a entry"); } m_box = NULL; nodeID = id; m_pageSize = pageSize; m_max = GetMax(pageSize); m_pageSize = pageSize; m_bytes = bytes; m_isLeaf = (bool*)m_bytes; m_numberOfEntries = (size_t *)(m_isLeaf + 1); m_values = (char*)(m_numberOfEntries + 1); m_ids = (size_t*)(m_values + (m_max * typeSize)); } template RTreeNode::RTreeNode(const RTreeNode& o){ m_box = o.m_box != NULL ? new Rectangle(*o.m_box) : NULL; nodeID = o.nodeID; m_pageSize = o.m_pageSize; m_max = o.m_max; m_bytes = new char[m_pageSize]; memcpy(m_bytes, o.m_bytes, m_pageSize); m_isLeaf = (bool*)m_bytes; m_numberOfEntries = (size_t *)(m_isLeaf + 1); m_values = (char*)(m_numberOfEntries + 1); m_ids = (size_t*)(m_values + (m_max * typeSize)); for(Overflow* overflow : o.m_overflow){ m_overflow.push_back(new Overflow(overflow->rectangle, overflow->id)); } } template RTreeNode::~RTreeNode(){ delete[] m_bytes; if ( m_box ) { delete m_box; m_box = 0; } // if } template void RTreeNode::AddEntry( const Rectangle& value, size_t id ){ if (m_max <= *m_numberOfEntries){ m_overflow.push_back(new Overflow(value, id)); } else{ memcpy(m_values + ((*m_numberOfEntries) * typeSize), (char*)&value, typeSize); m_ids[*m_numberOfEntries] = id; } (*m_numberOfEntries)++; if (m_box != NULL){ delete(m_box); m_box = NULL; } } template void RTreeNode::RemoveEntryAtEnd(){ if (*m_numberOfEntries <= 0){ throw out_of_range("RTreeNode::RemoveEntryAtEnd()"); } else{ if (m_max < *m_numberOfEntries){ delete(m_overflow.back()); m_overflow.pop_back(); } (*m_numberOfEntries)--; if (m_box != NULL){ delete(m_box); m_box = NULL; } } } template void RTreeNode::RemoveEntryAt(size_t index){ if (index >= *m_numberOfEntries){ throw out_of_range("RTreeNode::RemoveEntryAt(size_t)"); } else{ if (*m_numberOfEntries <= m_max){ if (index < (*m_numberOfEntries - 1)){ memmove(m_values + (index * typeSize), m_values + ((index + 1) * typeSize), ((*m_numberOfEntries) - index - 1) * typeSize); for (size_t i = index; i < *m_numberOfEntries - 1; i++){ m_ids[i] = m_ids[i + 1]; } } } else{ if (index < m_max){ memmove(m_values + (index * typeSize), m_values + ((index + 1) * typeSize), (m_max - index - 1) * typeSize); for (size_t i = index; i < m_max - 1; i++){ m_ids[i] = m_ids[i + 1]; } Overflow* overflow = m_overflow[0]; m_overflow.erase(m_overflow.begin()); memcpy(m_values + ((m_max - 1) * typeSize), (char*)&overflow->rectangle, typeSize); m_ids[m_max - 1] = overflow->id; delete(overflow); overflow = NULL; } else{ delete(m_overflow[index - m_max]); m_overflow.erase(m_overflow.begin() + index - m_max); } } (*m_numberOfEntries)--; if (m_box != NULL){ delete(m_box); m_box = NULL; } } } template void RTreeNode::ClearEntries(){ *m_numberOfEntries = 0; for(Overflow* overflow : m_overflow){ delete(overflow); } m_overflow.clear(); if (m_box != NULL){ delete(m_box); m_box = NULL; } } template const Rectangle& RTreeNode::GetValueAt(size_t index) const{ if (index >= *m_numberOfEntries){ throw out_of_range("RTreeNode::GetValueAt(size_t)"); } else{ if (index >= m_max){ return m_overflow[index - m_max]->rectangle; } else{ return *(Rectangle*)CastRectangle(m_values + (index * typeSize)); } } } template void RTreeNode::SetValueAt(size_t index, const Rectangle& value){ if (index >= *m_numberOfEntries){ throw out_of_range("RTreeNode::SetValueAt(size_t, " "const Rectangle&)"); } else{ if (index >= m_max){ m_overflow[index - m_max]->rectangle = value; } else{ memcpy(m_values + (index * typeSize), (char*)&value, typeSize); } if (m_box != NULL){ delete(m_box); m_box = NULL; } } } template size_t RTreeNode::GetIDAt(size_t index) const{ if (index >= *m_numberOfEntries){ throw out_of_range("RTreeNode::GetIDAt(size_t)"); } else{ return index >= m_max ? m_overflow[index - m_max]->id : m_ids[index]; } } template void RTreeNode::SetIDAt(size_t index, size_t id){ if (index >= *m_numberOfEntries){ throw out_of_range("RTreeNode::SetIDAt(size_t, size_t)"); } else{ if (index >= m_max){ m_overflow[index - m_max]->id = id; } else{ m_ids[index] = id; } } } template size_t RTreeNode::GetNumberOfEntries() const{ return *m_numberOfEntries; } template size_t RTreeNode::GetMax(){ return m_max; } template size_t RTreeNode::GetMax(size_t pageSize){ #ifdef RTreeNodeMax return RTreeNodeMax; #else return (pageSize - constantSize)/(typeSize + sizeof(size_t)); #endif } template char* RTreeNode::GetBytes(){ return m_bytes; } template bool RTreeNode::IsLeaf(){ return *m_isLeaf; } template size_t RTreeNode::GetNodeID() const{ return nodeID; } template void RTreeNode::SetNodeID(size_t id){ nodeID = id; } template const unsigned long RTreeNode::GetParentNodeID() const{ return parentNodeID; } template void RTreeNode::SetParentNodeID(unsigned long id){ parentNodeID = id; } template const Rectangle& RTreeNode::GetBox(){ if (m_box == NULL){ if (*m_numberOfEntries > 0){ m_box = new Rectangle(GetValueAt(0)); for(size_t i = 1; i < *m_numberOfEntries; i++){ *m_box = m_box->Union(GetValueAt(i)); } } else{ m_box = new Rectangle(false); } } return *m_box; } template RTreeNode& RTreeNode::operator=(const RTreeNode& o){ if (m_box != NULL){ delete(m_box); } m_box = o.m_box != NULL ? new Rectangle(*o.m_box) : NULL; m_pageSize = o.m_pageSize; m_max = o.m_max; m_bytes = new char[m_pageSize]; memcpy(m_bytes, o.m_bytes, m_pageSize); m_isLeaf = (bool*)m_bytes; m_numberOfEntries = (size_t *)(m_isLeaf + 1); m_values = (char*)(m_numberOfEntries + 1); m_ids = (size_t*)(m_values + (m_max * typeSize)); for(Overflow* overflow : o.m_overflow){ m_overflow.push_back(new Overflow(overflow->rectangle, overflow->id)); } return *this; } template bool RTreeNode::operator<(const RTreeNode& o){ return *m_numberOfEntries < *o.m_numberOfEntries; } template bool RTreeNode::operator==(const RTreeNode& o){ return *m_numberOfEntries == *o.m_numberOfEntries; } template RTreeNode::Overflow::Overflow(const Rectangle& rectangle, const size_t id){ this->rectangle = rectangle; this->id = id; } template void RTreeNode::PrintNodeToString(){ if(!IsLeaf()){ cout<<"Interne Knote: "; for(size_t i = 0; i < GetNumberOfEntries(); i++){ cout<<"EntryNumber: "<; template class RTreeNode<2>; template class RTreeNode<3>; template class RTreeNode<4>; template class RTreeNode<8>; }//end of namespace fialgebra