Tatooine
vtp_writer.h
Go to the documentation of this file.
1#ifndef TATOOINE_DETAIL_LINE_VTP_WRITER_H
2#define TATOOINE_DETAIL_LINE_VTP_WRITER_H
3//==============================================================================
4#include <tatooine/concepts.h>
6#include <tatooine/line.h>
7#include <tatooine/linspace.h>
8#include <tatooine/vtk/xml.h>
9
10#include <array>
11#include <vector>
12//==============================================================================
13namespace tatooine::detail::line {
14//==============================================================================
15template <typename Line, unsigned_integral HeaderType, integral ConnectivityInt,
16 integral OffsetInt>
17requires(Line::num_dimensions() == 2 || Line::num_dimensions() == 3)
18struct vtp_writer {
19 static auto constexpr num_dimensions() { return Line::num_dimensions(); }
21 template <typename T>
23 typename Line::template typed_vertex_property_type<T>;
24 //----------------------------------------------------------------------------
25 Line const& m_line;
26 //----------------------------------------------------------------------------
27 auto write(filesystem::path const& path) const {
28 auto file = std::ofstream{path};
29 if (!file.is_open()) {
30 throw std::runtime_error{"Could open file " + path.string() +
31 " for writing."};
32 }
33 auto offset = std::size_t{};
34 write_vtk_file(file, offset);
35 }
36 //----------------------------------------------------------------------------
37 private:
38 auto write_vtk_file(std::ofstream& file, std::size_t& offset) const {
39 file << "<VTKFile"
40 << " type=\"PolyData\""
41 << " version=\"1.0\""
42 << " byte_order=\"LittleEndian\""
43 << " header_type=\"" << vtk::xml::to_data_type<HeaderType>()
44 << "\">\n";
45 write_polydata(file, offset);
46 write_appended_data(file);
47 file << "</VTKFile>";
48 }
49 //----------------------------------------------------------------------------
50 auto write_polydata(std::ofstream& file, std::size_t& offset) const {
51 file << " <PolyData>\n";
52 write_piece(file, offset);
53 file << " </PolyData>\n";
54 }
55 //----------------------------------------------------------------------------
56 auto write_piece(std::ofstream& file, std::size_t& offset) const {
57 file << " <Piece"
58 << " NumberOfPoints=\"" << m_line.num_vertices() << "\""
59 << " NumberOfLines=\"" << m_line.num_line_segments() << "\""
60 << ">\n";
61 write_points(file, offset);
62 write_lines(file, offset);
63 write_point_data(file, offset);
64 file << " </Piece>\n";
65 }
66 //----------------------------------------------------------------------------
67 auto write_points(std::ofstream& file, std::size_t& offset) const {
68 auto const num_bytes_points = HeaderType(sizeof(typename Line::real_type) *
69 3 * m_line.num_vertices());
70 file << " <Points>\n"
71 << " <DataArray"
72 << " format=\"appended\""
73 << " offset=\"" << offset << "\""
74 << " type=\""
75 << vtk::xml::to_data_type<typename Line::real_type>()
76 << "\" NumberOfComponents=\"3\"/>\n"
77 << " </Points>\n";
78 offset += num_bytes_points + sizeof(HeaderType);
79 }
80 //----------------------------------------------------------------------------
81 auto write_lines(std::ofstream& file, std::size_t& offset) const {
82 file << " <Lines>\n";
83 write_lines_connectivity(file, offset);
84 write_lines_offsets(file, offset);
85 file << " </Lines>\n";
86 }
87 //----------------------------------------------------------------------------
88 auto write_lines_connectivity(std::ofstream& file,
89 std::size_t& offset) const {
90 auto const num_bytes =
91 m_line.num_line_segments() * 2 * sizeof(ConnectivityInt);
92 file << " <DataArray format=\"appended\" offset=\"" << offset
93 << "\" type=\""
94 << vtk::xml::to_data_type<ConnectivityInt>()
95 << "\" Name=\"connectivity\"/>\n";
96 offset += num_bytes + sizeof(HeaderType);
97 }
98 //----------------------------------------------------------------------------
99 auto write_lines_offsets(std::ofstream& file, std::size_t& offset) const {
100 auto const num_bytes = sizeof(OffsetInt) * m_line.num_line_segments();
101 file << " <DataArray format=\"appended\" offset=\"" << offset
102 << "\" type=\""
103 << vtk::xml::to_data_type<OffsetInt>()
104 << "\" Name=\"offsets\"/>\n";
105 offset += num_bytes + sizeof(HeaderType);
106 }
107 //----------------------------------------------------------------------------
108 auto write_point_data(std::ofstream& file, std::size_t& offset) const {
109 file << " <PointData>\n";
110 for (auto const& [name, prop] : m_line.vertex_properties()) {
111 write_vertex_property_data_array<HeaderType, float, double, vec2f, vec2d,
114 name, *prop, file, offset);
115 }
116 file << " </PointData>\n";
117 }
118 //----------------------------------------------------------------------------
119 auto write_appended_data(std::ofstream& file) const {
120 file << " <AppendedData encoding=\"raw\">\n_";
121 write_vertex_positions_to_appended_data(file);
122 write_line_connectivity_to_appended_data(file);
123 write_line_offsets_to_appended_data(file);
124 for (auto const& [name, prop] : m_line.vertex_properties()) {
125 write_vertex_property_appended_data<
126 HeaderType, float, vec2f, vec3f, vec4f, mat2f, mat3f, mat4f, double,
127 vec2d, vec3d, vec4d, mat2d, mat3d, mat4d>(*prop, file);
128 }
129 file << "\n </AppendedData>\n";
130 }
131 //----------------------------------------------------------------------------
132 auto write_vertex_positions_to_appended_data(std::ofstream& file) const {
133 auto arr_size = HeaderType(sizeof(typename Line::real_type) * 3 *
134 m_line.num_vertices());
135 file.write(reinterpret_cast<char const*>(&arr_size), sizeof(HeaderType));
136 auto zero = (typename Line::real_type)(0);
137 for (auto const v : m_line.vertices()) {
138 if constexpr (num_dimensions() == 2) {
139 file.write(reinterpret_cast<char const*>(m_line[v].data()),
140 sizeof(typename Line::real_type) * 2);
141 file.write(reinterpret_cast<char const*>(&zero),
142 sizeof(typename Line::real_type));
143 } else if constexpr (num_dimensions() == 3) {
144 file.write(reinterpret_cast<char const*>(m_line[v].data()),
145 sizeof(typename Line::real_type) * 3);
146 }
147 }
148 }
149 //----------------------------------------------------------------------------
150 // Writing polys connectivity data to appended data section
151 auto write_line_connectivity_to_appended_data(std::ofstream& file) const {
152 auto connectivity_data = std::vector<ConnectivityInt>{};
153 connectivity_data.reserve(m_line.num_line_segments() * 2);
154 for (ConnectivityInt i = 0;
155 i < static_cast<ConnectivityInt>(m_line.num_vertices()) - 1; ++i) {
156 connectivity_data.push_back(i);
157 connectivity_data.push_back(i + 1);
158 }
159 if (m_line.is_closed()) {
160 connectivity_data.push_back(
161 static_cast<ConnectivityInt>(m_line.num_vertices() - 1));
162 connectivity_data.push_back(0);
163 }
164 auto const arr_size = static_cast<HeaderType>(connectivity_data.size() *
165 sizeof(ConnectivityInt));
166 file.write(reinterpret_cast<char const*>(&arr_size), sizeof(HeaderType));
167 file.write(reinterpret_cast<char const*>(connectivity_data.data()),
168 arr_size);
169
170 // using namespace std::ranges;
171 // auto const num_bytes_connectivity =
172 // m_line.num_line_segments() * 2 * sizeof(ConnectivityInt);
173 // auto connectivity_data =
174 // std::vector<ConnectivityInt>(m_line.num_line_segments() * 2);
175 // auto index = [](auto const x) -> ConnectivityInt { return x.index(); };
176 // copy(m_line.simplices().data_container() | views::transform(index),
177 // begin(connectivity_data));
178 // file.write(reinterpret_cast<char const*>(&num_bytes_connectivity),
179 // sizeof(HeaderType));
180 // file.write(reinterpret_cast<char const*>(connectivity_data.data()),
181 // num_bytes_connectivity);
182 }
183 //----------------------------------------------------------------------------
184 auto write_line_offsets_to_appended_data(std::ofstream& file) const {
185 auto offsets = std::vector<OffsetInt>(m_line.num_line_segments(), 2);
186 for (std::size_t i = 1; i < size(offsets); ++i) {
187 offsets[i] += offsets[i - 1];
188 }
189 auto const arr_size =
190 static_cast<HeaderType>(sizeof(OffsetInt) * m_line.num_line_segments());
191 file.write(reinterpret_cast<char const*>(&arr_size), sizeof(HeaderType));
192 file.write(reinterpret_cast<char const*>(offsets.data()), arr_size);
193
194 // using namespace std::ranges;
195 // auto const num_bytes_offsets =
196 // sizeof(OffsetInt) * m_line.simplices().size();
197 // auto offsets = std::vector<OffsetInt>(m_line.simplices().size(),
198 // m_line.num_vertices_per_simplex());
199 // for (std::size_t i = 1; i < size(offsets); ++i) {
200 // offsets[i] += offsets[i - 1];
201 // };
202 // file.write(reinterpret_cast<char const*>(&num_bytes_offsets),
203 // sizeof(HeaderType));
204 // file.write(reinterpret_cast<char const*>(offsets.data()),
205 // num_bytes_offsets);
206 }
207 //----------------------------------------------------------------------------
208 template <typename... Ts>
209 auto write_vertex_property_data_array(auto const& name,
210 vertex_property_type const& prop,
211 std::ofstream& file,
212 std::size_t& offset) const {
213 invoke([&] {
214 if (prop.type() == typeid(Ts)) {
215 if constexpr (tensor_rank<Ts> <= 1) {
216 file << " <DataArray"
217 << " Name=\"" << name << "\""
218 << " format=\"appended\""
219 << " offset=\"" << offset << "\""
220 << " type=\""
221 << tatooine::vtk::xml::to_data_type<tatooine::value_type<Ts>>()
222 << "\" NumberOfComponents=\""
223 << tensor_num_components<Ts> << "\"/>\n";
224 offset += m_line.num_vertices() * sizeof(Ts) + sizeof(HeaderType);
225 } else if constexpr (tensor_rank<Ts> == 2) {
226 for (std::size_t i = 0; i < Ts::dimension(1); ++i) {
227 file << " <DataArray"
228 << " Name=\"" << name << "_col_" << i << "\""
229 << " format=\"appended\""
230 << " offset=\"" << offset << "\""
231 << " type=\""
232 << vtk::xml::to_data_type<tatooine::value_type<Ts>>()
233 << "\" NumberOfComponents=\"" << Ts::dimension(0) << "\"/>\n";
234 offset += m_line.num_vertices() * sizeof(tatooine::value_type<Ts>) *
235 tensor_dimension<Ts, 0> +
236 sizeof(HeaderType);
237 }
238 }
239 }
240 }...);
241 }
242 //----------------------------------------------------------------------------
243 template <typename... Ts>
245 std::ofstream& file) const {
246 invoke([&] {
247 if (prop.type() == typeid(Ts)) {
248 write_vertex_property_appended_data(prop.template cast_to_typed<Ts>(),
249 file);
250 }
251 }...);
252 }
253 //----------------------------------------------------------------------------
254 template <typename T>
256 typed_vertex_property_type<T> const& prop, std::ofstream& file) const {
257 if constexpr (tensor_rank<T> <= 1) {
258 auto data = std::vector<T>{};
259 for (auto const v : m_line.vertices()) {
260 data.push_back(prop[v]);
261 }
262 auto const num_bytes =
263 HeaderType(sizeof(tatooine::value_type<T>) * tensor_num_components<T> *
264 m_line.num_vertices());
265 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
266 file.write(reinterpret_cast<char const*>(data.data()), num_bytes);
267 } else if constexpr (tensor_rank<T> == 2) {
268 auto const num_bytes =
269 HeaderType(sizeof(tatooine::value_type<T>) * tensor_num_components<T> *
270 m_line.num_vertices() / tensor_dimension<T, 0>);
271 for (std::size_t i = 0; i < tensor_dimension<T, 1>; ++i) {
272 file.write(reinterpret_cast<char const*>(&num_bytes),
273 sizeof(HeaderType));
274 for (auto const v : m_line.vertices()) {
275 auto data_begin = &prop[v](0, i);
276 file.write(reinterpret_cast<char const*>(data_begin),
277 sizeof(tatooine::value_type<T>) * tensor_dimension<T, 0>);
278 }
279 }
280 }
281 }
282};
283//==============================================================================
284} // namespace tatooine::detail::line
285//==============================================================================
286#endif
Definition: merge.h:8
VecF< 3 > vec3f
Definition: vec_typedefs.h:40
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
mat44f mat4f
Definition: mat_typedefs.h:299
VecD< 3 > vec3d
Definition: vec_typedefs.h:51
mat22d mat2d
Definition: mat_typedefs.h:370
mat33d mat3d
Definition: mat_typedefs.h:371
constexpr auto invoke(invocable auto &&...funcs)
Definition: functional.h:8
mat33f mat3f
Definition: mat_typedefs.h:298
VecD< 2 > vec2d
Definition: vec_typedefs.h:50
VecF< 4 > vec4f
Definition: vec_typedefs.h:41
line< real_number, NumDimensions > Line
Definition: line.h:857
VecD< 4 > vec4d
Definition: vec_typedefs.h:52
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
mat22f mat2f
Definition: mat_typedefs.h:297
VecF< 2 > vec2f
Definition: vec_typedefs.h:39
Definition: vtp_writer.h:18
auto write_vertex_positions_to_appended_data(std::ofstream &file) const
Definition: vtp_writer.h:132
auto write(filesystem::path const &path) const
Definition: vtp_writer.h:27
auto write_points(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:67
auto write_line_connectivity_to_appended_data(std::ofstream &file) const
Definition: vtp_writer.h:151
static auto constexpr num_dimensions()
Definition: vtp_writer.h:19
auto write_lines_offsets(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:99
auto write_line_offsets_to_appended_data(std::ofstream &file) const
Definition: vtp_writer.h:184
typename Line::template typed_vertex_property_type< T > typed_vertex_property_type
Definition: vtp_writer.h:23
auto write_polydata(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:50
auto write_vertex_property_appended_data(typed_vertex_property_type< T > const &prop, std::ofstream &file) const
Definition: vtp_writer.h:255
auto write_point_data(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:108
auto write_piece(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:56
auto write_lines(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:81
auto write_vertex_property_appended_data(vertex_property_type const &prop, std::ofstream &file) const
Definition: vtp_writer.h:244
Line const & m_line
Definition: vtp_writer.h:25
auto write_appended_data(std::ofstream &file) const
Definition: vtp_writer.h:119
auto write_vtk_file(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:38
auto write_vertex_property_data_array(auto const &name, vertex_property_type const &prop, std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:209
typename Line::vertex_property_type vertex_property_type
Definition: vtp_writer.h:20
auto write_lines_connectivity(std::ofstream &file, std::size_t &offset) const
Definition: vtp_writer.h:88
Definition: line.h:35
auto vertices() const
Definition: line.h:250
auto num_vertices() const
Definition: line.h:251
Real real_type
Definition: line.h:38
auto num_line_segments() const
Definition: line.h:252
static constexpr auto num_dimensions() -> std::size_t
Definition: line.h:72
deque_property< vertex_handle > vertex_property_type
Definition: line.h:55
auto is_closed() const
Definition: line.h:305
auto vertex_properties() const -> auto const &
Definition: line.h:450
Definition: mat.h:14