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