writeMSH.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // high level interface for MshSaver
  2. //
  3. // Copyright (C) 2020 Vladimir Fonov <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla
  6. // Public License v. 2.0. If a copy of the MPL was not distributed
  7. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "writeMSH.h"
  9. #include "MshSaver.h"
  10. #include "MshLoader.h"
  11. #include <iostream>
  12. namespace igl {
  13. namespace internal {
  14. // helper function, appends contents of Eigen matrix to an std::vector, in RowMajor fashion
  15. template <typename T, typename Derived>
  16. void append_mat_to_vec(std::vector<T> &vec, const Eigen::MatrixBase<Derived> & mat)
  17. {
  18. size_t st = vec.size();
  19. vec.resize(st + mat.size());
  20. // Iterate over the rows and columns in row-major order
  21. for (int i = 0; i < mat.rows(); ++i)
  22. {
  23. for (int j = 0; j < mat.cols(); ++j)
  24. {
  25. vec[st++] = mat(i, j);
  26. }
  27. }
  28. }
  29. }
  30. }
  31. template <
  32. typename DerivedX,
  33. typename DerivedTri,
  34. typename DerivedTet,
  35. typename DerivedTriTag,
  36. typename DerivedTetTag,
  37. typename MatrixXF,
  38. typename MatrixTriF,
  39. typename MatrixTetF
  40. >
  41. IGL_INLINE bool igl::writeMSH(
  42. const std::string &msh,
  43. const Eigen::MatrixBase<DerivedX> &X,
  44. const Eigen::MatrixBase<DerivedTri> &Tri,
  45. const Eigen::MatrixBase<DerivedTet> &Tet,
  46. const Eigen::MatrixBase<DerivedTriTag> &TriTag,
  47. const Eigen::MatrixBase<DerivedTetTag> &TetTag,
  48. const std::vector<std::string> &XFields,
  49. const std::vector<MatrixXF> &XF,
  50. const std::vector<std::string> &EFields,
  51. const std::vector<MatrixTriF> &TriF,
  52. const std::vector<MatrixTetF> &TetF)
  53. {
  54. using namespace internal;
  55. try
  56. {
  57. // error checks
  58. if(!XFields.empty())
  59. {
  60. if(XFields.size()!=XF.size())
  61. throw std::invalid_argument("Vertex field count mismatch");
  62. for(int i=0;i<XFields.size();++i)
  63. if(XF[i].rows()!=X.rows())
  64. throw std::invalid_argument("Vertex field size mismatch");
  65. }
  66. if(!EFields.empty())
  67. {
  68. if(EFields.size()!=TriF.size())
  69. throw std::invalid_argument("Triangle field count mismatch");
  70. if(EFields.size()!=TetF.size())
  71. throw std::invalid_argument("Tetrahedra field count mismatch");
  72. for(int i=0;i<EFields.size();++i)
  73. {
  74. if(TriF[i].rows()!=Tri.rows())
  75. throw std::invalid_argument("Triangle field size mismatch");
  76. if(TetF[i].rows()!=Tet.rows())
  77. throw std::invalid_argument("Tetrahedra field size mismatch");
  78. }
  79. }
  80. // this is not the most optimal , it would be faster to modify RRMshSaver to work with Eiged data types
  81. std::vector<double> _X;
  82. append_mat_to_vec(_X, X);
  83. std::vector<int> _Tri_Tet;
  84. append_mat_to_vec( _Tri_Tet, Tri);
  85. append_mat_to_vec( _Tri_Tet, Tet);
  86. std::vector<int> _Tri_Tet_len(Tri.rows(), 3); //each is 3 elements long
  87. _Tri_Tet_len.insert(_Tri_Tet_len.end(), Tet.rows(), 4);
  88. std::vector<int> _Tri_Tet_type(Tri.rows(), MshLoader::ELEMENT_TRI);
  89. _Tri_Tet_type.insert(_Tri_Tet_type.end(), Tet.rows(), MshLoader::ELEMENT_TET);
  90. std::vector<int> _Tri_Tet_tag;
  91. // apparently TriTag and TetTag need to be present. Use zero arrays if their
  92. // empty
  93. if(TriTag.size() == 0)
  94. {
  95. append_mat_to_vec(_Tri_Tet_tag, Eigen::Matrix<int, Eigen::Dynamic, 1>::Zero(Tri.rows()));
  96. }else
  97. {
  98. append_mat_to_vec(_Tri_Tet_tag, TriTag);
  99. }
  100. if(TetTag.size() == 0)
  101. {
  102. append_mat_to_vec(_Tri_Tet_tag, Eigen::Matrix<int, Eigen::Dynamic, 1>::Zero(Tet.rows()));
  103. }else
  104. {
  105. append_mat_to_vec(_Tri_Tet_tag, TetTag);
  106. }
  107. igl::MshSaver msh_saver(msh, true);
  108. msh_saver.save_mesh( _X,
  109. _Tri_Tet,
  110. _Tri_Tet_len,
  111. _Tri_Tet_type,
  112. _Tri_Tet_tag);
  113. // append vertex data
  114. for(size_t i=0;i<XFields.size();++i)
  115. {
  116. assert(X.rows()==XF[i].rows());
  117. std::vector<double> _XF;
  118. append_mat_to_vec(_XF, XF[i]);
  119. if(XF[i].cols() == 1)
  120. msh_saver.save_scalar_field(XFields[i], _XF );
  121. else if(XF[i].cols() == 3)
  122. msh_saver.save_vector_field(XFields[i], _XF );
  123. else
  124. {
  125. throw std::invalid_argument("unsupported vertex field dimensionality");
  126. }
  127. }
  128. // append node data
  129. for(size_t i=0; i<EFields.size(); ++i)
  130. {
  131. assert(TriF[i].cols() == TetF[i].cols());
  132. assert(TriF[i].rows() == Tri.rows());
  133. assert(TetF[i].rows() == Tet.rows());
  134. std::vector<double> _EF;
  135. append_mat_to_vec(_EF, TriF[i]);
  136. append_mat_to_vec(_EF, TetF[i]);
  137. assert(_EF.size() == (TriF[i].size()+TetF[i].size()));
  138. if( TriF[i].cols() == 1 )
  139. msh_saver.save_elem_scalar_field(EFields[i], _EF );
  140. else if( TriF[i].cols() == 3 )
  141. msh_saver.save_elem_vector_field(EFields[i], _EF );
  142. else
  143. {
  144. throw std::invalid_argument("unsupported node field dimensionality");
  145. }
  146. }
  147. } catch(const std::exception& e) {
  148. std::cerr << e.what() << std::endl;
  149. return false;
  150. }
  151. return true;
  152. }
  153. #ifdef IGL_STATIC_LIBRARY
  154. // Explicit template instantiation
  155. template bool igl::writeMSH<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<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>>(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<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -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<Eigen::Matrix<double, -1, -1, 0, -1, -1>, std::allocator<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<Eigen::Matrix<double, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<double, -1, -1, 0, -1, -1>>> const&, std::vector<Eigen::Matrix<double, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<double, -1, -1, 0, -1, -1>>> const&);
  156. #endif