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
00035
00036
00037 #ifndef __VCGLIB_AABBBINARYTREEBASE_H
00038 #define __VCGLIB_AABBBINARYTREEBASE_H
00039
00040
00041 #include <assert.h>
00042
00043
00044 #include <vector>
00045
00046
00047 #include <vcg/space/point3.h>
00048 #include <vcg/space/box3.h>
00049
00050
00051
00052 namespace vcg {
00053
00054 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00055 class AABBBinaryTree {
00056 public:
00057 typedef AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE> ClassType;
00058 typedef OBJTYPE ObjType;
00059 typedef ObjType * ObjPtr;
00060 typedef SCALARTYPE ScalarType;
00061 typedef NODEAUXDATATYPE NodeAuxDataType;
00062 typedef Point3<ScalarType> CoordType;
00063
00064 typedef std::vector<ObjPtr> ObjPtrVector;
00065 typedef typename ObjPtrVector::iterator ObjPtrVectorIterator;
00066 typedef typename ObjPtrVector::const_iterator ObjPtrVectorConstIterator;
00067
00068 public:
00069 class AABBBinaryTreeNode {
00070 public:
00071 CoordType boxCenter;
00072 CoordType boxHalfDims;
00073 ObjPtrVectorIterator oBegin;
00074 ObjPtrVectorIterator oEnd;
00075 AABBBinaryTreeNode * children[2];
00076 unsigned char splitAxis;
00077 NodeAuxDataType auxData;
00078
00079 inline AABBBinaryTreeNode(void);
00080 inline ~AABBBinaryTreeNode(void);
00081
00082 inline void Clear(void);
00083 inline bool IsLeaf(void) const;
00084 inline unsigned int ObjectsCount(void) const;
00085
00086 inline unsigned int & Flags(void);
00087 inline const unsigned int & Flags(void) const;
00088
00089 inline ScalarType & ScalarValue(void);
00090 inline const ScalarType & ScalarValue(void) const;
00091
00092 inline int & IntValue(void);
00093 inline const int & IntValue(void) const;
00094
00095 inline unsigned int & UIntValue(void);
00096 inline const unsigned int & UIntValue(void) const;
00097
00098 inline void * & PtrValue(void);
00099 inline const void * & PtrValue(void) const;
00100
00101 protected:
00102 union SharedDataUnion {
00103 unsigned int flags;
00104 int intValue;
00105 unsigned int uintValue;
00106 ScalarType scalarValue;
00107 void * ptrValue;
00108 };
00109
00110 SharedDataUnion sharedData;
00111 };
00112
00113 typedef AABBBinaryTreeNode NodeType;
00114
00115 ObjPtrVector pObjects;
00116 NodeType * pRoot;
00117
00118 inline AABBBinaryTree(void);
00119 inline ~AABBBinaryTree(void);
00120
00121 inline void Clear(void);
00122
00123 template <class OBJITERATOR, class OBJITERATORPTRFUNCT, class OBJBOXFUNCT, class OBJBARYCENTERFUNCT>
00124 inline bool Set(const OBJITERATOR & oBegin, const OBJITERATOR & oEnd, OBJITERATORPTRFUNCT & objPtr, OBJBOXFUNCT & objBox, OBJBARYCENTERFUNCT & objBarycenter, const unsigned int maxElemsPerLeaf = 1, const ScalarType & leafBoxMaxVolume = ((ScalarType)0), const bool useVariance = true);
00125
00126 protected:
00127 template <class OBJBOXFUNCT, class OBJBARYCENTERFUNCT>
00128 inline static NodeType * BoundObjects(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const unsigned int size, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance, OBJBOXFUNCT & getBox, OBJBARYCENTERFUNCT & getBarycenter);
00129
00130 template <class OBJBARYCENTERFUNCT>
00131 inline static int BalanceMedian(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const int size, const int splitAxis, OBJBARYCENTERFUNCT & getBarycenter, ObjPtrVectorIterator & medianIter);
00132 };
00133
00134
00135
00136 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00137 AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTree(void) {
00138 this->pObjects.clear();
00139 this->pRoot = 0;
00140 }
00141
00142 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00143 AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::~AABBBinaryTree(void) {
00144 this->pObjects.clear();
00145 delete this->pRoot;
00146 }
00147
00148 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00149 void AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::Clear(void) {
00150 this->pObjects.clear();
00151 delete this->pRoot;
00152 this->pRoot = 0;
00153 }
00154
00155 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00156 template <class OBJITERATOR, class OBJITERATORPTRFUNCT, class OBJBOXFUNCT, class OBJBARYCENTERFUNCT>
00157 bool AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::Set(const OBJITERATOR & oBegin, const OBJITERATOR & oEnd, OBJITERATORPTRFUNCT & objPtr, OBJBOXFUNCT & objBox, OBJBARYCENTERFUNCT & objBarycenter, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance) {
00158 this->Clear();
00159
00160 if ((maxElemsPerLeaf == 0) && (leafBoxMaxVolume <= ((ScalarType)0))) {
00161 return (false);
00162 }
00163
00164 const unsigned int size = (unsigned int)std::distance(oBegin, oEnd);
00165
00166 this->pObjects.reserve(size);
00167 for (OBJITERATOR oi=oBegin; oi!=oEnd; ++oi) {
00168 this->pObjects.push_back(objPtr(*oi));
00169 }
00170
00171 this->pRoot = ClassType::BoundObjects(this->pObjects.begin(), this->pObjects.end(), size, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, objBox, objBarycenter);
00172
00173 return (this->pRoot != 0);
00174 }
00175
00176 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00177 template <class OBJBOXFUNCT, class OBJBARYCENTERFUNCT>
00178 typename AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::NodeType * AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::BoundObjects(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const unsigned int size, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance, OBJBOXFUNCT & getBox, OBJBARYCENTERFUNCT & getBarycenter) {
00179 if (size <= 0) {
00180 return (0);
00181 }
00182
00183 NodeType * pNode = new NodeType();
00184 if (pNode == 0) {
00185 return (0);
00186 }
00187
00188 pNode->children[0] = 0;
00189 pNode->children[1] = 0;
00190
00191 pNode->oBegin = oBegin;
00192 pNode->oEnd = oEnd;
00193
00194 Box3<ScalarType> bbox;
00195 bbox.SetNull();
00196 for (ObjPtrVectorConstIterator oi=pNode->oBegin; oi!=pNode->oEnd; ++oi) {
00197 Box3<ScalarType> tbox;
00198 getBox(*(*oi), tbox);
00199 bbox.Add(tbox);
00200 }
00201
00202 pNode->boxCenter = bbox.Center();
00203 pNode->boxHalfDims = bbox.Dim() / ((ScalarType)2);
00204
00205 const bool bMaxObjectsReached = (((maxElemsPerLeaf > 0) && (size <= maxElemsPerLeaf)) || (size == 1));
00206 const bool bMaxVolumeReached = ((leafBoxMaxVolume > ((ScalarType)0)) && (bbox.Volume() <= leafBoxMaxVolume));
00207 const bool isLeaf = bMaxObjectsReached || bMaxVolumeReached;
00208
00209 if (isLeaf) {
00210 pNode->splitAxis = 0;
00211 return (pNode);
00212 }
00213
00214 CoordType pSplit;
00215
00216 if (useVariance) {
00217 CoordType mean((ScalarType)0, (ScalarType)0, (ScalarType)0);
00218 CoordType variance((ScalarType)0, (ScalarType)0, (ScalarType)0);
00219 for (ObjPtrVectorIterator oi=oBegin; oi!=oEnd; ++oi) {
00220 CoordType bc;
00221 getBarycenter(*(*oi), bc);
00222 mean += bc;
00223 variance[0] += bc[0] * bc[0];
00224 variance[1] += bc[1] * bc[1];
00225 variance[2] += bc[2] * bc[2];
00226 }
00227 variance[0] -= (mean[0] * mean[0]) / ((ScalarType)size);
00228 variance[1] -= (mean[1] * mean[1]) / ((ScalarType)size);
00229 variance[2] -= (mean[2] * mean[2]) / ((ScalarType)size);
00230 pSplit = variance;
00231 }
00232 else {
00233 pSplit = pNode->boxHalfDims;
00234 }
00235
00236 ScalarType maxDim = pSplit[0];
00237 unsigned char splitAxis = 0;
00238 if (maxDim < pSplit[1]) {
00239 maxDim = pSplit[1];
00240 splitAxis = 1;
00241 }
00242 if (maxDim < pSplit[2]) {
00243 maxDim = pSplit[2];
00244 splitAxis = 2;
00245 }
00246
00247 pNode->splitAxis = splitAxis;
00248
00249 ObjPtrVectorIterator median;
00250 const int lSize = ClassType::BalanceMedian(pNode->oBegin, pNode->oEnd, size, splitAxis, getBarycenter, median);
00251 const int rSize = size - lSize;
00252
00253 if (lSize > 0) {
00254 pNode->children[0] = ClassType::BoundObjects(pNode->oBegin, median, lSize, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, getBox, getBarycenter);
00255 if (pNode->children[0] == 0) {
00256 delete pNode;
00257 return (0);
00258 }
00259 }
00260
00261 if (rSize > 0) {
00262 pNode->children[1] = ClassType::BoundObjects(median, pNode->oEnd, rSize, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, getBox, getBarycenter);
00263 if (pNode->children[1] == 0) {
00264 delete pNode;
00265 return (0);
00266 }
00267 }
00268
00269 return (pNode);
00270 }
00271
00272 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00273 template <class OBJBARYCENTERFUNCT>
00274 int AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::BalanceMedian(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const int size, const int splitAxis, OBJBARYCENTERFUNCT & getBarycenter, ObjPtrVectorIterator & medianIter) {
00275 const int iMedian = (size + 1) / 2;
00276
00277 ObjPtrVectorIterator l, r, i, j;
00278 ObjPtr iTmp;
00279 ScalarType pos;
00280 ObjPtrVectorIterator median = oBegin + iMedian;
00281 CoordType bc;
00282
00283 l = oBegin;
00284 r = oEnd - 1;
00285
00286 while (l < r) {
00287 getBarycenter(*(*r), bc);
00288 pos = bc[splitAxis];
00289
00290 i = l;
00291 j = r - 1;
00292
00293 while (true) {
00294 getBarycenter(*(*i), bc);
00295 while ((bc[splitAxis] <= pos) && (i < r)) {
00296 i++;
00297 getBarycenter(*(*i), bc);
00298 }
00299 getBarycenter(*(*j), bc);
00300 while ((bc[splitAxis] > pos) && (j > l)) {
00301 j--;
00302 getBarycenter(*(*j), bc);
00303 }
00304 if (i >= j) {
00305 break;
00306 }
00307 iTmp = (*i);
00308 (*i) = (*j);
00309 (*j) = iTmp;
00310 }
00311
00312 iTmp = (*i);
00313 (*i) = (*r);
00314 (*r) = iTmp;
00315
00316 if (i >= (median)) {
00317 r = i - 1;
00318 }
00319 if (i <= (median)) {
00320 l = i + 1;
00321 }
00322 }
00323
00324 medianIter = median;
00325
00326 return (iMedian);
00327 }
00328
00329 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00330 AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::AABBBinaryTreeNode(void) {
00331 this->children[0] = 0;
00332 this->children[1] = 0;
00333 }
00334
00335 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00336 AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::~AABBBinaryTreeNode(void) {
00337 delete this->children[0];
00338 delete this->children[1];
00339 }
00340
00341 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00342 void AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::Clear(void) {
00343 delete this->children[0];
00344 this->children[0] = 0;
00345
00346 delete this->children[1];
00347 this->children[1] = 0;
00348 }
00349
00350 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00351 bool AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::IsLeaf(void) const {
00352 return ((this->children[0] == 0) && (this->children[1] == 0));
00353 }
00354
00355 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00356 unsigned int AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::ObjectsCount(void) const {
00357 return ((unsigned int)(std::distance(this->oBegin, this->oEnd)));
00358 }
00359
00360 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00361 unsigned int & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::Flags(void) {
00362 return (this->sharedData.flags);
00363 }
00364
00365 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00366 const unsigned int & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::Flags(void) const {
00367 return (this->sharedData.flags);
00368 }
00369
00370 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00371 int & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::IntValue(void) {
00372 return (this->sharedData.intValue);
00373 }
00374
00375 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00376 const int & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::IntValue(void) const {
00377 return (this->sharedData.intValue);
00378 }
00379
00380 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00381 unsigned int & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::UIntValue(void) {
00382 return (this->sharedData.uintValue);
00383 }
00384
00385 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00386 const unsigned int & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::UIntValue(void) const {
00387 return (this->sharedData.uintValue);
00388 }
00389
00390 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00391 typename AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::ScalarType & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::ScalarValue(void) {
00392 return (this->sharedData.scalarValue);
00393 }
00394
00395 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00396 const typename AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::ScalarType & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::ScalarValue(void) const {
00397 return (this->sharedData.scalarValue);
00398 }
00399
00400 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00401 void * & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::PtrValue(void) {
00402 return (this->sharedData.ptrValue);
00403 }
00404
00405 template <class OBJTYPE, class SCALARTYPE, class NODEAUXDATATYPE>
00406 const void * & AABBBinaryTree<OBJTYPE, SCALARTYPE, NODEAUXDATATYPE>::AABBBinaryTreeNode::PtrValue(void) const {
00407 return (this->sharedData.ptrValue);
00408 }
00409
00410 }
00411
00412 #endif // #ifndef __VCGLIB_AABBBINARYTREEBASE_H