00001 #ifndef Complex1_HEADER
00002 #define Complex1_HEADER
00003
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007
00008 #include "SimplicialComplex.h"
00009 #include <boost/iterator/iterator_facade.hpp>
00010
00015 template <class Vertex_, class SimplexData_, class VertexPrinter_>
00016 class SimplicialComplex<1, Vertex_, SimplexData_, VertexPrinter_> {
00017
00018 public:
00019 typedef Vertex_ Vertex;
00020 typedef VertexPrinter_ VertexPrinter;
00021 typedef SimplexData_ SimplexData;
00023 typedef typename hudson::Bucket<SimplexData>::reference data_ref;
00024 typedef typename hudson::Bucket<SimplexData>::const_reference data_const_ref;
00025 class Star;
00026 class Cavity;
00027
00028 private:
00029 enum Index { LEFT, RIGHT, DONE };
00030 enum Status { BORN = 0, IN = 1, DEAD = 2 };
00031
00032 template <class Derived, class OutType, class Reference>
00033 class iterator_base : public boost::iterator_facade
00034 < Derived
00035 , OutType
00036 , boost::bidirectional_traversal_tag
00037 , Reference >
00038 {
00039 private:
00041
00042
00043
00044 Derived& derived() { return *static_cast<Derived*>(this); }
00045 Derived const& derived() const { return *static_cast<Derived const*>(this); }
00046
00047 protected:
00048 Index index_;
00049 iterator_base(Index index): index_(index) { }
00050
00051 public:
00052 void increment() { assert(index_ < DONE); index_ = Index(unsigned(index_) + 1); }
00053 void decrement() { assert(index_ > LEFT); index_ = Index(unsigned(index_) - 1); }
00054 bool equal(const Derived& other) const { return index_ == other.index_; }
00055 Reference dereference() const {
00056 switch(index_) {
00057 case LEFT: return derived().getLeft();
00058 case RIGHT: return derived().getRight();
00059 case DONE: assert(0 && "dereferencing end()");
00060 default: assert(0 && "major bug");
00061 return derived().getLeft();
00062 }
00063 }
00064 };
00065
00066 class ISimplex {
00067 ISimplex *left_;
00068 ISimplex *right_;
00069 Vertex *leftV_;
00070
00071 size_t refcount_:(sizeof(size_t)*8 - 2);
00072 Status status_:2;
00073
00074 public:
00075 hudson::Bucket<SimplexData> data_;
00076
00077 ISimplex() {
00078 left_ = right_ = 0;
00079 leftV_ = 0;
00080 refcount_ = 0;
00081 status_ = BORN;
00082 }
00083
00084 bool isDummy() const { return right_ == 0; }
00085
00086 ISimplex *getLeft() const { return left_; }
00087 ISimplex *getRight() const {
00088 assert(right_);
00089 if (right_->isDummy()) {
00090 return 0;
00091 } else return right_;
00092 }
00093 ISimplex *getRightOrDummy() const { return right_; }
00094
00095 Vertex *getLeftV() const {
00096 return leftV_;
00097 }
00098 Vertex *getRightV() const {
00099 assert(!isDummy());
00100 return getRightOrDummy()->getLeftV();
00101 }
00102
00103 Status getStatus() const { return status_; }
00104
00105
00106
00107 void setLeft(ISimplex *left) { left_ = left; }
00108 void setRight(ISimplex *right) { right_ = right; }
00109 void setVertex(Vertex *v) { leftV_ = v; }
00110 void setStatus(Status stat) {
00111 status_ = stat;
00112 switch(status_) {
00113 case IN: add_ref(this); break;
00114 case DEAD: release(this); break;
00115 case BORN: break;
00116 }
00117 }
00118
00119
00120 static void add_ref(ISimplex *s) {
00121 s->refcount_++;
00122 }
00123 static void release(ISimplex *s) {
00124 s->refcount_--;
00125 if (s->refcount_ == 0) {
00126 delete s;
00127 }
00128 }
00129 };
00130
00131 public:
00132 class Simplex {
00133 hudson::IntrusivePtr<ISimplex> s_;
00134
00135 friend class Cavity;
00136 friend class Star;
00137 friend class SimplicialComplex;
00138 ISimplex *get() const { return s_.get(); }
00139 ISimplex *operator->() const { return get(); }
00140 void set(ISimplex *is) { s_ = is; }
00141
00142 public:
00145 Simplex(const Simplex& other): s_(other.s_) { }
00146
00147 static const size_t dimension = 1;
00148
00152 Simplex(ISimplex *s): s_(s) { }
00153
00154 size_t hash() const { return hudson::hashWord((size_t)get()); }
00155 std::string toString() const {
00156 VertexPrinter printer;
00157 return std::string("<") + printer(s_->getLeftV()) + " " + printer(s_->getRightV()) + ">";
00158 }
00159
00160 class vertex_iterator : public iterator_base<vertex_iterator, Vertex*, Vertex*> {
00161 const Simplex& s;
00162 typedef iterator_base<vertex_iterator, Vertex*, Vertex*> super;
00163 friend class iterator_base<vertex_iterator, Vertex*, Vertex*>;
00164 friend class Simplex;
00165 Vertex *getLeft() const { return s->getLeftV(); }
00166 Vertex *getRight() const { return s->getRightV(); }
00167 vertex_iterator(const Simplex& s, Index i): super(i), s(s) { }
00168 };
00169 friend class vertex_iterator;
00170 typedef vertex_iterator iterator;
00171 typedef vertex_iterator const_iterator;
00172
00173 vertex_iterator begin() const { return vertex_iterator(*this, LEFT); }
00174 vertex_iterator end() const { return vertex_iterator(*this, DONE); }
00175
00176 Vertex *operator[](size_t i) const {
00177 switch(i) {
00178 case 0: return s_->getLeftV();
00179 case 1: return s_->getRightV();
00180 default: assert(0); return s_->getLeftV();
00181 }
00182 }
00183
00184 bool has(const Vertex *v) const {
00185 return v == s_->getLeftV() || v == s_->getRightV();
00186 }
00187 template <class BinaryPredicate>
00188 bool has(const Vertex *v, const BinaryPredicate& pred) const {
00189 return pred(v, s_->getLeftV()) || pred(v, s_->getRightV());
00190 }
00191
00192 bool operator== (const Simplex& other) const { return s_.get() == other.get(); }
00193 bool operator!= (const Simplex& other) const { return s_.get() != other.get(); }
00194 };
00195
00196
00197
00198
00199 private:
00200 void init(Vertex *leftV, Vertex *rightV) {
00201 ISimplex *left = handle_.get();
00202 ISimplex *right = new ISimplex;
00203
00204 left->setVertex(leftV);
00205 right->setVertex(rightV);
00206 left->setLeft(0);
00207 left->setRight(right);
00208 right->setLeft(left);
00209 right->setRight(0);
00210
00211 left->setStatus(IN);
00212 }
00213
00214 public:
00215 SimplicialComplex(Vertex *leftV, Vertex *rightV) : handle_(new ISimplex) {
00216 init(leftV, rightV);
00217 }
00218
00219 SimplicialComplex(const vector<Vertex*>& verts) : handle_(new ISimplex) {
00220 assert(verts.size() == 2);
00221 init(verts[0], verts[1]);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 public:
00235 static size_t dim() { return 1; }
00236 static const size_t dimension = 1;
00237
00238
00239
00240
00241
00242 public:
00243 struct Cavity {
00244 typedef const Simplex *iterator;
00245 typedef const Simplex *const_iterator;
00246
00247 Cavity(): s_(NULL) { }
00248
00249 iterator begin() const { return &s_; }
00250 iterator end() const { return begin()+1; }
00251
00252 bool empty() const { return s_.get() == NULL; }
00253 size_t size() const { return empty() ? 0 : 1; }
00254
00255 void add(const Simplex& s) {
00256 assert(empty());
00257 s_ = s;
00258 }
00259
00260 private:
00261 friend class SimplicialComplex;
00262 Simplex s_;
00263 };
00264
00265 class Star {
00266 Simplex left_;
00267 Simplex right_;
00268
00269 friend class SimplicialComplex;
00270
00271 public:
00272 Star() : left_(0), right_(0) { }
00273 void clear() {
00274 left_.set(0);
00275 right_.set(0);
00276 }
00277
00278 class iterator : public iterator_base<iterator, Simplex, const Simplex&> {
00279 typedef iterator_base<iterator, Simplex, const Simplex&> super;
00280 friend class iterator_base<iterator, Simplex, const Simplex&> ;
00281 friend class Star;
00282 const Star * star_;
00283 iterator(const Star& star, Index index): super(index), star_(&star) { }
00284 const Simplex& getLeft() const { return star_->left_; }
00285 const Simplex& getRight() const { return star_->right_; }
00286 };
00287 typedef iterator const_iterator;
00288
00289
00290 class neigh_iterator : public iterator_base<neigh_iterator, Simplex, Simplex> {
00291 typedef iterator_base<iterator, Simplex, Simplex> super;
00292 friend class iterator_base<iterator, Simplex, Simplex> ;
00293 friend class Star;
00294 const Star& star_;
00295 neigh_iterator(const Star& star, Index index): super(index), star_(star) { }
00296 const Simplex& getLeft() const { return star_.left_->getLeft(); }
00297 const Simplex& getRight() const { return star_.right_->getRight(); }
00298 };
00299
00300 iterator begin() const { return iterator(*this, LEFT); }
00301 iterator end() const { return iterator(*this, DONE); }
00302
00303 neigh_iterator begin_neighbours() const { return neigh_iterator(*this, LEFT); }
00304 neigh_iterator end_neighbours() const { return neigh_iterator(*this, DONE); }
00305
00306 const Simplex& operator[] (size_t i) {
00307 switch(i) {
00308 case 0: return left_;
00309 case 1: return right_;
00310 default: assert(0); return left_;
00311 }
00312 }
00313
00314 static size_t size() { return 2; }
00315
00316 const iterator& erase(const iterator& it) {
00317
00318
00319 assert(0);
00320 return it;
00321 }
00322
00323 private:
00324 void computeStar(const Simplex& tosplit, Vertex *v) {
00325 assert(!left_.get()); assert(!right_.get());
00326 left_.set(new ISimplex);
00327 right_.set(new ISimplex);
00328
00329 left_->setLeft(tosplit->getLeft());
00330 left_->setRight(right_.get());
00331 left_->setVertex(tosplit->getLeftV());
00332
00333 right_->setLeft(left_.get());
00334 right_->setRight(tosplit->getRightOrDummy());
00335 right_->setVertex(v);
00336 assert(left_.get()); assert(right_.get());
00337 }
00338
00339 void commit(const Simplex& tosplit) {
00340 assert(left_.get()); assert(right_.get());
00341 assert(left_->getLeftV() == tosplit->getLeftV());
00342 if (left_->getLeft()) {
00343 left_->getLeft()->setRight(left_.get());
00344 }
00345 assert(right_->getRightOrDummy());
00346 right_->getRightOrDummy()->setLeft(right_.get());
00347
00348
00349 assert(left_->getRight() == right_.get());
00350 assert(right_->getLeft() == left_.get());
00351 left_->setStatus(IN);
00352 right_->setStatus(IN);
00353 tosplit->setStatus(DEAD);
00354 }
00355 };
00356
00357 void computeStar(const Simplex& tosplit, Vertex *apex, Star& star) {
00358 assert(isMember(tosplit));
00359 star.computeStar(tosplit, apex);
00360 }
00361 void computeStar(const Cavity& cavity, Vertex *apex, Star& star) {
00362 computeStar(cavity.s_, apex, star);
00363 }
00364
00365 void replaceCavity(const Simplex& tosplit, Star& star) {
00366 assert(isMember(tosplit));
00367 star.commit(tosplit);
00368 setHandle(star.left_);
00369 }
00370 void replaceCavity(const Cavity& cavity, Star& star) {
00371 replaceCavity(cavity.s_, star);
00372 }
00373
00374 void replaceCavity(const Simplex& tosplit, Vertex *apex) {
00375 Star star;
00376 computeStar(tosplit, apex, star);
00377 replaceCavity(tosplit, star);
00378 }
00379 void replaceCavity(const Cavity& cavity, Vertex *apex) {
00380 replaceCavity(cavity.s_, apex);
00381 }
00382
00383 void checkedRemoveSimplex(const Simplex& s) {
00384 assert(isMember(s));
00385 assert(getHandle() != s);
00386 if (s->getLeft()) {
00387 s->getLeft()->setRight(0);
00388 }
00389 ISimplex *right = s->getRightOrDummy();
00390 assert(right);
00391 if (right->isDummy()) {
00392
00393 delete right;
00394 } else {
00395 right->setLeft(0);
00396 }
00397 s->setLeft(0);
00398 s->setRight(0);
00399 s->setStatus(DEAD);
00400 }
00401
00402
00403
00404 bool isMember(const Simplex& s) const {
00405 return s.get() && (s->getStatus() == IN) && !s->isDummy();
00406 }
00407
00408 const Simplex& getHandle() const {
00409 return handle_;
00410 }
00411
00412 void setHandle(const Simplex& s) {
00413 assert(isMember(s));
00414 handle_ = s;
00415 }
00416
00417
00418
00419 Simplex getNeighbour(int i, const Simplex& s) const {
00420 assert(isMember(s));
00421 switch (i) {
00422 case 0: return s->getRight();
00423 case 1: return s->getLeft();
00424 default: assert(0); return s->getLeft();
00425 }
00426 }
00427
00428
00429
00430 template <class SearchClosure>
00431 bool dfsBySimplex(SearchClosure& data, const Simplex& seed) const {
00432 assert(isMember(seed));
00433 if (!data.canEnter(seed)) {
00434 return false;
00435 } else if (data.choose(seed)) {
00436 return true;
00437 }
00438
00439 ISimplex *next = seed->getLeft();
00440 while (next && data.canEnter(next)) {
00441 if (data.choose(next)) { return true; }
00442 next = next->getLeft();
00443 }
00444
00445 next = seed->getRight();
00446 while (next && data.canEnter(next)) {
00447 if (data.choose(next)) { return true; }
00448 next = next->getRight();
00449 }
00450
00451 return false;
00452 }
00453
00454 template <class SearchClosure>
00455 bool bfsBySimplex(SearchClosure& data, const Simplex& seed) const {
00456 assert(isMember(seed));
00457 if (!data.canEnter(seed)) {
00458 return false;
00459 } else if (data.choose(seed)) {
00460 return true;
00461 }
00462
00463 ISimplex *left = seed->getLeft();
00464 ISimplex *right = seed->getRight();
00465
00466 while (left || right) {
00467 if (left) {
00468 if (!data.canEnter(left)) {
00469 left = 0;
00470 } else if (data.choose(left)) {
00471 return true;
00472 } else {
00473 left = left->getLeft();
00474 }
00475 }
00476 if (right) {
00477 if (!data.canEnter(right)) {
00478 right = 0;
00479 } else if (data.choose(right)) {
00480 return true;
00481 } else {
00482 right = right->getRight();
00483 }
00484 }
00485 }
00486
00487 return false;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 data_ref getDataRW(const Simplex& s) {
00497 return s->data_.getRef();
00498 }
00499
00501 data_const_ref getData(const Simplex& s) const {
00502 return s->data_.getCRef();
00503 }
00504
00505 private:
00506 Simplex handle_;
00507 };
00508
00509 #endif