readMESH.cpp 16 KB

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