quadMap.h

Go to the documentation of this file.
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       // Grr.  Temporarily trapped into using vector here, even though
00388       // it makes our data structure very clunky.  Will fix this when
00389       // time permits.
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   } // namespace computerVision
00400   
00401 } // namespace dlr
00402 
00403 
00404 /* ============ Definitions of inline & template functions ============ */
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     // The destructor cleans up any system resources during destruction.
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       // If adding more than one element, dispatch to the recursive,
00475       // vector-argument addElements method.
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       // If we have a local element, just check to see if it matches.
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       // If we're in a leaf node... a cell of the map that has no
00519       // children or can't have children, just remember this point.
00520       if((m_localStore.empty() && m_childrenPtr == 0) || m_maxDepth == 0) {
00521         m_localStore.push_back(elementPtr);
00522         return *elementPtr;
00523       }
00524 
00525       // We're going to pass this element on to one of the children of
00526       // *this.  If no children exist, create them now.
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       // Pass the new element to on of the child nodes.
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       // this->findNearestRecursive(element, bestElementPtr, distanceSquared);
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     /* ================ Protected ================= */
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       // Contents of this stack are std::pairs in which the first
00594       // element points to an un-searched map, and the second element
00595       // is a lower bound on the squared distance from argument
00596       // element to the elements contained in the un-searched map.
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             // Sanity check.
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           // Figure out which child the element belongs in.
00632           unsigned int nearChildIndex = currentMap->m_comparator.chooseChild(
00633             element, currentMap->m_border0, currentMap->m_border1);
00634 
00635           // We want to push the farthest child first and the nearest
00636           // last, so that near child will be popped first.  By
00637           // putting the appropriate indices in an array, we can do
00638           // the pushing in a for loop.
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           // We only want to push a child if it's plausible that it
00646           // contains a closer element than our best so far.  This
00647           // means we need to compute min distances to each of the
00648           // children.  We'll arrange the results in an array
00649           // corresponding to the index array above.
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           // At this point, childIndices[0] is the farthest quadrant,
00657           // and childIndices[3] is the nearest, but it's just luck as
00658           // to which of childIndices[1] and childIndices[2] has the
00659           // smaller minDistance.
00660           if(minDistances[1] < minDistances[2]) {
00661             std::swap(childIndices[1], childIndices[2]);
00662             std::swap(minDistances[1], minDistances[2]);
00663           }
00664 
00665           // At last we push the children onto the stack so that
00666           // they'll be searched in-turn.
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       // Note(xxx): The lower-bound-on-distance-to-element calculation
00687       // in this function could be more aggressive if we added a
00688       // "bound" argument, allowing the same kind of check as is done
00689       // in findNearestIterative().
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         // Figure out which child the element belongs in.
00704         unsigned int nearChildIndex = m_comparator.chooseChild(
00705           element, m_border0, m_border1);
00706 
00707         // We want to search the nearest child first and the others
00708         // later.  By putting the appropriate indices in an array, we
00709         // can do the searching in a for loop.
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         // We only want to search a child if it's plausible that it
00717         // contains a closer element than our best so far.  This
00718         // means we need to compute min distances to each of the
00719         // children.  We'll arrange the results in an array
00720         // corresponding to the index array above.
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         // At this point, childIndices[0] is the farthest quadrant,
00728         // and childIndices[3] is the nearest, but it's just luck as
00729         // to which of childIndices[1] and childIndices[2] has the
00730         // smaller minDistance.
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   } // namespace computerVision
00763   
00764 } // namespace dlr
00765 
00766 #endif /* #ifndef DLR_COMPUTERVISION_QUADMAP_H */

Generated on Wed Nov 25 12:15:05 2009 for dlrComputerVision Utility Library by  doxygen 1.5.8