SimplicialHelpers.h

Go to the documentation of this file.
00001 #ifndef SimplicialHelpers_HEADER
00002 #define SimplicialHelpers_HEADER
00003 
00004 /***************************************************************************
00005  * Benoit Hudson (C) 2007.
00006  ***************************************************************************/
00007 
00008 #include "SimplicialComplex.h"
00009 #include <iterator>
00010 #include <vector>
00011 #include <utilities/FastHash.h>
00012 #include <utilities/hash.h>
00013 #include <utilities/count_iterator.h>
00014 
00015 
00016 /***************************************************************************
00017  * \file
00018  * Helpers to use with SimplicialComplex.
00019  *
00020  * The idiom is to have a function foo(), which uses a namespace foo_.
00021  * This is because we can't have templated functions defining structures
00022  * in their own namespace, for some reason.
00023  ***************************************************************************/
00024 namespace Simplicial {
00025 
00026 
00027 template <class Vertex> class VertexSet : public hashers::hash_set<Vertex*, hudson::hash_by_cast<Vertex*> > { };
00028 
00029 /***************************************************************************
00030  * \name Debugging: Checking the shape of a complex
00031  *
00032  * The following functions and structures allow checking that the complex
00033  * has the expected shape.  I can only think of this being useful for
00034  * debugging and testing.
00035  ***************************************************************************/
00037 template <class Complex, class BinaryPredicate = std::equal_to<const typename Complex::Vertex*> >
00038 struct Element {
00039   typedef typename Complex::Vertex Vertex;
00040   typedef typename Complex::Simplex Simplex;
00041 
00042   private:
00043   vector<Vertex*> verts_;
00044 
00045   public:
00046   template <class iterator>
00047   Element(const iterator& begin, const iterator& end) : verts_(begin, end) { }
00048 
00049   Element(const vector<Vertex*>& v):verts_(v) { }
00050 
00051   template <class eiterator>
00052   Element(const vector<Vertex*>& v, eiterator begin, eiterator end, int offset) {
00053     while(begin != end) {
00054       verts_.push_back(v[*begin - offset]);
00055       ++begin;
00056     }
00057   }
00058 
00059   bool matches(const Simplex& s) const {
00060     BinaryPredicate pred;
00061     for (size_t i = 0; i < verts_.size(); ++i) {
00062       if (!s.has(verts_[i], pred)) {
00063         return false;
00064       }
00065     }
00066     return true;
00067   }
00068 };
00069 
00070 namespace checkComplex_ {
00071   template <class Complex>
00072     struct Checker {
00073       typedef Simplicial::Element<Complex> Element;
00074       typedef typename Complex::Simplex Simplex;
00075 
00076       const std::vector<Element>& correct_;
00077       size_t nseen_;
00078 
00079       Checker(const std::vector<Element>& c): correct_(c), nseen_(0) { }
00080       static bool canEnter(const Simplex&) { return true; }
00081       bool choose(const Simplex& s) {
00082         nseen_++;
00083         for(size_t i = 0; i < correct_.size(); ++i) {
00084           if (correct_[i].matches(s)) return false;
00085         }
00086         return true;
00087       }
00088     };
00089 }
00090 template <class Complex>
00091 void
00092 checkComplex(const Complex& cplx, const vector<Element<Complex> >& correct) {
00093   checkComplex_::Checker<Complex> checker(correct);
00094   typename Complex::OptSimplex bad
00095     = cplx.findSimplex(checker, cplx.getHandle());
00096   if (bad.isSome()) {
00097     printf("first bad simplex: %s\n", (*bad).toString().c_str());
00098     assert(0 && "bad simplex");
00099   }
00100   assert(checker.nseen_ == correct.size());
00101   static unsigned testnum = 0;
00102   printf("check #%u passed\n", testnum++);
00103 }
00104 
00105 template <class Complex>
00106 void
00107 checkComplex(const Complex& c,
00108     const vector<typename Complex::Vertex*>& vertices,
00109     const vector<vector<size_t> >& elements,
00110     ssize_t offset = 0) {
00111   typedef Element<Complex> Element;
00112   vector<Element> check;
00113   for(size_t i = 0; i < elements.size(); ++i) {
00114     check.push_back(Element(vertices, elements[i].begin(), elements[i].end(), offset));
00115   }
00116   checkComplex(c, check);
00117 }
00120 /***************************************************************************
00121  * \name Debugging: printing.
00122  *
00123  * Debugging support for printing a complex.  This uses the Simplex::toString()
00124  * call, which is not guaranteed to be pretty.
00125  ***************************************************************************/
00127 namespace printComplex_ {
00128   template <class Complex>
00129   struct printer {
00130     vector<string> strs;
00131     static bool canEnter(const typename Complex::Simplex&) { return true; }
00132     bool choose(const typename Complex::Simplex& os) {
00133       strs.push_back(os.toString());
00134       return false;
00135     }
00136   };
00137 }
00138 template <class Complex>
00139 void printComplex(const Complex& cplx) {
00140   printComplex_::printer<Complex> p;
00141   cplx.dfsBySimplex(p, cplx.getHandle());
00142   std::sort(p.strs.begin(), p.strs.end());
00143   printf("%u elements:\n", (unsigned)p.strs.size());
00144   for(size_t i = 0; i < p.strs.size(); ++i) {
00145     printf("  %s\n", p.strs[i].c_str());
00146   }
00147 }
00150 /***************************************************************************
00151  * \name Collecting the star of a vertex.
00152  *
00153  * Collect all the simplices around a named vertex (its star).
00154  ***************************************************************************/
00156 namespace collectStar_ {
00158   template <class Complex>
00159   struct finder {
00160     typedef typename Complex::Simplex Simplex;
00161     typedef typename Complex::Vertex Vertex;
00162     const Vertex *v;
00163     finder(const Vertex *v) : v(v) { }
00164     static bool canEnter(const Simplex&) { return true; }
00165     bool choose(const Simplex& os) const { return os.has(v); }
00166   };
00167 
00169   template <class Complex, class output_iterator>
00170   struct collector {
00171     typedef typename Complex::Simplex Simplex;
00172     typedef typename Complex::Vertex Vertex;
00173     const Vertex *v;
00174     output_iterator out;
00175     collector(const Vertex *v, const output_iterator& out) : v(v), out(out) { }
00176     bool canEnter(const Simplex& os) const { return os.has(v); }
00177     bool choose(const Simplex& os) { *out = os; ++out; return false; }
00178   };
00179 }
00180 
00183 template <class Complex, class output_iterator>
00184 output_iterator collectStar(const Complex& cplx,
00185                  const typename Complex::Vertex *v,
00186                  const typename Complex::Simplex& seed,
00187                  const output_iterator& out)
00188 {
00189   assert (seed.has(v));
00190   collectStar_::collector<Complex, output_iterator> c(v, out);
00191   cplx.dfsBySimplex(c, seed);
00192   return c.out;
00193 }
00194 
00198 template <class Complex, class output_iterator>
00199 output_iterator slowlyCollectStar(const Complex& cplx,
00200                                   const typename Complex::Vertex *v,
00201                                   output_iterator out)
00202 {
00203   typedef typename Complex::Simplex Simplex;
00204   typedef typename Complex::OptSimplex OptSimplex;
00205 
00206   collectStar_::finder<Complex> f(v);
00207   OptSimplex start = cplx.findSimplex(f, cplx.getHandle());
00208   if (start.isSome()) {
00209     out = collectStar(cplx, v, *start, out);
00210   }
00211   return out;
00212 }
00215 /***************************************************************************
00216  * \name Collect all the simplices in the mesh.
00217  ***************************************************************************/
00218 
00219 namespace collectSimplices_ {
00220   template <class Complex, class output_iterator>
00221   struct C {
00222     typedef typename Complex::Simplex Simplex;
00223     output_iterator out;
00224     C(output_iterator oo) : out(oo) { }
00225     static bool canEnter(const Simplex&) { return true; }
00226     bool choose(const Simplex& s) { *out = s; ++out; return false; }
00227   };
00228 }
00229 
00231 template <class Complex, class output_iterator>
00232 output_iterator collectSimplices(const Complex& cplx, output_iterator out) {
00233   collectSimplices_::C<Complex, output_iterator> c(out);
00234   cplx.dfsBySimplex(c, cplx.getHandle());
00235   return c.out;
00236 }
00237 
00239 template <class Complex>
00240 void collectSimplices(const Complex& cplx, std::vector<typename Complex::Simplex>& out) {
00241   collectSimplices(cplx, std::back_inserter(out));
00242 }
00243 
00245 template <class Complex>
00246 size_t countSimplices(const Complex& cplx) {
00247   return collectSimplices(cplx, hudson::count_iterator<typename Complex::Simplex>()).count;
00248 }
00249 
00250 
00251 /***************************************************************************
00252  * \name Collect all the vertices in the mesh.
00253  *
00254  * We use a set for this task.  At the moment, we also iterate over the set,
00255  * which has the unfortunate effect of essentially randomizing the order of
00256  * vertices.
00257  ***************************************************************************/
00259 namespace collectVertices_ {
00260   template <class Simplex, class Vertex>
00261   void addVertices(const Simplex& os, VertexSet<Vertex>& set) {
00262     for (size_t i = 0; i <= os.dimension; ++i) {
00263       set.insert(os[i]);
00264     }
00265   }
00266 
00267   template <class Complex>
00268   struct C {
00269     typedef typename Complex::Simplex Simplex;
00270     typedef typename Complex::Vertex Vertex;
00271     VertexSet<Vertex> set;
00272     C() { }
00273     C(const Complex& cplx) {
00274       cplx.dfsBySimplex(*this, cplx.getHandle());
00275     }
00276     static bool canEnter(const Simplex&) { return true; }
00277     bool choose(const Simplex& os) { addVertices(os, set); return false; }
00278   };
00279 }
00280 
00283 template <class iterator/*of Simplex */, class Vertex>
00284 void collectVertices(iterator begin, iterator end,
00285     std::vector<Vertex*>& out) {
00286   VertexSet<Vertex> set;
00287   while (begin != end) {
00288     collectVertices_::addVertices(*begin, set); ++begin;
00289   }
00290   std::copy(set.begin(), set.end(), std::back_inserter(out));
00291 }
00292 
00294 template <class Complex, class output_iterator>
00295 output_iterator collectVertices(const Complex& cplx,
00296     output_iterator out) {
00297   collectVertices_::C<Complex> c(cplx);
00298   return std::copy(c.set.begin(), c.set.end(), out);
00299 }
00300 
00302 template <class Complex>
00303 void collectVertices(const Complex& cplx,
00304     std::vector<typename Complex::Vertex*>& out) {
00305   collectVertices(cplx, std::back_inserter(out));
00306 }
00307 
00309 template <class Complex>
00310 size_t countVertices(const Complex& cplx) {
00311   collectVertices_::C<Complex> c(cplx);
00312   return c.set.size();
00313 }
00314 
00316 
00317 /***************************************************************************
00318  * \name Serialization code.
00319  *
00320  * This is the question of turning our complex into something we can store
00321  * on disk.  We translate it here into an array of vertices and an array
00322  * of indices (namely, something from which we could create a new complex).
00323  *
00324  * The implementation is quite fast given the output format of a vector
00325  * of vectors of integers: I only perform one pass over the complex.
00326  * However, a vector of vectors is agonizingly slow due to the memory
00327  * allocation cost.
00328  ***************************************************************************/
00330 template <class Complex>
00331 struct Serialize_ {
00332   typedef typename Complex::Simplex Simplex;
00333   typedef typename Complex::Vertex Vertex;
00334   typedef hashers::hash_map<Vertex*, unsigned, hudson::hash_by_cast<Vertex*> > VMap;
00335 
00336   vector<Vertex*>& verts;
00337   vector<vector<size_t> >& elements;
00338   VMap vmap;
00339   Serialize_(vector<Vertex*>& v, vector<vector<size_t> >& e)
00340     : verts(v), elements(e) { }
00341 
00342   static bool canEnter(const Simplex&) { return true; }
00343 
00344   bool choose(const Simplex& os) {
00345     elements.push_back(vector<size_t>());
00346     vector<size_t>& elt = elements.back();
00347     elt.resize(Complex::dimension+1);
00348     for (size_t j = 0; j <= Complex::dimension; ++j) {
00349       // Look up the vertex in the table, or insert it if it isn't there.
00350       size_t id;
00351       size_t n = vmap.size();
00352       pair<typename VMap::iterator, bool> p = vmap.insert(make_pair(os[j], n));
00353       if(p.second) {
00354         // Succeeded => this is a new vertex with id = n.
00355         verts.push_back(os[j]);
00356         id = n;
00357       } else {
00358         // Failed => we can read out the old ID.
00359         id = (*(p.first)).second;
00360       }
00361       // Now we know the ID, so we can write to the element array.
00362       elt[j] = id;
00363     }
00364     return false;
00365   }
00366 };
00367 
00368 template <class Complex>
00369 void serialize(const Complex& cplx,
00370     std::vector<typename Complex::Vertex*>& verts,
00371     std::vector<std::vector<size_t> >& elements)
00372 {
00373   Serialize_<Complex> s(verts, elements);
00374   cplx.dfsBySimplex(s, cplx.getHandle());
00375 }
00377 
00378 } // namespace Simplicial
00379 #endif

Generated on Thu Mar 27 19:04:14 2008 by  doxygen 1.4.6