contrib/brl/bbas/imesh/imesh_face.h
Go to the documentation of this file.
00001 // This is brl/bbas/imesh/imesh_face.h
00002 #ifndef imesh_face_h_
00003 #define imesh_face_h_
00004 //:
00005 // \file
00006 // \brief A mesh face
00007 // \author Matt Leotta (mleotta@lems.brown.edu)
00008 // \date May 2, 2008
00009 //
00010 // \verbatim
00011 //  Modifications
00012 //   <none yet>
00013 // \endverbatim
00014 
00015 #include <vcl_vector.h>
00016 #include <vcl_set.h>
00017 #include <vcl_cassert.h>
00018 #include <vcl_memory.h>
00019 #include <vcl_utility.h>
00020 #include <vcl_string.h>
00021 #include <vcl_algorithm.h>
00022 #include <vgl/vgl_vector_3d.h>
00023 
00024 #define imesh_invalid_idx (static_cast<unsigned int>(-1))
00025 
00026 
00027 //: A mesh face with a fixed number of vertices
00028 template <unsigned s>
00029 class imesh_regular_face
00030 {
00031  public:
00032   //: Default Constructor
00033   imesh_regular_face() { for (unsigned i=0; i<s; ++i) verts_[i]=imesh_invalid_idx; }
00034 
00035   //: Constructor from a vector
00036   imesh_regular_face(const vcl_vector<unsigned int>& verts)
00037   {assert(verts.size()==s); for (unsigned i=0; i<s; ++i) verts_[i]=verts[i];}
00038 
00039   //: return the number of vertices
00040   unsigned int num_verts() const { return s; }
00041 
00042   void flip_orientation()
00043   {
00044     vcl_reverse(verts_,verts_+s);
00045   }
00046 
00047   //: Accessor
00048   unsigned int operator[] (unsigned int i) const { return verts_[i]; }
00049   unsigned int& operator[] (unsigned int i) { return verts_[i]; }
00050  protected:
00051   unsigned int verts_[s];
00052 };
00053 
00054 
00055 //: A triangle face
00056 class imesh_tri : public imesh_regular_face<3>
00057 {
00058  public:
00059   imesh_tri(unsigned int a, unsigned int b, unsigned int c)
00060   {
00061     verts_[0] = a;
00062     verts_[1] = b;
00063     verts_[2] = c;
00064   }
00065 };
00066 
00067 //: A quadrilateral face
00068 class imesh_quad : public imesh_regular_face<4>
00069 {
00070  public:
00071   imesh_quad(unsigned int a, unsigned int b,
00072              unsigned int c, unsigned int d)
00073   {
00074     verts_[0] = a;
00075     verts_[1] = b;
00076     verts_[2] = c;
00077     verts_[3] = d;
00078   }
00079 };
00080 
00081 
00082 //: Abstract base class for a collection of faces
00083 class imesh_face_array_base
00084 {
00085  public:
00086   //: Destructor
00087   virtual ~imesh_face_array_base() {}
00088 
00089   //: returns the number of vertices per face if the same for all faces, zero otherwise
00090   virtual unsigned int regularity() const = 0;
00091 
00092   //: returns the number of faces
00093   virtual unsigned int size() const = 0;
00094 
00095   //: returns the number of vertices in face \param f
00096   virtual unsigned int num_verts(unsigned int f) const = 0;
00097 
00098   //: Access a vertex index by face index and within-face index
00099   virtual unsigned int operator() (unsigned int f, unsigned int i) const = 0;
00100 
00101   //: Flip a face over, inverting its orientation
00102   virtual void flip_orientation (unsigned int f)
00103   {
00104     if (has_normals())
00105       normals_[f] *= -1;
00106   }
00107 
00108   //: Produce a clone of this object (dynamic copy)
00109   virtual imesh_face_array_base* clone() const = 0;
00110 
00111   //: Append this array of faces (must be the same type)
00112   //  Optionally shift the indices in \param other by \param ind_shift
00113   virtual void append(const imesh_face_array_base& other,
00114                       unsigned int ind_shift=0);
00115 
00116   //: Return true if the faces have normals
00117   bool has_normals() const { return !normals_.empty(); }
00118 
00119   //: Set the face normals
00120   void set_normals(const vcl_vector<vgl_vector_3d<double> >& n)
00121   { assert(n.size() == this->size()); normals_ = n; }
00122 
00123   //: Access a face normal
00124   vgl_vector_3d<double>& normal(unsigned int f) { return normals_[f]; }
00125   const vgl_vector_3d<double>& normal(unsigned int f) const { return normals_[f]; }
00126 
00127   //: Access the entire vector of normals
00128   const vcl_vector<vgl_vector_3d<double> >& normals() const { return normals_; }
00129 
00130   //: Returns true if the faces have named groups
00131   bool has_groups() const { return !groups_.empty(); }
00132 
00133   //: Return the group name for a given face index
00134   vcl_string group_name(unsigned int f) const;
00135 
00136   //: Assign a group name to all faces currently unnamed
00137   //  Return the number of faces in the new group
00138   unsigned int make_group(const vcl_string& name);
00139 
00140   //: Return a set of all faces in a group
00141   vcl_set<unsigned int> group_face_set(const vcl_string& name) const;
00142 
00143   //: Access the groups
00144   const vcl_vector<vcl_pair<vcl_string,unsigned int> >& groups() const { return groups_; }
00145 
00146  protected:
00147   //: named groups of adjacent faces (a partition of the face array)
00148   //  Integers mark the group's ending vertex + 1
00149   vcl_vector<vcl_pair<vcl_string,unsigned int> > groups_;
00150 
00151   //: vectors that are normal to each face
00152   vcl_vector<vgl_vector_3d<double> > normals_;
00153 };
00154 
00155 
00156 //: An array of mesh faces of arbitrary size
00157 class imesh_face_array : public imesh_face_array_base
00158 {
00159   vcl_vector<vcl_vector<unsigned int> > faces_;
00160 
00161  public:
00162   //: Default Constructor
00163   imesh_face_array() {}
00164 
00165   //: Constructor
00166   imesh_face_array(unsigned int size) : faces_(size) {}
00167 
00168   //: Constructor (from a vector)
00169   imesh_face_array(const vcl_vector<vcl_vector<unsigned int> >& faces)
00170   : faces_(faces) {}
00171 
00172   //: Copy Constructor
00173   imesh_face_array(const imesh_face_array& other)
00174   : imesh_face_array_base(other), faces_(other.faces_) {}
00175 
00176   //: Construct from base class
00177   explicit imesh_face_array(const imesh_face_array_base& fb)
00178   : imesh_face_array_base(fb), faces_(fb.size())
00179   {
00180     for (unsigned int i=0; i<fb.size(); ++i)
00181       for (unsigned int j=0; j<fb.num_verts(i); ++j)
00182         faces_[i].push_back(fb(i,j));
00183   }
00184 
00185   //: returns the number of vertices per face if the same for all faces, zero otherwise
00186   virtual unsigned int regularity() const { return 0; }
00187 
00188   //: returns the number of faces
00189   virtual unsigned int size() const { return faces_.size(); }
00190 
00191   //: returns the number of vertices in face \param f
00192   virtual unsigned int num_verts(unsigned int f) const { return faces_[f].size(); }
00193 
00194   //: Access a vertex index by face index and within-face index
00195   virtual unsigned int operator() (unsigned int f, unsigned int i) const { return faces_[f][i]; }
00196 
00197   //: Flip a face over, inverting its orientation
00198   virtual void flip_orientation (unsigned int f)
00199   {
00200     vcl_reverse(faces_[f].begin(),faces_[f].end());
00201     imesh_face_array_base::flip_orientation(f);
00202   }
00203 
00204   //: Produce a clone of this object (dynamic copy)
00205   virtual imesh_face_array_base* clone() const
00206   {
00207     return new imesh_face_array(*this);
00208   }
00209 
00210   //: Append this array of faces
00211   //  Optionally shift the indices in \param other by \param ind_shift
00212   virtual void append(const imesh_face_array_base& other,
00213                       unsigned int ind_shift=0);
00214 
00215   //: Add a face to the array
00216   void push_back(const vcl_vector<unsigned int>& f) { faces_.push_back(f); }
00217 
00218   //: Add a face to the array
00219   template <unsigned int s>
00220   void push_back(const imesh_regular_face<s>& f)
00221   {
00222     vcl_vector<unsigned int> f2(s);
00223     for (unsigned int i=0; i<s; ++i)
00224       f2[i] = f[i];
00225     this->push_back(f2);
00226   }
00227 
00228   //: Access face \param f
00229   vcl_vector<unsigned int>& operator[] (unsigned int f) { return faces_[f]; }
00230   const vcl_vector<unsigned int>& operator[] (unsigned int f) const { return faces_[f]; }
00231 };
00232 
00233 
00234 //: An array of mesh faces of arbitrary size
00235 template <unsigned int s>
00236 class imesh_regular_face_array : public imesh_face_array_base
00237 {
00238   vcl_vector<imesh_regular_face<s> > faces_;
00239 
00240  public:
00241   //: Default Constructor
00242   imesh_regular_face_array<s>() {}
00243 
00244   //: Constructor
00245   imesh_regular_face_array<s>(unsigned int size) : faces_(size) {}
00246 
00247   //: Constructor (from a vector)
00248   imesh_regular_face_array<s>(const vcl_vector<imesh_regular_face<s> >& faces) : faces_(faces) {}
00249 
00250   //: returns the number of vertices per face if the same for all faces
00251   //  Returns zero otherwise
00252   virtual unsigned int regularity() const { return s; }
00253 
00254   //: returns the number of faces
00255   virtual unsigned int size() const { return faces_.size(); }
00256 
00257   //: returns the number of vertices in face \param f
00258   virtual unsigned int num_verts(unsigned int /*f*/) const { return s; }
00259 
00260   //: Access a vertex index by face index and within-face index
00261   virtual unsigned int operator() (unsigned int f, unsigned int i) const { return faces_[f][i]; }
00262 
00263   //: Flip a face over, inverting its orientation
00264   virtual void flip_orientation (unsigned int f)
00265   {
00266     faces_[f].flip_orientation();
00267     imesh_face_array_base::flip_orientation(f);
00268   }
00269 
00270   //: Produce a clone of this object (dynamic copy)
00271   virtual imesh_face_array_base* clone() const
00272   {
00273     return new imesh_regular_face_array<s>(*this);
00274   }
00275 
00276   //: Append this array of faces (must be the same type)
00277   //  Optionally shift the indices in \param other by \param ind_shift
00278   virtual void append(const imesh_face_array_base& other,
00279                       unsigned int ind_shift=0)
00280   {
00281     imesh_face_array_base::append(other,ind_shift);
00282     assert(other.regularity() == s);
00283     const imesh_regular_face_array<s>& fs =
00284         static_cast<const imesh_regular_face_array<s>&>(other);
00285     const unsigned int new_begin = faces_.size();
00286     faces_.insert(faces_.end(), fs.faces_.begin(), fs.faces_.end());
00287     if (ind_shift > 0) {
00288       for (unsigned int i=new_begin; i<faces_.size(); ++i) {
00289         imesh_regular_face<s>& f = faces_[i];
00290         for (unsigned int j=0; j<s; ++j)
00291           f[j] += ind_shift;
00292       }
00293     }
00294   }
00295 
00296   //: Add a face to the array
00297   void push_back(const imesh_regular_face<s>& f) { faces_.push_back(f); }
00298 
00299   //: Access face \param f
00300   imesh_regular_face<s>& operator[] (unsigned int f) { return faces_[f]; }
00301   const imesh_regular_face<s>& operator[] (unsigned int f) const { return faces_[f]; }
00302 
00303   //=====================================================
00304   // Face Iterators
00305   typedef typename vcl_vector<imesh_regular_face<s> >::iterator iterator;
00306   typedef typename vcl_vector<imesh_regular_face<s> >::const_iterator const_iterator;
00307 
00308   iterator begin() { return faces_.begin(); }
00309   const_iterator begin() const { return faces_.begin(); }
00310 
00311   iterator end() { return faces_.end(); }
00312   const_iterator end() const { return faces_.end(); }
00313 };
00314 
00315 
00316 //: Merge the two face arrays
00317 //  Shift the mesh indices in \param f2 by \param ind_shift
00318 vcl_auto_ptr<imesh_face_array_base>
00319 imesh_merge(const imesh_face_array_base& f1,
00320             const imesh_face_array_base& f2,
00321             unsigned int ind_shift=0);
00322 
00323 #endif // imesh_face_h_