Image Component Library (ICL)
QuadTree.h
Go to the documentation of this file.
1 /********************************************************************
2 ** Image Component Library (ICL) **
3 ** **
4 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld **
5 ** Neuroinformatics Group **
6 ** Website: www.iclcv.org and **
7 ** http://opensource.cit-ec.de/projects/icl **
8 ** **
9 ** File : ICLMath/src/ICLMath/QuadTree.h **
10 ** Module : ICLMath **
11 ** Authors: Christof Elbrechter **
12 ** **
13 ** **
14 ** GNU LESSER GENERAL PUBLIC LICENSE **
15 ** This file may be used under the terms of the GNU Lesser General **
16 ** Public License version 3.0 as published by the **
17 ** **
18 ** Free Software Foundation and appearing in the file LICENSE.LGPL **
19 ** included in the packaging of this file. Please review the **
20 ** following information to ensure the license requirements will **
21 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt **
22 ** **
23 ** The development of this software was supported by the **
24 ** Excellence Cluster EXC 277 Cognitive Interaction Technology. **
25 ** The Excellence Cluster EXC 277 is a grant of the Deutsche **
26 ** Forschungsgemeinschaft (DFG) in the context of the German **
27 ** Excellence Initiative. **
28 ** **
29 ********************************************************************/
30 
31 #pragma once
32 
33 
34 #include <ICLUtils/CompatMacros.h>
35 #include <ICLMath/FixedVector.h>
37 #include <ICLUtils/Rect32f.h>
38 #include <ICLUtils/Range.h>
39 #include <ICLUtils/StringUtils.h>
40 
41 #include <algorithm>
42 #include <set>
43 
44 namespace icl{
45 
46  namespace math{
47 
48 
50 
174  template<class Scalar, int CAPACITY=4, int SF=1, int ALLOC_CHUNK_SIZE=1024,
175  class VECTOR_TYPE=FixedColVector<Scalar,2> >
176  class QuadTree{
177  public:
178 
179  // 2D-point type, internally used
180  typedef VECTOR_TYPE Pt;
181 
182  protected:
183 
185 
187  struct AABB{
190 
192  AABB(){}
193 
195  AABB(const Pt &center, const Pt &halfSize):
197 
199  bool contains(const Pt &p) const{
200  return ( p[0] >= center[0] - halfSize[0]
201  && p[1] >= center[1] - halfSize[1]
202  && p[0] <= center[0] + halfSize[0]
203 
204  && p[1] <= center[1] + halfSize[1]);
205  }
206 
208  bool intersects(const AABB &o) const{
209 #ifdef WIN32
210  return (fabs((float)center[0] - o.center[0]) < (halfSize[0] + o.halfSize[0])
211  && fabs((float)center[1] - o.center[1]) < (halfSize[1] + o.halfSize[1]));
212 #else
213  return (fabs(center[0] - o.center[0]) < (halfSize[0] + o.halfSize[0])
214  && fabs(center[1] - o.center[1]) < (halfSize[1] + o.halfSize[1]));
215 #endif
216  }
217 
218 
220  return utils::Rect32f(double(center[0])/SF - double(halfSize[0])/SF, double(center[1])/SF - double(halfSize[1])/SF,
221  double(halfSize[0])/SF*2, double(halfSize[1])/SF*2);
222  }
223  };
224 
226 
228  struct Node{
230  Pt points[CAPACITY];
231  Pt *next;
234 
236  Node(){}
237 
239  Node(const AABB &boundary){
240  init(0,boundary);
241  }
243 
244  void init(Node *parent, const AABB &boundary){
245  this->boundary = boundary;
246  this->next = this->points;
247  this->children = 0;
248  this->parent = parent;
249  }
250 
252 
255  void query(const AABB &boundary, std::vector<Pt> &found) const{
256  if (!this->boundary.intersects(boundary)){
257  return;
258  }
259  for(const Pt *p=points; p<next ; ++p){
260  if(boundary.contains(*p)){
261  found.push_back((*p)/SF);//Pt((*p)[0]/SF,(*p)[1]/SF));
262  }
263  }
264  if(!children) return;
265 
266  children[0].query(boundary,found);
267  children[1].query(boundary,found);
268  children[2].query(boundary,found);
269  children[3].query(boundary,found);
270  }
271 
273 
277  const Pt half = boundary.halfSize/2;//*0.5;
278 
279  const Pt &c = boundary.center;
280  this->children = children;
281  this->children[0].init(this,AABB(Pt(c[0]-half[0],c[1]-half[1]),half));
282  this->children[1].init(this,AABB(Pt(c[0]+half[0],c[1]-half[1]),half));
283  this->children[2].init(this,AABB(Pt(c[0]-half[0],c[1]+half[1]),half));
284  this->children[3].init(this,AABB(Pt(c[0]+half[0],c[1]+half[1]),half));
285  }
286 
289  d.rect(boundary.rect());
290  if(children){
291  children[0].vis(d);
292  children[1].vis(d);
293  children[2].vis(d);
294  children[3].vis(d);
295  }
296  }
297 
298  void printStructure(int indent){
299  for(int i=0;i<indent;++i) std::cout << " ";
300  if(children){
301  std::cout << "Branch (";
302  }else{
303  std::cout << "Leaf (";
304  }
305  std::cout << "AABB=" << boundary.rect() << ", ";
306  std::cout << "Content=" <<(int)(next-points) << "/" << CAPACITY;
307  std::cout << ")";
308  if(children){
309  std::cout << " {" << std::endl;
310  children[0].printStructure(indent+1);
311  children[1].printStructure(indent+1);
312  children[2].printStructure(indent+1);
313  children[3].printStructure(indent+1);
314  for(int i=0;i<indent;++i) std::cout << " ";
315  std::cout << "}" << std::endl;;
316  }
317  else std::cout << std::endl;
318 
319  }
320 
321  };
322 
324 
326  struct Allocator{
327 
329  std::vector<Node*> allocated;
330 
332  int curr;
333 
335  Allocator(){ grow(); }
336 
338  void grow(){
339  allocated.push_back(new Node[ALLOC_CHUNK_SIZE*4]);
340  curr = 0;
341  }
342 
344  void clear(){
345  for(size_t i=1;i<allocated.size();++i){
346  delete [] allocated[i];
347  }
348  allocated.resize(1);
349  curr = 0;
350  }
351 
353  Node *next(){
354  if(curr == ALLOC_CHUNK_SIZE) grow();
355  return allocated.back()+4*curr++;
356  }
357 
360  for(size_t i=0;i<allocated.size();++i){
361  delete [] allocated[i];
362  }
363  }
364 
366  std::vector<Pt> all() const{
367  std::vector<Pt> pts;
368  for(size_t i=0;i<allocated.size()-1;++i){
369  const Node *ns = allocated[i];
370  for(size_t j=0;j<allocated.size();++j){
371  for(const Pt* p = ns[j].points; p != ns[j].next;++p){
372  pts.push_back((*p)/SF);//Pt((*p)[0]/SF,(*p)[1]/SF));
373  }
374  }
375  }
376  const Node *ns = allocated.back();
377  for(int i=0;i<curr*4;++i){
378  for(const Pt* p = ns[i].points; p != ns[i].next;++p){
379  pts.push_back((*p)/SF); //Pt((*p)[0]/SF,(*p)[1]/SF));
380  }
381  }
382  return pts;
383  }
384  };
385 
388 
391 
393  int num;
394 
395  public:
397  QuadTree(const Scalar &minX, const Scalar &minY, const Scalar &width, const Scalar &height):num(0){
398  this->root = new Node(AABB(Pt(SF*minX+SF*width/2, SF*minY+SF*height/2),
399  Pt(SF*width/2,SF*height/2)));
400  }
401 
403  QuadTree(const utils::Rect32f &bounds):num(0){
404  this->root = new Node(AABB(Pt(SF*bounds.x+SF*bounds.width/2, SF*bounds.y+SF*bounds.height/2),
405  Pt(SF*bounds.width/2,SF*bounds.height/2)));
406  }
407 
409  QuadTree(const utils::Rect &bounds):num(0){
410  this->root = new Node(AABB(Pt(SF*bounds.x+SF*bounds.width/2, SF*bounds.y+SF*bounds.height/2),
411  Pt(SF*bounds.width/2,SF*bounds.height/2)));
412  }
413 
415  QuadTree(const Scalar &width, const Scalar &height):num(0){
416  this->root = new Node(AABB(Pt(SF*width/2,SF*height/2),
417  Pt(SF*width/2,SF*height/2)));
418  }
419 
422  this->root = new Node(AABB(Pt(SF*size.width/2,SF*size.height/2),
423  Pt(SF*size.width/2,SF*size.height/2)));
424  }
425 
428  this->root = new Node(AABB(Pt(SF*size.width/2,SF*size.height/2),
429  Pt(SF*size.width/2,SF*size.height/2)));
430  }
431 
433 
435  // the root node is not part of the allocator
436  delete root;
437  }
438 
439  protected:
440 
442  const Pt &nn_approx_internal(const Pt &p, double &currMinDist, const Pt *&currNN) const {
443  // 1st find cell, that continas p
444  const Node *n = root;
445  while(n->children){
446  n = (n->children + (p[0] > n->boundary.center[0]) + 2 * (p[1] > n->boundary.center[1]));
447  }
448 
449  // this cell could be empty, in this case, the parent must contain good points
450  if(n->next == n->points){
451  n = n->parent;
452  if(!n) throw utils::ICLException("no nn found for given point " + utils::str(p));
453  }
454 
455  double sqrMinDist = utils::sqr(currMinDist);
456 
457  for(const Pt *x=n->points; x < n->next; ++x){
458  Scalar dSqr = utils::sqr(x->operator[](0)-p[0]) + utils::sqr(x->operator[](1)-p[1]);
459  if(dSqr < sqrMinDist){
460  sqrMinDist = dSqr;
461  currNN = x;
462  }
463  }
464  currMinDist = sqrt(sqrMinDist);
465 
466  if(!currNN){
467  throw utils::ICLException("no nn found for given point " + utils::str(p));
468  }
469  return *currNN;
470  }
471  public:
472 
473 
475 
484  Pt nn_approx(const Pt &p) const {
485  double currMinDist = sqrt(utils::Range<Scalar>::limits().maxVal-1);
486  const Pt *currNN = 0;
487  nn_approx_internal(p*SF /*Pt(SF*p[0],SF*p[1])*/,currMinDist,currNN);
488  return (*currNN)/SF; //Pt((*currNN)[0]/SF,(*currNN)[1]/SF) ;
489  }
490 
492 
510  Pt nn(const Pt &pIn) const {
511  const Pt p = pIn*SF;//p(SF*pIn[0],SF*pIn[1]);
512  std::vector<const Node*> stack;
513  stack.reserve(128);
514  stack.push_back(root);
515  double currMinDist = sqrt(utils::Range<Scalar>::limits().maxVal-1);
516  const Pt *currNN = 0;
517 
518  nn_approx_internal(p,currMinDist,currNN);
519 
520  while(stack.size()){
521  const Node *n = stack.back();
522  stack.pop_back();
523  if(n->children){
524  const AABB b(p, Pt(currMinDist,currMinDist));
525  if(b.intersects(n->children[0].boundary)) stack.push_back(n->children);
526  if(b.intersects(n->children[1].boundary)) stack.push_back(n->children+1);
527  if(b.intersects(n->children[2].boundary)) stack.push_back(n->children+2);
528  if(b.intersects(n->children[3].boundary)) stack.push_back(n->children+3);
529  }
530  Scalar sqrMinDist = utils::sqr(currMinDist);
531 
532  for(const Pt *x=n->points; x < n->next; ++x){
533  Scalar dSqr = utils::sqr(x->operator[](0)-p[0]) + utils::sqr(x->operator[](1)-p[1]);
534  if(dSqr < sqrMinDist){
535  sqrMinDist = dSqr;
536  currNN = x;
537  }
538  }
539  currMinDist = sqrt(sqrMinDist);
540  }
541  return (*currNN)/SF; //Pt((*currNN)[0]/SF, (*currNN)[1]/SF);
542  }
543 
545  const utils::Point32f nn(const utils::Point32f &p) const {
546  Pt n = nn(Pt(p.x,p.y));
547  return utils::Point32f(n[0],n[1]);
548  }
549 
551  const utils::Point nn(const utils::Point &p) const {
552  Pt n = nn(Pt(p.x,p.y));
553  return utils::Point(n[0],n[1]);
554  }
555 
556 
558 
561  void insert(const Pt &pIn){
562  ++num;
563  const Pt p = pIn*SF;//p(SF*pIn[0],SF*pIn[1]);
564  Node *n = root;
565  while(true){
566  if(n->next != n->points+CAPACITY){
567  *n->next++ = p;
568  return;
569  }
570  if(!n->children) n->split(alloc.next());
571  n = (n->children + (p[0] > n->boundary.center[0]) + 2 * (p[1] > n->boundary.center[1]));
572  }
573  }
574 
576  void insert(const utils::Point32f &p){
577  insert(Pt(p.x,p.y));
578  }
579 
581  void insert(const utils::Point &p){
582  insert(Pt(p.x,p.y));
583  }
584 
586  std::vector<Pt> query(const Scalar &minX, const Scalar &minY,
587  const Scalar &width, const Scalar &height) const{
588  AABB range(Pt(SF*minX+SF*width/2, SF*minY+SF*height/2),
589  Pt(SF*width/2,SF*height/2));
590  std::vector<Pt> found;
591  root->query(range,found);
592  return found;
593  }
594 
596  std::vector<Pt> query(const utils::Rect &r) const { return query(r.x,r.y,r.width,r.height); }
597 
599  std::vector<Pt> query(const utils::Rect32f &r) const { return query(r.x,r.y,r.width,r.height); }
600 
602  std::vector<Pt> queryAll() const {
603  return alloc.all();
604  }
605 
609  d.color(0,100,255,255);
610  d.fill(0,0,0,0);
611  root->vis(d);
612  return d;
613  }
614 
616 
617  void clear(){
618  root->next = root->points;
619  root->children = 0;
620  alloc.clear();
621  num = 0;
622  }
623 
625  int size() const {
626  return num;
627  }
628 
631  std::cout << "QuadTree{" << std::endl;
632  root->printStructure(1);
633  std::cout << "}" << std::endl;
634  }
635  };
636 
637  } // namespace math
638 } // namespace icl
639 
std::vector< Pt > query(const Scalar &minX, const Scalar &minY, const Scalar &width, const Scalar &height) const
returns all contained points within the given rectangle
Definition: QuadTree.h:586
ICLQt_API ImgQ sqrt(const ImgQ &image)
calls sqrt( each pixel)
class representing a range defined by min and max value
Definition: Range.h:49
void clear()
removes all contained points and nodes
Definition: QuadTree.h:617
bool contains(const Pt &p) const
returns whether a given 2D point is contained
Definition: QuadTree.h:199
void insert(const utils::Point &p)
convenience wrapper for the Point instances
Definition: QuadTree.h:581
void clear()
deletes all allocated data chunks (except for the first)
Definition: QuadTree.h:344
int size() const
number of elments inserted
Definition: QuadTree.h:625
undocument this line if you encounter any issues!
Definition: Any.h:37
Pt center
center point
Definition: QuadTree.h:188
utils::VisualizationDescription vis() const
returns a visualization description for QuadTree structure (not for the contained points)
Definition: QuadTree.h:607
void init(Node *parent, const AABB &boundary)
initialization methods (with given boundary)
Definition: QuadTree.h:244
QuadTree(const Scalar &width, const Scalar &height)
creates a QuadTree for the given 2D Size (minX and minY are set to 0 here)
Definition: QuadTree.h:415
void vis(utils::VisualizationDescription &d) const
recursively grabs visualizations commands
Definition: QuadTree.h:288
Pt halfSize
half dimension
Definition: QuadTree.h:189
float y
y position of this point
Definition: Point32f.h:48
float y
!< x pos (upper left)
Definition: Rect32f.h:49
~Allocator()
frees all allocated data
Definition: QuadTree.h:359
QuadTree(const utils::Size32f &size)
convenience wrapper for given Size32f bounds
Definition: QuadTree.h:421
void split(Node *children)
creates the children for this node
Definition: QuadTree.h:276
QuadTree(const utils::Size &size)
convenience wrapper for given Size bounds
Definition: QuadTree.h:427
const Pt & nn_approx_internal(const Pt &p, double &currMinDist, const Pt *&currNN) const
internal utility method that is used to find an approximated nearest neighbour
Definition: QuadTree.h:442
void grow()
allocates the next data chunk
Definition: QuadTree.h:338
Node * children
pointer to four child-nodes
Definition: QuadTree.h:232
VECTOR_TYPE Pt
Definition: QuadTree.h:180
float x
Definition: Rect32f.h:48
bool intersects(const AABB &o) const
returns whether the AABB intersects with another AABB
Definition: QuadTree.h:208
Inernally used block allocator.
Definition: QuadTree.h:326
Node(const AABB &boundary)
constructor from given AABB-boundary
Definition: QuadTree.h:239
int curr
current data
Definition: QuadTree.h:332
void rect(icl32f x, icl32f y, icl32f width, icl32f height)
add a rectangle
Definition: VisualizationDescription.h:202
AABB()
default constructor (does nothing)
Definition: QuadTree.h:192
Floating point precision implementation of the Rect class.
Definition: Rect32f.h:45
void printStructure()
prints the quad-tree structure hierachically (for debug purpose)
Definition: QuadTree.h:630
std::vector< Pt > query(const utils::Rect &r) const
convenience wrapper for Rect class
Definition: QuadTree.h:596
~QuadTree()
destructor
Definition: QuadTree.h:434
float height
!< width of the rect
Definition: Rect32f.h:51
Allocator()
allocates the first data chunk
Definition: QuadTree.h:335
std::vector< Node * > allocated
allocated data
Definition: QuadTree.h:329
Pt nn(const Pt &pIn) const
finds the nearest neighbor to the given node
Definition: QuadTree.h:510
Node()
empty default constructor (does nothing)
Definition: QuadTree.h:236
Generic QuadTree Implementation.
Definition: QuadTree.h:176
Size class of the ICL.
Definition: Size.h:61
QuadTree(const utils::Rect &bounds)
convenience constructor wrapper for given Rect32f bounds
Definition: QuadTree.h:409
AABB(const Pt &center, const Pt &halfSize)
constructor from given center and half size
Definition: QuadTree.h:195
Node * root
root node pointer
Definition: QuadTree.h:387
Pt * next
next node to fill
Definition: QuadTree.h:231
std::vector< Pt > queryAll() const
returns all contained points
Definition: QuadTree.h:602
int num
internal counter for the number of contained points
Definition: QuadTree.h:393
static T sqr(const T &x)
square template (faster than pow(x,2)
Definition: Macros.h:212
void insert(const utils::Point32f &p)
convenience wrapper for the Point32f instances
Definition: QuadTree.h:576
AABB boundary
node boundary
Definition: QuadTree.h:229
Internally used node structure.
Definition: QuadTree.h:228
std::vector< Pt > all() const
returns all contained points
Definition: QuadTree.h:366
Node * parent
Definition: QuadTree.h:233
std::string str(const T &t)
convert a data type into a string using an std::ostringstream instance
Definition: StringUtils.h:136
QuadTree(const Scalar &minX, const Scalar &minY, const Scalar &width, const Scalar &height)
creates a QuadTree for the given 2D rectangle
Definition: QuadTree.h:397
Pt nn_approx(const Pt &p) const
returns an approximated nearst neighbour
Definition: QuadTree.h:484
Abstract class for visualization tasks.
Definition: VisualizationDescription.h:73
Single precission 3D Vectors Point class of the ICL.
Definition: Point32f.h:41
Point class of the ICL used e.g. for the Images ROI offset.
Definition: Point.h:58
float x
x position of this point
Definition: Point32f.h:45
utils::Rect32f rect() const
Definition: QuadTree.h:219
Base class for Exception handling in the ICL.
Definition: Exception.h:42
const utils::Point nn(const utils::Point &p) const
convenience wrapper for the Point32f type
Definition: QuadTree.h:551
float width
!< y pos (upper left)
Definition: Rect32f.h:50
std::vector< Pt > query(const utils::Rect32f &r) const
convenience wrapper for Rect32f class
Definition: QuadTree.h:599
internally used axis-aligned bounding box
Definition: QuadTree.h:187
Size32f class of the ICL (float valued)
Definition: Size32f.h:40
void insert(const Pt &pIn)
inserts a node into the QuadTree
Definition: QuadTree.h:561
Rectangle class of the ICL used e.g. for the Images ROI-rect.
Definition: Rect.h:95
void query(const AABB &boundary, std::vector< Pt > &found) const
recursive getter function that queries all nodes within a given bounding box
Definition: QuadTree.h:255
void color(icl8u r, icl8u g, icl8u b)
sets the current draw color (no alpha)
Definition: VisualizationDescription.h:348
Allocator alloc
memory allocator for all children except for the root node
Definition: QuadTree.h:390
void fill(icl8u r, icl8u g, icl8u b)
sets the current fill color (no alpha)
Definition: VisualizationDescription.h:358
QuadTree(const utils::Rect32f &bounds)
convenience constructor wrapper for given Rect32f bounds
Definition: QuadTree.h:403
Pt points[CAPACITY]
contained nodes
Definition: QuadTree.h:230
const utils::Point32f nn(const utils::Point32f &p) const
convenience wrapper for the Point32f type
Definition: QuadTree.h:545
Node * next()
returns the next four Node instances (allocates new data on demand)
Definition: QuadTree.h:353
void printStructure(int indent)
Definition: QuadTree.h:298