writePLY.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. #include "writePLY.h"
  2. #include <fstream>
  3. #include "tinyply.h"
  4. #include <stdint.h>
  5. #include <cstdint>
  6. namespace igl
  7. {
  8. template <typename Scalar> tinyply::Type tynyply_type();
  9. template <> tinyply::Type IGL_INLINE tynyply_type<std::int8_t >() { return tinyply::Type::INT8; }
  10. template <> tinyply::Type IGL_INLINE tynyply_type<std::int16_t >() { return tinyply::Type::INT16; }
  11. template <> tinyply::Type IGL_INLINE tynyply_type<std::int32_t >() { return tinyply::Type::INT32; }
  12. template <> tinyply::Type IGL_INLINE tynyply_type<std::uint8_t >() { return tinyply::Type::UINT8; }
  13. template <> tinyply::Type IGL_INLINE tynyply_type<std::uint16_t >() { return tinyply::Type::UINT16; }
  14. template <> tinyply::Type IGL_INLINE tynyply_type<std::uint32_t >() { return tinyply::Type::UINT32; }
  15. template <> tinyply::Type IGL_INLINE tynyply_type<float >() { return tinyply::Type::FLOAT32; }
  16. template <> tinyply::Type IGL_INLINE tynyply_type<double >() { return tinyply::Type::FLOAT64; }
  17. }
  18. template <
  19. typename DerivedV,
  20. typename DerivedF,
  21. typename DerivedE,
  22. typename DerivedN,
  23. typename DerivedUV,
  24. typename DerivedVD,
  25. typename DerivedFD,
  26. typename DerivedED
  27. >
  28. bool igl::writePLY(
  29. std::ostream & ply_stream,
  30. const Eigen::MatrixBase<DerivedV> & V,
  31. const Eigen::MatrixBase<DerivedF> & F,
  32. const Eigen::MatrixBase<DerivedE> & E,
  33. const Eigen::MatrixBase<DerivedN> & N,
  34. const Eigen::MatrixBase<DerivedUV> & UV,
  35. const Eigen::MatrixBase<DerivedVD> & VD,
  36. const std::vector<std::string> & VDheader,
  37. const Eigen::MatrixBase<DerivedFD> & FD,
  38. const std::vector<std::string> & FDheader,
  39. const Eigen::MatrixBase<DerivedED> & ED,
  40. const std::vector<std::string> & EDheader,
  41. const std::vector<std::string> & comments,
  42. FileEncoding encoding
  43. )
  44. {
  45. typedef typename DerivedV::Scalar VScalar;
  46. typedef typename DerivedN::Scalar NScalar;
  47. typedef typename DerivedUV::Scalar UVScalar;
  48. typedef typename DerivedF::Scalar FScalar;
  49. typedef typename DerivedE::Scalar EScalar;
  50. typedef typename DerivedVD::Scalar VDScalar;
  51. typedef typename DerivedFD::Scalar FDScalar;
  52. typedef typename DerivedED::Scalar EDScalar;
  53. // temporary storage for data to be passed to tinyply internals
  54. std::vector<VScalar> _v;
  55. std::vector<NScalar> _n;
  56. std::vector<UVScalar> _uv;
  57. std::vector<VDScalar> _vd;
  58. std::vector<FDScalar> _fd;
  59. std::vector<EScalar> _ev;
  60. std::vector<EDScalar> _ed;
  61. // check dimensions
  62. if( V.cols()!=3)
  63. {
  64. std::cerr << "writePLY: unexpected dimensions " << std::endl;
  65. return false;
  66. }
  67. tinyply::PlyFile file;
  68. _v.resize(V.size());
  69. Eigen::Map< Eigen::Matrix<VScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_v[0], V.rows(), V.cols() ) = V;
  70. file.add_properties_to_element("vertex", { "x", "y", "z" },
  71. tynyply_type<VScalar>(), V.rows(), reinterpret_cast<uint8_t*>( &_v[0] ), tinyply::Type::INVALID, 0);
  72. if(N.rows()>0)
  73. {
  74. _n.resize(N.size());
  75. Eigen::Map<Eigen::Matrix<NScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_n[0], N.rows(), N.cols() ) = N;
  76. file.add_properties_to_element("vertex", { "nx", "ny", "nz" },
  77. tynyply_type<NScalar>(), N.rows(), reinterpret_cast<uint8_t*>( &_n[0] ),tinyply::Type::INVALID, 0);
  78. }
  79. if(UV.rows()>0)
  80. {
  81. _uv.resize(UV.size());
  82. Eigen::Map<Eigen::Matrix<UVScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_uv[0], UV.rows(), UV.cols() ) = UV;
  83. file.add_properties_to_element("vertex", { "u", "v" },
  84. tynyply_type<UVScalar>(), UV.rows() , reinterpret_cast<uint8_t*>( &_uv[0] ), tinyply::Type::INVALID, 0);
  85. }
  86. if(VD.cols()>0)
  87. {
  88. assert(VD.cols() == VDheader.size());
  89. assert(VD.rows() == V.rows());
  90. _vd.resize(VD.size());
  91. Eigen::Map< Eigen::Matrix<VDScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_vd[0], VD.rows(), VD.cols() ) = VD;
  92. file.add_properties_to_element("vertex", VDheader,
  93. tynyply_type<VDScalar>(), VD.rows(), reinterpret_cast<uint8_t*>( &_vd[0] ), tinyply::Type::INVALID, 0);
  94. }
  95. std::vector<FScalar> _f(F.size());
  96. Eigen::Map<Eigen::Matrix<FScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_f[0], F.rows(), F.cols() ) = F;
  97. file.add_properties_to_element("face", { "vertex_indices" },
  98. tynyply_type<FScalar>(), F.rows(), reinterpret_cast<uint8_t*>(&_f[0]), tinyply::Type::UINT8, F.cols() );
  99. if(FD.cols()>0)
  100. {
  101. assert(FD.rows()==F.rows());
  102. assert(FD.cols() == FDheader.size());
  103. _fd.resize(FD.size());
  104. Eigen::Map<Eigen::Matrix<FDScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_fd[0], FD.rows(), FD.cols() ) = FD;
  105. file.add_properties_to_element("face", FDheader,
  106. tynyply_type<FDScalar>(), FD.rows(), reinterpret_cast<uint8_t*>( &_fd[0] ), tinyply::Type::INVALID, 0);
  107. }
  108. if(E.rows()>0)
  109. {
  110. assert(E.cols()==2);
  111. _ev.resize(E.size());
  112. Eigen::Map<Eigen::Matrix<EScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_ev[0], E.rows(), E.cols() ) = E;
  113. file.add_properties_to_element("edge", { "vertex1", "vertex2" },
  114. tynyply_type<EScalar>(), E.rows() , reinterpret_cast<uint8_t*>( &_ev[0] ), tinyply::Type::INVALID, 0);
  115. }
  116. if(ED.cols()>0)
  117. {
  118. assert(ED.rows()==E.rows());
  119. assert(ED.cols() == EDheader.size());
  120. _ed.resize(ED.size());
  121. Eigen::Map<Eigen::Matrix<EDScalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > >( &_ed[0], ED.rows(), ED.cols() ) = ED;
  122. file.add_properties_to_element("edge", EDheader,
  123. tynyply_type<EDScalar>(), ED.rows(), reinterpret_cast<uint8_t*>( &_ed[0] ), tinyply::Type::INVALID, 0);
  124. }
  125. for(auto a:comments)
  126. file.get_comments().push_back(a);
  127. // Write a binary file
  128. file.write(ply_stream, (encoding == FileEncoding::Binary));
  129. return true;
  130. }
  131. template <
  132. typename DerivedV,
  133. typename DerivedF,
  134. typename DerivedE,
  135. typename DerivedN,
  136. typename DerivedUV,
  137. typename DerivedVD,
  138. typename DerivedFD,
  139. typename DerivedED
  140. >
  141. bool igl::writePLY(
  142. const std::string & filename,
  143. const Eigen::MatrixBase<DerivedV> & V,
  144. const Eigen::MatrixBase<DerivedF> & F,
  145. const Eigen::MatrixBase<DerivedE> & E,
  146. const Eigen::MatrixBase<DerivedN> & N,
  147. const Eigen::MatrixBase<DerivedUV> & UV,
  148. const Eigen::MatrixBase<DerivedVD> & VD,
  149. const std::vector<std::string> & VDheader,
  150. const Eigen::MatrixBase<DerivedFD> & FD,
  151. const std::vector<std::string> & FDheader,
  152. const Eigen::MatrixBase<DerivedED> & ED,
  153. const std::vector<std::string> & EDheader,
  154. const std::vector<std::string> & comments,
  155. FileEncoding encoding
  156. )
  157. {
  158. try
  159. {
  160. if(encoding == FileEncoding::Binary)
  161. {
  162. std::filebuf fb_binary;
  163. fb_binary.open(filename , std::ios::out | std::ios::binary);
  164. std::ostream outstream_binary(&fb_binary);
  165. if (outstream_binary.fail()) {
  166. std::cerr << "writePLY: Error opening file " << filename << std::endl;
  167. return false; //throw std::runtime_error("failed to open " + filename);
  168. }
  169. return writePLY(outstream_binary,V,F,E,N,UV,VD,VDheader,FD,FDheader,ED,EDheader,comments,encoding);
  170. } else {
  171. std::filebuf fb_ascii;
  172. fb_ascii.open(filename, std::ios::out);
  173. std::ostream outstream_ascii(&fb_ascii);
  174. if (outstream_ascii.fail()) {
  175. std::cerr << "writePLY: Error opening file " << filename << std::endl;
  176. return false; //throw std::runtime_error("failed to open " + filename);
  177. }
  178. return writePLY(outstream_ascii,V,F,E,N,UV,VD,VDheader,FD,FDheader,ED,EDheader,comments,encoding);
  179. }
  180. }
  181. catch(const std::exception& e)
  182. {
  183. std::cerr << "writePLY error: " << filename << e.what() << std::endl;
  184. }
  185. return false;
  186. }
  187. template <
  188. typename DerivedV,
  189. typename DerivedF
  190. >
  191. bool igl::writePLY(
  192. const std::string & filename,
  193. const Eigen::MatrixBase<DerivedV> & V,
  194. const Eigen::MatrixBase<DerivedF> & F
  195. )
  196. {
  197. Eigen::MatrixXd _dummy;
  198. std::vector<std::string> _dummy_header;
  199. return writePLY(filename,V,F,_dummy, _dummy, _dummy, _dummy, _dummy_header, _dummy, _dummy_header, _dummy, _dummy_header, _dummy_header, FileEncoding::Binary);
  200. }
  201. template <
  202. typename DerivedV,
  203. typename DerivedF,
  204. typename DerivedE
  205. >
  206. bool igl::writePLY(
  207. const std::string & filename,
  208. const Eigen::MatrixBase<DerivedV> & V,
  209. const Eigen::MatrixBase<DerivedF> & F,
  210. const Eigen::MatrixBase<DerivedE> & E
  211. )
  212. {
  213. Eigen::MatrixXd _dummy;
  214. std::vector<std::string> _dummy_header;
  215. return writePLY(filename,V,F,E, _dummy, _dummy, _dummy, _dummy_header, _dummy, _dummy_header, _dummy, _dummy_header, _dummy_header, FileEncoding::Binary);
  216. }
  217. template <
  218. typename DerivedV,
  219. typename DerivedF,
  220. typename DerivedN,
  221. typename DerivedUV
  222. >
  223. bool igl::writePLY(
  224. const std::string & filename,
  225. const Eigen::MatrixBase<DerivedV> & V,
  226. const Eigen::MatrixBase<DerivedF> & F,
  227. const Eigen::MatrixBase<DerivedN> & N,
  228. const Eigen::MatrixBase<DerivedUV> & UV
  229. )
  230. {
  231. Eigen::MatrixXd _dummy;
  232. std::vector<std::string> _dummy_header;
  233. return writePLY(filename,V,F,_dummy, N,UV, _dummy, _dummy_header, _dummy, _dummy_header, _dummy, _dummy_header, _dummy_header, FileEncoding::Binary);
  234. }
  235. template <
  236. typename DerivedV,
  237. typename DerivedF,
  238. typename DerivedE,
  239. typename DerivedN,
  240. typename DerivedUV
  241. >
  242. bool igl::writePLY(
  243. const std::string & filename,
  244. const Eigen::MatrixBase<DerivedV> & V,
  245. const Eigen::MatrixBase<DerivedF> & F,
  246. const Eigen::MatrixBase<DerivedE> & E,
  247. const Eigen::MatrixBase<DerivedN> & N,
  248. const Eigen::MatrixBase<DerivedUV> & UV
  249. )
  250. {
  251. Eigen::MatrixXd _dummy;
  252. std::vector<std::string> _dummy_header;
  253. return writePLY(filename,V,F,E, N,UV, _dummy, _dummy_header, _dummy, _dummy_header, _dummy, _dummy_header, _dummy_header, FileEncoding::Binary);
  254. }
  255. template <
  256. typename DerivedV,
  257. typename DerivedF
  258. >
  259. bool igl::writePLY(
  260. const std::string & filename,
  261. const Eigen::MatrixBase<DerivedV> & V,
  262. const Eigen::MatrixBase<DerivedF> & F,
  263. FileEncoding encoding
  264. )
  265. {
  266. Eigen::MatrixXd _dummy(0,0);
  267. std::vector<std::string> _dummy_header;
  268. return writePLY(filename,V,F,_dummy, _dummy,_dummy, _dummy, _dummy_header,
  269. _dummy, _dummy_header, _dummy, _dummy_header, _dummy_header, encoding);
  270. }
  271. template <
  272. typename DerivedV,
  273. typename DerivedF,
  274. typename DerivedE
  275. >
  276. bool igl::writePLY(
  277. const std::string & filename,
  278. const Eigen::MatrixBase<DerivedV> & V,
  279. const Eigen::MatrixBase<DerivedF> & F,
  280. const Eigen::MatrixBase<DerivedE> & E,
  281. FileEncoding encoding
  282. )
  283. {
  284. Eigen::MatrixXd _dummy(0,0);
  285. std::vector<std::string> _dummy_header;
  286. return writePLY(filename,V,F,E, _dummy,_dummy, _dummy, _dummy_header,
  287. _dummy, _dummy_header, _dummy, _dummy_header, _dummy_header, encoding);
  288. }
  289. template <
  290. typename DerivedV,
  291. typename DerivedF,
  292. typename DerivedN,
  293. typename DerivedUV,
  294. typename DerivedVD
  295. >
  296. bool igl::writePLY(
  297. const std::string & filename,
  298. const Eigen::MatrixBase<DerivedV> & V,
  299. const Eigen::MatrixBase<DerivedF> & F,
  300. const Eigen::MatrixBase<DerivedN> & N,
  301. const Eigen::MatrixBase<DerivedUV> & UV,
  302. const Eigen::MatrixBase<DerivedVD> & VD,
  303. const std::vector<std::string> & VDheader,
  304. const std::vector<std::string> & comments
  305. )
  306. {
  307. Eigen::MatrixXd _dummy(0,0);
  308. std::vector<std::string> _dummy_header;
  309. return writePLY(filename,V,F,_dummy, N, UV, VD, VDheader,
  310. _dummy, _dummy_header, _dummy, _dummy_header, comments, FileEncoding::Binary);
  311. }
  312. template <
  313. typename DerivedV,
  314. typename DerivedF,
  315. typename DerivedE,
  316. typename DerivedN,
  317. typename DerivedUV,
  318. typename DerivedVD
  319. >
  320. bool igl::writePLY(
  321. const std::string & filename,
  322. const Eigen::MatrixBase<DerivedV> & V,
  323. const Eigen::MatrixBase<DerivedF> & F,
  324. const Eigen::MatrixBase<DerivedE> & E,
  325. const Eigen::MatrixBase<DerivedN> & N,
  326. const Eigen::MatrixBase<DerivedUV> & UV,
  327. const Eigen::MatrixBase<DerivedVD> & VD,
  328. const std::vector<std::string> & VDheader,
  329. const std::vector<std::string> & comments
  330. )
  331. {
  332. Eigen::MatrixXd _dummy(0,0);
  333. std::vector<std::string> _dummy_header;
  334. return writePLY(filename,V,F,E, N, UV, VD, VDheader,
  335. _dummy, _dummy_header, _dummy, _dummy_header, comments, FileEncoding::Binary);
  336. }
  337. #ifdef IGL_STATIC_LIBRARY
  338. // Explicit template instantiation
  339. template bool igl::writePLY<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> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
  340. template bool igl::writePLY<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> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::FileEncoding);
  341. template bool igl::writePLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, igl::FileEncoding);
  342. template bool igl::writePLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
  343. template bool igl::writePLY<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::FileEncoding);
  344. template bool igl::writePLY<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, igl::FileEncoding);
  345. template bool igl::writePLY<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, igl::FileEncoding);
  346. template bool igl::writePLY<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, igl::FileEncoding);
  347. template bool igl::writePLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, igl::FileEncoding);
  348. #endif