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

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

Constructor & Destructor Documentation

inet::QuadTree::QuadTree ( const Coord boundaryMin,
const Coord boundaryMax,
unsigned int  quadrantCapacity,
QuadTree parent 
)

Referenced by splitPoints().

252 {
253  this->boundaryMax = boundaryMax;
254  this->boundaryMin = boundaryMin;
256  this->parent = parent;
257  setToLeaf();
258  // lastPosition containing information for all subtrees in a QuadTree
259  // so we only create it when we create a root (indicated by parent == nullptr)
260  // node. Each subtree inherits this pointer and use its global
261  // information
262  if (parent == nullptr)
263  lastPosition = new std::map<const cObject *, Coord>;
264  else
266 }
Coord boundaryMin
Definition: QuadTree.h:41
Coord boundaryMax
Definition: QuadTree.h:42
unsigned int quadrantCapacity
Definition: QuadTree.h:40
std::map< const cObject *, Coord > * lastPosition
Definition: QuadTree.h:37
void setToLeaf()
Definition: QuadTree.cc:100
QuadTree * parent
Definition: QuadTree.h:45
inet::QuadTree::~QuadTree ( )
269 {
270  for (auto & elem : quadrants)
271  delete elem;
272  // We clear lastPosition if and only if we delete the whole tree
273  // Take a look at the constructor to see why we do this!
274  if (parent == nullptr)
275  delete lastPosition;
276 }
std::map< const cObject *, Coord > * lastPosition
Definition: QuadTree.h:37
QuadTree * quadrants[4]
Definition: QuadTree.h:44
QuadTree * parent
Definition: QuadTree.h:45

Member Function Documentation

bool inet::QuadTree::doesIntersectWithQuadrant ( const Coord pos,
double  range 
) const
protected

Referenced by rangeQuery(), and strictRangeQuery().

141 {
142  Coord minRectangleBoundary = pos;
143  Coord maxRectangleBoundary = pos;
144  minRectangleBoundary.x -= range;
145  minRectangleBoundary.y -= range;
146  maxRectangleBoundary.x += range;
147  maxRectangleBoundary.y += range;
148  return !((minRectangleBoundary.x > boundaryMax.x) || (maxRectangleBoundary.x < boundaryMin.x) ||
149  (minRectangleBoundary.y > boundaryMax.y) || (maxRectangleBoundary.y < boundaryMin.y));
150 }
Coord boundaryMin
Definition: QuadTree.h:41
Coord boundaryMax
Definition: QuadTree.h:42
double y
Definition: Coord.h:50
double x
Definition: Coord.h:49
bool inet::QuadTree::hasChild ( ) const
protected

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

199 {
200  return quadrants[0] != nullptr;
201 }
QuadTree * quadrants[4]
Definition: QuadTree.h:44
bool inet::QuadTree::insert ( const cObject *  point,
const Coord pos 
)

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

23 {
24  if (!isInRectangleRange(pos))
25  return false;
26  if (points.size() < quadrantCapacity && !hasChild()) {
27  (*lastPosition)[point] = pos;
28  points.push_back(point);
29  return true;
30  }
31  // If the rootNode is a leaf with a point set
32  // with no free capacity, then we must split its
33  // points into new quadrants
34  if (!hasChild())
35  splitPoints();
36  for (auto & elem : quadrants)
37  if (elem->insert(point, pos))
38  return true;
39  throw cRuntimeError("QuadTree insertion failed for object: %s with position: (%f, %f, %f)", point->getFullName(), pos.x, pos.y, pos.z);
40  return false;
41 }
bool hasChild() const
Definition: QuadTree.cc:198
bool isInRectangleRange(const Coord &pointCoord) const
Definition: QuadTree.cc:134
unsigned int quadrantCapacity
Definition: QuadTree.h:40
void splitPoints()
Definition: QuadTree.cc:76
QuadTree * quadrants[4]
Definition: QuadTree.h:44
Points points
Definition: QuadTree.h:43
bool inet::QuadTree::isInRectangleRange ( const Coord pointCoord) const
protected

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

