INET Framework for OMNeT++/OMNEST
inet::QuadTree Class Reference

#include <QuadTree.h>

Public Types

typedef std::vector< const cObject * > Points
 

Public Member Functions

bool move (const cObject *point, const Coord &newPos)
 
bool remove (const cObject *point)
 
bool insert (const cObject *point, const Coord &pos)
 
void rangeQuery (const Coord &pos, double range, const IVisitor *visitor) const
 
void strictRangeQuery (const Coord &pos, double range, const IVisitor *visitor) const
 
 QuadTree (const Coord &boundaryMin, const Coord &boundaryMax, unsigned int quadrantCapacity, QuadTree *parent)
 
 ~QuadTree ()
 

Protected Member Functions

QuadTreesearchQuadrant (const Coord &lastPos)
 
unsigned int whichQuadrant (const Coord &pos) const
 
bool hasChild () const
 
void setBoundary (Coord *minBoundaries, Coord *maxBoundaries) const
 
void splitPoints ()
 
void setToLeaf ()
 
bool isInRectangleRange (const Coord &pointCoord) const
 
bool doesIntersectWithQuadrant (const Coord &pos, double range) const
 
void tryToJoinChildQuadrants ()
 

Protected Attributes

std::map< const cObject *, Coord > * lastPosition
 
unsigned int quadrantCapacity
 
Coord boundaryMin
 
Coord boundaryMax
 
Points points
 
QuadTreequadrants [4]
 
QuadTreeparent
 

Member Typedef Documentation

◆ Points

typedef std::vector<const cObject *> inet::QuadTree::Points

Constructor & Destructor Documentation

◆ QuadTree()

inet::QuadTree::QuadTree ( const Coord boundaryMin,
const Coord boundaryMax,
unsigned int  quadrantCapacity,
QuadTree parent 
)
241 {
242  this->boundaryMax = boundaryMax;
243  this->boundaryMin = boundaryMin;
245  this->parent = parent;
246  setToLeaf();
247  // lastPosition containing information for all subtrees in a QuadTree
248  // so we only create it when we create a root (indicated by parent == nullptr)
249  // node. Each subtree inherits this pointer and use its global
250  // information
251  if (parent == nullptr)
252  lastPosition = new std::map<const cObject *, Coord>;
253  else
255 }

Referenced by splitPoints().

◆ ~QuadTree()

inet::QuadTree::~QuadTree ( )
258 {
259  for (auto& elem : quadrants)
260  delete elem;
261  // We clear lastPosition if and only if we delete the whole tree
262  // Take a look at the constructor to see why we do this!
263  if (parent == nullptr)
264  delete lastPosition;
265 }

Member Function Documentation

◆ doesIntersectWithQuadrant()

bool inet::QuadTree::doesIntersectWithQuadrant ( const Coord pos,
double  range 
) const
protected
131 {
132  Coord minRectangleBoundary = pos;
133  Coord maxRectangleBoundary = pos;
134  minRectangleBoundary.x -= range;
135  minRectangleBoundary.y -= range;
136  maxRectangleBoundary.x += range;
137  maxRectangleBoundary.y += range;
138  return !((minRectangleBoundary.x > boundaryMax.x) || (maxRectangleBoundary.x < boundaryMin.x) ||
139  (minRectangleBoundary.y > boundaryMax.y) || (maxRectangleBoundary.y < boundaryMin.y));
140 }

Referenced by rangeQuery(), and strictRangeQuery().

◆ hasChild()

bool inet::QuadTree::hasChild ( ) const
protected
188 {
189  return quadrants[0] != nullptr;
190 }

Referenced by insert(), rangeQuery(), searchQuadrant(), and strictRangeQuery().

◆ insert()

