00001 #ifndef SimplicialHelpers_HEADER
00002 #define SimplicialHelpers_HEADER
00003
00004
00005
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
00018
00019
00020
00021
00022
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
00031
00032
00033
00034
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
00122
00123
00124
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
00152
00153
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
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
00253
00254
00255
00256
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, 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
00319
00320
00321
00322
00323
00324
00325
00326
00327
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
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
00355 verts.push_back(os[j]);
00356 id = n;
00357 } else {
00358
00359 id = (*(p.first)).second;
00360 }
00361
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 }
00379 #endif