135 {
136  return pointCoord.x <= boundaryMax.x && pointCoord.x >= boundaryMin.x &&
137  pointCoord.y <= boundaryMax.y && pointCoord.y >= boundaryMin.y;
138 }
Coord boundaryMin
Definition: QuadTree.h:41
Coord boundaryMax
Definition: QuadTree.h:42
double y
Definition: Coord.h:50
double x
Definition: Coord.h:49
bool inet::QuadTree::move ( const cObject *  point,
const Coord newPos 
)
235 {
236  QuadTree *quadrant = searchQuadrant(newPos);
237  // It is an error! Our QuadTree must find an appropriate quadrant since the root node
238  // boundary coordinates equal to the constraint area coordinates.
239  if (quadrant == nullptr)
240  throw cRuntimeError("Quadrant not found for point (%f %f %f)", newPos.x, newPos.y, newPos.z);
241  auto it = find(quadrant->points.begin(), quadrant->points.end(), point);
242  // If we search for a quadrant with the object's current position and then we find
243  // it in the quadrant's vector, then the move occurred inside this quadrant,
244  // thus we have nothing to do with this case
245  if (it != quadrant->points.end())
246  return true;
247  else // Otherwise, we remove the object and insert it again
248  return remove(point) && insert(point, newPos);
249 }
QuadTree * searchQuadrant(const Coord &lastPos)
Definition: QuadTree.cc:180
bool insert(const cObject *point, const Coord &pos)
Definition: QuadTree.cc:22
QuadTree(const Coord &boundaryMin, const Coord &boundaryMax, unsigned int quadrantCapacity, QuadTree *parent)
Definition: QuadTree.cc:251
std::vector< T >::iterator find(std::vector< T > &v, const T &a)
Definition: stlutils.h:48
void inet::QuadTree::rangeQuery ( const Coord pos,
double  range,
const IVisitor visitor 
) const

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

107 {
108  // If our rectangle intersects with a quadrant then we insert its objects to the
109  // neighbors vector
110  // Note that, a node have points only if it is a leaf node
111  if (!hasChild() && doesIntersectWithQuadrant(pos, range))
112  for (auto & elem : points)
113  visitor->visit(elem);
114  else if (hasChild())
115  for (auto & elem : quadrants)
116  elem->rangeQuery(pos, range, visitor);
117 }
bool hasChild() const
Definition: QuadTree.cc:198
QuadTree * quadrants[4]
Definition: QuadTree.h:44
Points points
Definition: QuadTree.h:43
bool doesIntersectWithQuadrant(const Coord &pos, double range) const
Definition: QuadTree.cc:140
bool inet::QuadTree::remove ( const cObject *  point)

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

153 {
154  // We search for the quadrant that may contain our object
155  // Note that, we need the last position of the object, that is, the position when we
156  // inserted it into the QuadTree
157  // This helps to searchRadioQuadrant(), since we don't have to traverse
158  // the whole QuadTree and check each node's vector one by one.
159  Coord lastPos;
160  auto lastIt = lastPosition->find(point);
161  if (lastIt != lastPosition->end())
162  lastPos = lastIt->second;
163  else
164  return false;
165  QuadTree *quadrant = searchQuadrant(lastPos);
166  if (quadrant == nullptr)
167  throw cRuntimeError("Quadrant not found for point: (%f, %f, %f)", lastPos.x, lastPos.y, lastPos.z);
168  auto it = find(quadrant->points.begin(), quadrant->points.end(), point);
169  // If we find the object then we erase it from the quadrant's vector and lastPosition map
170  if (it != quadrant->points.end()) {
171  lastPosition->erase(lastIt);
172  quadrant->points.erase(it);
173  }
174  else
175  throw cRuntimeError("Point (%f, %f, %f) not found in its quadrant's vector", lastPos.x, lastPos.y, lastPos.z);
176  quadrant->parent->tryToJoinChildQuadrants();
177  return true;
178 }
QuadTree * searchQuadrant(const Coord &lastPos)
Definition: QuadTree.cc:180
std::map< const cObject *, Coord > * lastPosition
Definition: QuadTree.h:37
QuadTree(const Coord &boundaryMin, const Coord &boundaryMax, unsigned int quadrantCapacity, QuadTree *parent)
Definition: QuadTree.cc:251
std::vector< T >::iterator find(std::vector< T > &v, const T &a)
Definition: stlutils.h:48
QuadTree * inet::QuadTree::searchQuadrant ( const Coord lastPos)
protected

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