bool inet::QuadTree::insert ( const cObject *  point,
const Coord pos 
)
15 {
16  if (!isInRectangleRange(pos))
17  return false;
18  if (points.size() < quadrantCapacity && !hasChild()) {
19  (*lastPosition)[point] = pos;
20  points.push_back(point);
21  return true;
22  }
23  // If the rootNode is a leaf with a point set
24  // with no free capacity, then we must split its
25  // points into new quadrants
26  if (!hasChild())
27  splitPoints();
28  for (auto& elem : quadrants)
29  if (elem->insert(point, pos))
30  return true;
31  throw cRuntimeError("QuadTree insertion failed for object: %s with position: (%f, %f, %f)", point->getFullName(), pos.x, pos.y, pos.z);
32  return false;
33 }

Referenced by inet::physicallayer::QuadTreeNeighborCache::addRadio(), inet::physicallayer::QuadTreeNeighborCache::fillQuadTreeWithRadios(), move(), and splitPoints().

◆ isInRectangleRange()

bool inet::QuadTree::isInRectangleRange ( const Coord pointCoord) const
protected
125 {
126  return pointCoord.x <= boundaryMax.x && pointCoord.x >= boundaryMin.x &&
127  pointCoord.y <= boundaryMax.y && pointCoord.y >= boundaryMin.y;
128 }

Referenced by insert(), searchQuadrant(), and whichQuadrant().

◆ move()

bool inet::QuadTree::move ( const cObject *  point,
const Coord newPos 
)
224 {
225  QuadTree *quadrant = searchQuadrant(newPos);
226  // It is an error! Our QuadTree must find an appropriate quadrant since the root node
227  // boundary coordinates equal to the constraint area coordinates.
228  if (quadrant == nullptr)
229  throw cRuntimeError("Quadrant not found for point (%f %f %f)", newPos.x, newPos.y, newPos.z);
230  auto it = find(quadrant->points, point);
231  // If we search for a quadrant with the object's current position and then we find
232  // it in the quadrant's vector, then the move occurred inside this quadrant,
233  // thus we have nothing to do with this case
234  if (it != quadrant->points.end())
235  return true;
236  else // Otherwise, we remove the object and insert it again
237  return remove(point) && insert(point, newPos);
238 }

◆ rangeQuery()

void inet::QuadTree::rangeQuery ( const Coord pos,
double  range,
const IVisitor visitor 
) const
97 {
98  // If our rectangle intersects with a quadrant then we insert its objects to the
99  // neighbors vector
100  // Note that, a node have points only if it is a leaf node
101  if (!hasChild() && doesIntersectWithQuadrant(pos, range))
102  for (auto& elem : points)
103  visitor->visit(elem);
104  else if (hasChild())
105  for (auto& elem : quadrants)
106  elem->rangeQuery(pos, range, visitor);
107 }

Referenced by inet::physicallayer::QuadTreeNeighborCache::sendToNeighbors().

◆ remove()

bool inet::QuadTree::remove ( const cObject *  point)
143 {
144  // We search for the quadrant that may contain our object
145  // Note that, we need the last position of the object, that is, the position when we
146  // inserted it into the QuadTree
147  // This helps to searchRadioQuadrant(), since we don't have to traverse
148  // the whole QuadTree and check each node's vector one by one.
149  Coord lastPos;
150  auto lastIt = lastPosition->find(point);
151  if (lastIt == lastPosition->end())
152  return false;
153  lastPos = lastIt->second;
154  QuadTree *quadrant = searchQuadrant(lastPos);
155  if (quadrant == nullptr)
156  throw cRuntimeError("Quadrant not found for point: (%f, %f, %f)", lastPos.x, lastPos.y, lastPos.z);
157  auto it = find(quadrant->points, point);
158  // If we find the object then we erase it from the quadrant's vector and lastPosition map
159  if (it != quadrant->points.end()) {
160  lastPosition->erase(lastIt);
161  quadrant->points.erase(it);
162  }
163  else
164  throw cRuntimeError("Point (%f, %f, %f) not found in its quadrant's vector", lastPos.x, lastPos.y, lastPos.z);
165  quadrant->parent->tryToJoinChildQuadrants();
166  return true;
167 }

Referenced by move(), and inet::physicallayer::QuadTreeNeighborCache::removeRadio().

◆ searchQuadrant()

