1 | /* |
2 | * VTKWriter_grids.hpp |
3 | * |
4 | * Created on: May 5, 2015 |
5 | * Author: Pietro Incardona |
6 | */ |
7 | |
8 | #ifndef VTKWRITER_GRIDS_HPP_ |
9 | #define VTKWRITER_GRIDS_HPP_ |
10 | |
11 | #include <boost/mpl/pair.hpp> |
12 | #include "VTKWriter_grids_util.hpp" |
13 | #include "is_vtk_writable.hpp" |
14 | |
15 | /*! \brief It store one grid |
16 | * |
17 | * \tparam Grid type of grid |
18 | * \tparam St type of space where the grid is defined |
19 | * |
20 | */ |
21 | template <typename Grid, typename St> |
22 | class ele_g |
23 | { |
24 | public: |
25 | |
26 | typedef Grid value_type; |
27 | |
28 | ele_g(const Grid & g, const Point<Grid::dims,St> & offset, const Point<Grid::dims,St> & spacing, const Box<Grid::dims,St> & dom) |
29 | :g(g),offset(offset),spacing(spacing),dom(dom) |
30 | {} |
31 | |
32 | //! Dataset name |
33 | std::string dataset; |
34 | //! Grid |
35 | const Grid & g; |
36 | //! offset where it start |
37 | Point<Grid::dims,St> offset; |
38 | // spacing of the grid |
39 | Point<Grid::dims,St> spacing; |
40 | // Part of the grid that is real domain |
41 | Box<Grid::dims,size_t> dom; |
42 | }; |
43 | |
44 | |
45 | |
46 | /*! \brief this class is a functor for "for_each" algorithm |
47 | * |
48 | * This class is a functor for "for_each" algorithm. For each |
49 | * element of the boost::vector the operator() is called. |
50 | * Is mainly used to produce at output for each property |
51 | * |
52 | * \tparam ele_g element that store the grid and its attributes |
53 | * \param St type of space where the grid live |
54 | * |
55 | */ |
56 | |
57 | template<typename ele_g, typename St> |
58 | struct prop_out_g |
59 | { |
60 | //! property output string |
61 | std::string & v_out; |
62 | |
63 | //! grid that we are processing |
64 | const openfpm::vector_std< ele_g > & vg; |
65 | |
66 | //! File type |
67 | file_type ft; |
68 | |
69 | //! list of names for the properties |
70 | const openfpm::vector<std::string> & prop_names; |
71 | |
72 | /*! \brief constructor |
73 | * |
74 | * \param v_out string to fill with the vertex properties |
75 | * \param vg vector of elements to write |
76 | * \param prop_names properties name |
77 | * \param ft file type |
78 | * |
79 | */ |
80 | prop_out_g(std::string & v_out, const openfpm::vector_std< ele_g > & vg, const openfpm::vector<std::string> & prop_names ,file_type ft) |
81 | :v_out(v_out),vg(vg),ft(ft),prop_names(prop_names) |
82 | {}; |
83 | |
84 | /*! It produce an output for each propert |
85 | * |
86 | * \param t prop-id |
87 | * |
88 | */ |
89 | template<typename T> |
90 | void operator()(T& t) const |
91 | { |
92 | typedef typename boost::mpl::at<typename ele_g::value_type::value_type::type,boost::mpl::int_<T::value>>::type ptype; |
93 | typedef typename std::remove_all_extents<ptype>::type base_ptype; |
94 | |
95 | meta_prop<boost::mpl::int_<T::value> ,ele_g,St, ptype, is_vtk_writable<base_ptype>::value > m(vg,v_out,prop_names,ft); |
96 | } |
97 | |
98 | /*! \brief Write the last property |
99 | * |
100 | * |
101 | * |
102 | */ |
103 | void lastProp() |
104 | { |
105 | // Create point data properties |
106 | v_out += "SCALARS domain float\n" ; |
107 | |
108 | // Default lookup table |
109 | v_out += "LOOKUP_TABLE default\n" ; |
110 | |
111 | // Produce point data |
112 | for (size_t k = 0 ; k < vg.size() ; k++) |
113 | { |
114 | //! Get a vertex iterator |
115 | auto it = vg.get(k).g.getIterator(); |
116 | |
117 | // if there is the next element |
118 | while (it.isNext()) |
119 | { |
120 | if (ft == file_type::ASCII) |
121 | { |
122 | if (vg.get(k).dom.isInside(it.get().toPoint()) == true) |
123 | { |
124 | float flag = 1.0; |
125 | flag += vg.get(k).g.getFlag(it.get()) * 2; |
126 | v_out += std::to_string(flag) + "\n" ; |
127 | } |
128 | else |
129 | { |
130 | float flag = 0.0; |
131 | flag += vg.get(k).g.getFlag(it.get()) * 2; |
132 | v_out += std::to_string(flag) + "\n" ; |
133 | } |
134 | } |
135 | else |
136 | { |
137 | if (vg.get(k).dom.isInside(it.get().toPoint()) == true) |
138 | { |
139 | float flag = 1.0; |
140 | flag = swap_endian_lt(flag); |
141 | v_out.append((const char *)&flag,sizeof(flag)); |
142 | } |
143 | else |
144 | { |
145 | float flag = 0.0; |
146 | flag = swap_endian_lt(flag); |
147 | v_out.append((const char *)&flag,sizeof(flag)); |
148 | } |
149 | } |
150 | |
151 | // increment the iterator and counter |
152 | ++it; |
153 | } |
154 | } |
155 | } |
156 | }; |
157 | |
158 | /*! |
159 | * |
160 | * It write a VTK format file in case of grids defined on a space |
161 | * |
162 | * \tparam boost::mpl::pair<G,S> |
163 | * |
164 | * where G is the type of grid S is the type of space, float, double ... |
165 | * |
166 | */ |
167 | template <typename pair> |
168 | class VTKWriter<pair,VECTOR_GRIDS> |
169 | { |
170 | //! Vector of grids |
171 | |
172 | openfpm::vector< ele_g<typename pair::first,typename pair::second> > vg; |
173 | /*! \brief Get the total number of points |
174 | * |
175 | * \return the total number |
176 | * |
177 | */ |
178 | size_t get_total() |
179 | { |
180 | size_t tot = 0; |
181 | |
182 | //! Calculate the full number of vertices |
183 | for (size_t i = 0 ; i < vg.size() ; i++) |
184 | { |
185 | tot += vg.get(i).g.size(); |
186 | } |
187 | return tot; |
188 | } |
189 | |
190 | /*! \brief It get the vertex properties list |
191 | * |
192 | * It get the vertex properties list of the vertex defined as VTK header |
193 | * |
194 | * \return a string that define the vertex properties in graphML format |
195 | * |
196 | */ |
197 | |
198 | std::string get_vertex_properties_list() |
199 | { |
200 | //! vertex property output string |
201 | std::string v_out; |
202 | |
203 | // write the number of vertex |
204 | v_out += "VERTICES " + std::to_string(get_total()) + " " + std::to_string(get_total() * 2) + "\n" ; |
205 | |
206 | // return the vertex properties string |
207 | return v_out; |
208 | } |
209 | |
210 | /*! \brief It get the vertex properties list |
211 | * |
212 | * It get the vertex properties list of the vertex defined as a VTK header |
213 | * |
214 | * \return a string that define the vertex properties in graphML format |
215 | * |
216 | */ |
217 | |
218 | std::string get_point_properties_list() |
219 | { |
220 | //! vertex property output string |
221 | std::string v_out; |
222 | |
223 | // write the number of vertex |
224 | v_out += "POINTS " + std::to_string(get_total()) + " float" + "\n" ; |
225 | |
226 | // return the vertex properties string |
227 | return v_out; |
228 | } |
229 | |
230 | /*! \brief Create the VTK point definition |
231 | * |
232 | * \param ft file type |
233 | * |
234 | * \return the string with the point list |
235 | * |
236 | */ |
237 | std::string get_point_list(file_type ft) |
238 | { |
239 | //! vertex node output string |
240 | std::stringstream v_out; |
241 | |
242 | //! For each defined grid |
243 | |
244 | for (size_t i = 0 ; i < vg.size() ; i++) |
245 | { |
246 | //! Get the iterator |
247 | auto it = vg.get(i).g.getIterator(); |
248 | |
249 | //! Where the grid is defined |
250 | Box<pair::first::dims,typename pair::second> dom; |
251 | |
252 | // if there is the next element |
253 | while (it.isNext()) |
254 | { |
255 | Point<pair::first::dims,typename pair::second> p; |
256 | p = it.get().toPoint(); |
257 | p = pmul(p,vg.get(i).spacing) + vg.get(i).offset; |
258 | |
259 | output_point<pair::first::dims,typename pair::second>(p,v_out,ft); |
260 | |
261 | // increment the iterator and counter |
262 | ++it; |
263 | } |
264 | } |
265 | |
266 | // return the vertex list |
267 | return v_out.str(); |
268 | } |
269 | |
270 | /*! \brief Create the VTK vertex definition |
271 | * |
272 | * \param ft file type |
273 | * |
274 | */ |
275 | std::string get_vertex_list(file_type ft) |
276 | { |
277 | //! vertex node output string |
278 | std::string v_out; |
279 | |
280 | size_t k = 0; |
281 | |
282 | for (size_t i = 0 ; i < vg.size() ; i++) |
283 | { |
284 | //! For each grid point create a vertex |
285 | auto it = vg.get(i).g.getIterator(); |
286 | |
287 | while (it.isNext()) |
288 | { |
289 | output_vertex(k,v_out,ft); |
290 | |
291 | ++k; |
292 | ++it; |
293 | } |
294 | } |
295 | // return the vertex list |
296 | return v_out; |
297 | } |
298 | |
299 | /*! \brief Get the point data header |
300 | * |
301 | * \return a string with the point data header for VTK format |
302 | * |
303 | */ |
304 | |
305 | std::string () |
306 | { |
307 | std::string v_out; |
308 | |
309 | v_out += "POINT_DATA " + std::to_string(get_total()) + "\n" ; |
310 | |
311 | return v_out; |
312 | } |
313 | |
314 | public: |
315 | |
316 | /*! |
317 | * |
318 | * VTKWriter constructor |
319 | * |
320 | */ |
321 | VTKWriter() |
322 | {} |
323 | |
324 | /*! \brief Add grid dataset |
325 | * |
326 | * \param g Grid to add |
327 | * \param offset grid offset |
328 | * \param spacing spacing of the grid |
329 | * \param dom part of the space that is the domain |
330 | * |
331 | */ |
332 | void add(const typename pair::first & g, |
333 | const Point<pair::first::dims,typename pair::second> & offset, |
334 | const Point<pair::first::dims,typename pair::second> & spacing, |
335 | const Box<pair::first::dims,typename pair::second> & dom) |
336 | { |
337 | ele_g<typename pair::first,typename pair::second> t(g,offset,spacing,dom); |
338 | |
339 | vg.add(t); |
340 | } |
341 | |
342 | /*! \brief It write a VTK file from a graph |
343 | * |
344 | * \tparam prp_out which properties to output [default = -1 (all)] |
345 | * |
346 | * \param file path where to write |
347 | * \param name of the graph |
348 | * \param prop_names properties name (can also be a vector of size 0) |
349 | * \param ft specify if it is a VTK BINARY or ASCII file [default = ASCII] |
350 | * |
351 | * \return true if the function write successfully |
352 | * |
353 | */ |
354 | template<int prp = -1> bool write(std::string file, |
355 | const openfpm::vector<std::string> & prop_names, |
356 | std::string f_name = "grids" , |
357 | file_type ft = file_type::ASCII) |
358 | { |
359 | // Header for the vtk |
360 | std::string ; |
361 | // Point list of the VTK |
362 | std::string point_list; |
363 | // Vertex list of the VTK |
364 | std::string vertex_list; |
365 | // Graph header |
366 | std::string vtk_binary_or_ascii; |
367 | // vertex properties header |
368 | std::string ; |
369 | // edge properties header |
370 | std::string ; |
371 | // Data point header |
372 | std::string ; |
373 | // Data point |
374 | std::string point_data; |
375 | |
376 | // VTK header |
377 | vtk_header = "# vtk DataFile Version 3.0\n" |
378 | + f_name + "\n" ; |
379 | |
380 | // Choose if binary or ASCII |
381 | if (ft == file_type::ASCII) |
382 | {vtk_header += "ASCII\n" ;} |
383 | else |
384 | {vtk_header += "BINARY\n" ;} |
385 | |
386 | // Data type for graph is DATASET POLYDATA |
387 | vtk_header += "DATASET POLYDATA\n" ; |
388 | |
389 | // point properties header |
390 | point_prop_header = get_point_properties_list(); |
391 | |
392 | // Get point list |
393 | point_list = get_point_list(ft); |
394 | |
395 | // vertex properties header |
396 | vertex_prop_header = get_vertex_properties_list(); |
397 | |
398 | // Get vertex list |
399 | vertex_list = get_vertex_list(ft); |
400 | |
401 | // Get the point data header |
402 | point_data_header = get_point_data_header(); |
403 | |
404 | // For each property in the vertex type produce a point data |
405 | |
406 | prop_out_g< ele_g<typename pair::first,typename pair::second>, typename pair::second > pp(point_data, vg, prop_names, ft); |
407 | |
408 | if (prp == -1) |
409 | {boost::mpl::for_each< boost::mpl::range_c<int,0, pair::first::value_type::max_prop> >(pp);} |
410 | else |
411 | {boost::mpl::for_each< boost::mpl::range_c<int,prp, prp> >(pp);} |
412 | |
413 | // Add the last property |
414 | pp.lastProp(); |
415 | |
416 | |
417 | // write the file |
418 | std::ofstream ofs(file); |
419 | |
420 | // Check if the file is open |
421 | if (ofs.is_open() == false) |
422 | {std::cerr << "Error cannot create the VTK file: " + file + "\n" ;} |
423 | |
424 | ofs << vtk_header << point_prop_header << point_list << |
425 | vertex_prop_header << vertex_list << point_data_header << point_data; |
426 | |
427 | // Close the file |
428 | |
429 | ofs.close(); |
430 | |
431 | // Completed succefully |
432 | return true; |
433 | } |
434 | }; |
435 | |
436 | |
437 | #endif /* VTKWRITER_GRAPH_HPP_ */ |
438 | |