BALL  1.4.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
surface.h
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 2; -*-
2 // vi: set ts=2:
3 //
4 
5 #ifndef BALL_MATHS_SURFACE_H
6 #define BALL_MATHS_SURFACE_H
7 
8 #ifndef BALL_MATHS_VECTOR3_H
9 # include <BALL/MATHS/vector3.h>
10 #endif
11 
12 namespace BALL
13 {
19 
26  template <typename T>
27  class TSurface
28  {
29  public:
30 
32 
33 
36 
39  class Triangle
40  {
41  public:
45 
46  bool operator == (const Triangle& triangle) const
47  {
48  return (v1 == triangle.v1) && (v2 == triangle.v2) && (v3 == triangle.v3);
49  }
50 
51 
52  bool operator != (const Triangle& triangle) const
53  {
54  return !(v1 == triangle.v1) && (v2 == triangle.v2) && (v3 == triangle.v3);
55  }
56  };
57 
60 
64 
68 
70  TSurface();
71 
73  TSurface(const TSurface& surface);
74 
76  virtual ~TSurface();
78 
82 
84  void set(const TSurface& surface);
85 
87  TSurface& operator = (const TSurface& surface);
88 
90  void get(TSurface& surface) const;
91 
93  void clear();
94 
100  void readMSMSFile(const String& vert_filename, const String& face_filename);
102 
106 
111  float getArea() const;
112 
114  Size getNumberOfTriangles() const;
115 
117  Size getNumberOfVertices() const;
118 
120  Size getNumberOfNormals() const;
121 
123  Triangle& getTriangle(Position index);
124 
126  const Triangle& getTriangle(Position index) const;
127 
129  void clearTriangles();
130 
132  void resizeTriangles(Size size);
133 
135  void pushBackTriangle(const Triangle& triangle);
136 
138  Vertex& getVertex(Position index);
139 
141  const Vertex& getVertex(Position index) const;
142 
144  void clearVertices();
145 
147  void resizeVertices(Size size);
148 
150  void pushBackVertex(const Vertex& vertex);
151 
153  Normal& getNormal(Position index);
154 
156  const Normal& getNormal(Position index) const;
157 
159  void clearNormals();
160 
162  void resizeNormals(Size size);
163 
165  void pushBackNormal(const Normal& n);
166 
168 
172 
174  bool operator == (const TSurface& surface) const;
175 
177  bool operator != (const TSurface& surface) const;
179 
183 
185  vector<Vertex> vertex;
186 
188  vector<Normal> normal;
189 
191  vector<Triangle> triangle;
193  };
195 
197 #ifdef BALL_COMPILER_MSVC
198  template class BALL_EXPORT TSurface<float>;
199 #endif
200 
201  template <typename T>
203  {
204  }
205 
206  template <typename T>
208  : vertex(surface.vertex),
209  normal(surface.normal),
210  triangle(surface.triangle)
211  {
212  }
213 
214  template <typename T>
216  {
217  }
218 
219  template <typename T>
221  {
222  vertex.clear();
223  normal.clear();
224  triangle.clear();
225  }
226 
227  template <typename T>
228  void TSurface<T>::set(const TSurface<T>& surface)
229  {
230  vertex = surface.vertex;
231  normal = surface.normal;
232  triangle = surface.triangle;
233  }
234 
235  template <typename T>
237  {
238  vertex = surface.vertex;
239  normal = surface.normal;
240  triangle = surface.triangle;
241  return *this;
242  }
243 
244  template <typename T>
245  void TSurface<T>::get(TSurface<T>& surface) const
246  {
247  surface.vertex = vertex;
248  surface.normal = normal;
249  surface.triangle = triangle;
250  }
251 
252  template <typename T>
253  void TSurface<T>::readMSMSFile(const String& vert_filename, const String& face_filename)
254  {
255  // delete old contents
256  normal.clear();
257  vertex.clear();
258  triangle.clear();
259 
260  std::ifstream file(vert_filename.c_str());
261  if (!file)
262  {
263  throw Exception::FileNotFound(__FILE__, __LINE__, vert_filename);
264  }
265 
266  // there are two formats: one with three lines of
267  // header and one without
268  String line;
269  while ((line.countFields() != 9) && file)
270  {
271  line.getline(file);
272  }
273 
274  String s[6];
275  while (file && (line.countFields() == 9))
276  {
277  // read the vertex coordinates and the normal vector
278  line.split(s, 6);
279  vertex.push_back(Vertex(s[0].toFloat(), s[1].toFloat(), s[2].toFloat()));
280  normal.push_back(Normal(s[3].toFloat(), s[4].toFloat(), s[5].toFloat()));
281 
282  // read the next line
283  line.getline(file);
284  }
285  file.close();
286  // workaround for trouble in File
287  file.clear();
288 
289  // now read the faces file:
290  file.open(face_filename.c_str());
291  if (!file)
292  {
293  throw Exception::FileNotFound(__FILE__, __LINE__, face_filename);
294  }
295 
296  // there are two formats: one with three lines of
297  // header and one without
298  while ((line.countFields() != 5) && file)
299  {
300  line.getline(file);
301  }
302 
303  Triangle t;
304  Size number_of_vertices = (Size)vertex.size();
305  while (file && (line.countFields() == 5))
306  {
307  // read the vertex indices
308  line.split(s, 5);
309  t.v1 = (Index)s[0].toInt() - 1;
310  t.v2 = (Index)s[1].toInt() - 1;
311  t.v3 = (Index)s[2].toInt() - 1;
312 
313  // if all three vertex indices are valid, insert the triangle
314  if ((t.v1 < (Index)number_of_vertices) && (t.v1 >= 0)
315  && (t.v1 < (Index)number_of_vertices) && (t.v1 >= 0)
316  && (t.v1 < (Index)number_of_vertices) && (t.v1 >= 0))
317  {
318  triangle.push_back(t);
319  }
320 
321  // read the next line
322  line.getline(file);
323  }
324  file.close();
325  }
326 
327  template <typename T>
328  float TSurface<T>::getArea() const
329  {
330  // add the areas of all triangles
331  double area = 0;
332  for (Size i = 0; i < triangle.size(); i++)
333  {
334  // add the length of the vector products of two sides of each triangle
335  // this is equivalent to the surface area of the parallelogram, and thus to twice the triangle area
336  area += ((vertex[triangle[i].v2] - vertex[triangle[i].v1]) % (vertex[triangle[i].v3] - vertex[triangle[i].v1])).getLength();
337  }
338 
339  // A = 1/2 \sum |r1 x r2|
340  return (float)( area * 0.5 );
341  }
342 
343  template <typename T>
344  bool TSurface<T>::operator == (const TSurface<T>& surface) const
345  {
346  return ((surface.vertex == vertex)
347  && (surface.normal == normal)
348  && (surface.triangle == triangle));
349  }
350 
351  template <typename T>
354  {
355  return (Size)triangle.size();
356  }
357 
358  template <typename T>
361  {
362  return (Size)vertex.size();
363  }
364 
365  template <typename T>
368  {
369  return (Size)normal.size();
370  }
371 
372  template <typename T>
375  {
376  return triangle[index];
377  }
378 
379  template <typename T>
382  {
383  return triangle[index];
384  }
385 
386  template <typename T>
389  {
390  triangle.clear();
391  }
392 
393  template <typename T>
396  {
397  triangle.resize(size);
398  }
399 
400  template <typename T>
403  {
404  triangle.push_back(t);
405  }
406 
407 
408  template <typename T>
411  {
412  return vertex[index];
413  }
414 
415  template <typename T>
418  {
419  return vertex[index];
420  }
421 
422  template <typename T>
425  {
426  vertex.clear();
427  }
428 
429  template <typename T>
432  {
433  vertex.resize(size);
434  }
435 
436 
437  template <typename T>
439  void TSurface<T>::pushBackVertex(const typename TSurface<T>::Vertex& position)
440  {
441  vertex.push_back(position);
442  }
443 
444  template <typename T>
447  {
448  return normal[index];
449  }
450 
451  template <typename T>
454  {
455  return normal[index];
456  }
457 
458  template <typename T>
461  {
462  normal.clear();
463  }
464 
465  template <typename T>
468  {
469  normal.resize(size);
470  }
471 
472  template <typename T>
475  {
476  normal.push_back(n);
477  }
478 
479  template <typename T>
480  bool TSurface<T>::operator != (const TSurface<T>& surface) const
481  {
482  return !(*this == surface);
483  }
484 
489 
490 } // namespace BALL
491 
492 #endif // BALL_MATHS_SURFACE_H