QuadTree * inet::QuadTree::searchQuadrant ( const Coord lastPos)
protected
170 {
171  // If lastPos is in the quadrant and that quadrant has no child,
172  // then we found the quadrant which _may_ contain our object.
173  // Note that, this can not guarantee that the object is in the quadrant's
174  // vector, so you must check it yourself!
175  if (!hasChild() && isInRectangleRange(lastPos))
176  return this;
177  else if (hasChild()) {
178  for (auto& elem : quadrants)
179  if (elem->isInRectangleRange(lastPos))
180  return elem->searchQuadrant(lastPos);
181  return nullptr;
182  }
183  else
184  return nullptr;
185 }

Referenced by move(), remove(), and searchQuadrant().

◆ setBoundary()

void inet::QuadTree::setBoundary ( Coord minBoundaries,
Coord maxBoundaries 
) const
protected
45 {
46  // We just divide a rectangle into four smaller congruent rectangle
47  maxBoundaries[0].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
48  minBoundaries[0].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
49  minBoundaries[0].x = boundaryMin.x;
50  maxBoundaries[0].y = boundaryMax.y;
51 
52  minBoundaries[1].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
53  minBoundaries[1].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
54  maxBoundaries[1].x = boundaryMax.x;
55  maxBoundaries[1].y = boundaryMax.y;
56 
57  maxBoundaries[2].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
58  maxBoundaries[2].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
59  minBoundaries[2].x = boundaryMin.x;
60  minBoundaries[2].y = boundaryMin.y;
61 
62  minBoundaries[3].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
63  maxBoundaries[3].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
64  maxBoundaries[3].x = boundaryMax.x;
65  minBoundaries[3].y = boundaryMin.y;
66 }

Referenced by splitPoints().

◆ setToLeaf()

void inet::QuadTree::setToLeaf ( )
protected
91 {
92  for (auto& elem : quadrants)
93  elem = nullptr;
94 }

Referenced by QuadTree(), and tryToJoinChildQuadrants().

◆ splitPoints()

void inet::QuadTree::splitPoints ( )
protected
69 {
70  Coord minBoundaries[4], maxBoundaries[4];
71  setBoundary(minBoundaries, maxBoundaries);
72  // We make four new quadrants
73  for (unsigned int i = 0; i < 4; i++)
74  quadrants[i] = new QuadTree(minBoundaries[i], maxBoundaries[i], quadrantCapacity, this);
75  // The node is not a leaf anymore
76  // so we have to split its point
77  for (auto& elem : points) {
78  auto it = lastPosition->find(elem);
79  if (it == lastPosition->end())
80  throw cRuntimeError("Last position not found for object: %s", elem->getFullName());
81  Coord pos = it->second;
82  unsigned int quadrantNum = whichQuadrant(pos);
83  // We recursively call insert() for each points
84  quadrants[quadrantNum]->insert(elem, pos);
85  }
86  // Now we can free the node's vector
87  points.clear();
88 }

Referenced by insert().

◆ strictRangeQuery()

void inet::QuadTree::strictRangeQuery ( const Coord pos,
double  range,
const IVisitor visitor 
) const
110 {
111  if (!hasChild() && doesIntersectWithQuadrant(pos, range)) {
112  for (auto& elem : points) {
113  Coord otherPos = (*lastPosition)[elem];
114  if (pos.sqrdist(otherPos) <= range * range)
115  visitor->visit(elem);
116  }
117  }
118  else if (hasChild()) {
119  for (auto& elem : quadrants)
120  elem->strictRangeQuery(pos, range, visitor);
121  }
122 }

◆ tryToJoinChildQuadrants()

void inet::QuadTree::tryToJoinChildQuadrants ( )
protected
193 {
194  unsigned int quadrantSum = 0;
195 
196  for (auto& elem : quadrants) {
197  // We surely can't join quadrants if one quadrant has another
198  // subquadrants
199  if (elem->hasChild())
200  return;
201  quadrantSum += elem->points.size();
202  }
203  // If the child quadrants together contain no more
204  // than quadrantCapacity objects then we can
205  // join these quadrants
206  if (quadrantSum <= quadrantCapacity) {
207  // Copy the points to the parent node
208  for (auto quadrant : quadrants) {
209 
210  for (auto& elem : quadrant->points)
211  points.push_back(elem);
212  // Delete the child quadrants
213  delete quadrant;
214  }
215  // Then set to leaf
216  setToLeaf();
217  // Finally, we call it for the parent node
218  if (parent)
220  }
221 }

