Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MeshGenerator.hpp
1 /*
2  * MeshGenerator.hh
3  *
4  * Created on: Mar 15, 2012
5  * Author: kremer
6  */
7 
8 #ifndef MESHGENERATOR_HH_
9 #define MESHGENERATOR_HH_
10 
11 #include <vector>
12 #include <set>
13 #include <map>
14 #include <algorithm>
15 
16 #include <boost/shared_ptr.hpp>
17 #include <boost/progress.hpp>
18 #include <boost/tuple/tuple.hpp>
19 #include <boost/tuple/tuple_comparison.hpp>
20 
21 #include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
22 #include <OpenVolumeMesh/Geometry/VectorT.hh>
23 
25 private:
26 
33 
34  typedef boost::tuple<VertexHandle, VertexHandle, VertexHandle> FaceTuple;
35 
36 public:
37 
39 
41 
42  MeshGenerator(PolyhedralMesh& _mesh) : v_component_(0), mesh_(_mesh), progress_() {}
43  MeshGenerator(const MeshGenerator& _cpy) :
44  v_component_(_cpy.v_component_),
45  vertex_(0.0, 0.0, 0.0),
46  c_vertices_(),
47  faceMap_(),
48  mesh_(_cpy.mesh_),
49  progress_() {}
50 
51  void add_vertex_component(double _comp) {
52 
53  if(v_component_ > 2) {
54  std::cerr << "Vertices of dimension higher than three not supported!" << std::endl;
55  return;
56  }
57  vertex_[v_component_] = _comp;
58  ++v_component_;
59  if(v_component_ == 3) {
60  add_vertex();
61  }
62  }
63 
64  void add_vertex() {
65 
66  OpenVolumeMesh::VertexHandle vh = mesh_.add_vertex(vertex_);
67  //std::cerr << "Added vertex " << mesh_.vertex(vh) << std::endl;
68  v_component_ = 0;
69  }
70 
71  void add_cell_vertex(unsigned int _idx) {
72 
73  assert(_idx > 0);
74 
75  c_vertices_.push_back(OpenVolumeMesh::VertexHandle((int)_idx - 1));
76  if(c_vertices_.size() == 4) {
77 
78  add_tetrahedral_cell();
79 // std::cerr << "Adding cell (" << c_vertices_[0] << ", " << c_vertices_[1] <<
80 // ", " << c_vertices_[2] << ", " << c_vertices_[3] << ")" << std::endl;
81  c_vertices_.clear();
82  }
83  }
84 
85  void set_num_cells(unsigned int _n) {
86 
87  if(progress_.get() == NULL) {
88  progress_.reset(new boost::progress_display(_n));
89  }
90  }
91 
92  void add_tetrahedral_cell() {
93 
94  if(c_vertices_.size() != 4) {
95  std::cerr << "The specified cell is not incident to four vertices!" << std::endl;
96  return;
97  }
98 
99  // Get cell's mid-point
100  Vec3d midP(0.0, 0.0, 0.0);
101  double valence = 0.0;
102  for(std::vector<OpenVolumeMesh::VertexHandle>::const_iterator it = c_vertices_.begin();
103  it != c_vertices_.end(); ++it) {
104  midP += mesh_.vertex(*it);
105  valence += 1.0;
106  }
107  midP /= valence;
108 
109  // Sort vertex vector
110  std::sort(c_vertices_.begin(), c_vertices_.end());
111 
112  std::vector<FaceTuple> tuples;
113 
114  // Create face tuple for all vertex combinations
115  tuples.push_back(FaceTuple(c_vertices_[0], c_vertices_[1], c_vertices_[2]));
116  tuples.push_back(FaceTuple(c_vertices_[1], c_vertices_[2], c_vertices_[3]));
117  tuples.push_back(FaceTuple(c_vertices_[0], c_vertices_[2], c_vertices_[3]));
118  tuples.push_back(FaceTuple(c_vertices_[0], c_vertices_[1], c_vertices_[3]));
119 
120  // Collect cell's half-faces in here
121  std::vector<HalfFaceHandle> cell_halffaces;
122 
123  for(std::vector<FaceTuple>::const_iterator it = tuples.begin();
124  it != tuples.end(); ++it) {
125 
126  // Check if face exists for current tuple
127  FaceMap::iterator f = faceMap_.find(*it);
128  if(f == faceMap_.end()) {
129  // Face does not exist, create it
130 
131  // Find right orientation, s.t. normal
132  // points inside the cell
133 
134  Vec3d e1 = mesh_.vertex(it->get<1>()) - mesh_.vertex(it->get<0>());
135  Vec3d e2 = mesh_.vertex(it->get<2>()) - mesh_.vertex(it->get<1>());
136 
137  // Get face normal (cross product)
138  Vec3d n = (e1 % e2).normalize();
139 
140  std::vector<VertexHandle> v_vec;
141  v_vec.push_back(it->get<0>());
142  v_vec.push_back(it->get<1>());
143  v_vec.push_back(it->get<2>());
144  FaceHandle fh = mesh_.add_face(v_vec);
145 
146  // Add face to face map
147  faceMap_[*it] = fh;
148 
149  // Check whether normal points inside cell
150  if(((midP - mesh_.vertex(it->get<0>())) | n) > 0.0) {
151 
152  // Normal points inside cell, just add half-face 0
153  // Add corresponding half-face to cell definition
154  cell_halffaces.push_back(mesh_.halfface_handle(fh, 0));
155 
156  } else {
157 
158  // Normal points outside cell, just add half-face 1
159  // Add corresponding half-face to cell definition
160  cell_halffaces.push_back(mesh_.halfface_handle(fh, 1));
161  }
162 
163  } else {
164 
165  // Face exists, find right orientation
166  FaceHandle fh = f->second;
167 
168  std::vector<HalfEdgeHandle> hes = mesh_.face(fh).halfedges();
169 
170  assert(hes.size() == 3);
171 
172  Vec3d e1 = mesh_.vertex(mesh_.halfedge(hes[0]).to_vertex()) -
173  mesh_.vertex(mesh_.halfedge(hes[0]).from_vertex());
174  Vec3d e2 = mesh_.vertex(mesh_.halfedge(hes[1]).to_vertex()) -
175  mesh_.vertex(mesh_.halfedge(hes[1]).from_vertex());
176 
177  Vec3d n = (e1 % e2).normalize();
178 
179  if(((midP - mesh_.vertex(mesh_.halfedge(hes[0]).from_vertex())) | n) > 0.0) {
180  // Normal points inside cell
181  cell_halffaces.push_back(mesh_.halfface_handle(fh, 0));
182  } else {
183  // Normal points outisde cell
184  cell_halffaces.push_back(mesh_.halfface_handle(fh, 1));
185  }
186  }
187  }
188 
189  // Check whether cell definition contains four half-faces
190  assert(cell_halffaces.size() == 4);
191 
192  // Finally, add cell
193 #ifndef NDEBUG
194  mesh_.add_cell(cell_halffaces, true);
195 #else
196  mesh_.add_cell(cell_halffaces, false);
197 #endif
198 
199  // Increase progress counter
200  if((progress_.get() != NULL) && (progress_->expected_count() != 0))
201  ++(*progress_);
202  }
203 
204 private:
205 
206  typedef std::map<FaceTuple, OpenVolumeMesh::FaceHandle> FaceMap;
207 
208  unsigned int v_component_;
210 
211  std::vector<VertexHandle> c_vertices_;
212 
213  FaceMap faceMap_;
214 
215  PolyhedralMesh& mesh_;
216 
217  boost::shared_ptr<boost::progress_display> progress_;
218 };
219 
220 #endif /* MESHGENERATOR_HH_ */
const VecT & vertex(const VertexHandle &_vh) const
Get point _vh's coordinates.
virtual VertexHandle add_vertex()
Override of empty add_vertex function.