00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef __VCGLIB_AABBBINARYTREE_CLOSEST_H
00035 #define __VCGLIB_AABBBINARYTREE_CLOSEST_H
00036
00037
00038 #include <limits>
00039 #include <vector>
00040
00041
00042 #include <vcg/math/base.h>
00043 #include <vcg/space/index/aabb_binary_tree/base.h>
00044 #include <wrap/utils.h>
00045
00046
00047
00048 namespace vcg {
00049
00050 template <class TREETYPE>
00051 class AABBBinaryTreeClosest {
00052 public:
00053 typedef AABBBinaryTreeClosest<TREETYPE> ClassType;
00054 typedef TREETYPE TreeType;
00055 typedef typename TreeType::ScalarType ScalarType;
00056 typedef typename TreeType::CoordType CoordType;
00057 typedef typename TreeType::NodeType NodeType;
00058 typedef typename TreeType::ObjPtr ObjPtr;
00059
00060 template <class OBJPOINTDISTANCEFUNCT>
00061 static inline ObjPtr Closest(TreeType & tree, OBJPOINTDISTANCEFUNCT & getPointDistance, const CoordType & p, const ScalarType & maxDist, ScalarType & minDist, CoordType & q) {
00062 typedef OBJPOINTDISTANCEFUNCT ObjPointDistanceFunct;
00063 typedef std::vector<NodeType *> NodePtrVector;
00064 typedef typename NodePtrVector::const_iterator NodePtrVector_ci;
00065
00066 NodeType * pRoot = tree.pRoot;
00067
00068 if (pRoot == 0) {
00069 return (0);
00070 }
00071
00072 NodePtrVector clist1;
00073 NodePtrVector clist2;
00074 NodePtrVector leaves;
00075
00076 NodePtrVector * candidates = &clist1;
00077 NodePtrVector * newCandidates = &clist2;
00078
00079 clist1.reserve(tree.pObjects.size());
00080 clist2.reserve(tree.pObjects.size());
00081 leaves.reserve(tree.pObjects.size());
00082
00083 clist1.resize(0);
00084 clist2.resize(0);
00085 leaves.resize(0);
00086
00087 ScalarType minMaxDist = maxDist * maxDist;
00088
00089 candidates->push_back(pRoot);
00090
00091 while (!candidates->empty()) {
00092 newCandidates->resize(0);
00093
00094 for (NodePtrVector_ci bv=candidates->begin(); bv!=candidates->end(); ++bv) {
00095 const CoordType dc = Abs(p - (*bv)->boxCenter);
00096 const ScalarType maxDist = (dc + (*bv)->boxHalfDims).SquaredNorm();
00097 (*bv)->ScalarValue() = LowClampToZero(dc - (*bv)->boxHalfDims).SquaredNorm();
00098 if (maxDist < minMaxDist) {
00099 minMaxDist = maxDist;
00100 }
00101 }
00102
00103 for (NodePtrVector_ci ci=candidates->begin(); ci!=candidates->end(); ++ci) {
00104 if ((*ci)->ScalarValue() < minMaxDist) {
00105 if ((*ci)->IsLeaf()) {
00106 leaves.push_back(*ci);
00107 }
00108 else {
00109 if ((*ci)->children[0] != 0) {
00110 newCandidates->push_back((*ci)->children[0]);
00111 }
00112 if ((*ci)->children[1] != 0) {
00113 newCandidates->push_back((*ci)->children[1]);
00114 }
00115 }
00116 }
00117 }
00118 NodePtrVector * cSwap = candidates;
00119 candidates = newCandidates;
00120 newCandidates = cSwap;
00121 }
00122
00123 clist1.clear();
00124 clist2.clear();
00125
00126 ObjPtr closestObject = 0;
00127 CoordType closestPoint;
00128 ScalarType closestDist = math::Sqrt(minMaxDist) + std::numeric_limits<ScalarType>::epsilon();
00129 ScalarType closestDistSq = closestDist * closestDist;
00130
00131
00132 for (NodePtrVector_ci ci=leaves.begin(); ci!=leaves.end(); ++ci) {
00133 if ((*ci)->ScalarValue() < closestDistSq) {
00134 for (typename TreeType::ObjPtrVectorConstIterator si=(*ci)->oBegin; si!=(*ci)->oEnd; ++si) {
00135 if (getPointDistance(*(*si), p, closestDist, closestPoint)) {
00136 closestDistSq = closestDist * closestDist;
00137 closestObject = (*si);
00138 q = closestPoint;
00139 minDist = closestDist;
00140 }
00141 }
00142 }
00143 }
00144
00145 leaves.clear();
00146
00147 return (closestObject);
00148 }
00149
00150 };
00151
00152 }
00153
00154 #endif // #ifndef __VCGLIB_AABBBINARYTREE_CLOSEST_H