1 // This is brl/bbas/imesh/imesh_face.h
2 #ifndef imesh_face_h_
3 #define imesh_face_h_
4 //:
5 // \file
6 // \brief A mesh face
7 // \author Matt Leotta (mleotta@lems.brown.edu)
8 // \date May 2, 2008
9 //
10 // \verbatim
11 //  Modifications
12 //   <none yet>
13 // \endverbatim
14 
15 #include <utility>
16 #include <vector>
17 #include <set>
18 #include <iostream>
19 #include <memory>
20 #include <string>
21 #include <algorithm>
22 #include <cassert>
23 #ifdef _MSC_VER
24 #  include <vcl_msvc_warnings.h>
25 #endif
26 #include <vgl/vgl_vector_3d.h>
27 
28 #define imesh_invalid_idx (static_cast<unsigned int>(-1))
29 
30 
31 //: A mesh face with a fixed number of vertices
32 template <unsigned s>
33 class imesh_regular_face
34 {
35  public:
36   //: Default Constructor
imesh_regular_face()37   imesh_regular_face() { for (unsigned i=0; i<s; ++i) verts_[i]=imesh_invalid_idx; }
38 
39   //: Constructor from a vector
imesh_regular_face(const std::vector<unsigned int> & verts)40   imesh_regular_face(const std::vector<unsigned int>& verts)
41   {assert(verts.size()==s); for (unsigned i=0; i<s; ++i) verts_[i]=verts[i];}
42 
43   //: return the number of vertices
num_verts()44   unsigned int num_verts() const { return s; }
45 
flip_orientation()46   void flip_orientation()
47   {
48     std::reverse(verts_,verts_+s);
49   }
50 
51   //: Accessor
52   unsigned int operator[] (unsigned int i) const { return verts_[i]; }
53   unsigned int& operator[] (unsigned int i) { return verts_[i]; }
54  protected:
55   unsigned int verts_[s];
56 };
57 
58 
59 //: A triangle face
60 class imesh_tri : public imesh_regular_face<3>
61 {
62  public:
imesh_tri(unsigned int a,unsigned int b,unsigned int c)63   imesh_tri(unsigned int a, unsigned int b, unsigned int c)
64   {
65     verts_[0] = a;
66     verts_[1] = b;
67     verts_[2] = c;
68   }
69 };
70 
71 //: A quadrilateral face
72 class imesh_quad : public imesh_regular_face<4>
73 {
74  public:
imesh_quad(unsigned int a,unsigned int b,unsigned int c,unsigned int d)75   imesh_quad(unsigned int a, unsigned int b,
76              unsigned int c, unsigned int d)
77   {
78     verts_[0] = a;
79     verts_[1] = b;
80     verts_[2] = c;
81     verts_[3] = d;
82   }
83 };
84 
85 
86 //: Abstract base class for a collection of faces
87 class imesh_face_array_base
88 {
89  public:
90   //: Destructor
91   virtual ~imesh_face_array_base() = default;
92 
93   //: returns the number of vertices per face if the same for all faces, zero otherwise
94   virtual unsigned int regularity() const = 0;
95 
96   //: returns the number of faces
97   virtual unsigned int size() const = 0;
98 
99   //: returns the number of vertices in face \param f
100   virtual unsigned int num_verts(unsigned int f) const = 0;
101 
102   //: Access a vertex index by face index and within-face index
103   virtual unsigned int operator() (unsigned int f, unsigned int i) const = 0;
104 
105   //: Flip a face over, inverting its orientation
flip_orientation(unsigned int f)106   virtual void flip_orientation (unsigned int f)
107   {
108     if (has_normals())
109       normals_[f] *= -1;
110   }
111 
112   //: Produce a clone of this object (dynamic copy)
113   virtual imesh_face_array_base* clone() const = 0;
114 
115   //: Append this array of faces (must be the same type)
116   //  Optionally shift the indices in \param other by \param ind_shift
117   virtual void append(const imesh_face_array_base& other,
118                       unsigned int ind_shift=0);
119 
120   //: Return true if the faces have normals
has_normals()121   bool has_normals() const { return !normals_.empty(); }
122 
123   //: Set the face normals
set_normals(const std::vector<vgl_vector_3d<double>> & n)124   void set_normals(const std::vector<vgl_vector_3d<double> >& n)
125   { assert(n.size() == this->size()); normals_ = n; }
126 
127   //: Access a face normal
normal(unsigned int f)128   vgl_vector_3d<double>& normal(unsigned int f) { return normals_[f]; }
normal(unsigned int f)129   const vgl_vector_3d<double>& normal(unsigned int f) const { return normals_[f]; }
130 
131   //: Access the entire vector of normals
normals()132   const std::vector<vgl_vector_3d<double> >& normals() const { return normals_; }
133 
134   //: Returns true if the faces have named groups
has_groups()135   bool has_groups() const { return !groups_.empty(); }
136 
137   //: Return the group name for a given face index
138   std::string group_name(unsigned int f) const;
139 
140   //: Assign a group name to all faces currently unnamed
141   //  Return the number of faces in the new group
142   unsigned int make_group(const std::string& name);
143 
144   //: Return a set of all faces in a group
145   std::set<unsigned int> group_face_set(const std::string& name) const;
146 
147   //: Access the groups
groups()148   const std::vector<std::pair<std::string,unsigned int> >& groups() const { return groups_; }
149 
150  protected:
151   //: named groups of adjacent faces (a partition of the face array)
152   //  Integers mark the group's ending vertex + 1
153   std::vector<std::pair<std::string,unsigned int> > groups_;
154 
155   //: vectors that are normal to each face
156   std::vector<vgl_vector_3d<double> > normals_;
157 };
158 
159 
160 //: An array of mesh faces of arbitrary size
161 class imesh_face_array : public imesh_face_array_base
162 {
163   std::vector<std::vector<unsigned int> > faces_;
164 
165  public:
166   //: Default Constructor
167   imesh_face_array() = default;
168 
169   //: Constructor
imesh_face_array(unsigned int size)170   imesh_face_array(unsigned int size) : faces_(size) {}
171 
172   //: Constructor (from a vector)
imesh_face_array(std::vector<std::vector<unsigned int>> faces)173   imesh_face_array(std::vector<std::vector<unsigned int> >  faces)
174   : faces_(std::move(faces)) {}
175 
176   //: Copy Constructor
imesh_face_array(const imesh_face_array & other)177   imesh_face_array(const imesh_face_array& other)
178   : imesh_face_array_base(other), faces_(other.faces_) {}
179 
180   //: Construct from base class
imesh_face_array(const imesh_face_array_base & fb)181   explicit imesh_face_array(const imesh_face_array_base& fb)
182   : imesh_face_array_base(fb), faces_(fb.size())
183   {
184     for (unsigned int i=0; i<fb.size(); ++i)
185       for (unsigned int j=0; j<fb.num_verts(i); ++j)
186         faces_[i].push_back(fb(i,j));
187   }
188 
189   //: returns the number of vertices per face if the same for all faces, zero otherwise
regularity()190   unsigned int regularity() const override { return 0; }
191 
192   //: returns the number of faces
size()193   unsigned int size() const override { return faces_.size(); }
194 
195   //: returns the number of vertices in face \param f
num_verts(unsigned int f)196   unsigned int num_verts(unsigned int f) const override { return faces_[f].size(); }
197 
198   //: Access a vertex index by face index and within-face index
operator()199   unsigned int operator() (unsigned int f, unsigned int i) const override { return faces_[f][i]; }
200 
201   //: Flip a face over, inverting its orientation
flip_orientation(unsigned int f)202   void flip_orientation (unsigned int f) override
203   {
204     std::reverse(faces_[f].begin(),faces_[f].end());
205     imesh_face_array_base::flip_orientation(f);
206   }
207 
208   //: Produce a clone of this object (dynamic copy)
clone()209   imesh_face_array_base* clone() const override
210   {
211     return new imesh_face_array(*this);
212   }
213 
214   //: Append this array of faces
215   //  Optionally shift the indices in \param other by \param ind_shift
216   void append(const imesh_face_array_base& other,
217                       unsigned int ind_shift=0) override;
218 
219   //: Add a face to the array
push_back(const std::vector<unsigned int> & f)220   void push_back(const std::vector<unsigned int>& f) { faces_.push_back(f); }
221 
222   //: Add a face to the array
223   template <unsigned int s>
push_back(const imesh_regular_face<s> & f)224   void push_back(const imesh_regular_face<s>& f)
225   {
226     std::vector<unsigned int> f2(s);
227     for (unsigned int i=0; i<s; ++i)
228       f2[i] = f[i];
229     this->push_back(f2);
230   }
231 
232   //: Access face \param f
233   std::vector<unsigned int>& operator[] (unsigned int f) { return faces_[f]; }
234   const std::vector<unsigned int>& operator[] (unsigned int f) const { return faces_[f]; }
235 };
236 
237 
238 //: An array of mesh faces of arbitrary size
239 template <unsigned int s>
240 class imesh_regular_face_array : public imesh_face_array_base
241 {
242   std::vector<imesh_regular_face<s> > faces_;
243 
244  public:
245   //: Default Constructor
246   imesh_regular_face_array<s>() = default;
247 
248   //: Constructor
faces_(size)249   imesh_regular_face_array<s>(unsigned int size) : faces_(size) {}
250 
251   //: Constructor (from a vector)
faces_(faces)252   imesh_regular_face_array<s>(const std::vector<imesh_regular_face<s> >& faces) : faces_(faces) {}
253 
254   //: returns the number of vertices per face if the same for all faces
255   //  Returns zero otherwise
regularity()256   unsigned int regularity() const override { return s; }
257 
258   //: returns the number of faces
size()259   unsigned int size() const override { return faces_.size(); }
260 
261   //: returns the number of vertices in face \param f
num_verts(unsigned int)262   unsigned int num_verts(unsigned int /*f*/) const override { return s; }
263 
264   //: Access a vertex index by face index and within-face index
operator()265   unsigned int operator() (unsigned int f, unsigned int i) const override { return faces_[f][i]; }
266 
267   //: Flip a face over, inverting its orientation
flip_orientation(unsigned int f)268   void flip_orientation (unsigned int f) override
269   {
270     faces_[f].flip_orientation();
271     imesh_face_array_base::flip_orientation(f);
272   }
273 
274   //: Produce a clone of this object (dynamic copy)
clone()275   imesh_face_array_base* clone() const override
276   {
277     return new imesh_regular_face_array<s>(*this);
278   }
279 
280   //: Append this array of faces (must be the same type)
281   //  Optionally shift the indices in \param other by \param ind_shift
282   void append(const imesh_face_array_base& other,
283                       unsigned int ind_shift=0) override
284   {
285     imesh_face_array_base::append(other,ind_shift);
286     assert(other.regularity() == s);
287     const imesh_regular_face_array<s>& fs =
288         static_cast<const imesh_regular_face_array<s>&>(other);
289     const unsigned int new_begin = faces_.size();
290     faces_.insert(faces_.end(), fs.faces_.begin(), fs.faces_.end());
291     if (ind_shift > 0) {
292       for (unsigned int i=new_begin; i<faces_.size(); ++i) {
293         imesh_regular_face<s>& f = faces_[i];
294         for (unsigned int j=0; j<s; ++j)
295           f[j] += ind_shift;
296       }
297     }
298   }
299 
300   //: Add a face to the array
push_back(const imesh_regular_face<s> & f)301   void push_back(const imesh_regular_face<s>& f) { faces_.push_back(f); }
302 
303   //: Access face \param f
304   imesh_regular_face<s>& operator[] (unsigned int f) { return faces_[f]; }
305   const imesh_regular_face<s>& operator[] (unsigned int f) const { return faces_[f]; }
306 
307   //=====================================================
308   // Face Iterators
309   typedef typename std::vector<imesh_regular_face<s> >::iterator iterator;
310   typedef typename std::vector<imesh_regular_face<s> >::const_iterator const_iterator;
311 
begin()312   iterator begin() { return faces_.begin(); }
begin()313   const_iterator begin() const { return faces_.begin(); }
314 
end()315   iterator end() { return faces_.end(); }
end()316   const_iterator end() const { return faces_.end(); }
317 };
318 
319 
320 //: Merge the two face arrays
321 //  Shift the mesh indices in \param f2 by \param ind_shift
322 std::unique_ptr<imesh_face_array_base>
323 imesh_merge(const imesh_face_array_base& f1,
324             const imesh_face_array_base& f2,
325             unsigned int ind_shift=0);
326 
327 #endif // imesh_face_h_
328