libspatialindex API Reference  (git-trunk)
tprtree/Node.cc
Go to the documentation of this file.
1 /******************************************************************************
2  * Project: libspatialindex - A C++ library for spatial indexing
3  * Author: Marios Hadjieleftheriou, mhadji@gmail.com
4  ******************************************************************************
5  * Copyright (c) 2002, Marios Hadjieleftheriou
6  *
7  * All rights reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26 ******************************************************************************/
27 
28 #include <cstring>
29 #include <cmath>
30 #include <limits>
31 
33 
34 #include "TPRTree.h"
35 #include "Node.h"
36 #include "Index.h"
37 
38 using namespace SpatialIndex;
39 using namespace SpatialIndex::TPRTree;
40 
41 //
42 // Tools::IObject interface
43 //
45 {
46  throw Tools::NotSupportedException("IObject::clone should never be called.");
47 }
48 
49 //
50 // Tools::ISerializable interface
51 //
53 {
54  return
55  (sizeof(uint32_t) +
56  sizeof(uint32_t) +
57  sizeof(uint32_t) +
58  sizeof(double) +
59  (m_children * (4 * m_pTree->m_dimension * sizeof(double) + sizeof(double) + sizeof(id_type) + sizeof(uint32_t))) +
60  m_totalDataLength +
61  (4 * m_pTree->m_dimension * sizeof(double)));
62 }
63 
64 void Node::loadFromByteArray(const uint8_t* ptr)
65 {
66  m_nodeMBR = m_pTree->m_infiniteRegion;
67 
68  // skip the node type information, it is not needed.
69  ptr += sizeof(uint32_t);
70 
71  memcpy(&m_level, ptr, sizeof(uint32_t));
72  ptr += sizeof(uint32_t);
73 
74  memcpy(&m_children, ptr, sizeof(uint32_t));
75  ptr += sizeof(uint32_t);
76 
77  memcpy(&(m_nodeMBR.m_startTime), ptr, sizeof(double));
78  ptr += sizeof(double);
79  m_nodeMBR.m_endTime = std::numeric_limits<double>::max();
80  //memcpy(&(m_nodeMBR.m_endTime), ptr, sizeof(double));
81  //ptr += sizeof(double);
82 
83  for (uint32_t cChild = 0; cChild < m_children; ++cChild)
84  {
85  m_ptrMBR[cChild] = m_pTree->m_regionPool.acquire();
86  m_ptrMBR[cChild]->makeDimension(m_pTree->m_dimension);
87 
88  memcpy(m_ptrMBR[cChild]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double));
89  ptr += m_pTree->m_dimension * sizeof(double);
90  memcpy(m_ptrMBR[cChild]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double));
91  ptr += m_pTree->m_dimension * sizeof(double);
92  memcpy(m_ptrMBR[cChild]->m_pVLow, ptr, m_pTree->m_dimension * sizeof(double));
93  ptr += m_pTree->m_dimension * sizeof(double);
94  memcpy(m_ptrMBR[cChild]->m_pVHigh, ptr, m_pTree->m_dimension * sizeof(double));
95  ptr += m_pTree->m_dimension * sizeof(double);
96  memcpy(&(m_ptrMBR[cChild]->m_startTime), ptr, sizeof(double));
97  ptr += sizeof(double);
98  m_ptrMBR[cChild]->m_endTime = std::numeric_limits<double>::max();
99 
100  memcpy(&(m_pIdentifier[cChild]), ptr, sizeof(id_type));
101  ptr += sizeof(id_type);
102 
103  memcpy(&(m_pDataLength[cChild]), ptr, sizeof(uint32_t));
104  ptr += sizeof(uint32_t);
105 
106  if (m_pDataLength[cChild] > 0)
107  {
108  m_totalDataLength += m_pDataLength[cChild];
109  m_pData[cChild] = new uint8_t[m_pDataLength[cChild]];
110  memcpy(m_pData[cChild], ptr, m_pDataLength[cChild]);
111  ptr += m_pDataLength[cChild];
112  }
113  else
114  {
115  m_pData[cChild] = nullptr;
116  }
117 
118  //m_nodeMBR.combineRegion(*(m_ptrMBR[cChild]));
119  }
120 
121  memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double));
122  ptr += m_pTree->m_dimension * sizeof(double);
123  memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double));
124  ptr += m_pTree->m_dimension * sizeof(double);
125  memcpy(m_nodeMBR.m_pVLow, ptr, m_pTree->m_dimension * sizeof(double));
126  ptr += m_pTree->m_dimension * sizeof(double);
127  memcpy(m_nodeMBR.m_pVHigh, ptr, m_pTree->m_dimension * sizeof(double));
128  //ptr += m_pTree->m_dimension * sizeof(double);
129 }
130 
131 void Node::storeToByteArray(uint8_t** data, uint32_t& len)
132 {
133  len = getByteArraySize();
134 
135  *data = new uint8_t[len];
136  uint8_t* ptr = *data;
137 
138  uint32_t nodeType;
139 
140  if (m_level == 0) nodeType = PersistentLeaf;
141  else nodeType = PersistentIndex;
142 
143  memcpy(ptr, &nodeType, sizeof(uint32_t));
144  ptr += sizeof(uint32_t);
145 
146  memcpy(ptr, &m_level, sizeof(uint32_t));
147  ptr += sizeof(uint32_t);
148 
149  memcpy(ptr, &m_children, sizeof(uint32_t));
150  ptr += sizeof(uint32_t);
151 
152  memcpy(ptr, &(m_nodeMBR.m_startTime), sizeof(double));
153  ptr += sizeof(double);
154 
155  for (uint32_t cChild = 0; cChild < m_children; ++cChild)
156  {
157  memcpy(ptr, m_ptrMBR[cChild]->m_pLow, m_pTree->m_dimension * sizeof(double));
158  ptr += m_pTree->m_dimension * sizeof(double);
159  memcpy(ptr, m_ptrMBR[cChild]->m_pHigh, m_pTree->m_dimension * sizeof(double));
160  ptr += m_pTree->m_dimension * sizeof(double);
161  memcpy(ptr, m_ptrMBR[cChild]->m_pVLow, m_pTree->m_dimension * sizeof(double));
162  ptr += m_pTree->m_dimension * sizeof(double);
163  memcpy(ptr, m_ptrMBR[cChild]->m_pVHigh, m_pTree->m_dimension * sizeof(double));
164  ptr += m_pTree->m_dimension * sizeof(double);
165  memcpy(ptr, &(m_ptrMBR[cChild]->m_startTime), sizeof(double));
166  ptr += sizeof(double);
167 
168  memcpy(ptr, &(m_pIdentifier[cChild]), sizeof(id_type));
169  ptr += sizeof(id_type);
170 
171  memcpy(ptr, &(m_pDataLength[cChild]), sizeof(uint32_t));
172  ptr += sizeof(uint32_t);
173 
174  if (m_pDataLength[cChild] > 0)
175  {
176  memcpy(ptr, m_pData[cChild], m_pDataLength[cChild]);
177  ptr += m_pDataLength[cChild];
178  }
179  }
180 
181  // store the node MBR for efficiency. This increases the node size a little bit.
182  memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double));
183  ptr += m_pTree->m_dimension * sizeof(double);
184  memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double));
185  ptr += m_pTree->m_dimension * sizeof(double);
186  memcpy(ptr, m_nodeMBR.m_pVLow, m_pTree->m_dimension * sizeof(double));
187  ptr += m_pTree->m_dimension * sizeof(double);
188  memcpy(ptr, m_nodeMBR.m_pVHigh, m_pTree->m_dimension * sizeof(double));
189  //ptr += m_pTree->m_dimension * sizeof(double);
190 
191  assert(len == (ptr - *data) + m_pTree->m_dimension * sizeof(double));
192 }
193 
194 //
195 // SpatialIndex::IEntry interface
196 //
198 {
199  return m_identifier;
200 }
201 
202 void Node::getShape(IShape** out) const
203 {
204  *out = new MovingRegion(m_nodeMBR);
205 }
206 
207 //
208 // SpatialIndex::INode interface
209 //
210 uint32_t Node::getChildrenCount() const
211 {
212  return m_children;
213 }
214 
216 {
217  if (index >= m_children) throw Tools::IndexOutOfBoundsException(index);
218 
219  return m_pIdentifier[index];
220 }
221 
222 void Node::getChildShape(uint32_t index, IShape** out) const
223 {
224  if (index >= m_children) throw Tools::IndexOutOfBoundsException(index);
225 
226  *out = new MovingRegion(*(m_ptrMBR[index]));
227 }
228 
229 void Node::getChildData(uint32_t index, uint32_t& length, uint8_t** data) const
230 {
231  if (index >= m_children) throw Tools::IndexOutOfBoundsException(index);
232  if (m_pData[index] == nullptr)
233  {
234  length = 0;
235  data = nullptr;
236  }
237  else
238  {
239  length = m_pDataLength[index];
240  *data = m_pData[index];
241  }
242 }
243 
244 uint32_t Node::getLevel() const
245 {
246  return m_level;
247 }
248 
249 bool Node::isLeaf() const
250 {
251  return (m_level == 0);
252 }
253 
254 bool Node::isIndex() const
255 {
256  return (m_level != 0);
257 }
258 
259 //
260 // Internal
261 //
262 
263 Node::Node()
264 = default;
265 
266 Node::Node(SpatialIndex::TPRTree::TPRTree* pTree, id_type id, uint32_t level, uint32_t capacity) :
267  m_pTree(pTree),
268  m_level(level),
269  m_identifier(id),
270  m_children(0),
271  m_capacity(capacity),
272  m_pData(nullptr),
273  m_ptrMBR(nullptr),
274  m_pIdentifier(nullptr),
275  m_pDataLength(nullptr),
276  m_totalDataLength(0)
277 {
278  m_nodeMBR.makeInfinite(m_pTree->m_dimension);
279 
280  try
281  {
282  m_pDataLength = new uint32_t[m_capacity + 1];
283  m_pData = new uint8_t*[m_capacity + 1];
284  m_ptrMBR = new MovingRegionPtr[m_capacity + 1];
285  m_pIdentifier = new id_type[m_capacity + 1];
286  }
287  catch (...)
288  {
289  delete[] m_pDataLength;
290  delete[] m_pData;
291  delete[] m_ptrMBR;
292  delete[] m_pIdentifier;
293  throw;
294  }
295 }
296 
298 {
299  if (m_pData != nullptr)
300  {
301  for (uint32_t cChild = 0; cChild < m_children; ++cChild)
302  {
303  if (m_pData[cChild] != nullptr) delete[] m_pData[cChild];
304  }
305 
306  delete[] m_pData;
307  }
308 
309  delete[] m_pDataLength;
310  delete[] m_ptrMBR;
311  delete[] m_pIdentifier;
312 }
313 
314 Node& Node::operator=(const Node&)
315 {
316  throw Tools::IllegalStateException("Node::operator =: This should never be called.");
317 }
318 
319 bool Node::insertEntry(uint32_t dataLength, uint8_t* pData, MovingRegion& mbr, id_type id)
320 {
321  assert(m_children < m_capacity);
322 
323  m_pDataLength[m_children] = dataLength;
324  m_pData[m_children] = pData;
325  m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire();
326  *(m_ptrMBR[m_children]) = mbr;
327  m_pIdentifier[m_children] = id;
328 
329  m_totalDataLength += dataLength;
330  ++m_children;
331 
332  if (m_nodeMBR.m_startTime != m_pTree->m_currentTime)
333  {
334  m_nodeMBR.m_startTime = m_pTree->m_currentTime;
335 
336  for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim)
337  {
338  m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
339  m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
340  m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max();
341  m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max();
342 
343  for (uint32_t cChild = 0; cChild < m_children; ++cChild)
344  {
345  m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime));
346  m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime));
347  m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]);
348  m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]);
349  }
350  m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon();
351  m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon();
352  }
353  }
354  else if (
355  //m_nodeMBR.m_pLow[0] != std::numeric_limits<double>::max() &&
356  ! m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, mbr))
357  {
358  for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim)
359  {
360  double l = m_nodeMBR.getExtrapolatedLow(cDim, m_pTree->m_currentTime);
361  double rl = mbr.getExtrapolatedLow(cDim, m_pTree->m_currentTime);
362  if (rl <= l)
363  {
364  m_nodeMBR.m_pLow[cDim] = rl - 2.0 * std::numeric_limits<double>::epsilon();
365  }
366 
367  double h = m_nodeMBR.getExtrapolatedHigh(cDim, m_pTree->m_currentTime);
368  double rh = mbr.getExtrapolatedHigh(cDim, m_pTree->m_currentTime);
369  if (rh >= h)
370  {
371  m_nodeMBR.m_pHigh[cDim] = rh + 2.0 * std::numeric_limits<double>::epsilon();
372  }
373 
374  m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], mbr.m_pVLow[cDim]);
375  m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], mbr.m_pVHigh[cDim]);
376  }
377  }
378 
379  return true;
380 }
381 
382 void Node::deleteEntry(uint32_t index)
383 {
384  assert(index >= 0 && index < m_children);
385 
386  // cache it, since I might need it for "touches" later.
387  MovingRegionPtr ptrR = m_ptrMBR[index];
388 
389  m_totalDataLength -= m_pDataLength[index];
390  if (m_pData[index] != nullptr) delete[] m_pData[index];
391 
392  if (m_children > 1 && index != m_children - 1)
393  {
394  m_pDataLength[index] = m_pDataLength[m_children - 1];
395  m_pData[index] = m_pData[m_children - 1];
396  m_ptrMBR[index] = m_ptrMBR[m_children - 1];
397  m_pIdentifier[index] = m_pIdentifier[m_children - 1];
398  }
399 
400  --m_children;
401 
402  // WARNING: index has now changed. Do not use it below here.
403 
404  if (m_children == 0)
405  {
406  m_nodeMBR = m_pTree->m_infiniteRegion;
407  }
408  else //if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesRegion(*ptrR))
409  {
410  m_nodeMBR.m_startTime = m_pTree->m_currentTime;
411 
412  for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim)
413  {
414  m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
415  m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
416  m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max();
417  m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max();
418 
419  for (uint32_t cChild = 0; cChild < m_children; ++cChild)
420  {
421  m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime));
422  m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime));
423  m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]);
424  m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]);
425  }
426  m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon();
427  m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon();
428  }
429 
430  }
431 }
432 
433 bool Node::insertData(uint32_t dataLength, uint8_t* pData, MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, uint8_t* overflowTable)
434 {
435  if (m_children < m_capacity)
436  {
437  bool bNeedToAdjust = insertEntry(dataLength, pData, mbr, id);
438  m_pTree->writeNode(this);
439 
440  if (bNeedToAdjust && ! pathBuffer.empty())
441  {
442  id_type cParent = pathBuffer.top(); pathBuffer.pop();
443  NodePtr ptrN = m_pTree->readNode(cParent);
444  Index* p = static_cast<Index*>(ptrN.get());
445  p->adjustTree(this, pathBuffer);
446  }
447 
448  return bNeedToAdjust;
449  }
450  else if (false &&
451  m_pTree->m_treeVariant == TPRV_RSTAR &&
452  !pathBuffer.empty() &&
453  overflowTable[m_level] == 0)
454  {
455  overflowTable[m_level] = 1;
456 
457  std::vector<uint32_t> vReinsert, vKeep;
458  reinsertData(dataLength, pData, mbr, id, vReinsert, vKeep);
459 
460  uint32_t lReinsert = static_cast<uint32_t>(vReinsert.size());
461  uint32_t lKeep = static_cast<uint32_t>(vKeep.size());
462 
463  uint8_t** reinsertdata = nullptr;
464  MovingRegionPtr* reinsertmbr = nullptr;
465  id_type* reinsertid = nullptr;
466  uint32_t* reinsertlen = nullptr;
467  uint8_t** keepdata = nullptr;
468  MovingRegionPtr* keepmbr = nullptr;
469  id_type* keepid = nullptr;
470  uint32_t* keeplen = nullptr;
471 
472  try
473  {
474  reinsertdata = new uint8_t*[lReinsert];
475  reinsertmbr = new MovingRegionPtr[lReinsert];
476  reinsertid = new id_type[lReinsert];
477  reinsertlen = new uint32_t[lReinsert];
478 
479  keepdata = new uint8_t*[m_capacity + 1];
480  keepmbr = new MovingRegionPtr[m_capacity + 1];
481  keepid = new id_type[m_capacity + 1];
482  keeplen = new uint32_t[m_capacity + 1];
483  }
484  catch (...)
485  {
486  delete[] reinsertdata;
487  delete[] reinsertmbr;
488  delete[] reinsertid;
489  delete[] reinsertlen;
490  delete[] keepdata;
491  delete[] keepmbr;
492  delete[] keepid;
493  delete[] keeplen;
494  throw;
495  }
496 
497  uint32_t cIndex;
498 
499  for (cIndex = 0; cIndex < lReinsert; ++cIndex)
500  {
501  reinsertlen[cIndex] = m_pDataLength[vReinsert[cIndex]];
502  reinsertdata[cIndex] = m_pData[vReinsert[cIndex]];
503  reinsertmbr[cIndex] = m_ptrMBR[vReinsert[cIndex]];
504  reinsertid[cIndex] = m_pIdentifier[vReinsert[cIndex]];
505  }
506 
507  for (cIndex = 0; cIndex < lKeep; ++cIndex)
508  {
509  keeplen[cIndex] = m_pDataLength[vKeep[cIndex]];
510  keepdata[cIndex] = m_pData[vKeep[cIndex]];
511  keepmbr[cIndex] = m_ptrMBR[vKeep[cIndex]];
512  keepid[cIndex] = m_pIdentifier[vKeep[cIndex]];
513  }
514 
515  delete[] m_pDataLength;
516  delete[] m_pData;
517  delete[] m_ptrMBR;
518  delete[] m_pIdentifier;
519 
520  m_pDataLength = keeplen;
521  m_pData = keepdata;
522  m_ptrMBR = keepmbr;
523  m_pIdentifier = keepid;
524  m_children = lKeep;
525  m_totalDataLength = 0;
526 
527  for (uint32_t cChild = 0; cChild < m_children; ++cChild) m_totalDataLength += m_pDataLength[cChild];
528 
529  m_nodeMBR.m_startTime = m_pTree->m_currentTime;
530 
531  for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim)
532  {
533  m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
534  m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
535  m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max();
536  m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max();
537 
538  for (uint32_t cChild = 0; cChild < m_children; ++cChild)
539  {
540  m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime));
541  m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime));
542  m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]);
543  m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]);
544  }
545  m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon();
546  m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon();
547  }
548 
549  m_pTree->writeNode(this);
550 
551  // Diversion from R*-Tree algorithm here. First adjust
552  // the path to the root, then start reinserts, to avoid complicated handling
553  // of changes to the same node from multiple insertions.
554  id_type cParent = pathBuffer.top(); pathBuffer.pop();
555  NodePtr ptrN = m_pTree->readNode(cParent);
556  Index* p = static_cast<Index*>(ptrN.get());
557  p->adjustTree(this, pathBuffer);
558 
559  for (cIndex = 0; cIndex < lReinsert; ++cIndex)
560  {
561  m_pTree->insertData_impl(
562  reinsertlen[cIndex], reinsertdata[cIndex],
563  *(reinsertmbr[cIndex]), reinsertid[cIndex],
564  m_level, overflowTable);
565  }
566 
567  delete[] reinsertdata;
568  delete[] reinsertmbr;
569  delete[] reinsertid;
570  delete[] reinsertlen;
571 
572  return true;
573  }
574  else
575  {
576  NodePtr n;
577  NodePtr nn;
578  split(dataLength, pData, mbr, id, n, nn);
579 
580  if (pathBuffer.empty())
581  {
582  n->m_level = m_level;
583  nn->m_level = m_level;
584  n->m_identifier = -1;
585  nn->m_identifier = -1;
586 
587  m_pTree->writeNode(n.get());
588  m_pTree->writeNode(nn.get());
589 
590  NodePtr ptrR = m_pTree->m_indexPool.acquire();
591  if (ptrR.get() == nullptr)
592  {
593  ptrR = NodePtr(new Index(m_pTree, m_pTree->m_rootID, m_level + 1), &(m_pTree->m_indexPool));
594  }
595  else
596  {
597  //ptrR->m_pTree = m_pTree;
598  ptrR->m_identifier = m_pTree->m_rootID;
599  ptrR->m_level = m_level + 1;
600  ptrR->m_nodeMBR = m_pTree->m_infiniteRegion;
601  }
602 
603  ptrR->insertEntry(0, nullptr, n->m_nodeMBR, n->m_identifier);
604  ptrR->insertEntry(0, nullptr, nn->m_nodeMBR, nn->m_identifier);
605 
606  m_pTree->writeNode(ptrR.get());
607 
608  m_pTree->m_stats.m_nodesInLevel[m_level] = 2;
609  m_pTree->m_stats.m_nodesInLevel.push_back(1);
610  m_pTree->m_stats.m_treeHeight = m_level + 2;
611  }
612  else
613  {
614  n->m_level = m_level;
615  nn->m_level = m_level;
616  n->m_identifier = m_identifier;
617  nn->m_identifier = -1;
618 
619  m_pTree->writeNode(n.get());
620  m_pTree->writeNode(nn.get());
621 
622  id_type cParent = pathBuffer.top(); pathBuffer.pop();
623  NodePtr ptrN = m_pTree->readNode(cParent);
624  Index* p = static_cast<Index*>(ptrN.get());
625  p->adjustTree(n.get(), nn.get(), pathBuffer, overflowTable);
626  }
627 
628  return true;
629  }
630 }
631 
632 void Node::reinsertData(uint32_t dataLength, uint8_t* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep)
633 {
634  ReinsertEntry** v = new ReinsertEntry*[m_capacity + 1];
635 
636  m_pDataLength[m_children] = dataLength;
637  m_pData[m_children] = pData;
638  m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire();
639  *(m_ptrMBR[m_children]) = mbr;
640  m_pIdentifier[m_children] = id;
641 
642  Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon);
643 
644  for (uint32_t cChild = 0; cChild < m_capacity + 1; ++cChild)
645  {
646  try
647  {
648  v[cChild] = new ReinsertEntry(cChild, 0.0);
649  }
650  catch (...)
651  {
652  for (uint32_t i = 0; i < cChild; ++i) delete v[i];
653  delete[] v;
654  throw;
655  }
656 
657  v[cChild]->m_dist = m_nodeMBR.getCenterDistanceInTime(ivT, *(m_ptrMBR[cChild]));
658  }
659 
660  // sort by increasing order of distances.
661  ::qsort(v, m_capacity + 1, sizeof(ReinsertEntry*), ReinsertEntry::compareReinsertEntry);
662 
663  uint32_t cReinsert = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_reinsertFactor));
664 
665  uint32_t cCount;
666 
667  for (cCount = 0; cCount < cReinsert; ++cCount)
668  {
669  reinsert.push_back(v[cCount]->m_index);
670  delete v[cCount];
671  }
672 
673  for (cCount = cReinsert; cCount < m_capacity + 1; ++cCount)
674  {
675  keep.push_back(v[cCount]->m_index);
676  delete v[cCount];
677  }
678 
679  delete[] v;
680 }
681 
682 /*
683 void Node::rtreeSplit(uint32_t dataLength, uint8_t* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2)
684 {
685  uint32_t cChild;
686  uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor));
687 
688  // use this mask array for marking visited entries.
689  uint8_t* mask = new uint8_t[m_capacity + 1];
690  memset(mask, 0, m_capacity + 1);
691 
692  // insert new data in the node for easier manipulation. Data arrays are always
693  // by one larger than node capacity.
694  m_pDataLength[m_capacity] = dataLength;
695  m_pData[m_capacity] = pData;
696  m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire();
697  *(m_ptrMBR[m_capacity]) = mbr;
698  m_pIdentifier[m_capacity] = id;
699 
700  // initialize each group with the seed entries.
701  uint32_t seed1, seed2;
702  pickSeeds(seed1, seed2);
703 
704  group1.push_back(seed1);
705  group2.push_back(seed2);
706 
707  mask[seed1] = 1;
708  mask[seed2] = 1;
709 
710  // find MBR of each group.
711  RegionPtr mbr1 = m_pTree->m_regionPool.acquire();
712  *mbr1 = *(m_ptrMBR[seed1]);
713  RegionPtr mbr2 = m_pTree->m_regionPool.acquire();
714  *mbr2 = *(m_ptrMBR[seed2]);
715 
716  // count how many entries are left unchecked (exclude the seeds here.)
717  uint32_t cRemaining = m_capacity + 1 - 2;
718 
719  while (cRemaining > 0)
720  {
721  if (minimumLoad - group1.size() == cRemaining)
722  {
723  // all remaining entries must be assigned to group1 to comply with minimum load requirement.
724  for (cChild = 0; cChild < m_capacity + 1; ++cChild)
725  {
726  if (mask[cChild] == 0)
727  {
728  group1.push_back(cChild);
729  mask[cChild] = 1;
730  --cRemaining;
731  }
732  }
733  }
734  else if (minimumLoad - group2.size() == cRemaining)
735  {
736  // all remaining entries must be assigned to group2 to comply with minimum load requirement.
737  for (cChild = 0; cChild < m_capacity + 1; ++cChild)
738  {
739  if (mask[cChild] == 0)
740  {
741  group2.push_back(cChild);
742  mask[cChild] = 1;
743  --cRemaining;
744  }
745  }
746  }
747  else
748  {
749  // For all remaining entries compute the difference of the cost of grouping an
750  // entry in either group. When done, choose the entry that yielded the maximum
751  // difference. In case of linear split, select any entry (e.g. the first one.)
752  uint32_t sel;
753  double md1 = 0.0, md2 = 0.0;
754  double m = -std::numeric_limits<double>::max();
755  double d1, d2, d;
756  double a1 = mbr1->getArea();
757  double a2 = mbr2->getArea();
758 
759  RegionPtr a = m_pTree->m_regionPool.acquire();
760  RegionPtr b = m_pTree->m_regionPool.acquire();
761 
762  for (cChild = 0; cChild < m_capacity + 1; ++cChild)
763  {
764  if (mask[cChild] == 0)
765  {
766  mbr1->getCombinedRegion(*a, *(m_ptrMBR[cChild]));
767  d1 = a->getArea() - a1;
768  mbr2->getCombinedRegion(*b, *(m_ptrMBR[cChild]));
769  d2 = b->getArea() - a2;
770  d = std::abs(d1 - d2);
771 
772  if (d > m)
773  {
774  m = d;
775  md1 = d1; md2 = d2;
776  sel = cChild;
777  if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break;
778  }
779  }
780  }
781 
782  // determine the group where we should add the new entry.
783  int32_t group = -1;
784 
785  if (md1 < md2)
786  {
787  group1.push_back(sel);
788  group = 1;
789  }
790  else if (md2 < md1)
791  {
792  group2.push_back(sel);
793  group = 2;
794  }
795  else if (a1 < a2)
796  {
797  group1.push_back(sel);
798  group = 1;
799  }
800  else if (a2 < a1)
801  {
802  group2.push_back(sel);
803  group = 2;
804  }
805  else if (group1.size() < group2.size())
806  {
807  group1.push_back(sel);
808  group = 1;
809  }
810  else if (group2.size() < group1.size())
811  {
812  group2.push_back(sel);
813  group = 2;
814  }
815  else
816  {
817  group1.push_back(sel);
818  group = 1;
819  }
820  mask[sel] = 1;
821  --cRemaining;
822  if (group == 1)
823  {
824  mbr1->combineRegion(*(m_ptrMBR[sel]));
825  }
826  else
827  {
828  mbr2->combineRegion(*(m_ptrMBR[sel]));
829  }
830  }
831  }
832 
833  delete[] mask;
834 }
835 */
836 
837 void Node::rstarSplit(uint32_t dataLength, uint8_t* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2)
838 {
839  RstarSplitEntry** dataLow = nullptr;
840  RstarSplitEntry** dataHigh = nullptr;
841  RstarSplitEntry** dataVLow = nullptr;
842  RstarSplitEntry** dataVHigh = nullptr;
843 
844  try
845  {
846  dataLow = new RstarSplitEntry*[m_capacity + 1];
847  dataHigh = new RstarSplitEntry*[m_capacity + 1];
848  dataVLow = new RstarSplitEntry*[m_capacity + 1];
849  dataVHigh = new RstarSplitEntry*[m_capacity + 1];
850  }
851  catch (...)
852  {
853  delete[] dataLow;
854  delete[] dataHigh;
855  delete[] dataVLow;
856  delete[] dataVHigh;
857  throw;
858  }
859 
860  m_pDataLength[m_capacity] = dataLength;
861  m_pData[m_capacity] = pData;
862  m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire();
863  *(m_ptrMBR[m_capacity]) = mbr;
864  m_pIdentifier[m_capacity] = id;
865 
866  uint32_t nodeSPF = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_splitDistributionFactor));
867  uint32_t splitDistribution = (m_capacity + 1) - (2 * nodeSPF) + 2;
868 
869  Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon);
870 
871  uint32_t cChild = 0, cDim, cIndex;
872 
873  for (cChild = 0; cChild <= m_capacity; ++cChild)
874  {
875  try
876  {
877  dataLow[cChild] = new RstarSplitEntry(m_ptrMBR[cChild].get(), cChild, 0);
878  }
879  catch (...)
880  {
881  for (uint32_t i = 0; i < cChild; ++i) delete dataLow[i];
882  delete[] dataLow;
883  delete[] dataHigh;
884  throw;
885  }
886 
887  dataHigh[cChild] = dataLow[cChild];
888  dataVLow[cChild] = dataLow[cChild];
889  dataVHigh[cChild] = dataLow[cChild];
890  }
891 
892  double minimumMargin = std::numeric_limits<double>::max();
893  uint32_t splitAxis = std::numeric_limits<uint32_t>::max();
894  uint32_t sortOrder = std::numeric_limits<uint32_t>::max();
895 
896  // chooseSplitAxis.
897  for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim)
898  {
899  ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow);
900  ::qsort(dataHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh);
901  ::qsort(dataVLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVLow);
902  ::qsort(dataVHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVHigh);
903 
904  // calculate sum of margins and overlap for all distributions.
905  double marginl = 0.0;
906  double marginh = 0.0;
907  double marginvl = 0.0;
908  double marginvh = 0.0;
909 
910  MovingRegion bbl1, bbl2, bbh1, bbh2;
911  MovingRegion bbvl1, bbvl2, bbvh1, bbvh2;
912 
913  for (cChild = 1; cChild <= splitDistribution; ++cChild)
914  {
915  uint32_t l = nodeSPF - 1 + cChild;
916 
917  bbl1 = *(dataLow[0]->m_pRegion);
918  bbh1 = *(dataHigh[0]->m_pRegion);
919  bbvl1 = *(dataVLow[0]->m_pRegion);
920  bbvh1 = *(dataVHigh[0]->m_pRegion);
921 
922  for (cIndex = 1; cIndex < l; ++cIndex)
923  {
924  bbl1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion));
925  bbh1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataHigh[cIndex]->m_pRegion));
926  bbvl1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVLow[cIndex]->m_pRegion));
927  bbvh1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVHigh[cIndex]->m_pRegion));
928  }
929 
930  bbl2 = *(dataLow[l]->m_pRegion);
931  bbh2 = *(dataHigh[l]->m_pRegion);
932  bbvl2 = *(dataVLow[l]->m_pRegion);
933  bbvh2 = *(dataVHigh[l]->m_pRegion);
934 
935  for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex)
936  {
937  bbl2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion));
938  bbh2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataHigh[cIndex]->m_pRegion));
939  bbvl2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVLow[cIndex]->m_pRegion));
940  bbvh2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVHigh[cIndex]->m_pRegion));
941  }
942 
943  marginl += bbl1.getProjectedSurfaceAreaInTime(ivT) + bbl2.getProjectedSurfaceAreaInTime(ivT);
944  marginh += bbh1.getProjectedSurfaceAreaInTime(ivT) + bbh2.getProjectedSurfaceAreaInTime(ivT);
945  marginvl += bbvl1.getProjectedSurfaceAreaInTime(ivT) + bbvl2.getProjectedSurfaceAreaInTime(ivT);
946  marginvh += bbvh1.getProjectedSurfaceAreaInTime(ivT) + bbvh2.getProjectedSurfaceAreaInTime(ivT);
947  } // for (cChild)
948 
949  double margin = std::min(std::min(marginl, marginh), std::min(marginvl, marginvh));
950 
951  // keep minimum margin as split axis.
952  if (margin < minimumMargin)
953  {
954  minimumMargin = margin;
955  splitAxis = cDim;
956  if (marginl < marginh && marginl < marginvl && marginl < marginvh) sortOrder = 0;
957  else if (marginh < marginl && marginh < marginvl && marginh < marginvh) sortOrder = 1;
958  else if (marginvl < marginl && marginvl < marginh && marginvl < marginvh) sortOrder = 2;
959  else if (marginvh < marginl && marginvh < marginh && marginvh < marginvl) sortOrder = 3;
960  }
961 
962  // increase the dimension according to which the data entries should be sorted.
963  for (cChild = 0; cChild <= m_capacity; ++cChild)
964  {
965  dataLow[cChild]->m_sortDim = cDim + 1;
966  }
967  } // for (cDim)
968 
969  for (cChild = 0; cChild <= m_capacity; ++cChild)
970  {
971  dataLow[cChild]->m_sortDim = splitAxis;
972  }
973 
974  if (sortOrder == 0)
975  ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow);
976  else if (sortOrder == 1)
977  ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh);
978  else if (sortOrder == 2)
979  ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVLow);
980  else if (sortOrder == 3)
981  ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVHigh);
982 
983  double ma = std::numeric_limits<double>::max();
984  double mo = std::numeric_limits<double>::max();
985  uint32_t splitPoint = std::numeric_limits<uint32_t>::max();
986 
987  MovingRegion bb1, bb2;
988 
989  for (cChild = 1; cChild <= splitDistribution; ++cChild)
990  {
991  uint32_t l = nodeSPF - 1 + cChild;
992 
993  bb1 = *(dataLow[0]->m_pRegion);
994 
995  for (cIndex = 1; cIndex < l; ++cIndex)
996  {
997  bb1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion));
998  }
999 
1000  bb2 = *(dataLow[l]->m_pRegion);
1001 
1002  for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex)
1003  {
1004  bb2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion));
1005  }
1006 
1007  double o = bb1.getIntersectingAreaInTime(ivT, bb2);
1008 
1009  if (o < mo)
1010  {
1011  splitPoint = cChild;
1012  mo = o;
1013  ma = bb1.getAreaInTime(ivT) + bb2.getAreaInTime(ivT);
1014  }
1015  else if (o == mo)
1016  {
1017  double a = bb1.getAreaInTime(ivT) + bb2.getAreaInTime(ivT);
1018 
1019  if (a < ma)
1020  {
1021  splitPoint = cChild;
1022  ma = a;
1023  }
1024  }
1025  } // for (cChild)
1026 
1027  uint32_t l1 = nodeSPF - 1 + splitPoint;
1028 
1029  for (cIndex = 0; cIndex < l1; ++cIndex)
1030  {
1031  group1.push_back(dataLow[cIndex]->m_index);
1032  delete dataLow[cIndex];
1033  }
1034 
1035  for (cIndex = l1; cIndex <= m_capacity; ++cIndex)
1036  {
1037  group2.push_back(dataLow[cIndex]->m_index);
1038  delete dataLow[cIndex];
1039  }
1040 
1041  delete[] dataLow;
1042  delete[] dataHigh;
1043  delete[] dataVLow;
1044  delete[] dataVHigh;
1045 }
1046 
1047 /*
1048 void Node::pickSeeds(uint32_t& index1, uint32_t& index2)
1049 {
1050  double separation = -std::numeric_limits<double>::max();
1051  double inefficiency = -std::numeric_limits<double>::max();
1052  uint32_t cDim, cChild, cIndex;
1053 
1054  switch (m_pTree->m_treeVariant)
1055  {
1056  case RV_LINEAR:
1057  case RV_RSTAR:
1058  for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim)
1059  {
1060  double leastLower = m_ptrMBR[0]->m_pLow[cDim];
1061  double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim];
1062  uint32_t greatestLower = 0;
1063  uint32_t leastUpper = 0;
1064  double width;
1065 
1066  for (cChild = 1; cChild <= m_capacity; ++cChild)
1067  {
1068  if (m_ptrMBR[cChild]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = cChild;
1069  if (m_ptrMBR[cChild]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = cChild;
1070 
1071  leastLower = std::min(m_ptrMBR[cChild]->m_pLow[cDim], leastLower);
1072  greatestUpper = std::max(m_ptrMBR[cChild]->m_pHigh[cDim], greatestUpper);
1073  }
1074 
1075  width = greatestUpper - leastLower;
1076  if (width <= 0) width = 1;
1077 
1078  double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width;
1079 
1080  if (f > separation)
1081  {
1082  index1 = leastUpper;
1083  index2 = greatestLower;
1084  separation = f;
1085  }
1086  } // for (cDim)
1087 
1088  if (index1 == index2)
1089  {
1090  if (index2 == 0) ++index2;
1091  else --index2;
1092  }
1093 
1094  break;
1095  case RV_QUADRATIC:
1096  // for each pair of Regions (account for overflow Region too!)
1097  for (cChild = 0; cChild < m_capacity; ++cChild)
1098  {
1099  double a = m_ptrMBR[cChild]->getArea();
1100 
1101  for (cIndex = cChild + 1; cIndex <= m_capacity; ++cIndex)
1102  {
1103  // get the combined MBR of those two entries.
1104  Region r;
1105  m_ptrMBR[cChild]->getCombinedRegion(r, *(m_ptrMBR[cIndex]));
1106 
1107  // find the inefficiency of grouping these entries together.
1108  double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea();
1109 
1110  if (d > inefficiency)
1111  {
1112  inefficiency = d;
1113  index1 = cChild;
1114  index2 = cIndex;
1115  }
1116  } // for (cIndex)
1117  } // for (cChild)
1118 
1119  break;
1120  default:
1121  throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported.");
1122  }
1123 }
1124 */
1125 
1126 void Node::condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis)
1127 {
1128  uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor));
1129 
1130  if (pathBuffer.empty())
1131  {
1132  // eliminate root if it has only one child.
1133  if (m_level != 0 && m_children == 1)
1134  {
1135  NodePtr ptrN = m_pTree->readNode(m_pIdentifier[0]);
1136  m_pTree->deleteNode(ptrN.get());
1137  ptrN->m_identifier = m_pTree->m_rootID;
1138  m_pTree->writeNode(ptrN.get());
1139 
1140  m_pTree->m_stats.m_nodesInLevel.pop_back();
1141  m_pTree->m_stats.m_treeHeight -= 1;
1142  // HACK: pending deleteNode for deleted child will decrease nodesInLevel, later on.
1143  m_pTree->m_stats.m_nodesInLevel[m_pTree->m_stats.m_treeHeight - 1] = 2;
1144  }
1145  }
1146  else
1147  {
1148  id_type cParent = pathBuffer.top(); pathBuffer.pop();
1149  NodePtr ptrParent = m_pTree->readNode(cParent);
1150  Index* p = static_cast<Index*>(ptrParent.get());
1151 
1152  // find the entry in the parent, that points to this node.
1153  uint32_t child;
1154 
1155  for (child = 0; child != p->m_children; ++child)
1156  {
1157  if (p->m_pIdentifier[child] == m_identifier) break;
1158  }
1159 
1160  if (m_children < minimumLoad)
1161  {
1162  // used space less than the minimum
1163  // 1. eliminate node entry from the parent. deleteEntry will fix the parent's MBR.
1164  p->deleteEntry(child);
1165  // 2. add this node to the stack in order to reinsert its entries.
1166  toReinsert.push(ptrThis);
1167  }
1168  else
1169  {
1170  // adjust the entry in 'p' to contain the new bounding region of this node.
1171  *(p->m_ptrMBR[child]) = m_nodeMBR;
1172 
1173  // global recalculation necessary since the MBR can only shrink in size,
1174  // due to data removal.
1175  //if (m_pTree->m_bTightMBRs)
1176  //{
1177 
1178  p->m_nodeMBR.m_startTime = m_pTree->m_currentTime;
1179 
1180  for (uint32_t cDim = 0; cDim < p->m_nodeMBR.m_dimension; ++cDim)
1181  {
1182  p->m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
1183  p->m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
1184  p->m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max();
1185  p->m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max();
1186 
1187  for (uint32_t cChild = 0; cChild < p->m_children; ++cChild)
1188  {
1189  p->m_nodeMBR.m_pLow[cDim] = std::min(p->m_nodeMBR.m_pLow[cDim], p->m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_pTree->m_currentTime));
1190  p->m_nodeMBR.m_pHigh[cDim] = std::max(p->m_nodeMBR.m_pHigh[cDim], p->m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_pTree->m_currentTime));
1191  p->m_nodeMBR.m_pVLow[cDim] = std::min(p->m_nodeMBR.m_pVLow[cDim], p->m_ptrMBR[cChild]->m_pVLow[cDim]);
1192  p->m_nodeMBR.m_pVHigh[cDim] = std::max(p->m_nodeMBR.m_pVHigh[cDim], p->m_ptrMBR[cChild]->m_pVHigh[cDim]);
1193  }
1194  p->m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon();
1195  p->m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon();
1196  }
1197  //}
1198  }
1199 
1200  // write parent node back to storage.
1201  m_pTree->writeNode(p);
1202 
1203  p->condenseTree(toReinsert, pathBuffer, ptrParent);
1204  }
1205 }
void makeDimension(uint32_t dimension) override
virtual double getCenterDistanceInTime(const MovingRegion &r) const
double getAreaInTime() const override
virtual bool containsRegionAfterTime(double t, const MovingRegion &r) const
virtual double getIntersectingAreaInTime(const MovingRegion &r) const
virtual void combineRegionAfterTime(double t, const MovingRegion &r)
virtual double getProjectedSurfaceAreaInTime() const
void makeInfinite(uint32_t dimension) override
virtual double getExtrapolatedLow(uint32_t index, double t) const
virtual double getExtrapolatedHigh(uint32_t index, double t) const
double * m_pHigh
Definition: Region.h:101
uint32_t m_dimension
Definition: Region.h:99
double * m_pLow
Definition: Region.h:100
uint32_t getLevel() const override
void getChildShape(uint32_t index, IShape **out) const override
void loadFromByteArray(const uint8_t *data) override
Definition: tprtree/Node.cc:64
void storeToByteArray(uint8_t **data, uint32_t &len) override
void getChildData(uint32_t index, uint32_t &length, uint8_t **data) const override
bool isIndex() const override
Tools::IObject * clone() override
Definition: tprtree/Node.cc:44
uint32_t getChildrenCount() const override
uint32_t getByteArraySize() override
Definition: tprtree/Node.cc:52
void getShape(IShape **out) const override
id_type getChildIdentifier(uint32_t index) const override
bool isLeaf() const override
id_type getIdentifier() const override
X * get() const noexcept
Definition: PoolPointer.h:55
Tools::PoolPointer< Node > NodePtr
Definition: tprtree/Node.h:39
int64_t id_type
Definition: SpatialIndex.h:41