Image Component Library (ICL)
Octree.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/Octree.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>
36 #include <ICLUtils/Rect32f.h>
37 #include <ICLUtils/Range.h>
38 #include <ICLUtils/StringUtils.h>
39 #include <ICLMath/FixedVector.h>
40 
41 #include <algorithm>
42 #include <set>
43 
44 namespace icl{
45 
46  namespace math{
47 
48 
50 
59  template<class Scalar, int CAPACITY=16, int SF=1, class Pt=FixedColVector<Scalar,4>, int ALLOC_CHUNK_SIZE=1024>
60  class Octree{
61  public:
62 
64 
66  struct AABB{
67  Pt center;
68  Pt halfSize;
69 
71  AABB(){}
72 
74  AABB(const Pt &center, const Pt &halfSize):
76 
78  bool contains(const Pt &p) const{
79  return ( p[0] >= center[0] - halfSize[0]
80  && p[1] >= center[1] - halfSize[1]
81  && p[2] >= center[2] - halfSize[2]
82  && p[0] <= center[0] + halfSize[0]
83  && p[1] <= center[1] + halfSize[1]
84  && p[2] <= center[2] + halfSize[2]);
85  }
86 
88  bool intersects(const AABB &o) const{
89  return (fabs(center[0] - o.center[0]) < (halfSize[0] + o.halfSize[0])
90  && fabs(center[1] - o.center[1]) < (halfSize[1] + o.halfSize[1])
91  && fabs(center[2] - o.center[2]) < (halfSize[2] + o.halfSize[2]));
92 
93  }
94  };
95 
97 
99  struct Node{
101  Pt points[CAPACITY];
102  Pt *next;
105  float radius;
106 
108  Node(){}
109 
111  Node(const AABB &boundary){
112  this->boundary = boundary;
113  this->next = this->points;
114  this->children = 0;
115  this->parent = 0;
116  this->radius = ::sqrt( utils::sqr(boundary.halfSize[0]) +
119  }
121 
122  void init(Node *parent, const AABB &boundary){
123  this->boundary = boundary;
124  this->next = this->points;
125  this->children = 0;
126  this->parent = parent;
127  this->radius = parent->radius/2;
128  }
129 
131 
134  void query(const AABB &boundary, std::vector<Pt> &found) const{
135  if (!this->boundary.intersects(boundary)){
136  return;
137  }
138  for(const Pt *p=points; p<next ; ++p){
139  if(boundary.contains(*p)){
140  found.push_back(scale_down(*p));
141  }
142  }
143  if(!children) return;
144 
145  for(int i=0;i<8;++i){
146  children[i].query(boundary,found);
147  }
148  }
149 
151 
155  const Pt half = boundary.halfSize/2;//*0.5;
156 
157  const Pt &c = boundary.center;
158  this->children = children;
159  this->children[0].init(this,AABB(Pt(c[0]-half[0],c[1]-half[1], c[2]-half[2]),half));
160  this->children[1].init(this,AABB(Pt(c[0]+half[0],c[1]-half[1], c[2]-half[2]),half));
161  this->children[2].init(this,AABB(Pt(c[0]-half[0],c[1]+half[1], c[2]-half[2]),half));
162  this->children[3].init(this,AABB(Pt(c[0]+half[0],c[1]+half[1], c[2]-half[2]),half));
163 
164  this->children[4].init(this,AABB(Pt(c[0]-half[0],c[1]-half[1], c[2]+half[2]),half));
165  this->children[5].init(this,AABB(Pt(c[0]+half[0],c[1]-half[1], c[2]+half[2]),half));
166  this->children[6].init(this,AABB(Pt(c[0]-half[0],c[1]+half[1], c[2]+half[2]),half));
167  this->children[7].init(this,AABB(Pt(c[0]+half[0],c[1]+half[1], c[2]+half[2]),half));
168 
169  }
170  };
171 
173 
175  struct Allocator{
176 
178  std::vector<Node*> allocated;
179 
181  int curr;
182 
184  Allocator(){ grow(); }
185 
187  void grow(){
188  allocated.push_back(new Node[ALLOC_CHUNK_SIZE*8]);
189  curr = 0;
190  }
191 
193  void clear(){
194  for(size_t i=1;i<allocated.size();++i){
195  delete [] allocated[i];
196  }
197  allocated.resize(1);
198  curr = 0;
199  }
200 
202  Node *next(){
203  if(curr == ALLOC_CHUNK_SIZE) grow();
204  return allocated.back()+8*curr++;
205  }
206 
209  for(size_t i=0;i<allocated.size();++i){
210  delete [] allocated[i];
211  }
212  }
213 
215  std::vector<Pt> all() const{
216  std::vector<Pt> pts;
217  for(size_t i=0;i<allocated.size()-1;++i){
218  const Node *ns = allocated[i];
219  for(size_t j=0;j<ALLOC_CHUNK_SIZE*8;++j){
220  for(const Pt* p = ns[j].points; p != ns[j].next;++p){
221  pts.push_back(scale_down(*p));
222  }
223  }
224  }
225  const Node *ns = allocated.back();
226  for(int i=0;i<curr*4;++i){
227  for(const Pt* p = ns[i].points; p != ns[i].next;++p){
228  pts.push_back(scale_down(*p));
229  }
230  }
231  return pts;
232  }
233  };
234 
235  protected:
236 
238  Node *root;
239 
241  Allocator alloc;
242 
244  int num;
245 
246  static inline Pt scale_up(const Pt &p){
247  if(SF == 1) return p;
248  Pt tmp = p;
249  tmp[0] *= SF;
250  tmp[1] *= SF;
251  tmp[2] *= SF;
252  return tmp;
253  }
254 
255  static inline Pt scale_down(const Pt &p){
256  if(SF == 1) return p;
257  Pt tmp = p;
258  tmp[0] /= SF;
259  tmp[1] /= SF;
260  tmp[2] /= SF;
261  return tmp;
262  }
263 
264  static inline Pt scale_down_1(const Pt &p){
265  Pt sdp = scale_down(p);
266  sdp[3] = 1;
267  return sdp;
268  }
269 
270 
271  public:
273  Octree(const Scalar &minX, const Scalar &minY, const Scalar &minZ,
274  const Scalar &width, const Scalar &height, const Scalar &depth):num(0){
275  this->root = new Node(AABB(scale_up(Pt(minX+width/2, minY+height/2, minZ+depth/2)),
276  scale_up(Pt(width/2,height/2, depth/2))));
277  }
278 
280  Octree(const Scalar &min, const Scalar &len):num(0){
281  this->root = new Node(AABB(scale_up(Pt(min+len/2, min+len/2, min+len/2)),
282  scale_up(Pt(len/2,len/2, len/2))));
283  }
284 
286 
288  // the root node is not part of the allocator
289  delete root;
290  }
291 
292  protected:
293 
295  const Pt &nn_approx_internal(const Pt &p, double &currMinDist, const Pt *&currNN) const {
296  // 1st find cell, that continas p
297  const Node *n = root;
298  while(n->children){
299  n = (n->children
300  + (p[0] > n->boundary.center[0])
301  + 2 * (p[1] > n->boundary.center[1])
302  + 4 * (p[2] > n->boundary.center[2]));
303  }
304 
305  // this cell could be empty, in this case, the parent must contain good points
306  if(n->next == n->points){
307  n = n->parent;
308  if(!n) throw utils::ICLException("no nn found for given point " + utils::str(p));
309  }
310 
311  double sqrMinDist = utils::sqr(currMinDist);
312 
313  for(const Pt *x=n->points; x < n->next; ++x){
314  Scalar dSqr = ( utils::sqr(x->operator[](0)-p[0])
315  + utils::sqr(x->operator[](1)-p[1])
316  + utils::sqr(x->operator[](2)-p[2]) );
317  if(dSqr < sqrMinDist){
318  sqrMinDist = dSqr;
319  currNN = x;
320  }
321  }
322  currMinDist = sqrt(sqrMinDist);
323 
324  if(!currNN){
325  throw utils::ICLException("no nn found for given point " + utils::str(p.transp()));
326  }
327  return *currNN;
328  }
329  public:
330 
332  const AABB &getRootAABB() const { return root->boundary; }
333 
335 
344  Pt nn_approx(const Pt &p) const {
345  double currMinDist = sqrt(utils::Range<Scalar>::limits().maxVal-1);
346  const Pt *currNN = 0;
347  nn_approx_internal(scale_up(p),currMinDist,currNN);
348  return scale_down_1(*currNN);
349  }
350 
352 
370  Pt nn(const Pt &pIn) const {
371  const Pt p = scale_up(pIn);
372  std::vector<const Node*> stack;
373  stack.reserve(128);
374  stack.push_back(root);
375  double currMinDist = sqrt(utils::Range<Scalar>::limits().maxVal-1);
376  const Pt *currNN = 0;
377 
378  nn_approx_internal(p,currMinDist,currNN);
379 
380  while(stack.size()){
381  const Node *n = stack.back();
382  stack.pop_back();
383  if(n->children){
384  const AABB b(p, Pt(currMinDist,currMinDist,currMinDist));
385  for(int i=0;i<8;++i){
386  if(b.intersects(n->children[i].boundary)) stack.push_back(n->children+i);
387  }
388  }
389  Scalar sqrMinDist = utils::sqr(currMinDist);
390 
391  for(const Pt *x=n->points; x < n->next; ++x){
392  Scalar dSqr = (utils::sqr(x->operator[](0)-p[0]) +
393  utils::sqr(x->operator[](1)-p[1]) +
394  utils::sqr(x->operator[](2)-p[2]));
395  if(dSqr < sqrMinDist){
396  sqrMinDist = dSqr;
397  currNN = x;
398  }
399  }
400  currMinDist = sqrt(sqrMinDist);
401  }
402  return scale_down_1(*currNN);
403  }
404 
406 
409  template<class OtherVectorType>
410  void insert(const OtherVectorType &pIn){
411  ++num;
412  Pt p = pIn;
413  p[0] *= SF;
414  p[1] *= SF;
415  p[2] *= SF;
416 
417  Node *n = root;
418  while(true){
419  if(n->next != n->points+CAPACITY){
420  *n->next++ = p;
421  return;
422  }
423  if(!n->children) n->split(alloc.next());
424  n = (n->children
425  + (p[0] > n->boundary.center[0])
426  + 2 * (p[1] > n->boundary.center[1])
427  + 4 * (p[2] > n->boundary.center[2]));
428  }
429  }
430 
432 
434  template<class ForwardIterator>
435  void assign(ForwardIterator begin, ForwardIterator end){
436  clear();
437  for(; begin != end; ++begin){
438  insert(*begin);
439  }
440  }
441 
442 
444  std::vector<Pt> query(const Scalar &minX, const Scalar &minY, const Scalar &minZ,
445  const Scalar &width, const Scalar &height, const Scalar &depth) const{
446  AABB range(scale_up(Pt(minX+width/2, minY+height/2, minZ+depth/2)),
447  scale_up(Pt(width/2,height/2, depth/2)));
448  std::vector<Pt> found;
449  root->query(range,found);
450  return found;
451  }
452 
454  std::vector<Pt> queryAll() const {
455  return alloc.all();
456  }
457 
458  /*
460  utils::VisualizationDescription vis() const{
461  utils::VisualizationDescription d;
462  d.color(0,100,255,255);
463  d.fill(0,0,0,0);
464  root->vis(d);
465  return d;
466  }
467  */
468 
470 
471  void clear(){
472  root->next = root->points;
473  root->children = 0;
474  alloc.clear();
475  num = 0;
476  }
477 
479  int size() const {
480  return num;
481  }
482 
483  /*
485  void printStructure(){
486  std::cout << "QuadTree{" << std::endl;
487  root->printStructure(1);
488  std::cout << "}" << std::endl;
489  }
490  */
491  };
492 
493  } // namespace math
494 } // namespace icl
495 
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
Octree(const Scalar &min, const Scalar &len)
creates a QuadTree for the given 2D rectangle
Definition: Octree.h:280
bool intersects(const AABB &o) const
returns whether the AABB intersects with another AABB
Definition: Octree.h:88
undocument this line if you encounter any issues!
Definition: Any.h:37
void grow()
allocates the next data chunk
Definition: Octree.h:187
void clear()
removes all contained points and nodes
Definition: Octree.h:471
void insert(const OtherVectorType &pIn)
inserts a node into the QuadTree
Definition: Octree.h:410
static Pt scale_down(const Pt &p)
Definition: Octree.h:255
float radius
aabb radius (can be used for bounding sphere tests)
Definition: Octree.h:105
std::vector< Pt > query(const Scalar &minX, const Scalar &minY, const Scalar &minZ, const Scalar &width, const Scalar &height, const Scalar &depth) const
returns all contained points within the given rectangle
Definition: Octree.h:444
Allocator alloc
memory allocator for all children except for the root node
Definition: Octree.h:241
internally used axis-aligned bounding box
Definition: Octree.h:66
Inernally used block allocator.
Definition: Octree.h:175
Node * parent
parent node
Definition: Octree.h:104
int size() const
number of elments inserted
Definition: Octree.h:479
Generic Octree Implementation.
Definition: Octree.h:60
Pt * next
next node to fill
Definition: Octree.h:102
Node * next()
returns the next four Node instances (allocates new data on demand)
Definition: Octree.h:202
AABB(const Pt &center, const Pt &halfSize)
constructor from given center and half size
Definition: Octree.h:74
void query(const AABB &boundary, std::vector< Pt > &found) const
recursive getter function that queries all nodes within a given bounding box
Definition: Octree.h:134
std::vector< Node * > allocated
allocated data
Definition: Octree.h:178
std::vector< Pt > all() const
returns all contained points
Definition: Octree.h:215
bool contains(const Pt &p) const
returns whether a given 2D point is contained
Definition: Octree.h:78
~Allocator()
frees all allocated data
Definition: Octree.h:208
Pt nn_approx(const Pt &p) const
returns an approximated nearst neighbour
Definition: Octree.h:344
Node * children
pointer to four child-nodes
Definition: Octree.h:103
Pt points[CAPACITY]
contained nodes
Definition: Octree.h:101
Internally used node structure.
Definition: Octree.h:99
std::vector< Pt > queryAll() const
returns all contained points
Definition: Octree.h:454
static T sqr(const T &x)
square template (faster than pow(x,2)
Definition: Macros.h:212
Node(const AABB &boundary)
constructor from given AABB-boundary
Definition: Octree.h:111
Pt halfSize
half dimension
Definition: Octree.h:68
std::string str(const T &t)
convert a data type into a string using an std::ostringstream instance
Definition: StringUtils.h:136
Allocator()
allocates the first data chunk
Definition: Octree.h:184
void clear()
deletes all allocated data chunks (except for the first)
Definition: Octree.h:193
depth
determines the pixel type of an image (8Bit-int or 32Bit-float)
Definition: Types.h:60
int curr
current data
Definition: Octree.h:181
static Pt scale_down_1(const Pt &p)
Definition: Octree.h:264
AABB()
default constructor (does nothing)
Definition: Octree.h:71
Octree(const Scalar &minX, const Scalar &minY, const Scalar &minZ, const Scalar &width, const Scalar &height, const Scalar &depth)
creates a QuadTree for the given 2D rectangle
Definition: Octree.h:273
Pt center
center point
Definition: Octree.h:67
Base class for Exception handling in the ICL.
Definition: Exception.h:42
static Pt scale_up(const Pt &p)
Definition: Octree.h:246
Pt nn(const Pt &pIn) const
finds the nearest neighbor to the given node
Definition: Octree.h:370
AABB boundary
node boundary
Definition: Octree.h:100
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: Octree.h:295
~Octree()
destructor
Definition: Octree.h:287
void split(Node *children)
creates the children for this node
Definition: Octree.h:154
const AABB & getRootAABB() const
returs the Octree's top-level bounding box
Definition: Octree.h:332
void init(Node *parent, const AABB &boundary)
initialization methods (with given boundary)
Definition: Octree.h:122
Node()
empty default constructor (does nothing)
Definition: Octree.h:108
Node * root
root node pointer
Definition: Octree.h:238
int num
internal counter for the number of contained points
Definition: Octree.h:244
void assign(ForwardIterator begin, ForwardIterator end)
utilty method to assign new data
Definition: Octree.h:435