readMESH.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "readMESH.h"
  9. #include <Eigen/Core>
  10. template <typename DerivedV, typename DerivedF, typename DerivedT>
  11. IGL_INLINE bool igl::readMESH(
  12. const std::string mesh_file_name,
  13. Eigen::PlainObjectBase<DerivedV>& V,
  14. Eigen::PlainObjectBase<DerivedT>& T,
  15. Eigen::PlainObjectBase<DerivedF>& F)
  16. {
  17. FILE * mesh_file = fopen(mesh_file_name.c_str(),"r");
  18. if(NULL==mesh_file)
  19. {
  20. fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
  21. return false;
  22. }
  23. return readMESH(mesh_file,V,T,F);
  24. }
  25. template <typename DerivedV, typename DerivedF, typename DerivedT>
  26. IGL_INLINE bool igl::readMESH(
  27. FILE * mesh_file,
  28. Eigen::PlainObjectBase<DerivedV>& V,
  29. Eigen::PlainObjectBase<DerivedT>& T,
  30. Eigen::PlainObjectBase<DerivedF>& F)
  31. {
  32. #ifndef LINE_MAX
  33. # define LINE_MAX 2048
  34. #endif
  35. char line[LINE_MAX];
  36. // eat comments at beginning of file
  37. const auto eat_comments = [&]()->bool
  38. {
  39. bool still_comments= true;
  40. bool has_line = false;
  41. const auto is_comment_line = [&](char * line)->bool
  42. {
  43. if(line[0] == '#' || line[0] == '\n' || line[0] == '\r')
  44. {
  45. return true;
  46. }
  47. // or if line is all whitespace
  48. for(int i = 0;i<LINE_MAX;i++)
  49. {
  50. if(line[i] == '\0')
  51. {
  52. return true;
  53. }
  54. if(!isspace(line[i]))
  55. {
  56. return false;
  57. }
  58. }
  59. return false;
  60. };
  61. while(still_comments)
  62. {
  63. has_line = fgets(line,LINE_MAX,mesh_file) != NULL;
  64. still_comments = has_line && is_comment_line(line);
  65. }
  66. return has_line;
  67. };
  68. eat_comments();
  69. char str[LINE_MAX];
  70. sscanf(line," %s",str);
  71. // check that first word is MeshVersionFormatted
  72. if(0!=strcmp(str,"MeshVersionFormatted"))
  73. {
  74. fprintf(stderr,
  75. "Error: first word should be MeshVersionFormatted not %s\n",str);
  76. fclose(mesh_file);
  77. return false;
  78. }
  79. int version = -1;
  80. if(2 != sscanf(line,"%s %d",str,&version)) { fscanf(mesh_file," %d",&version); }
  81. if(version != 1 && version != 2)
  82. {
  83. fprintf(stderr,"Error: second word should be 1 or 2 not %d\n",version);
  84. fclose(mesh_file);
  85. return false;
  86. }
  87. while(eat_comments())
  88. {
  89. sscanf(line," %s",str);
  90. int extra;
  91. // check that third word is Dimension
  92. if(0==strcmp(str,"Dimension"))
  93. {
  94. int three = -1;
  95. if(2 != sscanf(line,"%s %d",str,&three))
  96. {
  97. // 1 appears on next line?
  98. fscanf(mesh_file," %d",&three);
  99. }
  100. if(three != 3)
  101. {
  102. fprintf(stderr,"Error: only Dimension 3 supported not %d\n",three);
  103. fclose(mesh_file);
  104. return false;
  105. }
  106. }else if(0==strcmp(str,"Vertices"))
  107. {
  108. int number_of_vertices;
  109. if(1 != fscanf(mesh_file," %d",&number_of_vertices) || number_of_vertices > 1000000000)
  110. {
  111. fprintf(stderr,"Error: expecting number of vertices less than 10^9...\n");
  112. fclose(mesh_file);
  113. return false;
  114. }
  115. // allocate space for vertices
  116. V.resize(number_of_vertices,3);
  117. for(int i = 0;i<number_of_vertices;i++)
  118. {
  119. double x,y,z;
  120. if(4 != fscanf(mesh_file," %lg %lg %lg %d",&x,&y,&z,&extra))
  121. {
  122. fprintf(stderr,"Error: expecting vertex position...\n");
  123. fclose(mesh_file);
  124. return false;
  125. }
  126. V(i,0) = x;
  127. V(i,1) = y;
  128. V(i,2) = z;
  129. }
  130. }else if(0==strcmp(str,"Triangles"))
  131. {
  132. int number_of_triangles;
  133. if(1 != fscanf(mesh_file," %d",&number_of_triangles))
  134. {
  135. fprintf(stderr,"Error: expecting number of triangles...\n");
  136. fclose(mesh_file);
  137. return false;
  138. }
  139. // allocate space for triangles
  140. F.resize(number_of_triangles,3);
  141. // triangle indices
  142. int tri[3];
  143. for(int i = 0;i<number_of_triangles;i++)
  144. {
  145. if(4 != fscanf(mesh_file," %d %d %d %d",&tri[0],&tri[1],&tri[2],&extra))
  146. {
  147. printf("Error: expecting triangle indices...\n");
  148. return false;
  149. }
  150. for(int j = 0;j<3;j++)
  151. {
  152. F(i,j) = tri[j]-1;
  153. }
  154. }
  155. }else if(0==strcmp(str,"Tetrahedra"))
  156. {
  157. int number_of_tetrahedra;
  158. if(1 != fscanf(mesh_file," %d",&number_of_tetrahedra))
  159. {
  160. fprintf(stderr,"Error: expecting number of tetrahedra...\n");
  161. fclose(mesh_file);
  162. return false;
  163. }
  164. // allocate space for tetrahedra
  165. T.resize(number_of_tetrahedra,4);
  166. // tet indices
  167. int a,b,c,d;
  168. for(int i = 0;i<number_of_tetrahedra;i++)
  169. {
  170. if(5 != fscanf(mesh_file," %d %d %d %d %d",&a,&b,&c,&d,&extra))
  171. {
  172. fprintf(stderr,"Error: expecting tetrahedra indices...\n");
  173. fclose(mesh_file);
  174. return false;
  175. }
  176. T(i,0) = a-1;
  177. T(i,1) = b-1;
  178. T(i,2) = c-1;
  179. T(i,3) = d-1;
  180. }
  181. }else if(0==strcmp(str,"Edges"))
  182. {
  183. int number_of_edges;
  184. if(1 != fscanf(mesh_file," %d",&number_of_edges))
  185. {
  186. fprintf(stderr,"Error: expecting number of edges...\n");
  187. fclose(mesh_file);
  188. return false;
  189. }
  190. // allocate space for tetrahedra
  191. Eigen::MatrixXi E(number_of_edges,2);
  192. // tet indices
  193. int a,b;
  194. for(int i = 0;i<number_of_edges;i++)
  195. {
  196. if(3 != fscanf(mesh_file," %d %d %d",&a,&b,&extra))
  197. {
  198. fprintf(stderr,"Error: expecting tetrahedra indices...\n");
  199. fclose(mesh_file);
  200. return false;
  201. }
  202. E(i,0) = a-1;
  203. E(i,1) = b-1;
  204. }
  205. }else if(0==strcmp(str,"End"))
  206. {
  207. break;
  208. }else
  209. {
  210. fprintf(stderr,"Error: expecting "
  211. "Dimension|Triangles|Vertices|Tetrahedra|Edges instead of %s...\n",str);
  212. fclose(mesh_file);
  213. return false;
  214. }
  215. }
  216. fclose(mesh_file);
  217. return true;
  218. }
  219. #ifdef IGL_STATIC_LIBRARY
  220. // Explicit template instantiation
  221. // generated by autoexplicit.sh
  222. template bool igl::readMESH<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  223. template bool igl::readMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  224. template bool igl::readMESH<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  225. template bool igl::readMESH<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  226. template bool igl::readMESH<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  227. template bool igl::readMESH<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  228. template bool igl::readMESH<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  229. template bool igl::readMESH<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  230. template bool igl::readMESH<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  231. template bool igl::readMESH<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
  232. #endif