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 {
14     /** \defgroup GeometricSurface Surface in three-dimensional space.
15 
16             \ingroup GeometricObjects
17      */
18     //@{
19 
20     /**	Generic Three-dimensional Surface class.
21             This class describes a three-dimensional triangulated surface.
22             Each triangle is represented by three indices to vertices (as
23             described by the  \link TSurface::Triangle TSurface::Triangle \endlink ). Each of the vertices has
24             a position and possibly a normal vector associated.
25     */
26     template <typename T>
27     class TSurface
28     {
29         public:
30 
BALL_CREATE(TSurface)31         BALL_CREATE(TSurface)
32 
33         /**	@name	Type definitions
34         */
35         //@{
36 
37         /**
38         */
39         class Triangle
40         {
41             public:
42                 Index	v1;
43                 Index	v2;
44                 Index	v3;
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 
58         /// A vertex
59         typedef TVector3<T> Vertex;
60 
61         /// A normal
62         typedef TVector3<T> Normal;
63         //@}
64 
65         /**	@name	Constructors and Destructors
66         */
67         //@{
68 
69         ///
70         TSurface();
71 
72         ///
73         TSurface(const TSurface& surface);
74 
75         ///
76         virtual ~TSurface();
77         //@}
78 
79         /**	@name	Assignment
80         */
81         //@{
82 
83         ///
84         void set(const TSurface& surface);
85 
86         ///
87         TSurface& operator = (const TSurface& surface);
88 
89         ///
90         void get(TSurface& surface) const;
91 
92         ///
93         void clear();
94 
95         /**	Read from MSMS file.
96          * 	Read the contents of the vertex and faces file created by Michael
97          *	Sanners software MSMS.
98          *  @throw Exception::FileNotFound if the file could not be opened
99          */
100         //void readMSMSFile(const String& vert_filename, const String& face_filename);
101         //@}
102 
103         /**	@name	Accessors
104         */
105         //@{
106 
107         /** Compute the surface area.
108                 The area is computed as the sum of the areas of all
109                 triangles.
110         */
111         float getArea() const;
112 
113         /// Return the number of triangles
114         Size getNumberOfTriangles() const;
115 
116         /// Return the number of vertices
117         Size getNumberOfVertices() const;
118 
119         /// Return the number of normals
120         Size getNumberOfNormals() const;
121 
122         /// Return a triangle with a given index
123         Triangle& getTriangle(Position index);
124 
125         /// Return a triangle with a given index
126         const Triangle& getTriangle(Position index) const;
127 
128         /// Clear all triangles
129         void clearTriangles();
130 
131         /// Resize the triangle array
132         void resizeTriangles(Size size);
133 
134         /// Add a triangle
135         void pushBackTriangle(const Triangle& triangle);
136 
137         /// Return the position of a vertex
138         Vertex& getVertex(Position index);
139 
140         /// Return the position of a vertex
141         const Vertex& getVertex(Position index) const;
142 
143         /// Clear all vertices
144         void clearVertices();
145 
146         /// Resize the vertex array
147         void resizeVertices(Size size);
148 
149         /// Add a vertex
150         void pushBackVertex(const Vertex& vertex);
151 
152         /// Return the position of a normal
153         Normal& getNormal(Position index);
154 
155         /// Return the position of a normal
156         const Normal& getNormal(Position index) const;
157 
158         /// Clear all normals
159         void clearNormals();
160 
161         /// Resize the normal array
162         void resizeNormals(Size size);
163 
164         /// Add a normal
165         void pushBackNormal(const Normal& n);
166 
167         //@}
168 
169         /**	@name	Predicates
170         */
171         //@{
172 
173         ///
174         bool operator == (const TSurface& surface) const;
175 
176         ///
177         bool operator != (const TSurface& surface) const;
178         //@}
179 
180         /**	@name	Attributes
181         */
182         //@{
183 
184         /// the vertices
185         vector<Vertex>		vertex;
186 
187         /// the normals for each vertex
188         vector<Normal>		normal;
189 
190         /// the triangles
191         vector<Triangle>	triangle;
192         //@}
193     };
194     //@}
195 
196     /** This is required for windows dlls **/
197 #ifdef BALL_COMPILER_MSVC
198     template class BALL_EXPORT TSurface<float>;
199 #endif
200 
201     template <typename T>
TSurface()202     TSurface<T>::TSurface()
203     {
204     }
205 
206     template <typename T>
TSurface(const TSurface<T> & surface)207     TSurface<T>::TSurface(const TSurface<T>& surface)
208         :	vertex(surface.vertex),
209             normal(surface.normal),
210             triangle(surface.triangle)
211     {
212     }
213 
214     template <typename T>
~TSurface()215     TSurface<T>::~TSurface()
216     {
217     }
218 
219     template <typename T>
clear()220     void TSurface<T>::clear()
221     {
222         vertex.clear();
223         normal.clear();
224         triangle.clear();
225     }
226 
227     template <typename T>
set(const TSurface<T> & surface)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>
236     TSurface<T>& TSurface<T>::operator = (const TSurface<T>& surface)
237     {
238         vertex = surface.vertex;
239         normal = surface.normal;
240         triangle = surface.triangle;
241         return *this;
242     }
243 
244     template <typename T>
get(TSurface<T> & surface)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     /*
253     template <typename T>
254     void TSurface<T>::readMSMSFile(const String& vert_filename, const String& face_filename)
255     {
256         // delete old contents
257         normal.clear();
258         vertex.clear();
259         triangle.clear();
260 
261         std::ifstream file(vert_filename.c_str());
262         if (!file)
263         {
264             throw Exception::FileNotFound(__FILE__, __LINE__, vert_filename);
265         }
266 
267         // there are two formats: one with three lines of
268         // header and one without
269         String line;
270         while ((line.countFields() != 9) && file)
271         {
272             line.getline(file);
273         }
274 
275         String s[6];
276         while (file && (line.countFields() == 9))
277         {
278             // read the vertex coordinates and the normal vector
279             line.split(s, 6);
280             vertex.push_back(Vertex(s[0].toFloat(), s[1].toFloat(), s[2].toFloat()));
281             normal.push_back(Normal(s[3].toFloat(), s[4].toFloat(), s[5].toFloat()));
282 
283             // read the next line
284             line.getline(file);
285         }
286         file.close();
287         // workaround for trouble in File
288         file.clear();
289 
290         // now read the faces file:
291         file.open(face_filename.c_str());
292         if (!file)
293         {
294             throw Exception::FileNotFound(__FILE__, __LINE__, face_filename);
295         }
296 
297         // there are two formats: one with three lines of
298         // header and one without
299         while ((line.countFields() != 5) && file)
300         {
301             line.getline(file);
302         }
303 
304         Triangle t;
305         Size number_of_vertices = (Size)vertex.size();
306         while (file && (line.countFields() == 5))
307         {
308             // read the vertex indices
309             line.split(s, 5);
310             t.v1 = (Index)s[0].toInt() - 1;
311             t.v2 = (Index)s[1].toInt() - 1;
312             t.v3 = (Index)s[2].toInt() - 1;
313 
314             // if all three vertex indices are valid, insert the triangle
315             if ((t.v1 < (Index)number_of_vertices) && (t.v1 >= 0)
316                     && (t.v1 < (Index)number_of_vertices) && (t.v1 >= 0)
317                     && (t.v1 < (Index)number_of_vertices) && (t.v1 >= 0))
318             {
319                 triangle.push_back(t);
320             }
321 
322             // read the next line
323             line.getline(file);
324         }
325         file.close();
326     }
327     */
328 
329     template <typename T>
getArea()330     float TSurface<T>::getArea() const
331     {
332         // add the areas of all triangles
333         double area = 0;
334         for (Size i = 0; i < triangle.size(); i++)
335         {
336             // add the length of the vector products of two sides of each triangle
337             // this is equivalent to the surface area of the parallelogram, and thus to twice the triangle area
338             area += ((vertex[triangle[i].v2] - vertex[triangle[i].v1]) % (vertex[triangle[i].v3] - vertex[triangle[i].v1])).getLength();
339         }
340 
341         // A = 1/2 \sum |r1 x r2|
342         return (float)( area * 0.5 );
343     }
344 
345     template <typename T>
346     bool TSurface<T>::operator == (const TSurface<T>& surface) const
347     {
348         return ((surface.vertex == vertex)
349                         && (surface.normal == normal)
350                         && (surface.triangle == triangle));
351     }
352 
353     template <typename T>
354     BALL_INLINE
getNumberOfTriangles()355     Size TSurface<T>::getNumberOfTriangles() const
356     {
357         return (Size)triangle.size();
358     }
359 
360     template <typename T>
361     BALL_INLINE
getNumberOfVertices()362     Size TSurface<T>::getNumberOfVertices() const
363     {
364         return (Size)vertex.size();
365     }
366 
367     template <typename T>
368     BALL_INLINE
getNumberOfNormals()369     Size TSurface<T>::getNumberOfNormals() const
370     {
371         return (Size)normal.size();
372     }
373 
374     template <typename T>
375     BALL_INLINE
getTriangle(Position index)376     typename TSurface<T>::Triangle& TSurface<T>::getTriangle(Position index)
377     {
378         return triangle[index];
379     }
380 
381     template <typename T>
382     BALL_INLINE
getTriangle(Position index)383     const typename TSurface<T>::Triangle& TSurface<T>::getTriangle(Position index) const
384     {
385         return triangle[index];
386     }
387 
388     template <typename T>
389     BALL_INLINE
clearTriangles()390     void TSurface<T>::clearTriangles()
391     {
392         triangle.clear();
393     }
394 
395     template <typename T>
396     BALL_INLINE
resizeTriangles(Size size)397     void TSurface<T>::resizeTriangles(Size size)
398     {
399         triangle.resize(size);
400     }
401 
402     template <typename T>
403     BALL_INLINE
pushBackTriangle(const Triangle & t)404     void TSurface<T>::pushBackTriangle(const Triangle& t)
405     {
406         triangle.push_back(t);
407     }
408 
409 
410     template <typename T>
411     BALL_INLINE
getVertex(Position index)412     typename TSurface<T>::Vertex& TSurface<T>::getVertex(Position index)
413     {
414         return vertex[index];
415     }
416 
417     template <typename T>
418     BALL_INLINE
getVertex(Position index)419     const typename TSurface<T>::Vertex& TSurface<T>::getVertex(Position index) const
420     {
421         return vertex[index];
422     }
423 
424     template <typename T>
425     BALL_INLINE
clearVertices()426     void TSurface<T>::clearVertices()
427     {
428         vertex.clear();
429     }
430 
431     template <typename T>
432     BALL_INLINE
resizeVertices(Size size)433     void TSurface<T>::resizeVertices(Size size)
434     {
435         vertex.resize(size);
436     }
437 
438 
439     template <typename T>
440     BALL_INLINE
pushBackVertex(const typename TSurface<T>::Vertex & position)441     void TSurface<T>::pushBackVertex(const typename TSurface<T>::Vertex& position)
442     {
443         vertex.push_back(position);
444     }
445 
446     template <typename T>
447     BALL_INLINE
getNormal(Position index)448     typename TSurface<T>::Normal& TSurface<T>::getNormal(Position index)
449     {
450         return normal[index];
451     }
452 
453     template <typename T>
454     BALL_INLINE
getNormal(Position index)455     const typename TSurface<T>::Normal& TSurface<T>::getNormal(Position index) const
456     {
457         return normal[index];
458     }
459 
460     template <typename T>
461     BALL_INLINE
clearNormals()462     void TSurface<T>::clearNormals()
463     {
464         normal.clear();
465     }
466 
467     template <typename T>
468     BALL_INLINE
resizeNormals(Size size)469     void TSurface<T>::resizeNormals(Size size)
470     {
471         normal.resize(size);
472     }
473 
474     template <typename T>
475     BALL_INLINE
pushBackNormal(const typename TSurface<T>::Normal & n)476     void TSurface<T>::pushBackNormal(const typename TSurface<T>::Normal& n)
477     {
478         normal.push_back(n);
479     }
480 
481     template <typename T>
482     bool TSurface<T>::operator != (const TSurface<T>& surface) const
483     {
484         return !(*this == surface);
485     }
486 
487     /**	Default surface type.
488             \ingroup GeometricSurface
489     */
490     typedef TSurface<float> Surface;
491 
492 } // namespace BALL
493 
494 #endif // BALL_MATHS_SURFACE_H
495