00001 #ifndef SimplicialComplex_HEADER
00002 #define SimplicialComplex_HEADER
00003
00004
00005
00006
00007
00008 #include <boost/array.hpp>
00009 #include <boost/iterator/transform_iterator.hpp>
00010 #include <utilities/IntrusivePtr.h>
00011 #include <utilities/IntrusiveList.h>
00012 #include <utilities/FastHash.h>
00013 #include <utilities/FrontStack.h>
00014 #include <utilities/FrontQueue.h>
00015 #include <utilities/ArrayFunctions.h>
00016 #include <utilities/hash.h>
00017 #include <utilities/option.h>
00018 #include <utilities/SmallList.h>
00019 #include <utilities/Void.h>
00020 #include <utilities/foreach.h>
00021 #include <stack>
00022 #include <ext/slist>
00023
00027 #if 0
00028 #define dprintf(...) printf(__VA_ARGS__)
00029 #else
00030 #define dprintf(...)
00031 #endif
00032
00035 #define FRINGE_USES_INTRUSIVE_LIST
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 template <unsigned d, class Vertex_, class SimplexData_ = void, class VertexPrinter_ = typename Vertex_::Printer>
00062 class SimplicialComplex {
00063 struct Flipper;
00064 public:
00065 class OSimplex;
00066 class Simplex;
00067 class Face;
00068 struct Star;
00069 struct OptSimplex;
00070
00071 typedef Vertex_ Vertex;
00072 typedef VertexPrinter_ VertexPrinter;
00073 typedef SimplexData_ SimplexData;
00075 typedef typename hudson::PayloadBucket<size_t, SimplexData>::reference data_ref;
00076 typedef typename hudson::PayloadBucket<size_t, SimplexData>::const_reference data_const_ref;
00079
00080
00081
00082
00083
00084
00085
00086 private:
00087 struct ISimplex : public hudson::SmallMemoryItem<ISimplex> {
00088 friend struct Flipper;
00089
00090 boost::array<Vertex*, d+1> verts_;
00091 boost::array<ISimplex*, d+1> neigh_;
00092
00093
00094
00095 ISimplex *nextVisited_;
00096 #ifdef FRINGE_USES_INTRUSIVE_LIST
00097 ISimplex *nextFringe_;
00098 #endif
00099
00100
00101
00102 hudson::PayloadBucket<unsigned, SimplexData> refcount_and_user_;
00103
00104 unsigned& refcount() { return refcount_and_user_.data; }
00105
00106
00107
00108
00109 enum status {
00110 BORN = -2,
00111 INSERTED = hudson::IntrusiveListDefaultOut,
00112 DEAD = -3
00113 };
00114 BOOST_STATIC_ASSERT(hudson::IntrusiveListDefaultOut != BORN);
00115 BOOST_STATIC_ASSERT(hudson::IntrusiveListDefaultOut != DEAD);
00116
00117 void init() {
00118 #ifndef NDEBUG
00119 BOOST_FOREACH(const Vertex *v, verts_) { assert(v); }
00120 #endif
00121 neigh_.assign(NULL);
00122
00123 refcount() = 0;
00124
00125
00126 #ifdef FRINGE_USES_INTRUSIVE_LIST
00127 nextFringe_ = (ISimplex*)hudson::IntrusiveListDefaultOut;
00128 #endif
00129 setStatus(BORN);
00130 }
00131
00132
00133 ISimplex(const vector<Vertex*>& vs) {
00134 assert(vs.size() == d + 1);
00135 for(size_t i = 0; i < d + 1; ++i) {
00136 verts_[i] = vs[i];
00137 }
00138 init();
00139 }
00140
00141
00142
00143 ISimplex(const vector<Vertex*>& vs,
00144 const std::vector<size_t>& ids,
00145 ssize_t zeroindex) {
00146 #ifndef NDEBUG
00147 size_t n = vs.size();
00148 #endif
00149 assert(ids.size() == d + 1);
00150 for(unsigned i = 0; i < d + 1; ++i) {
00151 unsigned ii = ids[i] - zeroindex;
00152 assert(ii < n);
00153 verts_[i] = vs[ii];
00154 }
00155 init();
00156 }
00157
00158
00159
00160 ISimplex(const boost::array<Vertex*, d+1>& vs) : verts_(vs) {
00161 init();
00162 }
00163
00164 ~ISimplex() { dprintf("deleting %s\n", toString().c_str()); }
00165
00168 void grab() { refcount()++; }
00169 void drop() {
00170 refcount()--;
00171 if (refcount() == 0) {
00172 delete this;
00173 }
00174 }
00175 static void add_ref(ISimplex *s) { s->grab(); }
00176 static void release(ISimplex *s) { s->drop(); }
00177
00178 unsigned indexOf(const ISimplex *neigh) const {
00179 for (unsigned i = 0; i <= d; ++i) {
00180 if (neigh_[i] == neigh) {
00181 return i;
00182 }
00183 }
00184 abort();
00185 }
00186 Vertex *newApex(const ISimplex *origin) const {
00187 return verts_[indexOf(origin)];
00188 }
00189
00190 size_t hash() const {
00191 return hudson::hashArray(verts_, hudson::hash_by_cast<Vertex*>());
00192 }
00193
00194 std::string toString() const {
00195 string s = "<";
00196 VertexPrinter print;
00197 BOOST_FOREACH(const Vertex *v, verts_) {
00198 if (v) {
00199 s += " ";
00200 s += print(v);
00201 } else {
00202 s += " (null)";
00203 }
00204 }
00205 s += " >";
00206 return s;
00207 }
00208
00209 Vertex *operator[] (unsigned i) const {
00210 return get(i);
00211 }
00212 Vertex *get(unsigned i) const {
00213 return verts_[i];
00214 }
00215
00216 ISimplex *getN(unsigned i) const {
00217 return neigh_[i];
00218 }
00219
00220 bool has(const Vertex *q) const {
00221 BOOST_FOREACH(const Vertex *v, verts_) {
00222 if (v == q) { return true; }
00223 }
00224 return false;
00225 }
00226 template <class BinaryPredicate>
00227 bool has(const Vertex *q, const BinaryPredicate& pred) const {
00228 BOOST_FOREACH(const Vertex *v, verts_) {
00229 if (pred(v, q)) { return true; }
00230 }
00231 return false;
00232 }
00233 unsigned indexOf(const Vertex *v) const {
00234 for(unsigned i = 0; i <= d; ++i) {
00235 if (get(i) == v) { return i; }
00236 }
00237 abort();
00238 }
00239
00240 const boost::array<Vertex*, d+1>& toArray() const {
00241 return verts_;
00242 }
00243 typedef typename boost::array<Vertex*, d+1>::const_iterator vertex_iterator;
00244 vertex_iterator begin_vertices() const {
00245 return verts_.begin();
00246 }
00247 vertex_iterator end_vertices() const {
00248 return verts_.end();
00249 }
00250
00251 status getStatus() const {
00252 switch((ssize_t)nextVisited_) {
00253 case -2: return BORN;
00254 case -3: return DEAD;
00255 default: return INSERTED;
00256 }
00257 }
00258 void setStatus(status s) {
00259 nextVisited_ = (ISimplex*)s;
00260 }
00261 };
00262
00263 private:
00264
00265
00266
00267
00268 struct ILAdaptor_visited {
00269 static ISimplex *getNext(ISimplex *is) { return is->nextVisited_; }
00270 static void setNext(ISimplex *is, ISimplex *next) { is->nextVisited_ = next; }
00271 };
00272
00273 #ifdef FRINGE_USES_INTRUSIVE_LIST
00274
00275
00276
00277
00278 struct ILAdaptor_fringe {
00279 static ISimplex *getNext(ISimplex *is) { return is->nextFringe_; }
00280 static void setNext(ISimplex *is, ISimplex *next) { is->nextFringe_ = next; }
00281 };
00282 #endif
00283
00284
00285
00286
00287
00288
00289
00290
00291 private:
00292 struct IFace {
00293 ISimplex *simplex_;
00294 unsigned face_;
00295 IFace() : simplex_(NULL) { }
00296 IFace(ISimplex *s, unsigned i): simplex_(s), face_(i) { }
00297 IFace(const OSimplex& os): simplex_(os.get()), face_(simplex_->indexOf(os[d])) { }
00298 IFace(const OSimplex& os, unsigned i): simplex_(os.get()), face_(simplex_->indexOf(os[i])) { }
00299
00300 ISimplex *getN() const { return simplex_->getN(face_); }
00301 IFace getNFace() const {
00302 ISimplex *n = getN();
00303 if (n) {
00304 return IFace(n, n->indexOf(simplex_));
00305 } else {
00306 return IFace();
00307 }
00308 }
00309 operator bool() const { return simplex_ != NULL; }
00310 bool operator== (const ISimplex *other) const {
00311 return simplex_ == other;
00312 }
00313 bool operator!= (const ISimplex *other) const {
00314 return simplex_ != other;
00315 }
00316 string toString() const {
00317 if (simplex_) {
00318 char buffer[4000];
00319 sprintf(buffer, " face %u", face_);
00320 return simplex_->toString() + buffer;
00321 } else {
00322 return "(nil)";
00323 }
00324 }
00325
00326 void relink(const IFace& other) {
00327 simplex_->neigh_[face_] = other.simplex_;
00328 }
00329 void relink(ISimplex *other) {
00330 simplex_->neigh_[face_] = other;
00331 }
00332 };
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 public:
00345 class Simplex : public hudson::SmallMemoryItem<Simplex> {
00346 private:
00347 friend class SimplicialComplex;
00348 friend class OSimplex;
00349 friend struct Flipper;
00350 friend class Star;
00351 friend struct OptSimplex;
00352
00353 hudson::IntrusivePtr<ISimplex> s_;
00354 ISimplex *get() const { return s_.get(); }
00355 void reset(ISimplex *is) { s_ = is; }
00356 public:
00359 Simplex(const Simplex& other): s_(other.s_) { }
00360
00364 Simplex(ISimplex *s): s_(s) { }
00365
00366 static const unsigned dimension = d;
00367 static unsigned dim() { return d; }
00370 size_t hash() const { return s_->hash(); }
00371
00374 std::string toString() const { return s_->toString(); }
00375
00378 typedef typename ISimplex::vertex_iterator vertex_iterator;
00379 typedef vertex_iterator const_iterator;
00380 typedef vertex_iterator iterator;
00381 vertex_iterator begin() const { return s_->begin_vertices(); }
00382 vertex_iterator end() const { return s_->end_vertices(); }
00383 Vertex *operator[] (unsigned i) const { return s_->get(i); }
00384 Vertex *get(unsigned i) const { return s_->get(i); }
00385 unsigned indexOf(const Vertex *v) const { return s_->indexOf(v); }
00386 bool has(const Vertex *v) const { return s_->has(v); }
00389 template <class BinaryPredicate>
00390 bool has(const Vertex *v, const BinaryPredicate& pred) const {
00391 return s_->has(v,pred);
00392 }
00393
00394 bool operator== (const Simplex& other) const { return s_ == other.s_; }
00395 bool operator!= (const Simplex& other) const { return s_ != other.s_; }
00396 };
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 class OSimplex {
00415 private:
00416 friend class SimplicialComplex;
00417 friend class Face;
00418 friend struct Star;
00419 friend struct Flipper;
00420
00421 boost::array<Vertex*, d+1> t_;
00422 Simplex s_;
00423
00424 OSimplex(ISimplex *s) : t_(s->toArray()), s_(s) { }
00425
00426 OSimplex(ISimplex *s, unsigned i) : t_(s->toArray()), s_(s) {
00427 t_.multiSwapInPlace(i);
00428 if (d > 1 && (((d-i) % 2) == 1)) {
00429 t_.swapInPlace(0);
00430 }
00431 }
00432
00433 OSimplex(ISimplex *s, const boost::array<Vertex*, d+1>& verts)
00434 : t_(verts), s_(s) { }
00435
00436
00437 void setN(ISimplex *is) {
00438 s_->setN(s_->indexOf(t_[d]), is);
00439 }
00440
00441
00442
00443 ISimplex *get() const { return s_.get(); }
00444
00445 void reset(ISimplex *is) { s_.reset(is); }
00446 public:
00447
00448 static const unsigned dim = d;
00449
00450 bool isInternal() const { return t_[d] != NULL; }
00451
00452 bool has(const Vertex *v) const { return t_.has(const_cast<Vertex*>(v)); }
00453 template <class BinaryPredicate>
00454 bool has(const Vertex *v, const BinaryPredicate& pred ) const {
00455 return t_.has(const_cast<Vertex*>(v), pred);
00456 }
00457
00458 #if 0
00459
00460 bool operator==(OSimplex s) const { return t == s.t; }
00461 uint32_t hash() const { return t.hash(); }
00462 #endif
00463
00464 Vertex *getUnchecked(unsigned i) const { return t_[i]; }
00465 Vertex *get(unsigned i) const {
00466 Vertex *v = getUnchecked(i);
00467 assert(v);
00468 return v;
00469 }
00470 Vertex *operator[](unsigned i) const { return get(i); }
00471 const boost::array<Vertex*, d+1>& toArray() const { return t_; }
00472
00473 const Simplex& toSimplex() const { return s_; }
00474 Simplex& toSimplex() { return s_; }
00475
00476 operator const Simplex& () const { return s_; }
00477 operator Simplex& () { return s_; }
00478
00479 std::string toString() const {
00480 string s = "<";
00481 VertexPrinter print;
00482 BOOST_FOREACH(const Vertex *v, t_) {
00483 if (v) {
00484 s += " ";
00485 s += print(v);
00486 } else {
00487 s += " (null)";
00488 }
00489 }
00490 s += " >";
00491 return s;
00492 }
00493 };
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 public:
00505 class Face {
00506 private:
00507 boost::array<Vertex*, d> t;
00508 void init(const boost::array<Vertex*, d+1>& s, unsigned i) {
00509 for(unsigned j = 0; j < i; ++j) {
00510 t[j] = s[j];
00511 }
00512 for(unsigned j = i+1; j <= d; ++j) {
00513 t[j-1] = s[j];
00514 }
00515 hudson::sort(t);
00516 }
00517
00518
00519 friend class SimplicialComplex;
00520
00522 Face(const ISimplex *s, unsigned i) { init(s->toArray(), i); }
00523
00524 public:
00526 Face(const OSimplex& os): t(os.toArray()) { t.sort(); }
00527
00529 Face(const Simplex& s, unsigned i) { init(s.toArray(), i); }
00530
00531 bool operator==(const Face& f) const { return t == f.t; }
00532 bool operator!=(const Face& f) const { return !(t == f.t); }
00533
00535 size_t hash() const {
00536 return hudson::hashArray(t, hudson::hash_by_cast<Vertex*>());
00537 }
00538
00540 std::string toString() const {
00541 string s = "<";
00542 VertexPrinter print;
00543 BOOST_FOREACH(const Vertex *v, t) {
00544 if (v) {
00545 s += " ";
00546 s += print(v);
00547 } else {
00548 s += " (null)";
00549 }
00550 }
00551 s += " >";
00552 return s;
00553 }
00554 };
00555
00556
00557
00558
00559
00560
00561
00562
00563 public:
00564 class Face2 {
00565 private:
00566 boost::array<Vertex*, d - 1> t;
00567 void init(const boost::array<Vertex*, d+1>& s, unsigned i1, unsigned i2) {
00568 assert(i1 != i2);
00569 assert(i1 <= d);
00570 assert(i2 <= d);
00571 if (i1 > i2) {
00572
00573 unsigned tmp = i1;
00574 i1 = i2;
00575 i2 = tmp;
00576 }
00577 for(unsigned j = 0; j < i1; ++j) {
00578 t[j] = s[j];
00579 }
00580 for(unsigned j = i1+1; j < i2; ++j) {
00581 t[j-1] = s[j];
00582 }
00583 for(unsigned j = i2+1; j <= d; ++j) {
00584 t[j-2] = s[j];
00585 }
00586 hudson::sort(t);
00587 }
00588
00589 friend class SimplicialComplex;
00590
00592 Face2(const ISimplex *s, unsigned i1, unsigned i2) {
00593 init(s->toArray(), i1, i2);
00594 }
00595
00596 public:
00597 bool operator==(const Face2& f) const { return t == f.t; }
00598 bool operator!=(const Face2& f) const { return !(t == f.t); }
00599
00601 size_t hash() const {
00602 return hudson::hashArray(t, hudson::hash_by_cast<Vertex*>());
00603 }
00604
00606 std::string toString() const {
00607 string s = "<";
00608 VertexPrinter print;
00609 BOOST_FOREACH(const Vertex *v, t) {
00610 if (v) {
00611 s += " ";
00612 s += print(v);
00613 } else {
00614 s += " (null)";
00615 }
00616 }
00617 s += " >";
00618 return s;
00619 }
00620 };
00621
00622
00623
00624
00625
00626 private:
00627 Simplex handle_;
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00651 typedef std::pair<IFace,IFace> FaceNeigh;
00652 typedef hudson::FastHashMap<Face, FaceNeigh, hudson::hash_by_call<Face>, false> FaceHashMap;
00653 typedef hudson::FastHashMap<Face2, FaceNeigh, hudson::hash_by_call<Face2>, false> Face2HashMap;
00654 private:
00655
00656
00657
00658
00659
00660
00661 template <class Map, class Face>
00662 static void addFaceToFaceMap(Map& facemap, const Face& f, const IFace& s) {
00663 dprintf(" adding face %s => %s\n", f.toString().c_str(), s.toString().c_str());
00664 FaceNeigh& p = facemap[f];
00665 if (!p.first) {
00666 p.first = s;
00667 assert(!p.second);
00668 assert(p.second != s.simplex_);
00669 } else {
00670 #ifndef NDEBUG
00671
00672 if (p.second) {
00673 struct { string operator()(const IFace& s) const { return s.toString(); } } printer;
00674 string V = printer(s);
00675 string v1 = printer(p.first);
00676 string v2 = printer(p.second);
00677 printf("adding %s => %s\n", f.toString().c_str(), V.c_str());
00678 printf(" face %s conflicts: %s and %s.\n",
00679 f.toString().c_str(), v1.c_str(), v2.c_str());
00680 assert(0 && "there is already a simplex here");
00681 }
00682 #endif
00683 assert(p.first != s.simplex_);
00684 p.second = s;
00685
00686
00687 p.first.relink(p.second);
00688 p.second.relink(p.first);
00689 }
00690 }
00691
00692 static void addSimplexToFaceMap(FaceHashMap& facemap, ISimplex *s) {
00693 for(unsigned i = 0; i <= d; i++) {
00694 IFace iF(s, i);
00695 Face f (iF.simplex_, iF.face_);
00696 addFaceToFaceMap(facemap, f, iF);
00697 }
00698 }
00699
00700
00701
00702
00703
00704
00705
00706 private:
00707 void addSimplex(ISimplex *s) {
00708 dprintf(" committing simplex %s\n", s->toString().c_str());
00709 assert(s->getStatus() == ISimplex::BORN);
00710
00711 s->setStatus(ISimplex::INSERTED);
00712 s->refcount()++;
00713 }
00714
00715
00716
00717
00718
00719
00720 private:
00721 void removeSimplex(const Simplex& s) {
00722 dprintf(" removing simplex %s\n", s.toString().c_str());
00723 assert(isMember(s));
00724
00725 ISimplex *is = s.get();
00726
00727
00728 BOOST_FOREACH(ISimplex *neigh, is->neigh_) {
00729 if (neigh == NULL) { continue; }
00730 unsigned back = neigh->indexOf(is);
00731 neigh->neigh_[back] = NULL;
00732 }
00733
00734 removeSimplexNoUnlink(is);
00735 }
00736
00737 void removeSimplexNoUnlink(ISimplex *is) {
00738 assert(is->getStatus() == ISimplex::INSERTED);
00739
00740
00741
00742 assert(is->refcount() >= 2);
00743 is->refcount()--;
00744
00745 is->setStatus(ISimplex::DEAD);
00746 }
00747
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 public:
00770 SimplicialComplex(const vector<Vertex*>& verts) : handle_(new ISimplex(verts), verts) {
00771 assert(verts.size() == d + 1);
00772 dprintf("creating the simplex\n");
00773 addSimplex(handle_.get());
00774 dprintf("done\n");
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 public:
00787 SimplicialComplex(const std::vector<Vertex*>& verts,
00788 const std::vector<std::vector<size_t> >& elements, ssize_t zeroindex = 0)
00789 : handle_(new ISimplex(verts, elements[0], zeroindex))
00790 {
00791 assert(elements.size() > 0);
00792 dprintf("creating a complex\n");
00793
00794 FaceHashMap facemap;
00795 vector<ISimplex*> simplices;
00796 simplices.reserve(elements.size());
00797 facemap.reserve(elements.size() * (d+1));
00798
00799
00800 simplices.push_back(handle_.get());
00801 addSimplexToFaceMap(facemap, handle_.get());
00802 size_t n = elements.size();
00803 for(size_t i = 1; i < n; ++i) {
00804 ISimplex *s = new ISimplex(verts, elements[i], zeroindex);
00805 simplices.push_back(s);
00806 addSimplexToFaceMap(facemap, s);
00807 }
00808
00809
00810 BOOST_FOREACH(ISimplex *is, simplices) {
00811 addSimplex(is);
00812 }
00813 dprintf("done\n");
00814 }
00815
00816
00817
00818
00819
00820
00822 public:
00823 static unsigned dim() { return d; }
00824 static const unsigned dimension = d;
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00843
00844
00845
00846 public:
00847 bool isMember(const Simplex& s) const {
00848 return s.get()->getStatus() == ISimplex::INSERTED;
00849 }
00850
00851 public:
00853 const Simplex& getHandle() const {
00854 assert(isMember(handle_));
00855 return handle_;
00856 }
00857
00860 OSimplex orientSimplex(const Simplex& s) const {
00861 return OSimplex(s.get());
00862 }
00863
00866 public:
00867 void setHandle(const Simplex& s) {
00868 assert(isMember(s));
00869 handle_ = s;
00870 }
00871
00872 private:
00873
00874 struct Flipper {
00875 static bool canEnter(const Simplex&) { return true; }
00876 static bool choose(const Simplex& s) {
00877
00878
00879
00880 hudson::swapInPlace(s.get()->verts_, 0);
00881 hudson::swapInPlace(s.get()->neigh_, 0);
00882 return false;
00883 }
00884 };
00885
00886
00887
00888
00889 public:
00890 void flipOrientation() {
00891 Flipper flip;
00892 dfsBySimplex(flip, getHandle());
00893 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 public:
00924 struct Star {
00925 typedef hudson::SmallList<std::pair<Simplex,IFace> > StarData;
00926 typedef typename std::pair<Simplex,IFace> pair;
00927 typedef typename StarData::const_iterator pair_it;
00928
00929 Star() : apex_(NULL), size_(0) { }
00930
00931 void clear() {
00932 star_.clear();
00933 apex_ = NULL;
00934 size_ = 0;
00935 }
00936
00937 template <class sdata_iterator>
00938 class iterator_base : public boost::iterator_facade
00939 < iterator_base<sdata_iterator>
00940 , const Simplex
00941 , boost::forward_traversal_tag
00942 >
00943 {
00944 sdata_iterator it_;
00945 friend struct Star;
00946 explicit iterator_base (const sdata_iterator& it): it_(it) { }
00947 public:
00948 void increment() { ++it_; }
00949 bool equal(const iterator_base& other) const { return it_ == other.it_; }
00950 const Simplex& dereference() const { return (*it_).first; }
00951 };
00952 typedef iterator_base<typename StarData::iterator> iterator;
00953 typedef iterator_base<typename StarData::const_iterator> const_iterator;
00954
00955 iterator begin() { return iterator(star_.begin()); }
00956 iterator end() { return iterator(star_.end()); }
00957
00958 const_iterator begin() const { return const_iterator(star_.begin()); }
00959 const_iterator end() const { return const_iterator(star_.end()); }
00960
00961 struct neigh_iterator : public boost::iterator_facade
00962 < neigh_iterator
00963 , Simplex
00964 , boost::forward_traversal_tag
00965 , Simplex
00966 >
00967 {
00968 pair_it it_;
00969 friend struct Star;
00970 explicit neigh_iterator (const pair_it& it): it_(it) { }
00971 public:
00972 void increment() { ++it_; }
00973 bool equal(const iterator& other) const { return it_ == other.it_; }
00974 const Simplex& dereference() const {
00975 const IFace& iface = (*it_).second;
00976 return Simplex(iface.simplex_);
00977 }
00978 };
00979 neigh_iterator begin_neighbours() const { return star_.begin(); }
00980 neigh_iterator end_neighbours() const { return star_.end(); }
00981
00982 size_t size() const { return size_; }
00983
00993 iterator erase(const iterator& it) {
00994 size_--;
00995 return iterator(star_.erase(it.it_));
00996 }
00997
00998 private:
00999 friend class SimplicialComplex;
01000
01001
01002 StarData star_;
01003 Vertex *apex_;
01004 size_t size_;
01005
01006 pair_it beginPairs() const { return star_.begin(); }
01007 pair_it endPairs() const { return star_.end(); }
01008 static ISimplex *getSimplex(const pair_it& it) {
01009 return (*it).first.get();
01010 }
01011 static IFace& getNeighbour(const pair_it& it) {
01012 return (*it).second;
01013 }
01014
01015 void setApex(Vertex *apex) {
01016 assert(apex_ == NULL);
01017 apex_ = apex;
01018 }
01019
01020 void addBoundaryFace(IFace face) {
01021
01022 boost::array<Vertex*, d+1> starverts = face.simplex_->toArray();
01023 starverts[face.face_] = apex_;
01024 ISimplex *is = new ISimplex(starverts);
01025
01026
01027 IFace neigh = face.getNFace();
01028 dprintf(" neighbour %s\n", neigh.toString().c_str());
01029
01030
01031
01032 Simplex s(is);
01033 star_.push_front(make_pair(s, neigh));
01034 size_++;
01035 }
01036 };
01037
01038 struct Cavity {
01039 typedef hudson::SmallList<Simplex> storage_type;
01040 typedef typename storage_type::const_iterator iterator;
01041 typedef typename storage_type::const_iterator const_iterator;
01042
01043 Cavity(): size_(0) { }
01044
01045 iterator begin() { return cavity_.begin(); }
01046 iterator end() { return cavity_.end(); }
01047 const_iterator begin() const { return cavity_.begin(); }
01048 const_iterator end() const { return cavity_.end(); }
01049
01050 bool empty() const { return cavity_.empty(); }
01051 size_t size() const { return size_; }
01052
01053 void add(const Simplex& s) { cavity_.push_front(s); size_++; }
01054 void clear() { cavity_.clear(); size_ = 0; }
01055
01056 private:
01057 storage_type cavity_;
01058 size_t size_;
01059 };
01060
01064 void computeStar(const Cavity& cavity, Vertex *apex, Star& output)
01065 {
01066 assert(!cavity.empty());
01067 output.setApex(apex);
01068
01077 VisitedSet vset(this);
01078 BOOST_FOREACH(const Simplex& s, cavity) {
01079 assert(isMember(s));
01080 vset.insert(s.get());
01081 }
01082
01083 BOOST_FOREACH(const Simplex& s, cavity) {
01084 ISimplex *is = s.get();
01085
01086 for(unsigned j = 0; j <= d; ++j) {
01087 ISimplex *neigh = is->getN(j);
01088 if (!neigh || !vset.has(neigh)) {
01089 output.addBoundaryFace(IFace(is, j));
01090 }
01091 }
01092 }
01093 }
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 public:
01105 void replaceCavity(const Cavity& cavity, Star& star)
01106 {
01107 dprintf("replaceCavity\n");
01108
01109
01110 BOOST_FOREACH(const Simplex& s, cavity) {
01111 removeSimplexNoUnlink(s.get());
01112 }
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 Face2HashMap map (star.size() * d);
01124
01125
01126
01127 BOUNDED_FOREACH(typename Star::pair p, star.beginPairs(), star.endPairs()) {
01128 ISimplex *isimplex = p.first.get();
01129 IFace& exteriorNeighbour = p.second;
01130 unsigned apexIndex = isimplex->indexOf(star.apex_);
01131
01132
01133
01134 if (exteriorNeighbour) {
01135 exteriorNeighbour.relink(isimplex);
01136 IFace apexFace (isimplex, apexIndex);
01137 apexFace.relink(exteriorNeighbour);
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147 for (unsigned i = 0 ; i < apexIndex; ++i) {
01148 addFaceToFaceMap(map, Face2(isimplex, i, apexIndex), IFace(isimplex, i));
01149 }
01150 for (unsigned i = apexIndex + 1 ; i <= d; ++i) {
01151 addFaceToFaceMap(map, Face2(isimplex, apexIndex, i), IFace(isimplex, i));
01152 }
01153
01154
01155
01156 addSimplex(isimplex);
01157 }
01158
01159
01160 handle_ = *star.begin();
01161 dprintf("done\n");
01162 }
01163
01164
01165
01166
01167
01168 public:
01169 void replaceCavity(const Cavity& cavity, Vertex *v) {
01170 Star star;
01171 computeStar(cavity, v, star);
01172 replaceCavity(cavity, star);
01173 }
01174
01175
01176
01177
01178
01179
01180 public:
01181 void checkedRemoveSimplex(const Simplex& s) {
01182 assert(s != getHandle());
01183 removeSimplex(s);
01184 }
01187
01188
01189
01190
01191
01192
01194 data_ref getDataRW(const Simplex& s) {
01195 return s.get()->refcount_and_user_.payload_ref();
01196 }
01197
01198 data_const_ref getData(const Simplex& s) const {
01199 return s.get()->refcount_and_user_.payload_cref();