Free Electron
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
geodesic_cpp_mod/geodesic_mesh_elements.h
1 //Copyright (C) 2008 Danil Kirsanov, MIT License
2 #ifndef GEODESIC_MESH_ELEMENTS_20071231
3 #define GEODESIC_MESH_ELEMENTS_20071231
4 
5 // here we define the building elements of the mesh:
6 // 3D-points, vertices, edges, faces, and surface points
7 
8 #include <cstddef>
9 
10 namespace geodesic{
11 
12 class Vertex;
13 class Edge;
14 class Face;
15 class Mesh;
16 class MeshElementBase;
17 
18 typedef Vertex* vertex_pointer;
19 typedef Edge* edge_pointer;
20 typedef Face* face_pointer;
21 typedef Mesh* mesh_pointer;
22 typedef MeshElementBase* base_pointer;
23 
24 template <class Data> //simple vector that stores info about mesh references
25 class SimpleVector //for efficiency, it uses an outside memory allocator
26 {
27 public:
28  SimpleVector():
29  m_size(0),
30  m_begin(NULL)
31  {};
32 
33  typedef Data* iterator;
34 
35  unsigned size(){return m_size;};
36  iterator begin(){return m_begin;};
37  iterator end(){return m_begin + m_size;};
38 
39  template<class DataPointer>
40  void set_allocation(DataPointer begin, unsigned size)
41  {
42  FEASSERT(begin != NULL || size == 0);
43  m_size = size;
44  m_begin = (iterator)begin;
45  }
46 
47  Data& operator[](unsigned i)
48  {
49  FEASSERT(i < m_size);
50  return *(m_begin + i);
51  }
52 
53  void clear()
54  {
55  m_size = 0;
56  m_begin = NULL;
57  }
58 
59 private:
60  unsigned m_size;
61  Data* m_begin;
62 };
63 
64 enum PointType
65 {
66  VERTEX,
67  EDGE,
68  FACE,
69  UNDEFINED_POINT
70 };
71 
72 class MeshElementBase //prototype of vertices, edges and faces
73 {
74 public:
75  typedef SimpleVector<vertex_pointer> vertex_pointer_vector;
76  typedef SimpleVector<edge_pointer> edge_pointer_vector;
77  typedef SimpleVector<face_pointer> face_pointer_vector;
78 
79  MeshElementBase():
80  m_id(0),
81  m_type(UNDEFINED_POINT)
82  {};
83 
84  vertex_pointer_vector& adjacent_vertices(){return m_adjacent_vertices;};
85  edge_pointer_vector& adjacent_edges(){return m_adjacent_edges;};
86  face_pointer_vector& adjacent_faces(){return m_adjacent_faces;};
87 
88  unsigned& id(){return m_id;};
89  PointType type(){return m_type;};
90 
91 protected:
92  vertex_pointer_vector m_adjacent_vertices; //list of the adjacent vertices
93  edge_pointer_vector m_adjacent_edges; //list of the adjacent edges
94  face_pointer_vector m_adjacent_faces; //list of the adjacent faces
95 
96  unsigned m_id; //unique id
97  PointType m_type; //vertex, edge or face
98 };
99 
100 class Point3D //point in 3D and corresponding operations
101 {
102 public:
103  Point3D(){};
104  Point3D(Point3D* p)
105  {
106  x() = p->x();
107  y() = p->y();
108  z() = p->z();
109  };
110 
111  double* xyz(){return m_coordinates;};
112  double& x(){return *m_coordinates;};
113  double& y(){return *(m_coordinates+1);};
114  double& z(){return *(m_coordinates+2);};
115 
116  void set(double new_x, double new_y, double new_z)
117  {
118  x() = new_x;
119  y() = new_y;
120  z() = new_z;
121  }
122 
123  void set(double* data)
124  {
125  x() = *data;
126  y() = *(data+1);
127  z() = *(data+2);
128  }
129 
130  double distance(double* v)
131  {
132  double dx = m_coordinates[0] - v[0];
133  double dy = m_coordinates[1] - v[1];
134  double dz = m_coordinates[2] - v[2];
135 
136  return sqrt(dx*dx + dy*dy + dz*dz);
137  };
138 
139  double distance(Point3D* v)
140  {
141  return distance(v->xyz());
142  };
143 
144  void add(Point3D* v)
145  {
146  x() += v->x();
147  y() += v->y();
148  z() += v->z();
149  };
150 
151  void multiply(double v)
152  {
153  x() *= v;
154  y() *= v;
155  z() *= v;
156  };
157 
158 private:
159  double m_coordinates[3]; //xyz
160 };
161 
162 class Vertex: public MeshElementBase, public Point3D
163 {
164 public:
165  Vertex()
166  {
167  m_type = VERTEX;
168  };
169 
170  ~Vertex(){};
171 
172  bool& saddle_or_boundary(){return m_saddle_or_boundary;};
173 private:
174  //this flag speeds up exact geodesic algorithm
175  bool m_saddle_or_boundary; //it is true if total adjacent angle is larger than 2*PI or this vertex belongs to the mesh boundary
176 };
177 
178 
179 class Face: public MeshElementBase
180 {
181 public:
182  Face()
183  {
184  m_type = FACE;
185  };
186 
187  ~Face(){};
188 
189  edge_pointer opposite_edge(vertex_pointer v);
190  vertex_pointer opposite_vertex(edge_pointer e);
191  edge_pointer next_edge(edge_pointer e, vertex_pointer v);
192 
193  double vertex_angle(vertex_pointer v)
194  {
195  for(unsigned i=0; i<3; ++i)
196  {
197  if(adjacent_vertices()[i]->id() == v->id())
198  {
199  return m_corner_angles[i];
200  }
201  }
202  FEASSERT(0);
203  return 0;
204  }
205 
206  double* corner_angles(){return m_corner_angles;};
207 
208 private:
209  double m_corner_angles[3]; //triangle angles in radians; angles correspond to vertices in m_adjacent_vertices
210 };
211 
212 class Edge: public MeshElementBase
213 {
214 public:
215  Edge()
216  {
217  m_type = EDGE;
218  };
219 
220  ~Edge(){};
221 
222  double& length(){return m_length;};
223 
224  face_pointer opposite_face(face_pointer f)
225  {
226  if(adjacent_faces().size() == 1)
227  {
228  FEASSERT(adjacent_faces()[0]->id() == f->id());
229  return NULL;
230  }
231 
232  FEASSERT(adjacent_faces()[0]->id() == f->id() ||
233  adjacent_faces()[1]->id() == f->id());
234 
235  return adjacent_faces()[0]->id() == f->id() ?
236  adjacent_faces()[1] : adjacent_faces()[0];
237  };
238 
239  vertex_pointer opposite_vertex(vertex_pointer v)
240  {
241  FEASSERT(belongs(v));
242 
243  return adjacent_vertices()[0]->id() == v->id() ?
244  adjacent_vertices()[1] : adjacent_vertices()[0];
245  };
246 
247  bool belongs(vertex_pointer v)
248  {
249  return adjacent_vertices()[0]->id() == v->id() ||
250  adjacent_vertices()[1]->id() == v->id();
251  }
252 
253  bool is_boundary(){return adjacent_faces().size() == 1;};
254 
255  vertex_pointer v0(){return adjacent_vertices()[0];};
256  vertex_pointer v1(){return adjacent_vertices()[1];};
257 
258  void local_coordinates(Point3D* point,
259  double& x,
260  double& y)
261  {
262  double d0 = point->distance(v0());
263  if(d0 < 1e-50)
264  {
265  x = 0.0;
266  y = 0.0;
267  return;
268  }
269 
270  double d1 = point->distance(v1());
271  if(d1 < 1e-50)
272  {
273  x = m_length;
274  y = 0.0;
275  return;
276  }
277 
278  x = m_length/2.0 + (d0*d0 - d1*d1)/(2.0*m_length);
279  y = sqrt(std::max(0.0, d0*d0 - x*x));
280  return;
281  }
282 
283 private:
284  double m_length; //length of the edge
285 };
286 
287 class SurfacePoint:public Point3D //point on the surface of the mesh
288 {
289 public:
290  SurfacePoint():
291  m_p(NULL)
292  {};
293 
294  SurfacePoint(vertex_pointer v): //set the surface point in the vertex
295  SurfacePoint::Point3D(v),
296  m_p(v)
297  {};
298 
299  SurfacePoint(face_pointer f): //set the surface point in the center of the face
300  m_p(f)
301  {
302  set(0,0,0);
303  add(f->adjacent_vertices()[0]);
304  add(f->adjacent_vertices()[1]);
305  add(f->adjacent_vertices()[2]);
306  multiply(1./3.);
307  };
308 
309  SurfacePoint(edge_pointer e, //set the surface point in the middle of the edge
310  double a = 0.5):
311  m_p(e)
312  {
313  double b = 1 - a;
314 
315  vertex_pointer v0 = e->adjacent_vertices()[0];
316  vertex_pointer v1 = e->adjacent_vertices()[1];
317 
318  x() = b*v0->x() + a*v1->x();
319  y() = b*v0->y() + a*v1->y();
320  z() = b*v0->z() + a*v1->z();
321  };
322 
323  SurfacePoint(base_pointer g,
324  double x,
325  double y,
326  double z,
327  PointType t = UNDEFINED_POINT):
328  m_p(g)
329  {
330  set(x,y,z);
331  };
332 
333  void initialize(SurfacePoint const& p)
334  {
335  *this = p;
336  }
337 
338  ~SurfacePoint(){};
339 
340  PointType type(){return m_p ? m_p->type() : UNDEFINED_POINT;};
341  base_pointer& base_element(){return m_p;};
342 protected:
343  base_pointer m_p; //could be face, vertex or edge pointer
344 };
345 
346 inline edge_pointer Face::opposite_edge(vertex_pointer v)
347 {
348  for(unsigned i=0; i<3; ++i)
349  {
350  edge_pointer e = adjacent_edges()[i];
351  if(!e->belongs(v))
352  {
353  return e;
354  }
355  }
356  FEASSERT(0);
357  return NULL;
358 }
359 
360 inline vertex_pointer Face::opposite_vertex(edge_pointer e)
361 {
362  for(unsigned i=0; i<3; ++i)
363  {
364  vertex_pointer v = adjacent_vertices()[i];
365  if(!e->belongs(v))
366  {
367  return v;
368  }
369  }
370  FEASSERT(0);
371  return NULL;
372 }
373 
374 inline edge_pointer Face::next_edge(edge_pointer e, vertex_pointer v)
375 {
376  FEASSERT(e->belongs(v));
377 
378  for(unsigned i=0; i<3; ++i)
379  {
380  edge_pointer next = adjacent_edges()[i];
381  if(e->id() != next->id() && next->belongs(v))
382  {
383  return next;
384  }
385  }
386  FEASSERT(0);
387  return NULL;
388 }
389 
390 struct HalfEdge //prototype of the edge; used for mesh construction
391 {
392  unsigned face_id;
393  unsigned vertex_0; //adjacent vertices sorted by id value
394  unsigned vertex_1; //they are sorted, vertex_0 < vertex_1
395 };
396 
397 inline bool operator < (const HalfEdge &x, const HalfEdge &y)
398 {
399  if(x.vertex_0 == y.vertex_0)
400  {
401  return x.vertex_1 < y.vertex_1;
402  }
403  else
404  {
405  return x.vertex_0 < y.vertex_0;
406  }
407 }
408 
409 inline bool operator != (const HalfEdge &x, const HalfEdge &y)
410 {
411  return x.vertex_0 != y.vertex_0 || x.vertex_1 != y.vertex_1;
412 }
413 
414 inline bool operator == (const HalfEdge &x, const HalfEdge &y)
415 {
416  return x.vertex_0 == y.vertex_0 && x.vertex_1 == y.vertex_1;
417 }
418 
419 } //geodesic
420 
421 #endif
Definition: geodesic_cpp_03_02_2008/geodesic_algorithm_base.h:11