LBIBCell
 All Classes Functions Variables Friends Pages
QuadTreeNode.hpp
1 /* Copyright (c) 2012 David Sichau <mail"at"sichau"dot"eu>
2 
3  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
4  "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,
5  distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
6  the following conditions:
7 
8  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
11  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
12  NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
13  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
14  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15  */
16 #ifndef UTILLIB_GEOMETRY_QUADTREENODE_HPP
17 #define UTILLIB_GEOMETRY_QUADTREENODE_HPP
18 
19 #include <UtilLib/include/geometry/Rectangle.hpp>
20 #include <UtilLib/include/Log.hpp>
21 #include <algorithm>
22 #include <array>
23 #include <memory>
24 #include <vector>
25 
26 
27 namespace UtilLib {
28 namespace geometry {
33 template<class Node>
34 class QuadTreeNode {
35  public:
41  explicit QuadTreeNode(
42  const Rectangle& rect,
43  int maximumItems);
44 
48  ~QuadTreeNode();
49 
55  bool put(std::shared_ptr<Node> pt);
56 
63  std::vector<std::shared_ptr<Node> >& get(
64  const Rectangle& rect,
65  std::vector<std::shared_ptr<Node> >& vector);
66 
67  private:
71  void split();
72 
79  QuadTreeNode* getChild(
80  double x,
81  double y);
82 
87  bool hasChildren();
88 
92  enum Regions {NORTHWEST = 0, NORTHEAST = 1, SOUTHEAST = 2, SOUTHWEST = 3};
93 
97  std::vector<std::shared_ptr<Node> > items_;
98 
102  std::array<QuadTreeNode*, 4>* children_;
103 
107  unsigned int maxItems_;
111  Rectangle bounds_;
112 
116  const double minSize_;
117 };
118 
119 template<class Node>
121  const Rectangle& rect,
122  int maximumItems) : children_(nullptr),
123  maxItems_(maximumItems),
124  bounds_(rect),
125  minSize_(1E-4) {
126  LOG(UtilLib::logDEBUG2) << "new node generated with boarder n: " <<
127  bounds_.north << " s: " << bounds_.south << " w: " <<
128  bounds_.west << " e: " << bounds_.east;
129 }
130 
131 template<class Node>
133  if (children_ != nullptr) {
134  for (const auto& child :* children_) {
135  delete child;
136  }
137  delete children_;
138  children_ = nullptr;
139  }
140 }
141 
142 template<class Node>
144  return children_ != nullptr;
145 }
146 
147 template<class Node>
148 void QuadTreeNode<Node>::split() {
149  if ((std::abs(bounds_.north - bounds_.south) < minSize_) &&
150  (std::abs(bounds_.east - bounds_.west) < minSize_) ) {
151  LOG(UtilLib::logDEBUG4) << "below min size therefore no split";
152 
153  return;
154  }
155 
156  LOG(UtilLib::logDEBUG4) << "split executed";
157 
158  double nsHalf =
159  static_cast<double>(bounds_.north -
160  (bounds_.north - bounds_.south) / 2.0);
161  double ewHalf =
162  static_cast<double>(bounds_.east - (bounds_.east - bounds_.west) / 2.0);
163 
164  children_ = new std::array<QuadTreeNode*, 4>;
165 
166  (*children_)[NORTHWEST] =
167  new QuadTreeNode(Rectangle(bounds_.north, nsHalf, bounds_.west,
168  ewHalf), maxItems_);
169  (*children_)[NORTHEAST] =
170  new QuadTreeNode(Rectangle(bounds_.north, nsHalf, ewHalf,
171  bounds_.east), maxItems_);
172  (*children_)[SOUTHEAST] =
173  new QuadTreeNode(Rectangle(nsHalf, bounds_.south, ewHalf,
174  bounds_.east), maxItems_);
175  (*children_)[SOUTHWEST] =
176  new QuadTreeNode(Rectangle(nsHalf, bounds_.south, bounds_.west,
177  ewHalf), maxItems_);
178 
179  for (auto item : items_) {
180  put(item);
181  }
182  items_.clear();
183 }
184 
185 template<class Node>
186 QuadTreeNode<Node>* QuadTreeNode<Node>::getChild(
187  double x,
188  double y)
189 {
190  if (bounds_.pointWithinBounds(x, y))
191  {
192  if (children_ != nullptr) {
193  for (QuadTreeNode<Node>* child :* children_)
194  {
195  if (child->bounds_.pointWithinBounds(x, y))
196  return child->getChild(x, y);
197  }
198  } else {
199  return this; // no children, x, y here...
200  }
201  }
202  return nullptr;
203 }
204 
205 template<class Node>
206 bool QuadTreeNode<Node>::put(std::shared_ptr<Node> pt) {
207  if (children_ == nullptr) {
208  items_.push_back(pt);
209  if (items_.size() > maxItems_)
210  split();
211 
212  return true;
213  } else {
214  QuadTreeNode* node = getChild(pt->getXPos(), pt->getYPos());
215  if (node != nullptr) {
216  return node->put(pt);
217  }
218  }
219  return false;
220 }
221 
222 template<class Node>
223 std::vector<std::shared_ptr<Node> >& QuadTreeNode<Node>::get(
224  const Rectangle& rect,
225  std::vector<std::shared_ptr<Node> >& vector) {
226  if (children_ == nullptr) {
227  for (std::shared_ptr<Node> pt : items_) {
228  if (rect.pointWithinBounds(pt->getXPos(), pt->getYPos())) {
229  vector.push_back(pt);
230  LOG(UtilLib::logDEBUG4) << "point added: " << pt->getXPos() <<
231  " " << pt->getYPos();
232  }
233  }
234  } else {
235  for (QuadTreeNode* child :* children_) {
236  if (child->bounds_.within(rect)) {
237  LOG(UtilLib::logDEBUG4) << "went to children";
238  child->get(rect, vector);
239  }
240  }
241  }
242  return vector;
243 }
244 } // end namepace
245 } // end namepace
246 
247 #endif // UTILLIB_GEOMETRY_QUADTREENODE_HPP
bool put(std::shared_ptr< Node > pt)
put Inserts a point into the Node
const double north
the north border
Definition: Rectangle.hpp:74
QuadTreeNode(const Rectangle &rect, int maximumItems)
QuadTreeNode Constructs a new QuadTreeNode.
const double south
the north border
Definition: Rectangle.hpp:75
const double west
the north border
Definition: Rectangle.hpp:76
bool pointWithinBounds(double x, double y) const
pointWithinBounds Checks if point is contained inside this rectangle
Definition: Rectangle.cpp:63
const double east
the north border
Definition: Rectangle.hpp:77
std::vector< std::shared_ptr< Node > > & get(const Rectangle &rect, std::vector< std::shared_ptr< Node > > &vector)
get Get all Points in the defined rectangle
a class representing a rectangle
Definition: Rectangle.hpp:30
class representing a node of a quadtree The template parameter Node needs to provide the methods getX...