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 */
21template <typename Grid, typename St>
22class ele_g
23{
24public:
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
57template<typename ele_g, typename St>
58struct 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 */
167template <typename pair>
168class 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 get_point_data_header()
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
314public:
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 vtk_header;
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 point_prop_header;
369 // edge properties header
370 std::string vertex_prop_header;
371 // Data point header
372 std::string point_data_header;
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