181 {
182  // If lastPos is in the quadrant and that quadrant has no child,
183  // then we found the quadrant which _may_ contain our object.
184  // Note that, this can not guarantee that the object is in the quadrant's
185  // vector, so you must check it yourself!
186  if (!hasChild() && isInRectangleRange(lastPos))
187  return this;
188  else if (hasChild()) {
189  for (auto & elem : quadrants)
190  if (elem->isInRectangleRange(lastPos))
191  return elem->searchQuadrant(lastPos);
192  return nullptr;
193  }
194  else
195  return nullptr;
196 }
bool hasChild() const
Definition: QuadTree.cc:198
bool isInRectangleRange(const Coord &pointCoord) const
Definition: QuadTree.cc:134
QuadTree * quadrants[4]
Definition: QuadTree.h:44
void inet::QuadTree::setBoundary ( Coord minBoundaries,
Coord maxBoundaries 
) const
protected

Referenced by splitPoints().

53 {
54  // We just divide a rectangle into four smaller congruent rectangle
55  maxBoundaries[0].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
56  minBoundaries[0].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
57  minBoundaries[0].x = boundaryMin.x;
58  maxBoundaries[0].y = boundaryMax.y;
59 
60  minBoundaries[1].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
61  minBoundaries[1].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
62  maxBoundaries[1].x = boundaryMax.x;
63  maxBoundaries[1].y = boundaryMax.y;
64 
65  maxBoundaries[2].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
66  maxBoundaries[2].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
67  minBoundaries[2].x = boundaryMin.x;
68  minBoundaries[2].y = boundaryMin.y;
69 
70  minBoundaries[3].x = (boundaryMax.x - boundaryMin.x) / 2 + boundaryMin.x;
71  maxBoundaries[3].y = (boundaryMax.y - boundaryMin.y) / 2 + boundaryMin.y;
72  maxBoundaries[3].x = boundaryMax.x;
73  minBoundaries[3].y = boundaryMin.y;
74 }
Coord boundaryMin
Definition: QuadTree.h:41
Coord boundaryMax
Definition: QuadTree.h:42
double y
Definition: Coord.h:50
double x
Definition: Coord.h:49
void inet::QuadTree::setToLeaf ( )
protected

Referenced by QuadTree(), and tryToJoinChildQuadrants().

101 {
102  for (auto & elem : quadrants)
103  elem = nullptr;
104 }
QuadTree * quadrants[4]
Definition: QuadTree.h:44
void inet::QuadTree::splitPoints ( )
protected

Referenced by insert().

