SimplicialComplex.h

Go to the documentation of this file.
00001 #ifndef SimplicialComplex_HEADER
00002 #define SimplicialComplex_HEADER
00003 
00004 /***************************************************************************
00005  * Benoit Hudson (C) 2007
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  ** An arbitrary-dimensional simplicial complex, backed internally by a
00039  ** link structure.  Operations occur in the obvious amount of time (constant
00040  ** for traversing from one face to the next, or for adding or removing
00041  ** a simplex to the complex), assuming constant dimension.
00042  **
00043  ** We have an external point, represented as NULL.  All real vertices must be
00044  ** pointers, and they must be non-NULL.
00045  **
00046  ** Simplices have data on them, which saves the user from holding their
00047  ** own hash tables.
00048  **
00049  ** Simplices are consistently oriented.  To get finer control of orientation,
00050  ** use OSimplex.
00051  **
00052  ** The template arguments have underscores so that I can typedef them
00053  ** and reveal them.
00054  **
00055  ** Important revisions:
00056  ** - r301: best simplex-dictionary complex
00057  ** - r280: first working pointer-based complex; too slow, backed out.
00058  ** - r276: first working simplex-dictionary complex
00059  ** - r270: best face-dictionary complex
00060  ***************************************************************************/
00061 template <unsigned d, class Vertex_, class SimplexData_ = void, class VertexPrinter_ = typename Vertex_::Printer>
00062 class SimplicialComplex {
00063 struct Flipper; // for friendship purposes.
00064 public:
00065 class OSimplex; // Oriented simplex.  See below.
00066 class Simplex;  // Unoriented simplex.  See below.
00067 class Face;     // Unoriented (d-1)-facet.  See below.
00068 struct Star;    // Acts just like a vector<Simplex>.  See below.
00069 struct OptSimplex;  // for friendship
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  * The internal class that implements a simplex.  Private.
00081  *
00082  * We don't publicize this class' existence.  Therefore, everything is public,
00083  * since the user will never see an ISimplex, and so that I don't have to
00084  * befriend every class in this file.
00085  ***************************************************************************/
00086 private:
00087 struct ISimplex : public hudson::SmallMemoryItem<ISimplex> {
00088     friend struct Flipper;
00089 
00090     boost::array<Vertex*, d+1> verts_; // canonically oriented (not sorted)
00091     boost::array<ISimplex*, d+1> neigh_;
00092 
00093     // Intrusive-list pointers for searches.  We need two:
00094     // one for the visited set, one for the fringe.
00095     ISimplex *nextVisited_;
00096 #ifdef FRINGE_USES_INTRUSIVE_LIST
00097     ISimplex *nextFringe_;
00098 #endif
00099 
00100     // refcount, then payload goes last; pair them up so that a void
00101     // user-data item costs zero storage.
00102     hudson::PayloadBucket<unsigned, SimplexData> refcount_and_user_;
00103 
00104     unsigned& refcount() { return refcount_and_user_.data; }
00105 
00106     // Status of the simplex -- born (in a star); in the complex; or removed
00107     // (but not yet deallocated).  Stored using the nextVisited_ pointer, since
00108     // only an inserted simplex can be visited.
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       // This gets clobbered by setStatus() below.
00125       // nextVisited_ = (ISimplex*)hudson::IntrusiveListDefaultOut;
00126 #ifdef FRINGE_USES_INTRUSIVE_LIST
00127       nextFringe_ = (ISimplex*)hudson::IntrusiveListDefaultOut;
00128 #endif
00129       setStatus(BORN);
00130     }
00131 
00132     /* Initialize using the exactly d+1 vertices in the given vector. */
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     /* Initialize using the exactly d+1 vertices at the given indices of
00142        the vertex vector.  I assert the */
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(); // size() doesn't always get inlined.
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     /* Initialize given the array, which is known at compile time to have
00159        the proper size. */
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  * Handle the IntrusiveList for marking
00266  * simplices visited.
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  * Handle the IntrusiveList for putting
00276  * simplices on the search fringe.
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  * A class that represents the ith face of a simplex (across from the ith
00286  * vertex).
00287  *
00288  * Not ref-counted, so we don't leak this to the caller; it's used internally
00289  * during the modification routines.
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  * A reference-counted pointer to the internal structures.
00337  *
00338  * As long as the simplicial complex hasn't been deleted,
00339  * it is safe to hold the Simplex, even after a removeSimplex().
00340  *
00341  * Simplices are canonically oriented according to the orientation
00342  * defined at construction time (or after a flipOrientation() call).
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  * An oriented handle on an Simplex.
00400  *
00401  * While simplices are canonically oriented, OSimplex allows
00402  * holding the simplex in some different orientation.  Use
00403  * the switch, getFace, and getNeighbour operations to navigate.
00404  *
00405  * Note that this class is somewhat heavyweight: in a performance-critical
00406  * setting, it may be better to avoid OSimplex.
00407  *
00408  * Equality and hash functions are specifically not defined on this class:
00409  * users typically want equality to be simplex equality regardless of
00410  * orientation and would be shocked to have it be based on the particular
00411  * orientation.  I force them to make their wishes explicit by not making
00412  * operator== available.
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); // this is d-i swaps
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     // Set the neighbour through the face that we represent.
00437     void setN(ISimplex *is) {
00438       s_->setN(s_->indexOf(t_[d]), is);
00439     }
00440 
00441     // we can't change what the OSimplex points to by getting its ISimplex,
00442     // so it's const.
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     // dangerous; don't use these.
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  * A face is a (d-1) simplex.
00498  *
00499  * Faces are canonically ordered (the vertices are sorted by pointer value).
00500  * Thus, a face can be derived from either simplex that contains it.
00501  *
00502  * Note that this makes faces somewhat heavyweight.
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     // Friend for the ISimplex constructor.
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  * A face2 is a (d-2) simplex.
00558  *
00559  * This is used in computing a cavity, where we know one of
00560  * the vertices (the apex of the star), to reduce the number
00561  * of things we need to sort and hash.
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         // i1 should be < i2; fix that
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  * The underlying data structure is a ref-counted link structure.
00624  * It is rooted at the handle_.
00625  ***************************************************************************/
00626 private:
00627 Simplex handle_;
00628 
00629 /***************************************************************************
00630  * \name Internal modification routines.
00631  *
00632  * To add simplices, we need to determine the neighbourhood information.
00633  * We do that using a map from each face to its one or two neighbours;
00634  * this is identical to the face-based simplicial complex, but we only hold
00635  * this temporarily.  Of course, that also means we need to build it up
00636  * every time we need it.
00637  *
00638  * Remember to set the handle_ after adding simplices (by now, the handle is
00639  * probably invalid because we probably just deleted some simplices).
00640  *
00641  * The hashmap we use is my own, and we point out to it that the destructors
00642  * need not be called.  This is also why I use dumb pointers rather than
00643  * smart ones in the pair; I know the simplices are owned by someone else,
00644  * so I don't need to refcount this usage.
00645  *
00646  * To remove a simplex, we merely unlink it from its neighbours, mark
00647  * it dead, and decrement the reference count.
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 /* When the second face of the neighbour appears, immediately link the two.
00657  * Note that the null face won't appear; however:
00658  * (1) neighbours of the cavity always have an new neighbour in the star
00659  * (2) the star simplices default to having a null neighbour
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     // assert(p.second == NULL); // but do it with a printout
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     /* Now, link. */
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  * Put the simplex into the complex.
00704  * We assume it's been linked already.
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  * Remove a single simplex.
00717  * Warning: this may disconnect the complex, and it may invalidate the
00718  * handle_.  Therefore, it is private.
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   /* Unlink from the neighbours. */
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   // Update the refcount.
00734   removeSimplexNoUnlink(is);
00735 }
00736 
00737 void removeSimplexNoUnlink(ISimplex *is) {
00738   assert(is->getStatus() == ISimplex::INSERTED);
00739 
00740   // Someone's holding on to the Simplex, so there's at least one ref
00741   // there, plus we're just now removing the complex's link, for two.
00742   assert(is->refcount() >= 2);
00743   is->refcount()--;
00744 
00745   is->setStatus(ISimplex::DEAD);
00746 }
00747 
00752 /***************************************************************************
00753  * \name Initialization
00754  *
00755  * There are two constructors: one creates a single simplex, which can then
00756  * be turned into any other manifold simplicial complex using replaceCavity
00757  * operations.
00758  *
00759  * The other constructor creates an entire complex.  This complex is not
00760  * guaranteed to be manifold or orientable.  Use at your own risk (or benefit
00761  * -- you can't create a torus with the first constructor).
00762  *
00763  * Removing a simplex requires making sure that
00764  ***************************************************************************/
00765 
00766 /****************************************
00767  * Constructor: create a single simplex.
00768  ****************************************/
00769 public:
00770 SimplicialComplex(const vector<Vertex*>& verts) : handle_(new ISimplex(verts), verts) {
00771   assert(verts.size() == d + 1); // and no more
00772   dprintf("creating the simplex\n");
00773   addSimplex(handle_.get());
00774   dprintf("done\n");
00775 }
00776 
00777 /****************************************
00778  * Constructor: Construct a set of elements.
00779  *
00780  * Each element is made up of a tuple of vertices, but is named by a tuple of
00781  * indices.  If zeroindex is non-zero, then the indices need not be zero-based.
00782  * The orientations are as per the elements vector.  We do not check for
00783  * consistency (this allows creating an unorientable surface, which may or may
00784  * not be a problem).
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   /* Element 0 is already in handle_, so skip it in the loop. */
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   /* Link up the simplices. */
00810   BOOST_FOREACH(ISimplex *is, simplices) {
00811     addSimplex(is);
00812   }
00813   dprintf("done\n");
00814 }
00815 
00816 /***************************************************************************
00817  * \name Dimension
00818  *
00819  * Return the topological dimension of the complex.
00820  ***************************************************************************/
00822 public:
00823 static unsigned dim() { return d; }
00824 static const unsigned dimension = d;
00828 /***************************************************************************
00829  * \name Entering the complex.
00830  *
00831  * The complex maintains a handle; this is necessary after initialization,
00832  * and is useful besides that time.  On insertion of new vertices, the handle
00833  * is kept up to date; the user will only need to call setHandle() when removing
00834  * simplices (namely, if we remove the handle).
00835  *
00836  * Simplices in the complex are canonically oriented.  If the orientation is
00837  * the "wrong" one -- if you wish to view the complex from the opposite
00838  * orientation -- call flipOrientation().  This makes in-memory changes, and
00839  * takes linear time.  Prior handles into the complex are also flipped.
00840  ***************************************************************************/
00843 /***********************************
00844  * Check whether the given simplex appears in the complex.
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 // Helper for flipOrientation
00874 struct Flipper {
00875   static bool canEnter(const Simplex&) { return true; }
00876   static bool choose(const Simplex& s) {
00877     /* Note that this changes the complex in place, but
00878        we're not in the middle of reading s's neighbours,
00879        so it turns out to be safe. */
00880     hudson::swapInPlace(s.get()->verts_, 0);
00881     hudson::swapInPlace(s.get()->neigh_, 0);
00882     return false;
00883   }
00884 };
00885 /****************************************
00886  * Flip the orientation of the complex.
00887  * This operation is linear-time.
00888  ****************************************/
00889 public:
00890 void flipOrientation() {
00891   Flipper flip;
00892   dfsBySimplex(flip, getHandle());
00893 }
00896 /***************************************************************************
00897  * \name Inserting a vertex
00898  *
00899  * Vertex insertion happens as follows:
00900  * -# Compute a <i>cavity</i>: a connected set of simplices.
00901  * -# Create a vertex.
00902  * -# Call computeStar to compute the replacement of the cavity.  Inspect the
00903  *    star if you want; you may safely discard it.
00904  * -# Call replaceCavity, which commits the star to the structure.
00905  *
00906  * Steps 3-4 can be combined into one by calling the other form of insertVertex.
00907  *
00908  * The star is guaranteed to be oriented consistently with the prior orientation.
00909  ***************************************************************************/
00912 /***************************************************************************
00913  * Represents the star of a vertex.
00914  *
00915  * The star acts like a const vector<Simplex>: it has size(), operator[], and
00916  * begin/end.
00917  *
00918  * Internally, we hold the apex, the simplices of the star, and their
00919  * (possibly-null) neighbours outside the cavity.  This is all required for
00920  * initially constructing the star, and is also required for linking the star
00921  * in during replaceCavity.
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 /* not a ref: we construct it here */
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   /* pairs of <simplex, neighbour> */
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     // Build the new star simplex
01022     boost::array<Vertex*, d+1> starverts = face.simplex_->toArray();
01023     starverts[face.face_] = apex_;
01024     ISimplex *is = new ISimplex(starverts);
01025 
01026     // Remember its neighbour, if any.
01027     IFace neigh = face.getNFace();
01028     dprintf("  neighbour %s\n", neigh.toString().c_str());
01029 
01030     // Take ownership of is, so that it doesn't go away
01031     // when it gets used.
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  * Given a cavity, and a replacement for it, perform the replacement.
01097  *
01098  * Algorithm:
01099  * -# remove the old links to the cavity
01100  * -# compute all the links between star simplices
01101  * -# add the in-star links
01102  * -# add the star-neighbour links
01103  ***************************************************************************/
01104 public:
01105 void replaceCavity(const Cavity& cavity, Star& star)
01106 {
01107   dprintf("replaceCavity\n");
01108 
01109   // Remove the old.
01110   BOOST_FOREACH(const Simplex& s, cavity) {
01111     removeSimplexNoUnlink(s.get());
01112   }
01113 
01114   // Compute the face map and link faces.
01115   //
01116   // There are exactly d+1 faces for each star simplex.
01117   // Exactly one face points outside, so d point to other
01118   // star simplices.
01119   //
01120   // I can handle the exterior face specially, and then all the interior faces
01121   // share the apex.  So I use Face2, saving the sorting, hashing, and comparison
01122   // of one vertex from each of the cavity faces.
01123   Face2HashMap map (star.size() * d);
01124 
01125   // I merge this loop with the one that adds the simplices
01126   // in to the mesh.
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     /* Link the new simplex to its neighbour on the exterior of the cavity, if
01133      * there is a neighbour. */
01134     if (exteriorNeighbour) {
01135       exteriorNeighbour.relink(isimplex);
01136       IFace apexFace (isimplex, apexIndex);
01137       apexFace.relink(exteriorNeighbour);
01138     }
01139 
01140     /* Iterate over all faces except the face across from the
01141      * apex, linking through the given cavity-interior face.
01142      * The apex is always part of the cavity face, so we simply
01143      * omit it from the search structure.
01144      *
01145      * Break the loop in two and keep indices sorted to
01146      * let the optimizer do its work. */
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     /* Add the simplex to the mesh.  Note that it may not yet
01155        be fully linked in until the loop completes. */
01156     addSimplex(isimplex);
01157   }
01158 
01159   // Handle may be invalid; set it to something we know works.
01160   handle_ = *star.begin();
01161   dprintf("done\n");
01162 }
01163 
01164 /***************************************************************************
01165  * Given a star-shaped cavity, and a vertex, compute the star and install
01166  * it into the complex.
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  * Remove a single simplex.
01177  * Checks that the removed simplex is not the handle.
01178  * To remove a simplex that is the handle, call setHandle() first.
01179  ***************************************************************************/
01180 public:
01181 void checkedRemoveSimplex(const Simplex& s) {
01182   assert(s != getHandle());
01183   removeSimplex(s);
01184 }
01187 /***************************************************************************
01188  * \name Data access.
01189  *
01190  * We can handle void data.  However, it is an error to call these functions
01191  * when the data is void.
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();