44 : m_id(id), m_region(r), m_pData(nullptr), m_dataLength(len)
60 return new Data(m_dataLength, m_pData, m_region, m_id);
70 *out =
new Region(m_region);
80 *data =
new uint8_t[m_dataLength];
81 memcpy(*data, m_pData, m_dataLength);
91 m_region.getByteArraySize();
96 memcpy(&m_id, ptr,
sizeof(
id_type));
102 memcpy(&m_dataLength, ptr,
sizeof(uint32_t));
103 ptr +=
sizeof(uint32_t);
105 if (m_dataLength > 0)
107 m_pData =
new uint8_t[m_dataLength];
108 memcpy(m_pData, ptr, m_dataLength);
112 m_region.loadFromByteArray(ptr);
119 uint8_t* regiondata =
nullptr;
120 m_region.storeToByteArray(®iondata, regionsize);
122 len =
sizeof(
id_type) +
sizeof(uint32_t) + m_dataLength + regionsize;
124 *data =
new uint8_t[len];
125 uint8_t* ptr = *data;
127 memcpy(ptr, &m_id,
sizeof(
id_type));
129 memcpy(ptr, &m_dataLength,
sizeof(uint32_t));
130 ptr +=
sizeof(uint32_t);
132 if (m_dataLength > 0)
134 memcpy(ptr, m_pData, m_dataLength);
138 memcpy(ptr, regiondata, regionsize);
152 uint32_t indexCapacity,
153 uint32_t leafCapacity,
195 uint32_t indexCapacity,
196 uint32_t leafCapacity,
203 uint32_t bindex =
static_cast<uint32_t
>(std::floor(
static_cast<double>(indexCapacity * fillFactor)));
204 uint32_t bleaf =
static_cast<uint32_t
>(std::floor(
static_cast<double>(leafCapacity * fillFactor)));
230 double fillFactor(0.7);
231 uint32_t indexCapacity(100);
232 uint32_t leafCapacity(100);
233 uint32_t dimension(2);
234 uint32_t pageSize(10000);
235 uint32_t numberOfPages(100);
264 throw Tools::IllegalArgumentException(
"createAndBulkLoadNewRTree: Property FillFactor must be in range (0.0, 0.5) for LINEAR or QUADRATIC index types");
303 var = ps.
getProperty(
"ExternalSortBufferPageSize");
315 var = ps.
getProperty(
"ExternalSortBufferTotalPages");
328 uint32_t bindex =
static_cast<uint32_t
>(std::floor(
static_cast<double>(indexCapacity * fillFactor)));
329 uint32_t bleaf =
static_cast<uint32_t
>(std::floor(
static_cast<double>(leafCapacity * fillFactor)));
359 m_pStorageManager(&sm),
360 m_rootID(StorageManager::
NewPage),
361 m_headerID(StorageManager::
NewPage),
364 m_indexCapacity(100),
366 m_nearMinimumOverlapFactor(32),
367 m_splitDistributionFactor(0.4),
368 m_reinsertFactor(0.3),
412 uint8_t* buffer =
nullptr;
416 buffer =
new uint8_t[len];
417 memcpy(buffer, pData, len);
420 insertData_impl(len, buffer, *mbr,
id);
430 bool ret = deleteData_impl(*mbr,
id);
440 #ifdef HAVE_PTHREAD_H
441 Tools::LockGuard lock(&m_lock);
446 std::stack<NodePtr> st;
447 NodePtr root = readNode(m_rootID);
452 NodePtr n = st.top(); st.pop();
457 visitSubTree(n, vId);
459 uint64_t *obj =
new uint64_t[nObj];
462 Data data =
Data((uint32_t)(
sizeof(uint64_t) * nObj), (uint8_t *) obj, n->m_nodeMBR, n->
getIdentifier());
464 ++(m_stats.m_u64QueryResults);
470 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
476 ++(m_stats.m_u64QueryResults);
484 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
486 st.push(readNode(n->m_pIdentifier[cChild]));
506 std::stack<NodePtr> st;
507 NodePtr root = readNode(m_rootID);
512 NodePtr n = st.top(); st.pop();
518 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
522 Data data =
Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]);
524 ++(m_stats.m_u64QueryResults);
538 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
540 st.push(readNode(n->m_pIdentifier[cChild]));
565 template <
class T,
class S,
class C>
567 struct HackedQueue :
private std::priority_queue<T, S, C> {
568 static S&
Container(std::priority_queue<T, S, C>& q) {
569 return q.*&HackedQueue::c;
579 auto ascending = [](
const NNEntry& lhs,
const NNEntry& rhs) {
return lhs.m_minDist > rhs.m_minDist; };
580 std::priority_queue<NNEntry, std::vector<NNEntry>, decltype(ascending)> queue(ascending);
583 std::vector<NNEntry>& queue_c =
Container(queue);
586 queue.push(NNEntry(m_rootID,
nullptr, 0.0));
589 double knearest = 0.0;
591 while (! queue.empty())
593 NNEntry pFirst = queue.top();
595 if (max_dist && pFirst.m_minDist > max_dist)
break;
599 if (count >= k && pFirst.m_minDist > knearest)
break;
603 if (pFirst.m_pEntry ==
nullptr)
606 NodePtr n = readNode(pFirst.m_id);
609 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
613 Data* e =
new Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]);
620 queue.push(NNEntry(n->m_pIdentifier[cChild],
nullptr, nnc.
getMinimumDistance(query, *(n->m_ptrMBR[cChild]))));
627 ++(m_stats.m_u64QueryResults);
629 knearest = pFirst.m_minDist;
630 delete pFirst.m_pEntry;
634 for (
auto& e : queue_c)
645 return nearestNeighborQuery(k, query, v, nnc, max_dist);
656 selfJoinQuery(m_rootID, m_rootID, *mbr, v);
751 m_readNodeCommands.push_back(std::shared_ptr<ICommand>(pCommand));
754 m_writeNodeCommands.push_back(std::shared_ptr<ICommand>(pCommand));
757 m_deleteNodeCommands.push_back(std::shared_ptr<ICommand>(pCommand));
765 std::stack<ValidateEntry> st;
766 NodePtr root = readNode(m_rootID);
768 if (root->m_level != m_stats.m_u32TreeHeight - 1)
770 std::cerr <<
"Invalid tree height." << std::endl;
774 std::map<uint32_t, uint32_t> nodesInLevel;
775 nodesInLevel.insert(std::pair<uint32_t, uint32_t>(root->m_level, 1));
777 ValidateEntry e(root->m_nodeMBR, root);
782 e = st.top(); st.pop();
785 tmpRegion = m_infiniteRegion;
787 for (uint32_t cDim = 0; cDim < tmpRegion.
m_dimension; ++cDim)
789 tmpRegion.
m_pLow[cDim] = std::numeric_limits<double>::max();
790 tmpRegion.
m_pHigh[cDim] = -std::numeric_limits<double>::max();
792 for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild)
794 tmpRegion.
m_pLow[cDim] = std::min(tmpRegion.
m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pLow[cDim]);
795 tmpRegion.
m_pHigh[cDim] = std::max(tmpRegion.
m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pHigh[cDim]);
799 if (! (tmpRegion == e.m_pNode->m_nodeMBR))
801 std::cerr <<
"Invalid parent information." << std::endl;
804 else if (! (tmpRegion == e.m_parentMBR))
806 std::cerr <<
"Error in parent." << std::endl;
810 if (e.m_pNode->m_level != 0)
812 for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild)
814 NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]);
815 ValidateEntry tmpEntry(*(e.m_pNode->m_ptrMBR[cChild]), ptrN);
817 std::map<uint32_t, uint32_t>::iterator itNodes = nodesInLevel.find(tmpEntry.m_pNode->m_level);
819 if (itNodes == nodesInLevel.end())
821 nodesInLevel.insert(std::pair<uint32_t, uint32_t>(tmpEntry.m_pNode->m_level, 1l));
825 nodesInLevel[tmpEntry.m_pNode->m_level] = nodesInLevel[tmpEntry.m_pNode->m_level] + 1;
834 for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel)
836 if (nodesInLevel[cLevel] != m_stats.m_nodesInLevel[cLevel])
838 std::cerr <<
"Invalid nodesInLevel information." << std::endl;
842 nodes += m_stats.m_nodesInLevel[cLevel];
845 if (nodes != m_stats.m_u32Nodes)
847 std::cerr <<
"Invalid number of nodes information." << std::endl;
896 "(0.0, 0.5) for LINEAR or QUADRATIC index types");
899 "(0.0, 1.0) for RSTAR index type");
932 throw Tools::IllegalArgumentException(
"initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities");
1025 m_infiniteRegion.makeInfinite(m_dimension);
1027 m_stats.m_u32TreeHeight = 1;
1028 m_stats.m_nodesInLevel.push_back(0);
1030 Leaf root(
this, -1);
1031 m_rootID = writeNode(&root);
1068 throw Tools::IllegalArgumentException(
"initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities");
1070 m_nearMinimumOverlapFactor = var.
m_val.
ulVal;
1138 m_infiniteRegion.makeInfinite(m_dimension);
1141 void SpatialIndex::RTree::RTree::storeHeader()
1143 const uint32_t headerSize =
1157 m_stats.m_u32TreeHeight *
sizeof(uint32_t);
1159 uint8_t* header =
new uint8_t[headerSize];
1160 uint8_t* ptr = header;
1162 memcpy(ptr, &m_rootID,
sizeof(
id_type));
1166 memcpy(ptr, &m_fillFactor,
sizeof(
double));
1167 ptr +=
sizeof(double);
1168 memcpy(ptr, &m_indexCapacity,
sizeof(uint32_t));
1169 ptr +=
sizeof(uint32_t);
1170 memcpy(ptr, &m_leafCapacity,
sizeof(uint32_t));
1171 ptr +=
sizeof(uint32_t);
1172 memcpy(ptr, &m_nearMinimumOverlapFactor,
sizeof(uint32_t));
1173 ptr +=
sizeof(uint32_t);
1174 memcpy(ptr, &m_splitDistributionFactor,
sizeof(
double));
1175 ptr +=
sizeof(double);
1176 memcpy(ptr, &m_reinsertFactor,
sizeof(
double));
1177 ptr +=
sizeof(double);
1178 memcpy(ptr, &m_dimension,
sizeof(uint32_t));
1179 ptr +=
sizeof(uint32_t);
1180 char c = (char) m_bTightMBRs;
1181 memcpy(ptr, &c,
sizeof(
char));
1182 ptr +=
sizeof(char);
1183 memcpy(ptr, &(m_stats.m_u32Nodes),
sizeof(uint32_t));
1184 ptr +=
sizeof(uint32_t);
1185 memcpy(ptr, &(m_stats.m_u64Data),
sizeof(uint64_t));
1186 ptr +=
sizeof(uint64_t);
1187 memcpy(ptr, &(m_stats.m_u32TreeHeight),
sizeof(uint32_t));
1188 ptr +=
sizeof(uint32_t);
1190 for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel)
1192 memcpy(ptr, &(m_stats.m_nodesInLevel[cLevel]),
sizeof(uint32_t));
1193 ptr +=
sizeof(uint32_t);
1196 m_pStorageManager->storeByteArray(m_headerID, headerSize, header);
1201 void SpatialIndex::RTree::RTree::loadHeader()
1203 uint32_t headerSize;
1204 uint8_t* header =
nullptr;
1205 m_pStorageManager->loadByteArray(m_headerID, headerSize, &header);
1207 uint8_t* ptr = header;
1209 memcpy(&m_rootID, ptr,
sizeof(
id_type));
1213 memcpy(&m_fillFactor, ptr,
sizeof(
double));
1214 ptr +=
sizeof(double);
1215 memcpy(&m_indexCapacity, ptr,
sizeof(uint32_t));
1216 ptr +=
sizeof(uint32_t);
1217 memcpy(&m_leafCapacity, ptr,
sizeof(uint32_t));
1218 ptr +=
sizeof(uint32_t);
1219 memcpy(&m_nearMinimumOverlapFactor, ptr,
sizeof(uint32_t));
1220 ptr +=
sizeof(uint32_t);
1221 memcpy(&m_splitDistributionFactor, ptr,
sizeof(
double));
1222 ptr +=
sizeof(double);
1223 memcpy(&m_reinsertFactor, ptr,
sizeof(
double));
1224 ptr +=
sizeof(double);
1225 memcpy(&m_dimension, ptr,
sizeof(uint32_t));
1226 ptr +=
sizeof(uint32_t);
1228 memcpy(&c, ptr,
sizeof(
char));
1229 m_bTightMBRs = (c != 0);
1230 ptr +=
sizeof(char);
1231 memcpy(&(m_stats.m_u32Nodes), ptr,
sizeof(uint32_t));
1232 ptr +=
sizeof(uint32_t);
1233 memcpy(&(m_stats.m_u64Data), ptr,
sizeof(uint64_t));
1234 ptr +=
sizeof(uint64_t);
1235 memcpy(&(m_stats.m_u32TreeHeight), ptr,
sizeof(uint32_t));
1236 ptr +=
sizeof(uint32_t);
1238 for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel)
1241 memcpy(&cNodes, ptr,
sizeof(uint32_t));
1242 ptr +=
sizeof(uint32_t);
1243 m_stats.m_nodesInLevel.push_back(cNodes);
1249 void SpatialIndex::RTree::RTree::insertData_impl(uint32_t dataLength, uint8_t* pData,
Region& mbr,
id_type id)
1253 std::stack<id_type> pathBuffer;
1254 uint8_t* overflowTable =
nullptr;
1258 NodePtr root = readNode(m_rootID);
1260 overflowTable =
new uint8_t[root->m_level];
1261 memset(overflowTable, 0, root->m_level);
1263 NodePtr l = root->chooseSubtree(mbr, 0, pathBuffer);
1264 if (l.
get() == root.
get())
1269 l->insertData(dataLength, pData, mbr,
id, pathBuffer, overflowTable);
1271 delete[] overflowTable;
1272 ++(m_stats.m_u64Data);
1276 delete[] overflowTable;
1281 void SpatialIndex::RTree::RTree::insertData_impl(uint32_t dataLength, uint8_t* pData,
Region& mbr,
id_type id, uint32_t level, uint8_t* overflowTable)
1285 std::stack<id_type> pathBuffer;
1286 NodePtr root = readNode(m_rootID);
1287 NodePtr n = root->chooseSubtree(mbr, level, pathBuffer);
1289 assert(n->m_level == level);
1291 if (n.
get() == root.
get())
1296 n->insertData(dataLength, pData, mbr,
id, pathBuffer, overflowTable);
1299 bool SpatialIndex::RTree::RTree::deleteData_impl(
const Region& mbr,
id_type id)
1303 std::stack<id_type> pathBuffer;
1304 NodePtr root = readNode(m_rootID);
1305 NodePtr l = root->findLeaf(mbr,
id, pathBuffer);
1306 if (l.
get() == root.
get())
1312 if (l.
get() !=
nullptr)
1316 --(m_stats.m_u64Data);
1326 uint32_t dataLength;
1331 else page = n->m_identifier;
1335 m_pStorageManager->storeByteArray(page, dataLength, buffer);
1341 std::cerr << e.
what() << std::endl;
1345 if (n->m_identifier < 0)
1347 n->m_identifier = page;
1348 ++(m_stats.m_u32Nodes);
1350 m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] + 1;
1353 ++(m_stats.m_u64Writes);
1355 for (
size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex)
1357 m_writeNodeCommands[cIndex]->execute(*n);
1365 uint32_t dataLength;
1370 m_pStorageManager->loadByteArray(page, dataLength, &buffer);
1374 std::cerr << e.
what() << std::endl;
1381 memcpy(&nodeType, buffer,
sizeof(uint32_t));
1389 if (n.
get() ==
nullptr)
1396 n->m_identifier = page;
1399 ++(m_stats.m_u64Reads);
1401 for (
size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex)
1403 m_readNodeCommands[cIndex]->execute(*n);
1416 void SpatialIndex::RTree::RTree::deleteNode(
Node* n)
1420 m_pStorageManager->deleteByteArray(n->m_identifier);
1424 std::cerr << e.
what() << std::endl;
1428 --(m_stats.m_u32Nodes);
1429 m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] - 1;
1431 for (
size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex)
1433 m_deleteNodeCommands[cIndex]->execute(*n);
1439 std::stack<NodePtr> st;
1440 NodePtr root = readNode(m_rootID);
1442 if (root->m_children > 0 && query.
intersectsShape(root->m_nodeMBR)) st.push(root);
1444 while (! st.empty())
1446 NodePtr n = st.top(); st.pop();
1448 if (n->m_level == 0)
1452 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
1460 Data data =
Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]);
1462 ++(m_stats.m_u64QueryResults);
1470 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
1472 if (query.
intersectsShape(*(n->m_ptrMBR[cChild]))) st.push(readNode(n->m_pIdentifier[cChild]));
1485 for (uint32_t cChild1 = 0; cChild1 < n1->m_children; ++cChild1)
1489 for (uint32_t cChild2 = 0; cChild2 < n2->m_children; ++cChild2)
1495 if (n1->m_level == 0)
1497 if (n1->m_pIdentifier[cChild1] != n2->m_pIdentifier[cChild2])
1499 assert(n2->m_level == 0);
1501 std::vector<const IData*> v;
1502 Data e1(n1->m_pDataLength[cChild1], n1->m_pData[cChild1], *(n1->m_ptrMBR[cChild1]), n1->m_pIdentifier[cChild1]);
1503 Data e2(n2->m_pDataLength[cChild2], n2->m_pData[cChild2], *(n2->m_ptrMBR[cChild2]), n2->m_pIdentifier[cChild2]);
1512 selfJoinQuery(n1->m_pIdentifier[cChild1], n2->m_pIdentifier[cChild2], rr, vis);
1520 void SpatialIndex::RTree::RTree::visitSubTree(
NodePtr subTree,
IVisitor& v)
1522 std::stack<NodePtr> st;
1525 while (! st.empty())
1527 NodePtr n = st.top(); st.pop();
1532 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
1534 Data data =
Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]);
1536 ++(m_stats.m_u64QueryResults);
1541 for (uint32_t cChild = 0; cChild < n->m_children; ++cChild)
1543 st.push(readNode(n->m_pIdentifier[cChild]));
1551 os <<
"Dimension: " << t.m_dimension << std::endl
1552 <<
"Fill factor: " << t.m_fillFactor << std::endl
1553 <<
"Index capacity: " << t.m_indexCapacity << std::endl
1554 <<
"Leaf capacity: " << t.m_leafCapacity << std::endl
1555 <<
"Tight MBRs: " << ((t.m_bTightMBRs) ?
"enabled" :
"disabled") << std::endl;
1559 os <<
"Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl
1560 <<
"Reinsert factor: " << t.m_reinsertFactor << std::endl
1561 <<
"Split distribution factor: " << t.m_splitDistributionFactor << std::endl;
S & Container(std::priority_queue< T, S, C > &q)
std::vector< uint64_t > & GetResults()
uint64_t GetResultCount() const
virtual double getMinimumDistance(const IShape &query, const IShape &entry)=0
virtual void getNextEntry(const IEntry &previouslyFetched, id_type &nextEntryToFetch, bool &bFetchNextEntry)=0
virtual bool containsShape(const IShape &in) const =0
virtual bool intersectsShape(const IShape &in) const =0
virtual uint32_t getDimension() const =0
virtual void getMBR(Region &out) const =0
virtual void visitNode(const INode &in)=0
virtual void visitData(const IData &in)=0
std::string what() override
void bulkLoadUsingSTR(RTree *pTree, IDataStream &stream, uint32_t bindex, uint32_t bleaf, uint32_t pageSize, uint32_t numberOfPages)
id_type getIdentifier() const override
void getShape(IShape **out) const override
void storeToByteArray(uint8_t **data, uint32_t &len) override
void getData(uint32_t &len, uint8_t **data) const override
Data(uint32_t len, uint8_t *pData, Region &r, id_type id)
uint32_t getByteArraySize() override
void loadFromByteArray(const uint8_t *data) override
virtual void deleteData(const Region &mbr, id_type id, std::stack< id_type > &pathBuffer)
void loadFromByteArray(const uint8_t *data) override
void storeToByteArray(uint8_t **data, uint32_t &len) override
id_type getIdentifier() const override
virtual bool deleteData(const IShape &shape, id_type id)
virtual void getStatistics(IStatistics **out) const
virtual double nearestNeighborQuery(uint32_t k, const IShape &query, IVisitor &v, INearestNeighborComparator &, double max_dist=0.0)
virtual void queryStrategy(IQueryStrategy &qs)
RTree(IStorageManager &, Tools::PropertySet &)
virtual void addCommand(ICommand *pCommand, CommandType ct)
virtual void getIndexProperties(Tools::PropertySet &out) const
virtual void pointLocationQuery(const Point &query, IVisitor &v)
virtual void internalNodesQuery(const IShape &query, IVisitor &v)
virtual void containsWhatQuery(const IShape &query, IVisitor &v)
virtual bool isIndexValid()
virtual void intersectsWithQuery(const IShape &query, IVisitor &v)
virtual void insertData(uint32_t len, const uint8_t *pData, const IShape &shape, id_type shapeIdentifier)
virtual void selfJoinQuery(const IShape &s, IVisitor &v)
uint64_t getNumberOfData() const override
virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const
uint32_t getDimension() const override
virtual Region getIntersectingRegion(const Region &r) const
virtual bool intersectsRegion(const Region &in) const
SIDX_DLL ISpatialIndex * loadRTree(IStorageManager &in, id_type indexIdentifier)
SIDX_DLL ISpatialIndex * createAndBulkLoadNewRTree(BulkLoadMethod m, IDataStream &stream, IStorageManager &sm, double fillFactor, uint32_t indexCapacity, uint32_t leafCapacity, uint32_t dimension, RTreeVariant rv, id_type &indexIdentifier)
Tools::PoolPointer< Node > NodePtr
SIDX_DLL ISpatialIndex * returnRTree(IStorageManager &ind, Tools::PropertySet &in)
SIDX_DLL ISpatialIndex * createNewRTree(IStorageManager &sm, double fillFactor, uint32_t indexCapacity, uint32_t leafCapacity, uint32_t dimension, RTreeVariant rv, id_type &indexIdentifier)
std::ostream & operator<<(std::ostream &os, const RTree &t)