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