00001
00015 #ifndef DLR_COMPUTERVISION_QUADMAP_H
00016 #define DLR_COMPUTERVISION_QUADMAP_H
00017
00018 #include <functional>
00019 #include <vector>
00020
00021
00022 namespace dlr {
00023
00024 namespace computerVision {
00025
00048 template <class Type>
00049 class QuadMapComparator
00050 : public std::binary_function<Type, Type, bool>
00051 {
00052 public:
00053
00057 QuadMapComparator() {}
00058
00059
00063 virtual
00064 ~QuadMapComparator() {}
00065
00066
00087 unsigned int
00088 chooseChild(Type const& element,
00089 double border0,
00090 double border1) const {
00091 #if 1
00092 unsigned int quadrantIndex = 0;
00093 quadrantIndex |= (element[0] < border0) ? 0x00 : 0x01;
00094 quadrantIndex |= (element[1] < border1) ? 0x00 : 0x02;
00095 return quadrantIndex;
00096 #else
00097 if(element[1] < border1) {
00098 if
00099 return 0;
00100 }
00101 return 1;
00102 }
00103 if(element[0] < border0) {
00104 return 2;
00105 }
00106 return 3;
00107 #endif
00108 }
00109
00110
00124 double
00125 computeDistanceSquared(Type const& arg0, Type const& arg1) const {
00126 double term0 = arg1[0] - arg0[0];
00127 double term1 = arg1[1] - arg0[1];
00128 return term0 * term0 + term1 * term1;
00129 }
00130
00131
00146 void
00147 getLowerBoundSquaredDistances(Type const& element,
00148 double boundary0,
00149 double boundary1,
00150 double& minDistance0,
00151 double& minDistance1,
00152 double& minDistance01) const {
00153 double term0 = element[0] - boundary0;
00154 double term1 = element[1] - boundary1;
00155 minDistance0 = term0 * term0;
00156 minDistance1 = term1 * term1;
00157 minDistance01 = minDistance0 + minDistance1;
00158 }
00159
00160
00174 bool isEqual(Type const& arg0, Type const& arg1) const {
00175 return arg0 == arg1;
00176 }
00177
00178 };
00179
00180
00181
00244 template <class Type>
00245 class QuadMap {
00246 public:
00247
00251 QuadMap(double minCoord0, double minCoord1,
00252 double maxCoord0, double maxCoord1,
00253 unsigned int maxDepth);
00254
00255
00260 virtual
00261 ~QuadMap();
00262
00263
00271 Type&
00272 addElement(Type const& element);
00273
00274
00288 template <class Iter>
00289 void
00290 addElements(Iter beginIter, Iter endIter);
00291
00292
00299 bool
00300 empty() {return this->isEmpty();}
00301
00302
00316 bool
00317 find(Type const& element) const;
00318
00319
00340 Type const&
00341 findNearest(Type const& element, double& distance) const;
00342
00343
00350 bool
00351 isEmpty() {return m_localStore.empty() && (m_childrenPtr == 0);}
00352
00353
00354 protected:
00355
00356 QuadMap();
00357
00358
00359 Type&
00360 addElement(Type* elementPtr);
00361
00362
00363 void
00364 findNearestIterative(Type const& element,
00365 Type const*& bestElementPtr,
00366 double& bestDistanceSquared) const;
00367
00368
00369 void
00370 findNearestRecursive(Type const& element,
00371 Type const*& bestElementPtr,
00372 double& bestDistanceSquared) const;
00373
00374
00375 void
00376 setBounds(double minCoord0, double minCoord1,
00377 double maxCoord0, double maxCoord1,
00378 unsigned int maxDepth);
00379
00380
00381
00382 double m_border0;
00383 double m_border1;
00384 QuadMap* m_childrenPtr;
00385 QuadMapComparator<Type> m_comparator;
00386
00387
00388
00389
00390 std::vector<Type*> m_localStore;
00391
00392 double m_maxCoord0;
00393 double m_maxCoord1;
00394 unsigned int m_maxDepth;
00395 double m_minCoord0;
00396 double m_minCoord1;
00397 };
00398
00399 }
00400
00401 }
00402
00403
00404
00405
00406 #include <algorithm>
00407 #include <cmath>
00408 #include <limits>
00409 #include <stack>
00410 #include <dlrCommon/exception.h>
00411
00412 namespace dlr {
00413
00414 namespace computerVision {
00415
00416 template <class Type>
00417 QuadMap<Type>::
00418 QuadMap(double minCoord0, double minCoord1,
00419 double maxCoord0, double maxCoord1,
00420 unsigned int maxDepth)
00421 : m_border0((minCoord0 + maxCoord0) / 2.0),
00422 m_border1((minCoord1 + maxCoord1) / 2.0),
00423 m_childrenPtr(0),
00424 m_comparator(),
00425 m_localStore(),
00426 m_maxCoord0(maxCoord0),
00427 m_maxCoord1(maxCoord1),
00428 m_maxDepth(maxDepth),
00429 m_minCoord0(minCoord0),
00430 m_minCoord1(minCoord1)
00431 {}
00432
00433
00434
00435 template <class Type>
00436 QuadMap<Type>::
00437 ~QuadMap() {
00438 for(unsigned int ii = 0; ii < m_localStore.size(); ++ii) {
00439 delete m_localStore[ii];
00440 }
00441 if(m_childrenPtr != 0) {
00442 delete[] m_childrenPtr;
00443 }
00444 }
00445
00446
00447 template <class Type>
00448 Type&
00449 QuadMap<Type>::
00450 addElement(Type const& element)
00451 {
00452 Type* elementPtr = new Type(element);
00453 this->addElement(elementPtr);
00454 return *elementPtr;
00455 }
00456
00457
00458 template <class Type>
00459 template <class Iter>
00460 void
00461 QuadMap<Type>::
00462 addElements(Iter beginIter, Iter endIter)
00463 {
00464 #if 0
00465 size_t numberOfElements = endIter - beginIter;
00466 if(numberOfElements == 0) {
00467 return;
00468 }
00469 if(numberOfElements == 1) {
00470 this->addElement(*beginIter);
00471 return;
00472 }
00473
00474
00475
00476 std::vector<Type> elementVector(numberOfElements);
00477 std::copy(beginIter, endIter, elementVector.begin());
00478 this->addElements(elementVector, 0, numberOfElements);
00479 #else
00480 while(beginIter != endIter) {
00481 this->addElement(*beginIter);
00482 ++beginIter;
00483 }
00484 #endif
00485 }
00486
00487
00488 template <class Type>
00489 bool
00490 QuadMap<Type>::
00491 find(Type const& element) const
00492 {
00493
00494 if(!m_localStore.empty()) {
00495 for(unsigned int ii = 0; ii < m_localStore.size(); ++ii) {
00496 if(m_comparator.isEqual(*(m_localStore[ii]), element)) {
00497 return true;
00498 }
00499 }
00500 return false;
00501 }
00502
00503 if(m_childrenPtr != 0) {
00504 unsigned int childIndex = m_comparator.chooseChild(
00505 element, m_border0, m_border1);
00506 return m_childrenPtr[childIndex].find(element);
00507 }
00508
00509 return false;
00510 }
00511
00512
00513 template <class Type>
00514 Type&
00515 QuadMap<Type>::
00516 addElement(Type* elementPtr)
00517 {
00518
00519
00520 if((m_localStore.empty() && m_childrenPtr == 0) || m_maxDepth == 0) {
00521 m_localStore.push_back(elementPtr);
00522 return *elementPtr;
00523 }
00524
00525
00526
00527 if(m_childrenPtr == 0) {
00528 m_childrenPtr = new QuadMap<Type>[4];
00529 m_childrenPtr[0].setBounds(
00530 m_minCoord0, m_minCoord1, m_border0, m_border1, m_maxDepth - 1);
00531 m_childrenPtr[1].setBounds(
00532 m_border0, m_minCoord1, m_maxCoord0, m_border1, m_maxDepth - 1);
00533 m_childrenPtr[2].setBounds(
00534 m_minCoord0, m_border1, m_border0, m_maxCoord1, m_maxDepth - 1);
00535 m_childrenPtr[3].setBounds(
00536 m_border0, m_border1, m_maxCoord0, m_maxCoord1, m_maxDepth - 1);
00537 for(unsigned int ii = 0; ii < m_localStore.size(); ++ii) {
00538 unsigned int childIndex = m_comparator.chooseChild(
00539 *(m_localStore[ii]), m_border0, m_border1);
00540 m_childrenPtr[childIndex].addElement(m_localStore[ii]);
00541 }
00542 m_localStore.clear();
00543 }
00544
00545
00546 unsigned int childIndex = m_comparator.chooseChild(
00547 *elementPtr, m_border0, m_border1);
00548 return m_childrenPtr[childIndex].addElement(elementPtr);
00549 }
00550
00551
00552 template <class Type>
00553 Type const&
00554 QuadMap<Type>::
00555 findNearest(Type const& element, double& distanceSquared) const
00556 {
00557 distanceSquared = std::numeric_limits<double>::max();
00558 Type const* bestElementPtr = 0;
00559
00560 this->findNearestIterative(element, bestElementPtr, distanceSquared);
00561 if(bestElementPtr == 0) {
00562 DLR_THROW(common::StateException, "QuadMap::findNearest()",
00563 "Can't find nearest element in an empty map.");
00564 }
00565 return *bestElementPtr;
00566 }
00567
00568
00569
00570
00571 template <class Type>
00572 QuadMap<Type>::
00573 QuadMap()
00574 : m_border0(0.0),
00575 m_border1(0.0),
00576 m_childrenPtr(0),
00577 m_comparator(),
00578 m_localStore(),
00579 m_maxCoord0(0.0),
00580 m_maxCoord1(0.0),
00581 m_minCoord0(0.0),
00582 m_minCoord1(0.0)
00583 {}
00584
00585
00586 template <class Type>
00587 void
00588 QuadMap<Type>::
00589 findNearestIterative(Type const& element,
00590 Type const*& bestElementPtr,
00591 double& bestDistance) const
00592 {
00593
00594
00595
00596
00597 std::stack< std::pair< QuadMap<Type> const*, double> >
00598 quadMapStack;
00599 quadMapStack.push(std::make_pair(this, 0.0));
00600
00601 while(!(quadMapStack.empty())) {
00602 QuadMap<Type> const* currentMap = quadMapStack.top().first;
00603 double bound = quadMapStack.top().second;
00604 quadMapStack.pop();
00605
00606 if(bestDistance < bound) {
00607 continue;
00608 }
00609
00610 if(!(currentMap->m_localStore).empty()) {
00611 for(unsigned int ii = 0; ii < (currentMap->m_localStore).size();
00612 ++ii) {
00613 double myDistance = currentMap->m_comparator.computeDistanceSquared(
00614 element, *(currentMap->m_localStore[ii]));
00615
00616
00617 if(myDistance < bound) {
00618 DLR_THROW(LogicException, "QuadMap<Type>::findNearestIterative()",
00619 "Bounds calculation is erronious.");
00620 }
00621
00622 if(myDistance < bestDistance) {
00623 bestDistance = myDistance;
00624 bestElementPtr = currentMap->m_localStore[ii];
00625 }
00626 }
00627 continue;
00628 }
00629
00630 if(currentMap->m_childrenPtr != 0) {
00631
00632 unsigned int nearChildIndex = currentMap->m_comparator.chooseChild(
00633 element, currentMap->m_border0, currentMap->m_border1);
00634
00635
00636
00637
00638
00639 unsigned int childIndices[4];
00640 childIndices[0] = nearChildIndex ^ 0x03;
00641 childIndices[1] = nearChildIndex ^ 0x02;
00642 childIndices[2] = nearChildIndex ^ 0x01;
00643 childIndices[3] = nearChildIndex;
00644
00645
00646
00647
00648
00649
00650 double minDistances[4];
00651 minDistances[3] = bound;
00652 currentMap->m_comparator.getLowerBoundSquaredDistances(
00653 element, currentMap->m_border0, currentMap->m_border1,
00654 minDistances[2], minDistances[1], minDistances[0]);
00655
00656
00657
00658
00659
00660 if(minDistances[1] < minDistances[2]) {
00661 std::swap(childIndices[1], childIndices[2]);
00662 std::swap(minDistances[1], minDistances[2]);
00663 }
00664
00665
00666
00667 for(unsigned int ii = 0; ii < 4; ++ii) {
00668 if(minDistances[ii] < bestDistance) {
00669 quadMapStack.push(
00670 std::make_pair(&(currentMap->m_childrenPtr[childIndices[ii]]),
00671 std::max(bound, minDistances[ii])));
00672 }
00673 }
00674 }
00675 }
00676 }
00677
00678
00679 template <class Type>
00680 void
00681 QuadMap<Type>::
00682 findNearestRecursive(Type const& element,
00683 Type const*& bestElementPtr,
00684 double& bestDistance) const
00685 {
00686
00687
00688
00689
00690
00691 if(!m_localStore.empty()) {
00692 for(unsigned int ii = 0; ii < m_localStore.size(); ++ii) {
00693 double myDistance = m_comparator.computeDistanceSquared(
00694 element, *(m_localStore[ii]));
00695 if(myDistance < bestDistance) {
00696 bestDistance = myDistance;
00697 bestElementPtr = m_localStore[ii];
00698 }
00699 }
00700 }
00701
00702 if(m_childrenPtr) {
00703
00704 unsigned int nearChildIndex = m_comparator.chooseChild(
00705 element, m_border0, m_border1);
00706
00707
00708
00709
00710 unsigned int childIndices[4];
00711 childIndices[0] = nearChildIndex;
00712 childIndices[1] = nearChildIndex ^ 0x01;
00713 childIndices[2] = nearChildIndex ^ 0x02;
00714 childIndices[3] = nearChildIndex ^ 0x03;
00715
00716
00717
00718
00719
00720
00721 double minDistances[4];
00722 minDistances[0] = 0.0;
00723 m_comparator.getLowerBoundSquaredDistances(
00724 element, m_border0, m_border1,
00725 minDistances[1], minDistances[2], minDistances[3]);
00726
00727
00728
00729
00730
00731 if(minDistances[1] < minDistances[2]) {
00732 std::swap(childIndices[1], childIndices[2]);
00733 std::swap(minDistances[1], minDistances[2]);
00734 }
00735
00736 for(unsigned int ii = 0; ii < 4; ++ii) {
00737 if(minDistances[ii] < bestDistance) {
00738 m_childrenPtr[childIndices[ii]].findNearestRecursive(
00739 element, bestElementPtr, bestDistance);
00740 }
00741 }
00742 }
00743 }
00744
00745
00746 template <class Type>
00747 void
00748 QuadMap<Type>::
00749 setBounds(double minCoord0, double minCoord1,
00750 double maxCoord0, double maxCoord1,
00751 unsigned int maxDepth)
00752 {
00753 m_border0 = (minCoord0 + maxCoord0) / 2.0;
00754 m_border1 = (minCoord1 + maxCoord1) / 2.0;
00755 m_minCoord0 = minCoord0;
00756 m_minCoord1 = minCoord1;
00757 m_maxCoord0 = maxCoord0;
00758 m_maxCoord1 = maxCoord1;
00759 m_maxDepth = maxDepth;
00760 }
00761
00762 }
00763
00764 }
00765
00766 #endif