77 {
78  Coord minBoundaries[4], maxBoundaries[4];
79  setBoundary(minBoundaries, maxBoundaries);
80  // We make four new quadrants
81  for (unsigned int i = 0; i < 4; i++)
82  quadrants[i] = new QuadTree(minBoundaries[i], maxBoundaries[i], quadrantCapacity, this);
83  // The node is not a leaf anymore
84  // so we have to split its point
85  for (auto & elem : points) {
86  auto it = lastPosition->find(elem);
87  Coord pos;
88  if (it != lastPosition->end())
89  pos = it->second;
90  else
91  throw cRuntimeError("Last position not found for object: %s", elem->getFullName());
92  unsigned int quadrantNum = whichQuadrant(pos);
93  // We recursively call insert() for each points
94  quadrants[quadrantNum]->insert(elem, pos);
95  }
96  // Now we can free the node's vector
97  points.clear();
98 }
void setBoundary(Coord *minBoundaries, Coord *maxBoundaries) const
Definition: QuadTree.cc:52
unsigned int whichQuadrant(const Coord &pos) const
Definition: QuadTree.cc:43
unsigned int quadrantCapacity
Definition: QuadTree.h:40
std::map< const cObject *, Coord > * lastPosition
Definition: QuadTree.h:37
bool insert(const cObject *point, const Coord &pos)
Definition: QuadTree.cc:22
QuadTree * quadrants[4]
Definition: QuadTree.h:44
QuadTree(const Coord &boundaryMin, const Coord &boundaryMax, unsigned int quadrantCapacity, QuadTree *parent)
Definition: QuadTree.cc:251
Points points
Definition: QuadTree.h:43
void inet::QuadTree::strictRangeQuery ( const Coord pos,
double  range,
const IVisitor visitor 
) const
120 {
121  if (!hasChild() && doesIntersectWithQuadrant(pos, range)) {
122  for (auto & elem : points) {
123  Coord otherPos = (*lastPosition)[elem];
124  if (pos.sqrdist(otherPos) <= range * range)
125  visitor->visit(elem);
126  }
127  }
128  else if (hasChild()) {
129  for (auto & elem : quadrants)
130  elem->strictRangeQuery(pos, range, visitor);
131  }
132 }
bool hasChild() const
Definition: QuadTree.cc:198
QuadTree * quadrants[4]
Definition: QuadTree.h:44
Points points
Definition: QuadTree.h:43
bool doesIntersectWithQuadrant(const Coord &pos, double range) const
Definition: QuadTree.cc:140
void inet::QuadTree::tryToJoinChildQuadrants ( )
protected

Referenced by tryToJoinChildQuadrants().

204 {
205  unsigned int quadrantSum = 0;
206 
207  for (auto & elem : quadrants) {
208  // We surely can't join quadrants if one quadrant has another
209  // subquadrants
210  if (elem->hasChild())
211  return;
212  quadrantSum += elem->points.size();
213  }
214  // If the child quadrants together contain no more
215  // than quadrantCapacity objects then we can
216  // join these quadrants
217  if (quadrantSum <= quadrantCapacity) {
218  // Copy the points to the parent node
219  for (auto quadrant : quadrants) {
220 
221  for (auto & elem : quadrant->points)
222  points.push_back(elem);
223  // Delete the child quadrants
224  delete quadrant;
225  }
226  // Then set to leaf
227  setToLeaf();
228  // Finally, we call it for the parent node
229  if (parent)
231  }
232 }
unsigned int quadrantCapacity
Definition: QuadTree.h:40
void setToLeaf()
Definition: QuadTree.cc:100
QuadTree * quadrants[4]
Definition: QuadTree.h:44
void tryToJoinChildQuadrants()
Definition: QuadTree.cc:203
QuadTree * parent
Definition: QuadTree.h:45
Points points
Definition: QuadTree.h:43
unsigned int inet::QuadTree::whichQuadrant ( const Coord pos) const
protected

Referenced by splitPoints().

44 {
45  for (unsigned int i = 0; i < 4; i++)
46  if (quadrants[i]->isInRectangleRange(pos))
47  return i;
48  throw cRuntimeError("QuadTree failed to determine to which quadrant point (%f, %f, %f) belongs to", pos.x, pos.y, pos.z);
49  return 19920213;
50 }
bool isInRectangleRange(const Coord &pointCoord) const
Definition: QuadTree.cc:134
QuadTree * quadrants[4]
Definition: QuadTree.h:44

Member Data Documentation

Coord inet::QuadTree::boundaryMax
protected
Coord inet::QuadTree::boundaryMin
protected
std::map<const cObject *, Coord>* inet::QuadTree::lastPosition
protected
QuadTree* inet::QuadTree::parent
protected
Points inet::QuadTree::points
protected
unsigned int inet::QuadTree::quadrantCapacity
protected

The documentation for this class was generated from the following files: