00001
00002
00003
00004
00005
00006
00007
00008 #ifndef OCTREESPACE_HPP_
00009 #define OCTREESPACE_HPP_
00010
00011 #include <stack>
00012 #include <algorithm>
00013 #include "fv_float.h"
00014 #include "MathHelper.h"
00015 #include "BBox3D.h"
00016
00017 namespace FemViewer {
00018
00019
00020
00021 template<typename TObject,
00022 typename TContent = ArrayT<TObject> >
00023 class Octree
00024 {
00025 typedef TObject OctElement;
00026 typedef fvmath::CVec3<CoordType> OctPoint;
00027 typedef TContent OctElems;
00028 typedef typename OctElems::iterator OctElemIter;
00029 protected:
00030
00031 enum eNode { leaf, branch };
00032
00033 class iterator;
00034
00035 class INode {
00036 public:
00037 virtual eNode type() const = 0;
00038
00039 };
00040
00041
00042 class Leaf : public INode {
00043 private:
00044
00045 int _resolution;
00046
00047 OctPoint _position;
00048
00049 OctElems _elems;
00050
00051 public:
00052 eNode type() const { return leaf; }
00053 int& resolution() { return _resolution; }
00054 const int& resolution() const { return _resolution; }
00055 const OctPoint& position() const { return _position; }
00056
00057 void addElem(const OctElement& el)
00058 {
00059 _elems.insert(el);
00060 }
00061
00062 void deleteElem(const OctElement& el)
00063 {
00064 _elems.erase(el);
00065 }
00066
00067 Leaf(const OctPoint& pos, int res = 1) : _resolution(res), _position(pos), _elems()
00068 {;}
00069 Leaf(const Leaf& lf) : _resolution(lf._resolution), _position(lf._position), _elems(lf._elems)
00070 {;}
00071 virtual ~Leaf()
00072 {;}
00073 };
00074
00075
00076 class Branch : public INode {
00077 private:
00078
00079 INode* _children[1 + 8];
00080 public:
00081 eNode type() const { return branch; }
00082 INode*& child(size_t idx)
00083 {
00084 return _children[idx];
00085 }
00086
00087 iterator& serach(const OctPoint& X, const OctPoint& center, const CoordType size,
00088 iterator& cell)
00089 {
00090 uint_t num(0);
00091 uint_t atb[3];
00092 for (uint_t i(0);i<3;++i) {
00093 atb[i] = (X[i] > center[i]);
00094 num += (atb[i] << (2-i));
00095 }
00096
00097 cell.addHandle(this);
00098 cell.level() = num;
00099
00100 if (_children[num]==0) {
00101 cell.level() = -1;
00102 cell++;
00103 } else {
00104 CoordType cor = 0.5*size;
00105 OctPoint newcenter(center);
00106
00107 for (int i(0);i<3;++i) newcenter[i] += (atb[i]*2 -1)*cor;
00108
00109 if ((*_children[num]).type() == branch) {
00110 (static_cast<Branch&>(*_children[num])).search(X,newcenter,cor,cell);
00111 } else {
00112 cell._leaf = static_cast<Leaf*>(_children[num]);
00113 }
00114 }
00115 return cell;
00116 }
00117
00118 void addLeaf(const OctPoint& center,CoordType size,Leaf* lf)
00119 {
00120 int num(0);
00121 int atb[3];
00122 for (int i=0;i<3;++i) {
00123 atb[i] = ((*lf).position()[i] > center[i]);
00124 num += (atb[i] << (2-i));
00125 }
00126
00127
00128 if (_children[num] == 0) {
00129
00130 _children[num] = lf;
00131 } else {
00132 CoordType cor = CoordType(0.5)*size;
00133 OctPoint newcenter(center);
00134
00135 for (int i(0);i<3;++i) newcenter += (atb[i]*2 -1)*cor;
00136
00137 if ((*_children[num]).type() == branch) {
00138 (static_cast<Branch&>(*_children[num])).addLeaf(newcenter,cor,lf);
00139 } else {
00140 Leaf* oldlf = static_cast<Leaf*>(_children[num]);
00141 Branch* br = new Branch();
00142 _children[num] = br;
00143 br->addLeaf(center,cor,lf);
00144 br->addLeaf(center,cor,oldlf);
00145 }
00146 }
00147 }
00148
00149 void insert(const OctPoint& cent,
00150 const CoordType& size,
00151 const int res,
00152 const int num,
00153 const OctElems& el,
00154 const BBox3D& itembb)
00155 {
00156 if (num==0) {
00157 if (_children[0]==0) {
00158 int lres = std::min(_maxres,res);
00159 _children[0] = new Leaf(cent,lres);
00160 }
00161 static_cast<Leaf*>(_children[0])->addElem(el);
00162 } else {
00163 if (_children[num]==0) {
00164 _children[num] = new Branch();
00165 }
00166
00167
00168 int num = 0;
00169 int atb[8];
00170 for (int i=0;i<8;++i) {
00171 atb[i] = it.v[i] > center[i]);
00172 num += (atb[i] << (2-i));
00173 }
00174 CoordType hs = CoordType(0.5) * size;
00175 OctPoint nc(cent);
00176 for(int i=0;i<3;++i) nc[i] += (atb[i]*2 -1)*hs;
00177
00178 Branch* br(0);
00179 if (_children[++num]==0) {
00180 br = new Branch();
00181 _children[num] = br;
00182 } else {
00183 br = static_cast<Branch*>(_children[num]);
00184 }
00185 int lres = getResolution(el.bbox.maxDim() * 0.5);
00186 br->insert(nc,hs,lres,num,el);
00187
00188 }
00189 }
00190
00191
00192 OctElemIter begin()
00193 {
00194 OctElemIter it;
00195 it.addHandle(this);
00196 it++;
00197 return it;
00198 }
00199 explicit Branch(){ memset(_children,0x0,sizeof(_children)); }
00200 Branch(const Branch& br){;}
00201 virtual ~Branch() {;}
00202 private:
00203 };
00204
00205
00206
00207 public:
00208 Octree(const BBox3D& bbox,uint_t res)
00209 : _pos(), _root(0), _maxres(0), _maxsize(0), _minsize(0)
00210 {
00211 assert(bbox.isInitialized());
00212 assert(res > 0);
00213 this->setResolution(res);
00214 }
00215 ~Octree() {;}
00216 public:
00217 class iterator {
00218 public:
00219 friend class Branch;
00220 typedef std::pair<int,Branch*> lHandle;
00221 private:
00222 Leaf* _leaf;
00223 std::stack<lHandle> _handles;
00224 public:
00225 size_t getdepth() { return _handles.szie(); }
00226 Branch* getcurrfather()
00227 {
00228 if (_handles.size() >0) {
00229 return _handles.top().second;
00230 }
00231 else return 0;
00232 }
00233 iterator& operator++(int)
00234 {
00235 _leaf = 0;
00236 Branch* fa = getcurrfather();
00237 if (fa != 0) {
00238 _handles.top().first++;
00239 if (_handles.top().first < 8) {
00240 INode* node = fa->child(_handles.top().first);
00241 if (node != 0) {
00242 if (node->type() == leaf) {
00243 _leaf = static_cast<Leaf*>(node);
00244 } else {
00245 Branch* br = static_cast<Branch*>(node);
00246 this->addHandle(br);
00247 (*this)++;
00248 }
00249 } else {
00250 (*this)++;
00251 }
00252 } else {
00253 _handles.pop();
00254 (*this)++;
00255 }
00256 }
00257 return(*this);
00258 }
00259
00260 int& level() { return _handles.top().first; }
00261 const int& level() const { return _handles.top().first; }
00262
00263 void addHandle(Branch* br)
00264 {
00265 lHandle h;
00266 h.first = -1;
00267 h.second = br;
00268 _handles.push(h);
00269 }
00270
00271 operator Leaf*() { return _leaf; }
00272
00273 iterator() : _leaf(0) {;}
00274 iterator(const iterator& it) : _leaf(it), _handles(it) {;}
00275 ~iterator() {;}
00276
00277 };
00278
00279 iterator begin() const
00280 {
00281 iterator it;
00282 if (_root != 0) {
00283 if ((*_root).type() == leaf) {
00284
00285 } else {
00286 Branch& br = static_cast<Branch&>(*_root);
00287 it = br.begin();
00288 }
00289 }
00290 return it;
00291 }
00292
00293 iterator end() const
00294 {
00295 return iterator();
00296 }
00297
00298 iterator search(const OctPoint& X)
00299 {
00300 iterator it;
00301 if (_root==0) {
00302 return this->end();
00303 } else if ((*_root).type() != branch) {
00304 it._leaf = static_cast<Leaf*>(_root);
00305 return it;
00306 } else {
00307 return (static_cast<Branch&>(*_root)).serach(X,_bbmesh.getCenter(),size,it);
00308 }
00309
00310 return it;
00311 }
00312
00313 void setResolution(const uint_t res)
00314 {
00315 if (!(res && (res & (res-1)))) _maxres = fvmath::npow2(res);
00316 else _maxres = res;
00317 }
00318
00319 void setDimensions(const BBox3D& bbox)
00320 {
00321 if (_maxres > 0)
00322 {
00323 _pos = bbox.center();
00324 _maxsize = bbox.maxDim();
00325 _minsize = _maxsize / _maxres;
00326 }
00327 }
00328
00329 void add(const OctElement& c, const BBox3D& elbb)
00330 {
00331
00332 if (_root==0) {
00333 _root = new Leaf(elbbo.center());
00334 static_cast<Leaf&>(*_root).addElem(c);
00335 } else {
00336 if ((*_root).type() == leaf) {
00337 Leaf* lf = static_cast<Leaf*>(_root);
00338
00339
00340
00341
00342 Branch* br = new Branch();
00343 _root = br;
00344 br->addLeaf(_pos,_size,lf);
00345 Leaf* nlf = new Leaf(position);
00346 nlf->addElem(c);
00347 br->addLeaf(_center,_size,nlf);
00348 } else {
00349 Leaf* nlf = new Leaf(position);
00350 nlf->addElem(c);
00351 (static_cast<Branch&>(*_root)).addLeaf(_center,_size,nlf);
00352
00353 }
00354 }
00355 }
00356
00357 void insert(const OctElement& item,const BBox3D& itembb)
00358 {
00359 OctPoint pos(_pos);
00360 int noct = check(pos,_maxsize*0.5,itembb);
00361 assert((0<=noct) && (noct <= 9));
00362
00363 if (noct==0)
00364 {
00365
00366 if ( _root==0) {
00367 _root = new Leaf(_pos);
00368 }
00369
00370
00371 if ((*_root).type() == leaf) {
00372 (static_cast<Leaf*>(_root))->addElem(item);
00373 }
00374 else {
00375 Branch* br = static_cast<Branch*>(_root);
00376 Leaf* lf;
00377 if (br->child(0)==0)
00378 {
00379 lf = new Leaf(_pos,1);
00380 br->child(0) = lf;
00381 }
00382 else {
00383 lf = static_cast<Leaf*>(br->child(0));
00384 }
00385 lf->addElem(item);
00386 }
00387
00388 }
00389 else {
00390 Branch* br;
00391
00392 if (_root==0) {
00393
00394 br = new Branch();
00395 static_cast<Branch*>(_root)->child(noct) = br;
00396 }
00397
00398 if ((*_root).type() == leaf) {
00399 Leaf* lf = static_cast<Leaf*>(_root);
00400 br = new Branch();
00401 _root = br;
00402 br->child(0) = lf;
00403 } else {
00404 br = static_cast<Branch*>(_root);
00405 }
00406
00407 br->insert(pos,_maxsize*0.5,_maxres,item,itembb);
00408 }
00409 }
00410
00411 static int check(const OctPoint& pos, const CoordType size, const BBox3D& elem);
00412 inline BBox3D genBBoxForNode(const Vec3D& cent,int level)
00413 {
00414 assert(((level -1) & level) == 0);
00415 if (level==0) {
00416 return BBox3D(_pos,_maxsize*0.5f);
00417 } else {
00418 float size = this->_maxsize / static_cast<float>(1 << level);
00419 return BBox3D(cent,size);
00420 }
00421 }
00422
00423 inline int getResolution(const T& size)
00424 {
00425 assert(size > 0);
00426 assert(_minsize > 0);
00427 int aln = npow2( static_cast<float>( ceil( (size / _minsize) ) );
00428 int lg2 = log2(aln);
00429 return this->_maxres >> lg2;
00430 }
00431
00432 private:
00433 OctPoint _pos;
00434 Branch* _root;
00435 unsigned int _maxres;
00436 CoordType _maxsize;
00437 CoordType _minsize;
00438
00439 };
00440
00441
00442 template<typename TObject,typename TContent>
00443 int
00444 Octree<TObject,TContent>::check(const OctPoint& pos, const CoordType hs, const BBox3D& elbb)
00445 {
00446 int num;
00447 int atb[8];
00448 OctPoint bc(elbb.center());
00449
00450 atb[0] = (bc.x > pos.x);
00451 num = atb[0] << 2;
00452 atb[1] = (bc.y > pos.y);
00453 num += atb[1] << 1;
00454 atb[2] = (bc.z > pos.z);
00455 num += atb[2];
00456
00457
00458 assert(hs > 0);
00459 OctPoint mv(hs,hs,hs);
00460
00461 switch(num)
00462 {
00463 case 0:
00464 mv.x *= -1;
00465 mv.y *= -1;
00466 mv.z *= -1;
00467 break;
00468 case 1:
00469 mv.x *= -1;
00470 mv.y *= -1;
00471 break;
00472 case 2:
00473 mv.x *= -1;
00474 mv.z *= -1;
00475 break;
00476 case 3:
00477 mv.x *= -1
00478 break;
00479 case 4:
00480 mv.y *= -1;
00481 mv.z *= -1;
00482 break;
00483 case 5:
00484 mv.y *= -1;
00485 break;
00486 case 6:
00487 mv.z *= -1;
00488 break;
00489 case 7:
00490 break;
00491 }
00492
00493 pos += mv;
00494 BBox3D lbb(pos,hs);
00495 unsigned int lo, up;
00496 lo = lbb.IsInside(elbb.mn) ? 1 : 0;
00497 up = lbb.IsInside(elbb.mx) ? 1 : 0;
00498
00499 return (lo && up) ? num + 1 : 0;
00500 }
00501
00502
00503 }
00504
00505 #endif
00506
00507