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