BALL
1.4.1
|
00001 // -*- Mode: C++; tab-width: 2; -*- 00002 // vi: set ts=2: 00003 // 00004 00005 #ifndef BALL_MATHS_SURFACE_H 00006 #define BALL_MATHS_SURFACE_H 00007 00008 #ifndef BALL_MATHS_VECTOR3_H 00009 # include <BALL/MATHS/vector3.h> 00010 #endif 00011 00012 namespace BALL 00013 { 00019 00026 template <typename T> 00027 class TSurface 00028 { 00029 public: 00030 00031 BALL_CREATE(TSurface) 00032 00033 00036 00039 class Triangle 00040 { 00041 public: 00042 Index v1; 00043 Index v2; 00044 Index v3; 00045 00046 bool operator == (const Triangle& triangle) const 00047 { 00048 return (v1 == triangle.v1) && (v2 == triangle.v2) && (v3 == triangle.v3); 00049 } 00050 00051 00052 bool operator != (const Triangle& triangle) const 00053 { 00054 return !(v1 == triangle.v1) && (v2 == triangle.v2) && (v3 == triangle.v3); 00055 } 00056 }; 00057 00059 typedef TVector3<T> Vertex; 00060 00062 typedef TVector3<T> Normal; 00064 00068 00070 TSurface(); 00071 00073 TSurface(const TSurface& surface); 00074 00076 virtual ~TSurface(); 00078 00082 00084 void set(const TSurface& surface); 00085 00087 TSurface& operator = (const TSurface& surface); 00088 00090 void get(TSurface& surface) const; 00091 00093 void clear(); 00094 00100 void readMSMSFile(const String& vert_filename, const String& face_filename); 00102 00106 00111 float getArea() const; 00112 00114 Size getNumberOfTriangles() const; 00115 00117 Size getNumberOfVertices() const; 00118 00120 Size getNumberOfNormals() const; 00121 00123 Triangle& getTriangle(Position index); 00124 00126 const Triangle& getTriangle(Position index) const; 00127 00129 void clearTriangles(); 00130 00132 void resizeTriangles(Size size); 00133 00135 void pushBackTriangle(const Triangle& triangle); 00136 00138 Vertex& getVertex(Position index); 00139 00141 const Vertex& getVertex(Position index) const; 00142 00144 void clearVertices(); 00145 00147 void resizeVertices(Size size); 00148 00150 void pushBackVertex(const Vertex& vertex); 00151 00153 Normal& getNormal(Position index); 00154 00156 const Normal& getNormal(Position index) const; 00157 00159 void clearNormals(); 00160 00162 void resizeNormals(Size size); 00163 00165 void pushBackNormal(const Normal& n); 00166 00168 00172 00174 bool operator == (const TSurface& surface) const; 00175 00177 bool operator != (const TSurface& surface) const; 00179 00183 00185 vector<Vertex> vertex; 00186 00188 vector<Normal> normal; 00189 00191 vector<Triangle> triangle; 00193 }; 00195 00197 #ifdef BALL_COMPILER_MSVC 00198 template class BALL_EXPORT TSurface<float>; 00199 #endif 00200 00201 template <typename T> 00202 TSurface<T>::TSurface() 00203 { 00204 } 00205 00206 template <typename T> 00207 TSurface<T>::TSurface(const TSurface<T>& surface) 00208 : vertex(surface.vertex), 00209 normal(surface.normal), 00210 triangle(surface.triangle) 00211 { 00212 } 00213 00214 template <typename T> 00215 TSurface<T>::~TSurface() 00216 { 00217 } 00218 00219 template <typename T> 00220 void TSurface<T>::clear() 00221 { 00222 vertex.clear(); 00223 normal.clear(); 00224 triangle.clear(); 00225 } 00226 00227 template <typename T> 00228 void TSurface<T>::set(const TSurface<T>& surface) 00229 { 00230 vertex = surface.vertex; 00231 normal = surface.normal; 00232 triangle = surface.triangle; 00233 } 00234 00235 template <typename T> 00236 TSurface<T>& TSurface<T>::operator = (const TSurface<T>& surface) 00237 { 00238 vertex = surface.vertex; 00239 normal = surface.normal; 00240 triangle = surface.triangle; 00241 return *this; 00242 } 00243 00244 template <typename T> 00245 void TSurface<T>::get(TSurface<T>& surface) const 00246 { 00247 surface.vertex = vertex; 00248 surface.normal = normal; 00249 surface.triangle = triangle; 00250 } 00251 00252 template <typename T> 00253 void TSurface<T>::readMSMSFile(const String& vert_filename, const String& face_filename) 00254 { 00255 // delete old contents 00256 normal.clear(); 00257 vertex.clear(); 00258 triangle.clear(); 00259 00260 std::ifstream file(vert_filename.c_str()); 00261 if (!file) 00262 { 00263 throw Exception::FileNotFound(__FILE__, __LINE__, vert_filename); 00264 } 00265 00266 // there are two formats: one with three lines of 00267 // header and one without 00268 String line; 00269 while ((line.countFields() != 9) && file) 00270 { 00271 line.getline(file); 00272 } 00273 00274 String s[6]; 00275 while (file && (line.countFields() == 9)) 00276 { 00277 // read the vertex coordinates and the normal vector 00278 line.split(s, 6); 00279 vertex.push_back(Vertex(s[0].toFloat(), s[1].toFloat(), s[2].toFloat())); 00280 normal.push_back(Normal(s[3].toFloat(), s[4].toFloat(), s[5].toFloat())); 00281 00282 // read the next line 00283 line.getline(file); 00284 } 00285 file.close(); 00286 // workaround for trouble in File 00287 file.clear(); 00288 00289 // now read the faces file: 00290 file.open(face_filename.c_str()); 00291 if (!file) 00292 { 00293 throw Exception::FileNotFound(__FILE__, __LINE__, face_filename); 00294 } 00295 00296 // there are two formats: one with three lines of 00297 // header and one without 00298 while ((line.countFields() != 5) && file) 00299 { 00300 line.getline(file); 00301 } 00302 00303 Triangle t; 00304 Size number_of_vertices = (Size)vertex.size(); 00305 while (file && (line.countFields() == 5)) 00306 { 00307 // read the vertex indices 00308 line.split(s, 5); 00309 t.v1 = (Index)s[0].toInt() - 1; 00310 t.v2 = (Index)s[1].toInt() - 1; 00311 t.v3 = (Index)s[2].toInt() - 1; 00312 00313 // if all three vertex indices are valid, insert the triangle 00314 if ((t.v1 < (Index)number_of_vertices) && (t.v1 >= 0) 00315 && (t.v1 < (Index)number_of_vertices) && (t.v1 >= 0) 00316 && (t.v1 < (Index)number_of_vertices) && (t.v1 >= 0)) 00317 { 00318 triangle.push_back(t); 00319 } 00320 00321 // read the next line 00322 line.getline(file); 00323 } 00324 file.close(); 00325 } 00326 00327 template <typename T> 00328 float TSurface<T>::getArea() const 00329 { 00330 // add the areas of all triangles 00331 double area = 0; 00332 for (Size i = 0; i < triangle.size(); i++) 00333 { 00334 // add the length of the vector products of two sides of each triangle 00335 // this is equivalent to the surface area of the parallelogram, and thus to twice the triangle area 00336 area += ((vertex[triangle[i].v2] - vertex[triangle[i].v1]) % (vertex[triangle[i].v3] - vertex[triangle[i].v1])).getLength(); 00337 } 00338 00339 // A = 1/2 \sum |r1 x r2| 00340 return (float)( area * 0.5 ); 00341 } 00342 00343 template <typename T> 00344 bool TSurface<T>::operator == (const TSurface<T>& surface) const 00345 { 00346 return ((surface.vertex == vertex) 00347 && (surface.normal == normal) 00348 && (surface.triangle == triangle)); 00349 } 00350 00351 template <typename T> 00352 BALL_INLINE 00353 Size TSurface<T>::getNumberOfTriangles() const 00354 { 00355 return (Size)triangle.size(); 00356 } 00357 00358 template <typename T> 00359 BALL_INLINE 00360 Size TSurface<T>::getNumberOfVertices() const 00361 { 00362 return (Size)vertex.size(); 00363 } 00364 00365 template <typename T> 00366 BALL_INLINE 00367 Size TSurface<T>::getNumberOfNormals() const 00368 { 00369 return (Size)normal.size(); 00370 } 00371 00372 template <typename T> 00373 BALL_INLINE 00374 typename TSurface<T>::Triangle& TSurface<T>::getTriangle(Position index) 00375 { 00376 return triangle[index]; 00377 } 00378 00379 template <typename T> 00380 BALL_INLINE 00381 const typename TSurface<T>::Triangle& TSurface<T>::getTriangle(Position index) const 00382 { 00383 return triangle[index]; 00384 } 00385 00386 template <typename T> 00387 BALL_INLINE 00388 void TSurface<T>::clearTriangles() 00389 { 00390 triangle.clear(); 00391 } 00392 00393 template <typename T> 00394 BALL_INLINE 00395 void TSurface<T>::resizeTriangles(Size size) 00396 { 00397 triangle.resize(size); 00398 } 00399 00400 template <typename T> 00401 BALL_INLINE 00402 void TSurface<T>::pushBackTriangle(const Triangle& t) 00403 { 00404 triangle.push_back(t); 00405 } 00406 00407 00408 template <typename T> 00409 BALL_INLINE 00410 typename TSurface<T>::Vertex& TSurface<T>::getVertex(Position index) 00411 { 00412 return vertex[index]; 00413 } 00414 00415 template <typename T> 00416 BALL_INLINE 00417 const typename TSurface<T>::Vertex& TSurface<T>::getVertex(Position index) const 00418 { 00419 return vertex[index]; 00420 } 00421 00422 template <typename T> 00423 BALL_INLINE 00424 void TSurface<T>::clearVertices() 00425 { 00426 vertex.clear(); 00427 } 00428 00429 template <typename T> 00430 BALL_INLINE 00431 void TSurface<T>::resizeVertices(Size size) 00432 { 00433 vertex.resize(size); 00434 } 00435 00436 00437 template <typename T> 00438 BALL_INLINE 00439 void TSurface<T>::pushBackVertex(const typename TSurface<T>::Vertex& position) 00440 { 00441 vertex.push_back(position); 00442 } 00443 00444 template <typename T> 00445 BALL_INLINE 00446 typename TSurface<T>::Normal& TSurface<T>::getNormal(Position index) 00447 { 00448 return normal[index]; 00449 } 00450 00451 template <typename T> 00452 BALL_INLINE 00453 const typename TSurface<T>::Normal& TSurface<T>::getNormal(Position index) const 00454 { 00455 return normal[index]; 00456 } 00457 00458 template <typename T> 00459 BALL_INLINE 00460 void TSurface<T>::clearNormals() 00461 { 00462 normal.clear(); 00463 } 00464 00465 template <typename T> 00466 BALL_INLINE 00467 void TSurface<T>::resizeNormals(Size size) 00468 { 00469 normal.resize(size); 00470 } 00471 00472 template <typename T> 00473 BALL_INLINE 00474 void TSurface<T>::pushBackNormal(const typename TSurface<T>::Normal& n) 00475 { 00476 normal.push_back(n); 00477 } 00478 00479 template <typename T> 00480 bool TSurface<T>::operator != (const TSurface<T>& surface) const 00481 { 00482 return !(*this == surface); 00483 } 00484 00488 typedef TSurface<float> Surface; 00489 00490 } // namespace BALL 00491 00492 #endif // BALL_MATHS_SURFACE_H