readMESH.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  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 <cstdio>
  10. #include "verbose.h"
  11. template <typename Scalar, typename Index>
  12. IGL_INLINE bool igl::readMESH(
  13. const std::string mesh_file_name,
  14. std::vector<std::vector<Scalar > > & V,
  15. std::vector<std::vector<Index > > & T,
  16. std::vector<std::vector<Index > > & F)
  17. {
  18. using namespace std;
  19. using namespace igl;
  20. FILE * mesh_file = fopen(mesh_file_name.c_str(),"r");
  21. if(NULL==mesh_file)
  22. {
  23. fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
  24. return false;
  25. }
  26. #ifndef LINE_MAX
  27. # define LINE_MAX 2048
  28. #endif
  29. char line[LINE_MAX];
  30. bool still_comments;
  31. V.clear();
  32. T.clear();
  33. F.clear();
  34. // eat comments at beginning of file
  35. still_comments= true;
  36. while(still_comments)
  37. {
  38. fgets(line,LINE_MAX,mesh_file);
  39. still_comments = (line[0] == '#' || line[0] == '\n');
  40. }
  41. char str[LINE_MAX];
  42. sscanf(line," %s",str);
  43. // check that first word is MeshVersionFormatted
  44. if(0!=strcmp(str,"MeshVersionFormatted"))
  45. {
  46. fprintf(stderr,
  47. "Error: first word should be MeshVersionFormatted not %s\n",str);
  48. fclose(mesh_file);
  49. return false;
  50. }
  51. int one = -1;
  52. if(2 != sscanf(line,"%s %d",str,&one))
  53. {
  54. // 1 appears on next line?
  55. fscanf(mesh_file," %d",&one);
  56. }
  57. if(one != 1)
  58. {
  59. fprintf(stderr,"Error: second word should be 1 not %d\n",one);
  60. fclose(mesh_file);
  61. return false;
  62. }
  63. // eat comments
  64. still_comments= true;
  65. while(still_comments)
  66. {
  67. fgets(line,LINE_MAX,mesh_file);
  68. still_comments = (line[0] == '#' || line[0] == '\n');
  69. }
  70. sscanf(line," %s",str);
  71. // check that third word is Dimension
  72. if(0!=strcmp(str,"Dimension"))
  73. {
  74. fprintf(stderr,"Error: third word should be Dimension not %s\n",str);
  75. fclose(mesh_file);
  76. return false;
  77. }
  78. int three = -1;
  79. if(2 != sscanf(line,"%s %d",str,&three))
  80. {
  81. // 1 appears on next line?
  82. fscanf(mesh_file," %d",&three);
  83. }
  84. if(three != 3)
  85. {
  86. fprintf(stderr,"Error: only Dimension 3 supported not %d\n",three);
  87. fclose(mesh_file);
  88. return false;
  89. }
  90. // eat comments
  91. still_comments= true;
  92. while(still_comments)
  93. {
  94. fgets(line,LINE_MAX,mesh_file);
  95. still_comments = (line[0] == '#' || line[0] == '\n');
  96. }
  97. sscanf(line," %s",str);
  98. // check that fifth word is Vertices
  99. if(0!=strcmp(str,"Vertices"))
  100. {
  101. fprintf(stderr,"Error: fifth word should be Vertices not %s\n",str);
  102. fclose(mesh_file);
  103. return false;
  104. }
  105. //fgets(line,LINE_MAX,mesh_file);
  106. int number_of_vertices;
  107. if(1 != fscanf(mesh_file," %d",&number_of_vertices) || number_of_vertices > 1000000000)
  108. {
  109. fprintf(stderr,"Error: expecting number of vertices less than 10^9...\n");
  110. fclose(mesh_file);
  111. return false;
  112. }
  113. // allocate space for vertices
  114. V.resize(number_of_vertices,vector<Scalar>(3,0));
  115. int extra;
  116. for(int i = 0;i<number_of_vertices;i++)
  117. {
  118. double x,y,z;
  119. if(4 != fscanf(mesh_file," %lg %lg %lg %d",&x,&y,&z,&extra))
  120. {
  121. fprintf(stderr,"Error: expecting vertex position...\n");
  122. fclose(mesh_file);
  123. return false;
  124. }
  125. V[i][0] = x;
  126. V[i][1] = y;
  127. V[i][2] = z;
  128. }
  129. // eat comments
  130. still_comments= true;
  131. while(still_comments)
  132. {
  133. fgets(line,LINE_MAX,mesh_file);
  134. still_comments = (line[0] == '#' || line[0] == '\n');
  135. }
  136. sscanf(line," %s",str);
  137. // check that sixth word is Triangles
  138. if(0!=strcmp(str,"Triangles"))
  139. {
  140. fprintf(stderr,"Error: sixth word should be Triangles not %s\n",str);
  141. fclose(mesh_file);
  142. return false;
  143. }
  144. int number_of_triangles;
  145. if(1 != fscanf(mesh_file," %d",&number_of_triangles))
  146. {
  147. fprintf(stderr,"Error: expecting number of triangles...\n");
  148. fclose(mesh_file);
  149. return false;
  150. }
  151. // allocate space for triangles
  152. F.resize(number_of_triangles,vector<Index>(3));
  153. // triangle indices
  154. int tri[3];
  155. for(int i = 0;i<number_of_triangles;i++)
  156. {
  157. if(4 != fscanf(mesh_file," %d %d %d %d",&tri[0],&tri[1],&tri[2],&extra))
  158. {
  159. printf("Error: expecting triangle indices...\n");
  160. return false;
  161. }
  162. for(int j = 0;j<3;j++)
  163. {
  164. F[i][j] = tri[j]-1;
  165. }
  166. }
  167. // eat comments
  168. still_comments= true;
  169. while(still_comments)
  170. {
  171. fgets(line,LINE_MAX,mesh_file);
  172. still_comments = (line[0] == '#' || line[0] == '\n');
  173. }
  174. sscanf(line," %s",str);
  175. // check that sixth word is Triangles
  176. if(0!=strcmp(str,"Tetrahedra"))
  177. {
  178. fprintf(stderr,"Error: seventh word should be Tetrahedra not %s\n",str);
  179. fclose(mesh_file);
  180. return false;
  181. }
  182. int number_of_tetrahedra;
  183. if(1 != fscanf(mesh_file," %d",&number_of_tetrahedra))
  184. {
  185. fprintf(stderr,"Error: expecting number of tetrahedra...\n");
  186. fclose(mesh_file);
  187. return false;
  188. }
  189. // allocate space for tetrahedra
  190. T.resize(number_of_tetrahedra,vector<Index>(4));
  191. // tet indices
  192. int a,b,c,d;
  193. for(int i = 0;i<number_of_tetrahedra;i++)
  194. {
  195. if(5 != fscanf(mesh_file," %d %d %d %d %d",&a,&b,&c,&d,&extra))
  196. {
  197. fprintf(stderr,"Error: expecting tetrahedra indices...\n");
  198. fclose(mesh_file);
  199. return false;
  200. }
  201. T[i][0] = a-1;
  202. T[i][1] = b-1;
  203. T[i][2] = c-1;
  204. T[i][3] = d-1;
  205. }
  206. fclose(mesh_file);
  207. return true;
  208. }
  209. #include <Eigen/Core>
  210. #include "list_to_matrix.h"
  211. template <typename DerivedV, typename DerivedF, typename DerivedT>
  212. IGL_INLINE bool igl::readMESH(
  213. const std::string mesh_file_name,
  214. Eigen::PlainObjectBase<DerivedV>& V,
  215. Eigen::PlainObjectBase<DerivedT>& T,
  216. Eigen::PlainObjectBase<DerivedF>& F)
  217. {
  218. using namespace std;
  219. using namespace igl;
  220. FILE * mesh_file = fopen(mesh_file_name.c_str(),"r");
  221. if(NULL==mesh_file)
  222. {
  223. fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
  224. return false;
  225. }
  226. #ifndef LINE_MAX
  227. # define LINE_MAX 2048
  228. #endif
  229. char line[LINE_MAX];
  230. bool still_comments;
  231. // eat comments at beginning of file
  232. still_comments= true;
  233. while(still_comments)
  234. {
  235. fgets(line,LINE_MAX,mesh_file);
  236. still_comments = (line[0] == '#' || line[0] == '\n');
  237. }
  238. char str[LINE_MAX];
  239. sscanf(line," %s",str);
  240. // check that first word is MeshVersionFormatted
  241. if(0!=strcmp(str,"MeshVersionFormatted"))
  242. {
  243. fprintf(stderr,
  244. "Error: first word should be MeshVersionFormatted not %s\n",str);
  245. fclose(mesh_file);
  246. return false;
  247. }
  248. int one = -1;
  249. if(2 != sscanf(line,"%s %d",str,&one))
  250. {
  251. // 1 appears on next line?
  252. fscanf(mesh_file," %d",&one);
  253. }
  254. if(one != 1)
  255. {
  256. fprintf(stderr,"Error: second word should be 1 not %d\n",one);
  257. fclose(mesh_file);
  258. return false;
  259. }
  260. // eat comments
  261. still_comments= true;
  262. while(still_comments)
  263. {
  264. fgets(line,LINE_MAX,mesh_file);
  265. still_comments = (line[0] == '#' || line[0] == '\n');
  266. }
  267. sscanf(line," %s",str);
  268. // check that third word is Dimension
  269. if(0!=strcmp(str,"Dimension"))
  270. {
  271. fprintf(stderr,"Error: third word should be Dimension not %s\n",str);
  272. fclose(mesh_file);
  273. return false;
  274. }
  275. int three = -1;
  276. if(2 != sscanf(line,"%s %d",str,&three))
  277. {
  278. // 1 appears on next line?
  279. fscanf(mesh_file," %d",&three);
  280. }
  281. if(three != 3)
  282. {
  283. fprintf(stderr,"Error: only Dimension 3 supported not %d\n",three);
  284. fclose(mesh_file);
  285. return false;
  286. }
  287. // eat comments
  288. still_comments= true;
  289. while(still_comments)
  290. {
  291. fgets(line,LINE_MAX,mesh_file);
  292. still_comments = (line[0] == '#' || line[0] == '\n');
  293. }
  294. sscanf(line," %s",str);
  295. // check that fifth word is Vertices
  296. if(0!=strcmp(str,"Vertices"))
  297. {
  298. fprintf(stderr,"Error: fifth word should be Vertices not %s\n",str);
  299. fclose(mesh_file);
  300. return false;
  301. }
  302. //fgets(line,LINE_MAX,mesh_file);
  303. int number_of_vertices;
  304. if(1 != fscanf(mesh_file," %d",&number_of_vertices) || number_of_vertices > 1000000000)
  305. {
  306. fprintf(stderr,"Error: expecting number of vertices less than 10^9...\n");
  307. fclose(mesh_file);
  308. return false;
  309. }
  310. // allocate space for vertices
  311. V.resize(number_of_vertices,3);
  312. int extra;
  313. for(int i = 0;i<number_of_vertices;i++)
  314. {
  315. double x,y,z;
  316. if(4 != fscanf(mesh_file," %lg %lg %lg %d",&x,&y,&z,&extra))
  317. {
  318. fprintf(stderr,"Error: expecting vertex position...\n");
  319. fclose(mesh_file);
  320. return false;
  321. }
  322. V(i,0) = x;
  323. V(i,1) = y;
  324. V(i,2) = z;
  325. }
  326. // eat comments
  327. still_comments= true;
  328. while(still_comments)
  329. {
  330. fgets(line,LINE_MAX,mesh_file);
  331. still_comments = (line[0] == '#' || line[0] == '\n');
  332. }
  333. sscanf(line," %s",str);
  334. // check that sixth word is Triangles
  335. if(0!=strcmp(str,"Triangles"))
  336. {
  337. fprintf(stderr,"Error: sixth word should be Triangles not %s\n",str);
  338. fclose(mesh_file);
  339. return false;
  340. }
  341. int number_of_triangles;
  342. if(1 != fscanf(mesh_file," %d",&number_of_triangles))
  343. {
  344. fprintf(stderr,"Error: expecting number of triangles...\n");
  345. fclose(mesh_file);
  346. return false;
  347. }
  348. // allocate space for triangles
  349. F.resize(number_of_triangles,3);
  350. // triangle indices
  351. int tri[3];
  352. for(int i = 0;i<number_of_triangles;i++)
  353. {
  354. if(4 != fscanf(mesh_file," %d %d %d %d",&tri[0],&tri[1],&tri[2],&extra))
  355. {
  356. printf("Error: expecting triangle indices...\n");
  357. return false;
  358. }
  359. for(int j = 0;j<3;j++)
  360. {
  361. F(i,j) = tri[j]-1;
  362. }
  363. }
  364. // eat comments
  365. still_comments= true;
  366. while(still_comments)
  367. {
  368. fgets(line,LINE_MAX,mesh_file);
  369. still_comments = (line[0] == '#' || line[0] == '\n');
  370. }
  371. sscanf(line," %s",str);
  372. // check that sixth word is Triangles
  373. if(0!=strcmp(str,"Tetrahedra"))
  374. {
  375. fprintf(stderr,"Error: seventh word should be Tetrahedra not %s\n",str);
  376. fclose(mesh_file);
  377. return false;
  378. }
  379. int number_of_tetrahedra;
  380. if(1 != fscanf(mesh_file," %d",&number_of_tetrahedra))
  381. {
  382. fprintf(stderr,"Error: expecting number of tetrahedra...\n");
  383. fclose(mesh_file);
  384. return false;
  385. }
  386. // allocate space for tetrahedra
  387. T.resize(number_of_tetrahedra,4);
  388. // tet indices
  389. int a,b,c,d;
  390. for(int i = 0;i<number_of_tetrahedra;i++)
  391. {
  392. if(5 != fscanf(mesh_file," %d %d %d %d %d",&a,&b,&c,&d,&extra))
  393. {
  394. fprintf(stderr,"Error: expecting tetrahedra indices...\n");
  395. fclose(mesh_file);
  396. return false;
  397. }
  398. T(i,0) = a-1;
  399. T(i,1) = b-1;
  400. T(i,2) = c-1;
  401. T(i,3) = d-1;
  402. }
  403. fclose(mesh_file);
  404. return true;
  405. }
  406. //{
  407. // std::vector<std::vector<double> > vV,vT,vF;
  408. // bool success = igl::readMESH(mesh_file_name,vV,vT,vF);
  409. // if(!success)
  410. // {
  411. // // readMESH already printed error message to std err
  412. // return false;
  413. // }
  414. // bool V_rect = igl::list_to_matrix(vV,V);
  415. // if(!V_rect)
  416. // {
  417. // // igl::list_to_matrix(vV,V) already printed error message to std err
  418. // return false;
  419. // }
  420. // bool T_rect = igl::list_to_matrix(vT,T);
  421. // if(!T_rect)
  422. // {
  423. // // igl::list_to_matrix(vT,T) already printed error message to std err
  424. // return false;
  425. // }
  426. // bool F_rect = igl::list_to_matrix(vF,F);
  427. // if(!F_rect)
  428. // {
  429. // // igl::list_to_matrix(vF,F) already printed error message to std err
  430. // return false;
  431. // }
  432. // assert(V.cols() == 3);
  433. // assert(T.cols() == 4);
  434. // assert(F.cols() == 3);
  435. // return true;
  436. //}
  437. #ifdef IGL_STATIC_LIBRARY
  438. // Explicit template specialization
  439. // generated by autoexplicit.sh
  440. 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> >&);
  441. // generated by autoexplicit.sh
  442. 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> >&);
  443. #endif