NiHu  2.0
read_off_mesh.hpp
Go to the documentation of this file.
1 // This file is a part of NiHu, a C++ BEM template library.
2 //
3 // Copyright (C) 2012-2014 Peter Fiala <fiala@hit.bme.hu>
4 // Copyright (C) 2012-2014 Peter Rucz <rucz@hit.bme.hu>
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
24 #ifndef READ_OFF_MESH_HPP_INCLUDED
25 #define READ_OFF_MESH_HPP_INCLUDED
26 
27 #include "../core/mesh.hpp"
28 #include "../library/lib_element.hpp"
29 #include "../util/type2tag.hpp"
30 
31 #include <string>
32 #include <fstream>
33 #include <stdexcept>
34 
35 namespace NiHu
36 {
37 
38 namespace internal
39 {
40  template <class Tag1, class...Tags>
41  struct nvert2elem_id_impl
42  {
43  typedef typename tag2type<Tag1>::type elem_t;
44  static unsigned eval(unsigned nvert)
45  {
46  if (nvert == elem_t::num_nodes)
47  return elem_t::id;
48  return nvert2elem_id_impl<Tags...>::eval(nvert);
49  }
50  };
51 
52  template <class Tag1>
53  struct nvert2elem_id_impl<Tag1>
54  {
55  typedef typename tag2type<Tag1>::type elem_t;
56  static unsigned eval(unsigned nvert)
57  {
58  if (nvert == elem_t::num_nodes)
59  return elem_t::id;
60  throw std::runtime_error("Invalid number of vertices for current element tag vector");
61  }
62  };
63 }
64 
65 
72 template <class...Tags>
73 unsigned nvert2elem_id(unsigned nvert, Tags...tags)
74 {
75  return internal::nvert2elem_id_impl<Tags...>::eval(nvert);
76 }
77 
78 typedef Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic> uMatrix;
79 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> dMatrix;
80 
81 template <class...Tags>
82 void read_off_data(std::istream &is, dMatrix &nodes, uMatrix &elements, Tags...tags)
83 {
84  // read header from file (first row is 'OFF')
85  std::string header;
86  if (!(is >> header) || header != "OFF")
87  throw std::runtime_error("Possibly invalid off file");
88 
89  // read number of nodes and number of elements
90  unsigned nNodes, nElements, nEdges;
91  if (!(is >> nNodes >> nElements >> nEdges))
92  throw std::runtime_error("Error reading number of mesh entries");
93 
94  nodes.resize(nNodes, 3);
95  elements.resize(nElements, 5);
96 
97  // read nodes
98  for (unsigned i = 0; i < nNodes; ++i)
99  if (!(is >> nodes(i, 0) >> nodes(i, 1) >> nodes(i, 2)))
100  throw std::runtime_error("Error reading mesh nodes");
101 
102  // read elements
103  for (unsigned i = 0; i < nElements; ++i)
104  {
105  unsigned nvert;
106  if (!(is >> nvert))
107  throw std::runtime_error("Error reading mesh elements");
108  for (unsigned c = 0; c < nvert; ++c)
109  if (!(is >> elements(i, c + 1)))
110  throw std::runtime_error("Error reading mesh elements");
111  elements(i, 0) = nvert2elem_id(nvert, tags...);
112  }
113 }
114 
115 template <class...Tags>
116 void read_off_data(std::string const &fname, dMatrix &nodes, uMatrix &elements, Tags...tags)
117 {
118  std::ifstream ifs(fname);
119  read_off_data(ifs, nodes, elements, tags...);
120  ifs.close();
121 }
122 
123 
130 template <class...Tags>
131 mesh<tmp::vector<typename tag2type<Tags>::type...> >
132 read_off_mesh(std::istream &is, Tags...tags)
133 {
134  uMatrix elements;
135  dMatrix nodes;
136 
137  read_off_data(is, nodes, elements, tags...);
138 
139 
140  // create and return the mesh
141  return create_mesh(nodes, elements, tags...);
142 }
143 
144 
151 template <class...Tags>
152 mesh<tmp::vector<typename tag2type<Tags>::type...> >
153  read_off_mesh(std::string const &fname, Tags...tags)
154 {
155  // read mesh file for reading
156  std::ifstream is(fname);
157  if (!is)
158  throw std::runtime_error("Error reading mesh file");
159 
160  return read_off_mesh(is, tags...);
161 }
162 
163 } // namespace NiHu
164 
165 #endif // READ_OFF_MESH_HPP_INCLUDED
166 
NiHu::volume_element
class describing a volume element that has no normal vector
Definition: element.hpp:455
NiHu::create_mesh
mesh< tmp::vector< typename tag2type< Args >::type... > > create_mesh(nodes_t const &nodes, elements_t const &elements, Args...)
factory function to create a mesh from nodes and elements matrices
Definition: mesh.hpp:298
NiHu::mex::real_matrix
Definition: mex_matrix_separate.hpp:133
NiHu::read_off_mesh
mesh< tmp::vector< typename tag2type< Tags >::type... > > read_off_mesh(std::istream &is, Tags...tags)
Read mesh from OFF format.
Definition: read_off_mesh.hpp:132
NiHu::nvert2elem_id
unsigned nvert2elem_id(unsigned nvert, Tags...tags)
convert number of vertices to element id
Definition: read_off_mesh.hpp:73