MeshSet.h

Go to the documentation of this file.
00001 #ifndef MeshSet_HEADER
00002 #define MeshSet_HEADER
00003 
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007 
00008 #include <boost/array.hpp>
00009 #include "MeshTypes.h"
00010 #include "Mesh.h"
00011 
00017 namespace details {
00018 
00019   /* These should be in MeshSet, but C++ won't abide by a
00020    * specialized template in non-namespace scope. */
00021 
00022 
00023   /***************************************************************************
00024    * Helper class for MeshSet; use that class instead.
00025    *
00026    * To implement MeshVector::get(), I need this other class in order to
00027    * type-check the more obvious:<code>
00028    * if (i == topological) {
00029    *   return meshes_; // type error when i != topological
00030    * } else {
00031    *   return lowers_.get<i>();
00032    * }</code>
00033    * I came up with the idea of this side template independently, decided it
00034    * was idiotic, then looked up how boost::tuple does it, and wept.
00035    *
00036    * Note that the 'i' template argument here is the number of times to
00037    * recur into the lower, and is not the dimension.
00038    ***************************************************************************/
00039   template <int i> struct MVget {
00040     template <class MV, class RET>
00041     static RET& get(MV& mv) {
00042       return MVget<i-1>::template get<typename MV::lower_type, RET>(mv.lowers_);
00043     }
00044   };
00045 
00051   template <> struct MVget<0> {
00052     template <class MV, class RET>
00053     static RET& get(MV& mv) {
00054       return mv.meshes_;
00055     }
00056   };
00057 
00058   /***************************************************************************
00059     * Helper class for MeshSet; use that class instead.
00060     *
00061     * Implementation of one dimension of the set of meshes.
00062     * Each level is a cons cell storing:
00063     * - the meshes of dimension 'topological'
00064     * - a lower-dimensional MeshVector
00065    ***************************************************************************/
00066   template <size_t ambient, size_t topological> struct MeshVector {
00067     vector<Mesh<ambient, topological>*> meshes_;
00068     MeshVector<ambient, topological-1> lowers_;
00069     typedef MeshVector<ambient, topological-1> lower_type; //<! Used by MVget
00070 
00072     template <size_t i> vector<Mesh<ambient, i>*>& get() {
00073       BOOST_STATIC_ASSERT(i <= topological);
00074       BOOST_STATIC_ASSERT(i > 0);
00075       typedef vector<Mesh<ambient, i>*> RET;
00076       return MVget<topological - i>::template get<MeshVector, RET>(*this);
00077     }
00078 
00080     template <size_t i> const vector<Mesh<ambient, i>*>& get() const {
00081       BOOST_STATIC_ASSERT(i <= topological);
00082       BOOST_STATIC_ASSERT(i > 0);
00083       typedef const vector<Mesh<ambient, i>*> RET;
00084       return MVget<topological - i>::template get<const MeshVector, RET>(*this);
00085     }
00086 
00088     vector<typename MeshTypes<ambient>::Vertex*>& getVertices() {
00089       return lowers_.getVertices();
00090     }
00091 
00093     const vector<typename MeshTypes<ambient>::Vertex*>& getVertices() const {
00094       return lowers_.getVertices();
00095     }
00096 
00102     template <class output_iterator> output_iterator outputAllBalls(output_iterator out) const {
00103       for(size_t i = 0; i < meshes_.size(); ++i) {
00104         out = meshes_[i]->collectAllBalls(out);
00105       }
00106       return lowers_.outputAllBalls(out);
00107     }
00108 
00110     template <size_t d, class output_iterator> output_iterator outputSomeBalls(output_iterator out) const {
00111       if (d == topological) {
00112         for(size_t i = 0; i < meshes_.size(); ++i) {
00113           out = meshes_[i]->collectAllBalls(out);
00114         }
00115         return out;
00116       } else {
00117         return lowers_.template outputSomeBalls<d, output_iterator>(out);
00118       }
00119     }
00120   };
00121 
00128   template <size_t ambient> struct MeshVector<ambient, 0> {
00129     vector<typename MeshTypes<ambient>::Vertex*> verts_;
00130 
00131     vector<typename MeshTypes<ambient>::Vertex*>& getVertices() {
00132       return verts_;
00133     }
00134 
00135     const vector<typename MeshTypes<ambient>::Vertex*>& getVertices() const {
00136       return verts_;
00137     }
00138 
00139     template <class output_iterator> output_iterator outputAllBalls(const output_iterator& out) const { return out; }
00140     template <size_t i, class output_iterator> output_iterator outputSomeBalls(const output_iterator& out) const { return out; }
00141   };
00142 }
00143 
00144 
00145 /***************************************************************************
00146  * This class maintains the set of meshes, from dimension 0..d.
00147  *
00148  * Most of the work is handed off to the classes in the details namespace
00149  * above.  Those more naturally fit in MeshSet, but one can't specialize
00150  * template members of a template for some silly reason.
00151  *
00152  * The functions below are templated by the appropriate dimension.  Those that
00153  * have a function argument of the given dimension can guess the template
00154  * argument.  Those that can't must be told explicitly; for instance,
00155  *   <code> ms.get<2>()</code>
00156  * to get the set of 2-dimensional meshes.  Clearly, the template argument must
00157  * be a compile-time constant.  Furthermore, in some cases (which this author
00158  * does not fully understand), that will give an illegible parse error.  Try:
00159  *   <code> ms.template get<2>()</code>
00160  * This monstrosity is to deal with the fact that C++ syntax tries
00161  * very hard to be a context-free grammar.
00162  ***************************************************************************/
00163 template <size_t ambient>
00164 class MeshSet {
00165   details::MeshVector<ambient, ambient> meshes_;
00166 
00167   typedef typename MeshTypes<ambient>::Vertex Vertex;
00168 
00169   public:
00170 
00171   /* Monstrously, to call theses functions, you may need to use
00172      <code>meshes_.template get<i>();</code>
00173      And so on.
00174    */
00175 
00177   template <size_t i> void add(Mesh<ambient, i> *mesh) {
00178     meshes_.get<i>().push_back(mesh);
00179   }
00180 
00182   void add(Vertex *v) {
00183     meshes_.getVertices().push_back(v);
00184   }
00185 
00188   template <size_t i> const vector<Mesh<ambient, i>*>& get() const {
00189     return meshes_.get<i>();
00190   }
00191   Mesh<ambient, ambient> *getTopMesh() const { 
00192     return meshes_.get<ambient>().front();
00193   }
00194 
00196   const vector<Vertex*>& getVertices() const {
00197     return meshes_.getVertices();
00198   }
00199 
00203   template <class output_iterator> output_iterator outputAllBalls(const output_iterator& out) const {
00204     return meshes_.outputAllBalls(out);
00205   }
00206 
00210   template <size_t i, class output_iterator> output_iterator outputSomeBalls(const output_iterator& out) const {
00211     return meshes_.outputSomeBalls<i, output_iterator>(out);
00212   }
00213 };
00214 
00215 #endif

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