Referenced by remove(), and tryToJoinChildQuadrants().

◆ whichQuadrant()

unsigned int inet::QuadTree::whichQuadrant ( const Coord pos) const
protected
36 {
37  for (unsigned int i = 0; i < 4; i++)
38  if (quadrants[i]->isInRectangleRange(pos))
39  return i;
40  throw cRuntimeError("QuadTree failed to determine to which quadrant point (%f, %f, %f) belongs to", pos.x, pos.y, pos.z);
41  return 19920213;
42 }

Referenced by splitPoints().

Member Data Documentation

◆ boundaryMax

Coord inet::QuadTree::boundaryMax
protected

◆ boundaryMin

Coord inet::QuadTree::boundaryMin
protected

◆ lastPosition

std::map<const cObject *, Coord>* inet::QuadTree::lastPosition
protected

◆ parent

QuadTree* inet::QuadTree::parent
protected

◆ points

Points inet::QuadTree::points
protected

◆ quadrantCapacity

unsigned int inet::QuadTree::quadrantCapacity
protected

◆ quadrants


The documentation for this class was generated from the following files:
inet::QuadTree::setBoundary
void setBoundary(Coord *minBoundaries, Coord *maxBoundaries) const
Definition: QuadTree.cc:44
inet::QuadTree::doesIntersectWithQuadrant
bool doesIntersectWithQuadrant(const Coord &pos, double range) const
Definition: QuadTree.cc:130
inet::QuadTree::points
Points points
Definition: QuadTree.h:33
inet::find
std::vector< T >::iterator find(std::vector< T > &v, const Tk &a)
Definition: stlutils.h:44
inet::Coord::x
double x
Definition: Coord.h:36
inet::QuadTree::boundaryMax
Coord boundaryMax
Definition: QuadTree.h:32
inet::QuadTree::hasChild
bool hasChild() const
Definition: QuadTree.cc:187
inet::QuadTree::remove
bool remove(const cObject *point)
Definition: QuadTree.cc:142
inet::QuadTree::splitPoints
void splitPoints()
Definition: QuadTree.cc:68
inet::QuadTree::parent
QuadTree * parent
Definition: QuadTree.h:35
inet::QuadTree::boundaryMin
Coord boundaryMin
Definition: QuadTree.h:31
inet::QuadTree::whichQuadrant
unsigned int whichQuadrant(const Coord &pos) const
Definition: QuadTree.cc:35
inet::QuadTree::lastPosition
std::map< const cObject *, Coord > * lastPosition
Definition: QuadTree.h:27
inet::QuadTree::insert
bool insert(const cObject *point, const Coord &pos)
Definition: QuadTree.cc:14
inet::QuadTree::setToLeaf
void setToLeaf()
Definition: QuadTree.cc:90
inet::Coord::y
double y
Definition: Coord.h:37
inet::QuadTree::tryToJoinChildQuadrants
void tryToJoinChildQuadrants()
Definition: QuadTree.cc:192
inet::QuadTree::isInRectangleRange
bool isInRectangleRange(const Coord &pointCoord) const
Definition: QuadTree.cc:124
inet::QuadTree::quadrants
QuadTree * quadrants[4]
Definition: QuadTree.h:34
inet::QuadTree::QuadTree
QuadTree(const Coord &boundaryMin, const Coord &boundaryMax, unsigned int quadrantCapacity, QuadTree *parent)
Definition: QuadTree.cc:240
inet::QuadTree::quadrantCapacity
unsigned int quadrantCapacity
Definition: QuadTree.h:30
inet::QuadTree::searchQuadrant
QuadTree * searchQuadrant(const Coord &lastPos)
Definition: QuadTree.cc:169