readOFF.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "readOFF.h"
  2. #include "list_to_matrix.h"
  3. template <typename Scalar, typename Index>
  4. IGL_INLINE bool igl::readOFF(
  5. const std::string off_file_name,
  6. std::vector<std::vector<Scalar > > & V,
  7. std::vector<std::vector<Index > > & F,
  8. std::vector<std::vector<Scalar > > & N)
  9. {
  10. FILE * off_file = fopen(off_file_name.c_str(),"r");
  11. if(NULL==off_file)
  12. {
  13. printf("IOError: %s could not be opened...",off_file_name.c_str());
  14. return false;
  15. }
  16. V.clear();
  17. F.clear();
  18. N.clear();
  19. // First line is always OFF
  20. char header[1000];
  21. const std::string OFF("OFF");
  22. const std::string NOFF("NOFF");
  23. if(!fscanf(off_file,"%s\n",header)==1
  24. || !(OFF == header || NOFF == header))
  25. {
  26. printf("Error: %s's first line should be OFF or NOFF not %s...",off_file_name.c_str(),header);
  27. fclose(off_file);
  28. return false;
  29. }
  30. bool has_normals = NOFF==header;
  31. // Second line is #vertices #faces #edges
  32. int number_of_vertices;
  33. int number_of_faces;
  34. int number_of_edges;
  35. char tic_tac_toe;
  36. char line[1000];
  37. bool still_comments = true;
  38. while(still_comments)
  39. {
  40. fgets(line,1000,off_file);
  41. still_comments = line[0] == '#';
  42. }
  43. sscanf(line,"%d %d %d",&number_of_vertices,&number_of_faces,&number_of_edges);
  44. V.resize(number_of_vertices);
  45. if (has_normals)
  46. N.resize(number_of_vertices);
  47. F.resize(number_of_faces);
  48. //printf("%s %d %d %d\n",(has_normals ? "NOFF" : "OFF"),number_of_vertices,number_of_faces,number_of_edges);
  49. // Read vertices
  50. for(int i = 0;i<number_of_vertices;)
  51. {
  52. float x,y,z,nx,ny,nz;
  53. if((has_normals && fscanf(off_file, "%g %g %g %g %g %g\n",&x,&y,&z,&nx,&ny,&nz)==6) ||
  54. (!has_normals && fscanf(off_file, "%g %g %g\n",&x,&y,&z)==3))
  55. {
  56. std::vector<Scalar > vertex;
  57. vertex.resize(3);
  58. vertex[0] = x;
  59. vertex[1] = y;
  60. vertex[2] = z;
  61. V[i] = vertex;
  62. if (has_normals)
  63. {
  64. std::vector<Scalar > normal;
  65. normal.resize(3);
  66. normal[0] = nx;
  67. normal[1] = ny;
  68. normal[2] = nz;
  69. N[i] = normal;
  70. }
  71. i++;
  72. }else if(
  73. fscanf(off_file,"%[#]",&tic_tac_toe)==1)
  74. {
  75. char comment[1000];
  76. fscanf(off_file,"%[^\n]",comment);
  77. }else
  78. {
  79. printf("Error: bad line in %s\n",off_file_name.c_str());
  80. fclose(off_file);
  81. return false;
  82. }
  83. }
  84. // Read faces
  85. for(int i = 0;i<number_of_faces;)
  86. {
  87. std::vector<Index > face;
  88. int valence;
  89. if(fscanf(off_file,"%d",&valence)==1)
  90. {
  91. face.resize(valence);
  92. for(int j = 0;j<valence;j++)
  93. {
  94. int index;
  95. if(j<valence-1)
  96. {
  97. fscanf(off_file,"%d",&index);
  98. }else{
  99. fscanf(off_file,"%d%*[^\n]",&index);
  100. }
  101. face[j] = index;
  102. }
  103. F[i] = face;
  104. i++;
  105. }else if(
  106. fscanf(off_file,"%[#]",&tic_tac_toe)==1)
  107. {
  108. char comment[1000];
  109. fscanf(off_file,"%[^\n]",comment);
  110. }else
  111. {
  112. printf("Error: bad line in %s\n",off_file_name.c_str());
  113. fclose(off_file);
  114. return false;
  115. }
  116. }
  117. fclose(off_file);
  118. return true;
  119. }
  120. template <typename DerivedV, typename DerivedF>
  121. IGL_INLINE bool igl::readOFF(
  122. const std::string str,
  123. Eigen::PlainObjectBase<DerivedV>& V,
  124. Eigen::PlainObjectBase<DerivedF>& F)
  125. {
  126. std::vector<std::vector<double> > vV;
  127. std::vector<std::vector<double> > vN;
  128. std::vector<std::vector<int> > vF;
  129. bool success = igl::readOFF(str,vV,vF,vN);
  130. if(!success)
  131. {
  132. // readOFF(str,vV,vF) should have already printed an error
  133. // message to stderr
  134. return false;
  135. }
  136. bool V_rect = igl::list_to_matrix(vV,V);
  137. if(!V_rect)
  138. {
  139. // igl::list_to_matrix(vV,V) already printed error message to std err
  140. return false;
  141. }
  142. bool F_rect = igl::list_to_matrix(vF,F);
  143. if(!F_rect)
  144. {
  145. // igl::list_to_matrix(vF,F) already printed error message to std err
  146. return false;
  147. }
  148. return true;
  149. }
  150. template <typename DerivedV, typename DerivedF>
  151. IGL_INLINE bool igl::readOFF(
  152. const std::string str,
  153. Eigen::PlainObjectBase<DerivedV>& V,
  154. Eigen::PlainObjectBase<DerivedF>& F,
  155. Eigen::PlainObjectBase<DerivedV>& N)
  156. {
  157. std::vector<std::vector<double> > vV;
  158. std::vector<std::vector<double> > vN;
  159. std::vector<std::vector<int> > vF;
  160. bool success = igl::readOFF(str,vV,vF,vN);
  161. if(!success)
  162. {
  163. // readOFF(str,vV,vF) should have already printed an error
  164. // message to stderr
  165. return false;
  166. }
  167. bool V_rect = igl::list_to_matrix(vV,V);
  168. if(!V_rect)
  169. {
  170. // igl::list_to_matrix(vV,V) already printed error message to std err
  171. return false;
  172. }
  173. bool F_rect = igl::list_to_matrix(vF,F);
  174. if(!F_rect)
  175. {
  176. // igl::list_to_matrix(vF,F) already printed error message to std err
  177. return false;
  178. }
  179. if (vN.size())
  180. {
  181. bool N_rect = igl::list_to_matrix(vN,N);
  182. if(!N_rect)
  183. {
  184. // igl::list_to_matrix(vN,N) already printed error message to std err
  185. return false;
  186. }
  187. }
  188. return true;
  189. }
  190. #ifndef IGL_HEADER_ONLY
  191. // Explicit template specialization
  192. // generated by autoexplicit.sh
  193. template bool igl::readOFF<Eigen::Matrix<double, -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> >&);
  194. template bool igl::readOFF<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, -1, 1, -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<unsigned int, -1, -1, 1, -1, -1> >&);
  195. #endif