00001 #ifndef NAIVE_QUADTREE_H
00002 #define NAIVE_QUADTREE_H
00003
00004 #include <math.h>
00005
00006 #include "boost/concept/assert.hpp"
00007
00008 #include "Order2StatisticalConcept.h"
00009 #include "QuadtreeConcept.h"
00010
00011 #include "dmath.h"
00012 #include "debug.h"
00013 #include "profile.h"
00014
00015 namespace za_co_codespot
00016 {
00017 namespace datastructures
00018 {
00019 using math::sqr;
00020
00031 template <typename T>
00032 class NaiveQuadtree
00033 {
00034
00035 BOOST_CONCEPT_ASSERT((Order2StatisticalConcept<T>));
00036
00037
00038
00039 #ifdef CODE_SPOT_CO_ZA_DEBUG
00040 BOOST_CONCEPT_ASSERT((QuadtreeConcept<NaiveQuadtree<T>, T>));
00041 #endif
00042
00043 public:
00048 NaiveQuadtree(T ar[], unsigned int width, unsigned int height, T threshold);
00049
00050
00051 virtual ~NaiveQuadtree();
00052
00056 inline unsigned int getWidth() const;
00057
00061 inline unsigned int getHeight() const;
00062
00066 const T& operator()(unsigned int x, unsigned int y) const;
00067
00071 unsigned int getLevel(unsigned int x, unsigned int y) const;
00072
00076 unsigned int getNodeCount() const;
00077
00078 private:
00079
00083 class Node
00084 {
00085 public:
00086 explicit Node();
00087 virtual ~Node() = 0;
00088
00095 virtual inline const T& getValue(unsigned int x, unsigned int y) const = 0;
00096
00103 virtual inline unsigned int getLevel(unsigned int x, unsigned int y) const = 0;
00104
00112 virtual unsigned int getNodeCount() const = 0;
00113 };
00114
00118 template <unsigned int childCount>
00119 class BranchNode : public Node
00120 {
00121 public:
00122 explicit BranchNode();
00123 virtual ~BranchNode();
00124 virtual inline const T& getValue(unsigned int x, unsigned int y) const = 0;
00125 virtual unsigned int getNodeCount() const;
00126 protected:
00127 Node * mChildren[childCount];
00128 };
00129
00135 class RectangularBranchNode : public BranchNode<4>
00136 {
00137 public:
00142 RectangularBranchNode(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr);
00143
00144 virtual inline const T& getValue(unsigned int x, unsigned int y) const;
00145 virtual inline unsigned int getLevel(unsigned int x, unsigned int y) const;
00146
00147 private:
00153 unsigned int mMidX;
00154 unsigned int mMidY;
00155 };
00156
00160 class HorizontalBranchNode : public BranchNode<2>
00161 {
00162 public:
00163 HorizontalBranchNode(T ar[], unsigned int width, unsigned int x0, unsigned int y0, int unsigned x1, int unsigned y1, T threshold_sqr);
00164
00165 virtual inline const T& getValue(unsigned int x, unsigned int y) const;
00166 virtual inline unsigned int getLevel(unsigned int x, unsigned int y) const;
00167 private:
00168
00169 unsigned int mMidX;
00170 };
00171
00175 class VerticalBranchNode : public BranchNode<2>
00176 {
00177 public:
00178 VerticalBranchNode(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr);
00179
00180 virtual inline const T& getValue(unsigned int x, unsigned int y) const;
00181 virtual inline unsigned int getLevel(unsigned int x, unsigned int y) const;
00182 private:
00183 unsigned int mMidY;
00184 };
00185
00186 class LeafNode : public Node
00187 {
00188 public:
00189 LeafNode(T value);
00190 virtual inline const T& getValue(unsigned int x, unsigned int y) const;
00191 virtual unsigned int getNodeCount() const;
00192 virtual inline unsigned int getLevel(unsigned int x, unsigned int y) const;
00193 private:
00194
00195
00196
00197
00198
00199
00200
00201 T mValue;
00202 };
00203
00204
00208 static T getMean(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1);
00209
00215 static T getVariance(T ar[], unsigned int width, T mean, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1);
00216
00221 static Node * initializeChild(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr);
00222
00226 Node * mRoot;
00227
00231 unsigned int mWidth;
00232
00236 unsigned int mHeight;
00237 };
00238
00239
00240
00241
00242 template <typename T>
00243 NaiveQuadtree<T>::Node::Node()
00244 {
00245
00246 }
00247
00248 template <typename T>
00249 NaiveQuadtree<T>::Node::~Node()
00250 {
00251
00252 }
00253
00254 template <typename T>
00255 template <unsigned int childCount>
00256 NaiveQuadtree<T>::BranchNode<childCount>::~BranchNode()
00257 {
00258 for(unsigned int k = 0; k < childCount; k++)
00259 {
00260 delete mChildren[k];
00261 mChildren[k] = 0;
00262 }
00263 }
00264
00265 template <typename T>
00266 template <unsigned int childCount>
00267 NaiveQuadtree<T>::BranchNode<childCount>::BranchNode():
00268 Node()
00269 {
00270 for(unsigned int k = 0; k < childCount; k++)
00271 {
00272
00273
00274
00275 mChildren[k] = 0;
00276 }
00277 }
00278
00279 template <typename T>
00280 template <unsigned int childCount>
00281 unsigned int NaiveQuadtree<T>::BranchNode<childCount>::getNodeCount() const
00282 {
00283 unsigned int sum = 1;
00284
00285 for(unsigned int k = 0; k < childCount; k++)
00286 {
00287 assert(mChildren[k] != 0);
00288
00289 sum += mChildren[k]->getNodeCount();
00290 }
00291
00292 return sum;
00293 }
00294
00295 template <typename T>
00296 NaiveQuadtree<T>::RectangularBranchNode::RectangularBranchNode(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr):
00297 BranchNode<4>(),
00298 mMidX((x0 + x1) / 2),
00299 mMidY((y0 + y1) / 2)
00300 {
00301 assert(x0 != x1 + 1);
00302 assert(y0 != y1 + 1);
00303
00304 mChildren[0] = NaiveQuadtree<T>::initializeChild(ar, width, x0, y0, mMidX, mMidY, threshold_sqr);
00305 mChildren[1] = NaiveQuadtree<T>::initializeChild(ar, width, mMidX, y0, x1, mMidY, threshold_sqr);
00306 mChildren[2] = NaiveQuadtree<T>::initializeChild(ar, width, x0, mMidY, mMidX, y1, threshold_sqr);
00307 mChildren[3] = NaiveQuadtree<T>::initializeChild(ar, width, mMidX, mMidY, x1, y1, threshold_sqr);
00308
00309 }
00310
00311 template <typename T>
00312 const T& NaiveQuadtree<T>::RectangularBranchNode::getValue(unsigned int x, unsigned int y) const
00313 {
00314 if (x < mMidX)
00315 {
00316 if (y < mMidY)
00317 {
00318 return mChildren[0]->getValue(x,y);
00319 }
00320 else
00321 {
00322 return mChildren[2]->getValue(x,y);
00323 }
00324 }
00325 else
00326 {
00327 if (y < mMidY)
00328 {
00329 return mChildren[1]->getValue(x,y);
00330 }
00331 else
00332 {
00333 return mChildren[3]->getValue(x,y);
00334 }
00335 }
00336 }
00337
00338 template <typename T>
00339 unsigned int NaiveQuadtree<T>::RectangularBranchNode::getLevel(unsigned int x, unsigned int y) const
00340 {
00341 if (x < mMidX)
00342 {
00343 if (y < mMidY)
00344 {
00345 return mChildren[0]->getLevel(x,y) + 1;
00346 }
00347 else
00348 {
00349 return mChildren[2]->getLevel(x,y) + 1;
00350 }
00351 }
00352 else
00353 {
00354 if (y < mMidY)
00355 {
00356 return mChildren[1]->getLevel(x,y) + 1;
00357 }
00358 else
00359 {
00360 return mChildren[3]->getLevel(x,y) + 1;
00361 }
00362 }
00363 }
00364
00365
00366 template <typename T>
00367 NaiveQuadtree<T>::HorizontalBranchNode::HorizontalBranchNode(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr):
00368 BranchNode<2>(),
00369 mMidX((x0 + x1) / 2)
00370 {
00371 assert(x0 != x1 + 1);
00372 assert(y0 != y1 + 1);
00373
00374 mChildren[0] = NaiveQuadtree<T>::initializeChild(ar, width, x0, y0, mMidX, y1, threshold_sqr);
00375 mChildren[1] = NaiveQuadtree<T>::initializeChild(ar, width, mMidX, y0, x1, y1, threshold_sqr);
00376 }
00377
00378 template <typename T>
00379 const T& NaiveQuadtree<T>::HorizontalBranchNode::getValue(unsigned int x, unsigned int y) const
00380 {
00381 if (x < mMidX)
00382 {
00383 return mChildren[0]->getValue(x,y);
00384 }
00385 else
00386 {
00387 return mChildren[1]->getValue(x,y);
00388 }
00389 }
00390
00391 template <typename T>
00392 unsigned int NaiveQuadtree<T>::HorizontalBranchNode::getLevel(unsigned int x, unsigned int y) const
00393 {
00394 if (x < mMidX)
00395 {
00396 return mChildren[0]->getLevel(x,y) + 1;
00397 }
00398 else
00399 {
00400 return mChildren[1]->getLevel(x,y) + 1;
00401 }
00402 }
00403
00404 template <typename T>
00405 NaiveQuadtree<T>::VerticalBranchNode::VerticalBranchNode(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr):
00406 BranchNode<2>(),
00407 mMidY((y0 + y1) / 2)
00408 {
00409 assert(x0 != x1 + 1);
00410 assert(y0 != y1 + 1);
00411
00412 mChildren[0] = NaiveQuadtree<T>::initializeChild(ar, width, x0, y0, x1, mMidY, threshold_sqr);
00413 mChildren[1] = NaiveQuadtree<T>::initializeChild(ar, width, x0, mMidY, x1, y1, threshold_sqr);
00414 }
00415
00416 template <typename T>
00417 const T& NaiveQuadtree<T>::VerticalBranchNode::getValue(unsigned int x, unsigned int y) const
00418 {
00419 if (y < mMidY)
00420 {
00421 return mChildren[0]->getValue(x,y);
00422 }
00423 else
00424 {
00425 return mChildren[1]->getValue(x,y);
00426 }
00427 }
00428
00429 template <typename T>
00430 unsigned int NaiveQuadtree<T>::VerticalBranchNode::getLevel(unsigned int x, unsigned int y) const
00431 {
00432 if (y < mMidY)
00433 {
00434 return mChildren[0]->getLevel(x,y) + 1;
00435 }
00436 else
00437 {
00438 return mChildren[1]->getLevel(x,y) + 1;
00439 }
00440 }
00441
00442
00443 template <typename T>
00444 NaiveQuadtree<T>::LeafNode::LeafNode(T value):
00445 Node(),
00446 mValue(value)
00447 {}
00448
00449 template <typename T>
00450 const T& NaiveQuadtree<T>::LeafNode::getValue(unsigned int x, unsigned int y) const
00451 {
00452 return mValue;
00453 }
00454
00455 template <typename T>
00456 unsigned int NaiveQuadtree<T>::LeafNode::getLevel(unsigned int x, unsigned int y) const
00457 {
00458 return 0;
00459 }
00460
00461 template <typename T>
00462 unsigned int NaiveQuadtree<T>::LeafNode::getNodeCount() const
00463 {
00464 return 1;
00465 }
00466
00467 template <typename T>
00468 NaiveQuadtree<T>::NaiveQuadtree(T ar[], unsigned int width, unsigned int height, T threshold):
00469 mWidth(width),
00470 mHeight(height),
00471 mRoot(initializeChild(ar, width, 0, 0, width, height, sqr(threshold)))
00472 {}
00473
00474 template <typename T>
00475 NaiveQuadtree<T>::~NaiveQuadtree()
00476 {
00477 delete mRoot;
00478 mRoot = 0;
00479 }
00480
00481 template <typename T>
00482 unsigned int NaiveQuadtree<T>::getWidth() const
00483 {
00484 return mWidth;
00485 }
00486
00487 template <typename T>
00488 unsigned int NaiveQuadtree<T>::getHeight() const
00489 {
00490 return mHeight;
00491 }
00492
00493 template <typename T>
00494 T NaiveQuadtree<T>::getMean(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
00495 {
00496 T sum(0);
00497
00498 assert(x0 != x1);
00499 assert(y0 != y1);
00500
00501 for(unsigned int i = x0; i < x1; i++)
00502 {
00503 for(unsigned int j = y0; j < y1; j++)
00504 {
00505 sum = sum + ar[j * width + i];
00506 }
00507 }
00508
00509 return sum / ((x1 - x0) * (y1 - y0));
00510 }
00511
00512 template <typename T>
00513 T NaiveQuadtree<T>::getVariance(T ar[], unsigned int width, T mean, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
00514 {
00515 T sum(0);
00516
00517 assert(x0 != x1);
00518 assert(y0 != y1);
00519
00520 for(unsigned int i = x0; i < x1; i++)
00521 {
00522 for(unsigned int j = y0; j < y1; j++)
00523 {
00524 sum = sum + sqr(mean - ar[j * width + i]);
00525 }
00526 }
00527
00528 return sum / ((x1 - x0) * (y1 - y0));
00529 }
00530
00531 template <typename T>
00532 const T& NaiveQuadtree<T>::operator()(unsigned int x, unsigned int y) const
00533 {
00534 return mRoot->getValue(x,y);
00535 }
00536
00537 template <typename T>
00538 unsigned int NaiveQuadtree<T>::getLevel(unsigned int x, unsigned int y) const
00539 {
00540 return mRoot->getLevel(x, y);
00541 }
00542
00543 template<typename T>
00544 typename NaiveQuadtree<T>::Node * NaiveQuadtree<T>::initializeChild(T ar[], unsigned int width, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, T threshold_sqr)
00545 {
00546 if (x0 + 1 == x1)
00547 {
00548 if (y0 + 1 == y1)
00549 {
00550 return new LeafNode(ar[y0*width + x0]);
00551 }
00552 else
00553 {
00554 return new VerticalBranchNode(ar, width, x0, y0, x1, y1, threshold_sqr);
00555 }
00556 }
00557 else
00558 {
00559 if (y0 + 1 == y1)
00560 {
00561 return new HorizontalBranchNode(ar, width, x0, y0, x1, y1, threshold_sqr);
00562 }
00563 }
00564
00565 T mean(getMean(ar, width, x0, y0, x1, y1));
00566 T variance(getVariance(ar, width, mean, x0, y0, x1, y1));
00567
00568
00569
00570
00571
00572
00573
00574
00575 if(variance <= threshold_sqr)
00576 {
00577 return new LeafNode(mean);
00578 }
00579 else
00580 {
00581 return new RectangularBranchNode(ar, width, x0, y0, x1, y1, threshold_sqr);
00582 }
00583
00584 assert(UNREACHABLE);
00585 }
00586
00587 template<typename T>
00588 unsigned int NaiveQuadtree<T>::getNodeCount() const
00589 {
00590 return mRoot->getNodeCount();
00591 }
00592
00593 }
00594 }
00595
00596 #endif //NAIVE_QUADTREE_H