1/*
2 * VTKWriter_graph.hpp
3 *
4 * Created on: May 5, 2015
5 * Author: Pietro Incardona
6 */
7
8#ifndef VTKWRITER_DIST_GRAPH_HPP_
9#define VTKWRITER_DIST_GRAPH_HPP_
10
11#include "VCluster/VCluster.hpp"
12
13/*! Property data store for scalar and vector
14 *
15 */
16template<bool is_array>
17struct vtk_dist_vertex_node_array_scalar_selector
18{
19 /*! /brief Print the geometric informations in case it is not an array
20 *
21 * \tparam T Type of the vertex
22 * \tparam ele_v Attribute element to check
23 * \tparam G Graph of reference
24 * \tparam s_type Vertex spatial type information
25 *
26 * \param vo Vertex object container
27 * \param x Array to store geometric informations
28 * \param z_set Value set to true id z axis is in use
29 */
30 template<typename T, typename ele_v, typename G, typename s_type>
31 static inline void move(typename G::V_container &vo, s_type (&x)[3], bool &z_set)
32 {
33 if (G::V_type::attributes::name[T::value] == "x")
34 {
35 x[0] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>())>::type>::template to<s_type>(vo.template get<T::value>());
36 }
37 else if (G::V_type::attributes::name[T::value] == "y")
38 {
39 x[1] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>())>::type>::template to<s_type>(vo.template get<T::value>());
40 }
41 else if (G::V_type::attributes::name[T::value] == "z")
42 {
43 x[2] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>())>::type>::template to<s_type>(vo.template get<T::value>());
44 z_set = true;
45 }
46 }
47};
48
49/*! Template specialization in the case of array type attribute
50 *
51 */
52template<>
53struct vtk_dist_vertex_node_array_scalar_selector<true>
54{
55 /*! \brief Store the geometric informations in case it is an array
56 *
57 * \tparam T Type of the vertex
58 * \tparam ele_v Attribute element to check
59 * \tparam G Graph of reference
60 * \tparam s_type Vertex spatial type information
61 *
62 * \param vo Vertex object container
63 * \param x Array to store geometric informations
64 * \param z_set Value set to true id z axis is in use
65 */
66 template<typename T, typename ele_v, typename G, typename s_type>
67 static inline void move(typename G::V_container &vo, s_type (&x)[3], bool &z_set)
68 {
69 if (std::extent<ele_v>::value == 3)
70 z_set = true;
71
72 for (size_t i = 0; i < std::extent<ele_v>::value; i++)
73 x[i] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>()[i])>::type>::template to<s_type>(vo.template get<T::value>()[i]);
74
75 }
76};
77
78/*! \brief this class is a functor for "for_each" algorithm
79 *
80 * This class is a functor for "for_each" algorithm. For each
81 * element of the boost::vector the operator() is called.
82 * Is mainly used to create a string containing all the vertex
83 * properties
84 *
85 * \tparam G graph type
86 * \tparam attr has the vertex attributes
87 *
88 */
89
90template<typename G, bool attr>
91struct vtk_dist_vertex_node
92{
93 //! Vertex spatial type information
94 typedef typename G::V_type::s_type s_type;
95
96 //! indicate if the z coordinate has been set
97 bool z_set;
98
99 //! coordinate of the vertex node
100 s_type (&x)[3];
101
102 //! Vertex object container
103 typename G::V_container & vo;
104
105 //! vertex position converted to string
106 std::string & v_node;
107
108 /*! \brief Constructor
109 *
110 * Create a vertex properties list
111 *
112 * \param v_node std::string that is filled with the graph properties in the GraphML format
113 * \param n_obj object container to access its properties for example encapc<...>
114 * \param x position of the vertex
115 *
116 */
117 vtk_dist_vertex_node(std::string & v_node, typename G::V_container & n_obj, s_type (&x)[3])
118 :z_set(false),x(x), vo(n_obj), v_node(v_node)
119 {
120 }
121
122 //! \brief Write collected information
123 void write()
124 {
125 v_node += std::to_string(x[0]) + " " + std::to_string(x[1]) + " " + std::to_string(x[2]) + "\n";
126 }
127
128 /*! \brief It call the functor for each attribute
129 *
130 * \param t attribute id
131 *
132 */
133 template<typename T>
134 void operator()(T& t)
135 {
136 typedef typename boost::mpl::at<typename G::V_type::type, boost::mpl::int_<T::value>>::type ele_v;
137
138 // if the attribute name is x y or z, create a string with the value of the properties and store it
139
140 vtk_dist_vertex_node_array_scalar_selector<std::is_array<ele_v>::value>::template move<T, ele_v, G, s_type>(vo, x, z_set);
141
142 }
143};
144
145/*! \brief this class is a functor for "for_each" algorithm
146 *
147 * This class is a functor for "for_each" algorithm. For each
148 * element of the boost::vector the operator() is called.
149 * Is mainly used to create a string containing all the vertex
150 * properties
151 *
152 * Specialization when we do not have vertex attributes
153 *
154 * \tparam G graph type
155 *
156 */
157
158template<typename G>
159struct vtk_dist_vertex_node<G, false>
160{
161 //! Vertex object container
162 typename G::V_container & vo;
163
164 //! vertex position string
165 std::string & v_node;
166
167 /*! \brief Constructor
168 *
169 * Create a vertex properties list
170 *
171 * \param v_node std::string that is filled with the graph properties in the GraphML format
172 * \param n_obj object container to access its properties for example encapc<...>
173 *
174 */
175 vtk_dist_vertex_node(std::string & v_node, typename G::V_container & n_obj) :
176 vo(n_obj), v_node(v_node)
177 {
178 }
179
180 /*! \brief It call the functor for each attribute
181 *
182 * \param t attribute id
183 *
184 */
185 template<typename T>
186 void operator()(T& t)
187 {
188 v_node += "0 0 0\n";
189 }
190};
191
192/*! \brief this class is a functor for "for_each" algorithm
193 *
194 * This class is a functor for "for_each" algorithm. For each
195 * element of the boost::vector the operator() is called.
196 * Is mainly used to create a string containing all the edge
197 * properties
198 *
199 */
200
201template<typename G>
202struct vtk_dist_edge_node
203{
204 //! Vertex object container
205 typename G::E_container & vo;
206
207 //! edge node string
208 std::string & e_node;
209
210 /*! \brief Constructor
211 *
212 * Create an edge node
213 *
214 * \param e_node std::string that is filled with the graph properties in the GraphML format
215 * \param n_obj object container to access the object properties for example encapc<...>
216 *
217 */
218 vtk_dist_edge_node(std::string & e_node, typename G::E_container & n_obj)
219 :vo(n_obj), e_node(e_node)
220 {
221 }
222
223 /*! \brief Create an edge
224 *
225 * \param vc node id
226 * \param s source node
227 * \param d destination node
228 *
229 */
230 void new_node(size_t vc, size_t s, size_t d)
231 {
232 // start a new node
233 e_node += "2 " + std::to_string(s) + " " + std::to_string(d) + "\n";
234 }
235};
236
237/*! \brief Property writer for scalar and vector
238 *
239 */
240template<bool is_array>
241struct dist_prop_output_array_scalar_selector_vertex
242{
243 /*! \brief Writer in case the property is not an array
244 *
245 * \tparam ele_v Property element
246 * \tparam Graph Graph of reference
247 * \tparam i Property id
248 *
249 * \param v_out Buffer to write into
250 * \param g Graph
251 * \param p Property id
252 */
253 template<typename ele_v, typename Graph, unsigned int i>
254 static inline void write(std::string &v_out, const Graph &g, size_t p)
255 {
256 v_out += std::to_string(g.vertex(p).template get<i>()) + "\n";
257 }
258};
259
260/*! \brief Property writer for vector
261 *
262 */
263template<>
264struct dist_prop_output_array_scalar_selector_vertex<true>
265{
266 /*! \brief Writer in case the property is an array
267 *
268 * \tparam ele_v Property element
269 * \tparam Graph Graph of reference
270 * \tparam i Property id
271 *
272 * \param v_out Buffer to write into
273 * \param g Graph
274 * \param p Property id
275 */
276 template<typename ele_v, typename Graph, unsigned int i>
277 static inline void write(std::string &v_out, const Graph &g, size_t p)
278 {
279 for (size_t j = 0; j < 2; j++)
280 {
281 v_out += std::to_string(g.vertex(p).template get<i>()[j]) + " ";
282 }
283
284 if (std::extent<ele_v>::value == 2)
285 v_out += "0";
286 else
287 v_out += std::to_string(g.vertex(p).template get<i>()[2]);
288
289 v_out += "\n";
290 }
291};
292
293/*! \brief Property writer for scalar and vector
294 *
295 */
296template<bool is_array>
297struct dist_prop_output_array_scalar_selector_edge
298{
299 /*! \brief Writer in case the property is not an array
300 *
301 * \tparam ele_v Property element
302 * \tparam Graph Graph of reference
303 * \tparam i Property id for the edge
304 *
305 * \param v_out Buffer to write into
306 * \param g Graph
307 * \param edge edge object
308 */
309 template<typename ele_v, typename Graph, unsigned int i>
310 static inline void write(std::string &v_out, const Graph &g, const typename Graph::E_container &edge)
311 {
312 v_out += std::to_string(edge.template get<i>()) + "\n";
313 }
314};
315
316/*! \brief Property writer for vector
317 *
318 */
319template<>
320struct dist_prop_output_array_scalar_selector_edge<true>
321{
322 /*! \brief Writer in case the property is an array
323 *
324 * \tparam ele_v Property element
325 * \tparam Graph Graph of reference
326 * \tparam i Property id
327 *
328 * \param v_out Buffer to write into
329 * \param g Graph
330 * \param edge edge object
331 */
332 template<typename ele_v, typename Graph, unsigned int i>
333 static inline void write(std::string &v_out, const Graph &g, const typename Graph::E_container &edge)
334 {
335 for (size_t j = 0; j < 2; j++)
336 {
337 v_out += std::to_string(edge.template get<i>()[j]) + " ";
338 }
339
340 if (std::extent<ele_v>::value == 2)
341 v_out += "0";
342 else
343 v_out += std::to_string(edge.template get<i>()[2]);
344
345 v_out += "\n";
346 }
347};
348
349/*! \brief Property writer for scalar and vector, it fill the vertex data (needed for edge representation in vtk)
350 *
351 */
352template<bool is_array>
353struct dist_prop_output_array_scalar_selector_edge_fill_vertex
354{
355 /*! \brief Writer in case the property is not an array
356 *
357 * \param v_out Buffer to write into
358 */
359 static inline void write(std::string &v_out)
360 {
361 v_out += "0\n";
362 }
363};
364
365/*! \brief Property writer for vector
366 *
367 */
368template<>
369struct dist_prop_output_array_scalar_selector_edge_fill_vertex<true>
370{
371 /*! \brief Writer in case the property is an array
372 *
373 * \param v_out Buffer to write into
374 */
375 static inline void write(std::string &v_out)
376 {
377 v_out += "0 0 0\n";
378 }
379};
380
381/*! \brief This class specialize functions in the case the type T
382 * has or not defined attributes
383 *
384 * In C++ partial specialization of a function is not allowed so we have to
385 * encapsulate this function in a class
386 *
387 * \tparam has_attributes parameter that specialize the function in case the vertex
388 * define or not attributes name
389 *
390 * \tparam Graph type of graph we are processing
391 * \tparam i the property we are going to write
392 *
393 */
394
395template<bool has_attributes, typename Graph, unsigned int i>
396class dist_prop_output
397{
398public:
399
400 /*! \brief For each vertex set the value
401 *
402 *
403 * \param g graph to output
404 *
405 * \return get the point data string
406 *
407 */
408 static std::string get_point_data(const Graph & g)
409 {
410 //! vertex node output string
411 std::string v_out;
412
413 //! Get a vertex iterator
414 auto it = g.getVertexIterator();
415
416 // if there is the next element
417 while (it.isNext())
418 {
419 typedef typename boost::mpl::at<typename Graph::V_type::type, boost::mpl::int_<i>>::type ele_v;
420 dist_prop_output_array_scalar_selector_vertex<std::is_array<ele_v>::value>::template write<ele_v, Graph, i>(v_out, g, it.get());
421
422 // increment the iterator and counter
423 ++it;
424 }
425
426 return v_out;
427 }
428
429 /*! \brief For each edge set the value, set 1 on vertices, needed by vtk file format
430 *
431 * \param g graph to output
432 *
433 * \return the cell-data string
434 *
435 */
436
437 static std::string get_cell_data(const Graph & g)
438 {
439 //! vertex node output string
440 std::string e_out;
441
442 //! Get a vertex iterator
443 auto it_v = g.getVertexIterator();
444
445 // if there is the next element
446 while (it_v.isNext())
447 {
448 // Print the property
449 typedef typename boost::mpl::at<typename Graph::E_type::type, boost::mpl::int_<i>>::type ele_v;
450 dist_prop_output_array_scalar_selector_edge_fill_vertex<std::is_array<ele_v>::value>::write(e_out);
451
452 // increment the iterator and counter
453 ++it_v;
454 }
455
456 //! Get an edge iterator
457 auto it_e = g.getEdgeIterator();
458
459 // if there is the next element
460 while (it_e.isNext())
461 {
462 typedef typename boost::mpl::at<typename Graph::E_type::type, boost::mpl::int_<i>>::type ele_v;
463 dist_prop_output_array_scalar_selector_edge<std::is_array<ele_v>::value>::template write<ele_v, Graph, i>(e_out, g, g.edge(it_e.get()));
464
465 // increment the iterator and counter
466 ++it_e;
467 }
468
469 return e_out;
470 }
471
472 /*! \brief Given a Graph return the point data header for a typename T
473 *
474 * \param prop property id
475 *
476 * \return the string with the property header
477 *
478 */
479 static std::string get_point_property_header(size_t prop)
480 {
481 //! vertex node output string
482 std::string v_out;
483
484 // Type of the property
485 std::string type;
486
487 typedef typename boost::mpl::at<typename Graph::V_type::type, boost::mpl::int_<i>>::type T;
488
489 // Check if T is a supported format
490 // for now we support only scalar of native type
491 if (std::is_array<T>::value == true && std::is_array<typename std::remove_extent<T>::type>::value == false)
492 {
493 //Get type of the property
494 type = getType<typename std::remove_all_extents<T>::type>();
495
496 // if the type is not supported return
497 if (type.size() == 0)
498 return v_out;
499
500 // Create point data properties
501 v_out += "VECTORS " + get_attributes_vertex() + " " + type + "\n";
502 }
503 else
504 {
505 type = getType<T>();
506
507 // if the type is not supported return
508 if (type.size() == 0)
509 return v_out;
510
511 // Create point data properties
512 v_out += "SCALARS " + get_attributes_vertex() + " " + type + "\n";
513
514 // Default lookup table
515 v_out += "LOOKUP_TABLE default\n";
516
517 }
518
519 // return the vertex list
520 return v_out;
521 }
522
523 /*! \brief Given a Graph return the cell data header for a typename T
524 *
525 * \param prop property number
526 *
527 * \return the cell string header
528 *
529 */
530 static std::string get_cell_property_header(size_t prop)
531 {
532 //! edge node output string
533 std::string e_out;
534
535 // Type of the property
536 std::string type;
537
538 typedef typename boost::mpl::at<typename Graph::E_type::type, boost::mpl::int_<i>>::type T;
539
540 // Check if T is a supported format
541 // for now we support only scalar of native type
542 if (std::is_array<T>::value == true && std::is_array<typename std::remove_extent<T>::type>::value == false)
543 {
544 //Get type of the property
545 type = getType<typename std::remove_all_extents<T>::type>();
546
547 // if the type is not supported return
548 if (type.size() == 0)
549 return e_out;
550
551 // Create point data properties
552 e_out += "VECTORS " + get_attributes_edge() + " " + type + "\n";
553 }
554 else
555 {
556 type = getType<T>();
557
558 // if the type is not supported return
559 if (type.size() == 0)
560 return e_out;
561
562 // Create point data properties
563 e_out += "SCALARS " + get_attributes_edge() + " " + type + "\n";
564
565 // Default lookup table
566 e_out += "LOOKUP_TABLE default\n";
567
568 }
569
570 // return the vertex list
571 return e_out;
572 }
573
574 /*! \brief Get the attributes name for vertex
575 *
576 * \return string with the attribute name
577 *
578 */
579 static std::string get_attributes_vertex()
580 {
581 return Graph::V_type::attributes::name[i];
582 }
583
584 /*! \brief Get the attributes name for edge
585 *
586 * \return the attribute name for the edge
587 *
588 */
589 static std::string get_attributes_edge()
590 {
591 return Graph::E_type::attributes::name[i];
592 }
593};
594
595/*! \brief This class specialize functions in the case the type T
596 * has not defined attributes
597 *
598 * In C++ partial specialization of a function is not allowed so we have to
599 * encapsulate this function in a class
600 *
601 * \tparam has_attributes parameter that specialize the function in case the vertex
602 * define or not attributes name
603 *
604 * \tparam i id of the property we are going to write
605 *
606 */
607
608template<typename Graph, unsigned int i>
609class dist_prop_output<false, Graph, i>
610{
611 /*! \brief For each vertex output the property string
612 *
613 * \param g graph to print
614 *
615 * \return the string with the point data
616 *
617 */
618 static std::string get_point_data(Graph & g)
619 {
620 //! vertex node output string
621 std::string v_out;
622
623 //! Get a vertex iterator
624 auto it = g.getVertexIterator();
625
626 // if there is the next element
627 while (it.isNext())
628 {
629 // Print the property
630 v_out += std::to_string(g.vertex(it.get()).template get<i>()) + "\n";
631
632 // increment the iterator and counter
633 ++it;
634 }
635
636 return v_out;
637 }
638
639 /*! \brief For each edge output the property string
640 *
641 * \param g graph to print
642 *
643 * \return the string containing cell-data
644 *
645 */
646 static std::string get_cell_data(const Graph & g)
647 {
648 //! vertex node output string
649 std::string e_out;
650
651 //! Get a vertex iterator
652 auto it_v = g.getVertexIterator();
653
654 // if there is the next element
655 while (it_v.isNext())
656 {
657 // Print the property
658 e_out += std::to_string(0) + "\n";
659
660 // increment the iterator and counter
661 ++it_v;
662 }
663
664 //! Get an edge iterator
665 auto it_e = g.getEdgeIterator();
666
667 // if there is the next element
668 while (it_e.isNext())
669 {
670 // Print the property
671 e_out += std::to_string(g.edge(it_e.get()).template get<i>()) + "\n";
672
673 // increment the iterator and counter
674 ++it_e;
675 }
676
677 return e_out;
678 }
679
680 /*! \brief Given a Graph return the point data header for a typename T
681 *
682 * \param prop id of the property
683 *
684 * \return the string containing the header
685 *
686 */
687 static std::string get_point_property_header(size_t prop)
688 {
689 //! vertex node output string
690 std::string v_out;
691
692 // Check if T is a supported format
693 // for now we support only scalar of native type
694
695 std::string type = getType<boost::fusion::result_of::at<typename Graph::V_type::type, boost::mpl::int_<i>>>("attr" + std::to_string(prop));
696
697 // if the type is not supported return
698 if (type.size() == 0)
699 {
700 return v_out;
701 }
702
703 // Create point data properties
704 v_out += "SCALARS " + get_attributes_vertex() + " " + type + "\n";
705
706 // Default lookup table
707 v_out += "LOOKUP_TABLE default\n";
708
709 // return the vertex list
710 return v_out;
711 }
712
713 /*! \brief Given a Graph return the cell data header for a typename T
714 *
715 * \param prop property id
716 *
717 * \return the string containing the header
718 *
719 */
720 static std::string get_cell_property_header(size_t prop)
721 {
722 //! edge node output string
723 std::string e_out;
724
725 // Type of the property
726 std::string type;
727
728 typedef typename boost::mpl::at<typename Graph::E_type::type, boost::mpl::int_<i>>::type T;
729
730 // Check if T is a supported format
731 // for now we support only scalar of native type
732 if (std::is_array<T>::value == true && std::is_array<typename std::remove_extent<T>::type>::value == false)
733 {
734 //Get type of the property
735 type = getType<typename std::remove_all_extents<T>::type>();
736
737 // if the type is not supported return
738 if (type.size() == 0)
739 return e_out;
740
741 // Create point data properties
742 e_out += "VECTORS " + get_attributes_edge() + " " + type + "\n";
743 }
744 else
745 {
746 type = getType<T>();
747
748 // if the type is not supported return
749 if (type.size() == 0)
750 return e_out;
751
752 // Create point data properties
753 e_out += "SCALARS " + get_attributes_edge() + " " + type + "\n";
754
755 // Default lookup table
756 e_out += "LOOKUP_TABLE default\n";
757
758 }
759
760 // return the vertex list
761 return e_out;
762 }
763
764 /*! \brief Get the attributes name for vertex
765 *
766 * \return the string containing the vertex attribute name
767 *
768 */
769 static std::string get_attributes_vertex()
770 {
771 return Graph::V_type::attributes::name[i];
772 }
773
774 /*! \brief Get the attributes name for edge
775 *
776 * \return the edge attribute name
777 *
778 */
779 static std::string get_attributes_edge()
780 {
781 return Graph::E_type::attributes::name[i];
782 }
783};
784
785/*! \brief this class is a functor for "for_each" algorithm
786 *
787 * This class is a functor for "for_each" algorithm. For each
788 * element of the boost::vector the operator() is called.
789 * Is mainly used to produce at output for each property
790 *
791 * \tparam Graph graph we are processing
792 *
793 * \param dim Dimensionality
794 * \param S type of grid
795 *
796 */
797
798template<typename Graph>
799struct dist_prop_out_vertex
800{
801 //! property output string
802 std::string & v_out;
803
804 //! Graph that we are processing
805 const Graph & g;
806
807 /*! \brief constructor
808 *
809 * \param v_out string to fill with the vertex properties
810 * \param g graph to process
811 *
812 */
813 dist_prop_out_vertex(std::string & v_out, const Graph & g)
814 :v_out(v_out), g(g)
815 {
816 }
817
818 /*! \brief It produce an output for each property
819 *
820 * \param t property id
821 *
822 */
823 template<typename T>
824 void operator()(T& t) const
825 {
826 // actual string size
827 size_t sz = v_out.size();
828
829 // Produce the point properties header
830 v_out += dist_prop_output<has_attributes<typename Graph::V_type>::value, Graph, T::value>::get_point_property_header(t);
831
832 // If the output has changed, we have to write the properties
833 if (v_out.size() != sz)
834 {
835 std::string attr = dist_prop_output<has_attributes<typename Graph::V_type>::value, Graph, T::value>::get_attributes_vertex();
836
837 // Produce point data
838 v_out += dist_prop_output<has_attributes<typename Graph::V_type>::value, Graph, T::value>::get_point_data(g);
839 }
840 }
841};
842
843/*! \brief this class is a functor for "for_each" algorithm
844 *
845 * This class is a functor for "for_each" algorithm. For each
846 * element of the boost::vector the operator() is called.
847 * Is mainly used to produce at output for each property
848 *
849 * \tparam Graph graph we are processing
850 *
851 * \param dim Dimensionality
852 * \param S type of grid
853 *
854 */
855
856template<typename Graph>
857struct dist_prop_out_edge
858{
859 //! property output string
860 std::string & e_out;
861
862 //! Graph that we are processing
863 const Graph & g;
864
865 /*! \brief constructor
866 *
867 * \param e_out string to fill with the edge properties
868 * \param g graph to write
869 *
870 */
871 dist_prop_out_edge(std::string & e_out, const Graph & g) :
872 e_out(e_out), g(g)
873 {};
874
875 /*! \brief It produce an output for each property
876 *
877 * \param t index property
878 *
879 */
880 template<typename T>
881 void operator()(T& t) const
882 {
883 // actual string size
884 size_t sz = e_out.size();
885
886 // Produce the point properties header
887 e_out += dist_prop_output<has_attributes<typename Graph::E_type>::value, Graph, T::value>::get_cell_property_header(t);
888
889 // If the output has changed, we have to write the properties
890 if (e_out.size() != sz)
891 {
892 std::string attr = dist_prop_output<has_attributes<typename Graph::E_type>::value, Graph, T::value>::get_attributes_edge();
893
894 // Produce cell data
895 e_out += dist_prop_output<has_attributes<typename Graph::E_type>::value, Graph, T::value>::get_cell_data(g);
896 }
897 }
898};
899
900/*!
901 *
902 * It write a VTK format file in case for a graph
903 *
904 * \tparam Type of graph
905 *
906 */
907
908template<typename Graph>
909class VTKWriter<Graph, DIST_GRAPH>
910{
911 //! Graph to output
912 Graph & g;
913
914 /*! \brief It get the vertex properties list
915 *
916 * It get the vertex properties list of the vertex defined as VTK header
917 *
918 * \return a string that define the vertex properties in graphML format
919 *
920 */
921
922 std::string get_vertex_properties_list()
923 {
924 //! vertex property output string
925 std::string v_out;
926
927 // write the number of vertex
928 v_out += "VERTICES " + std::to_string(g.getNVertex()) + " " + std::to_string(g.getNVertex() * 2) + "\n";
929
930 // return the vertex properties string
931 return v_out;
932 }
933
934 /*! \brief It get the vertex properties list
935 *
936 * It get the vertex properties list of the vertex defined as a VTK header
937 *
938 * \return a string that define the vertex properties in graphML format
939 *
940 */
941
942 std::string get_point_properties_list()
943 {
944 //! vertex property output string
945 std::string v_out;
946
947 // write the number of vertex
948 v_out += "POINTS " + std::to_string(g.getNVertex()) + " float" + "\n";
949
950 // return the vertex properties string
951 return v_out;
952 }
953
954 /*! \brief Get the VTK point info string
955 *
956 * \return the point info string
957 *
958 */
959 std::string get_point_info()
960 {
961 //! vertex property output string
962 std::string v_out;
963
964 // write the ids
965 v_out += "SCALARS id unsigned_long\nLOOKUP_TABLE default\n";
966
967 for (size_t i = 0; i < g.getNVertex(); ++i)
968 {
969 v_out += std::to_string(g.getVertexId(i)) + "\n";
970 }
971
972 // write the ids
973 v_out += "SCALARS gid unsigned_long\nLOOKUP_TABLE default\n";
974
975 for (size_t i = 0; i < g.getNVertex(); ++i)
976 {
977 v_out += std::to_string(g.getVertexGlobalId(i)) + "\n";
978 }
979
980 // return the vertex properties string
981 return v_out;
982 }
983
984 /*! \brief It get the edge properties list
985 *
986 * It get the edge properties list of the edge defined as a GraphML header
987 *
988 * \return a string that define the edge properties in graphML format
989 *
990 */
991
992 std::string get_edge_properties_list()
993 {
994 //! vertex property output string
995 std::string e_out;
996
997 // write the number of lines
998 e_out += "LINES " + std::to_string(g.getNEdge()) + " " + std::to_string(3 * g.getNEdge()) + "\n";
999
1000 // return the vertex properties string
1001 return e_out;
1002 }
1003
1004 /*! \brief Create the VTK point definition
1005 *
1006 * \tparam attr false x,y,z are set to 0 for each vertex
1007 *
1008 * \return the point list string
1009 *
1010 */
1011
1012 template<bool attr> std::string get_point_list()
1013 {
1014 //! VTK spatial information
1015 typename Graph::V_type::s_type x[3] = { 0, 0, 0 };
1016
1017 //! vertex node output string
1018 std::string v_out;
1019
1020 //! Get a vertex iterator
1021 auto it = g.getVertexIterator();
1022
1023 // if there is the next element
1024 while (it.isNext())
1025 {
1026 // Get vtk vertex node
1027 auto obj = g.vertex(it.get());
1028
1029 // create a vertex list functor
1030 vtk_dist_vertex_node<Graph, attr> vn(v_out, obj, x);
1031
1032 // Iterate through all the vertex and create the vertex list
1033 boost::mpl::for_each<boost::mpl::range_c<int, 0, Graph::V_type::max_prop> >(vn);
1034
1035 // write the node string
1036 vn.write();
1037
1038 // increment the iterator and counter
1039 ++it;
1040 }
1041
1042 // return the vertex list
1043 return v_out;
1044 }
1045
1046 /*! \brief Create the VTK vertex definition
1047 *
1048 * \tparam attr false x,y,z are set to 0 for each vertex
1049 *
1050 * \return the vertex list string
1051 *
1052 */
1053 std::string get_vertex_list()
1054 {
1055 //! vertex node output string
1056 std::string v_out;
1057
1058 //! For each point create a vertex
1059 for (size_t i = 0; i < g.getNVertex(); i++)
1060 {
1061 v_out += "1 " + std::to_string(i) + "\n";
1062 }
1063
1064 // return the vertex list
1065 return v_out;
1066 }
1067
1068 /*! \brief Get the point data header
1069 *
1070 * \return a string with the point data header for VTK format
1071 *
1072 */
1073
1074 std::string get_point_data_header()
1075 {
1076 std::string v_out;
1077
1078 v_out += "POINT_DATA " + std::to_string(g.getNVertex()) + "\n";
1079
1080 return v_out;
1081 }
1082
1083 /*! \brief Get the point data header
1084 *
1085 * \return a string with the point data header for VTK format
1086 *
1087 */
1088
1089 std::string get_cell_data_header()
1090 {
1091 std::string v_out;
1092
1093 v_out += "CELL_DATA " + std::to_string(g.getNVertex() + g.getNEdge()) + "\n";
1094
1095 return v_out;
1096 }
1097
1098 /*! \brief Return the edge list
1099 *
1100 * \return the edge list
1101 *
1102 */
1103
1104 std::string get_edge_list()
1105 {
1106 //! edge node output string
1107 std::string e_out;
1108
1109 //! Get an edge iterator
1110 auto it = g.getEdgeIterator();
1111
1112 // if there is the next element
1113 while (it.isNext())
1114 {
1115 e_out += "2 " + std::to_string(it.source()) + " " + std::to_string(g.nodeById(it.target())) + "\n";
1116
1117 // increment the operator
1118 ++it;
1119 }
1120
1121 // return the edge list
1122 return e_out;
1123 }
1124
1125public:
1126
1127 /*!
1128 *
1129 * VTKWriter constructor, it take a graph and write a GraphML format
1130 *
1131 * \param g Graph to write
1132 *
1133 */
1134 VTKWriter(Graph & g) :
1135 g(g)
1136 {
1137 }
1138
1139 /*! \brief It write a VTK file from a graph
1140 *
1141 * \tparam prp_out which properties to output [default = -1 (all)]
1142 *
1143 * \param file path where to write
1144 * \param graph_name of the graph
1145 * \param ft specify if it is a VTK BINARY or ASCII file [default = ASCII]
1146 *
1147 * \return true if it succeed
1148 *
1149 */
1150 template<int prp = -1> bool write(std::string file, std::string graph_name = "Graph", file_type ft = file_type::ASCII)
1151 {
1152
1153 Vcluster<> & v_cl = create_vcluster();
1154
1155 g.deleteGhosts();
1156
1157 if (v_cl.getProcessUnitID() == 0)
1158 {
1159 for (size_t i = 0; i < g.getTotNVertex(); ++i)
1160 {
1161 g.reqVertex(i);
1162 }
1163 }
1164
1165 g.sync();
1166
1167 if (v_cl.getProcessUnitID() == 0)
1168 {
1169 // Check that the Vertex type define x y and z attributes
1170
1171 if (has_attributes<typename Graph::V_type>::value == false)
1172 {
1173 std::cerr << "Error writing a graph: Vertex must has defines x,y,z properties" << "\n";
1174 return false;
1175 }
1176
1177 // Header for the vtk
1178 std::string vtk_header;
1179 // Point list of the VTK
1180 std::string point_list;
1181 // Vertex list of the VTK
1182 std::string vertex_list;
1183 // Graph header
1184 std::string vtk_binary_or_ascii;
1185 // Edge list of the GraphML
1186 std::string edge_list;
1187 // vertex properties header
1188 std::string point_prop_header;
1189 // edge properties header
1190 std::string vertex_prop_header;
1191 // edge properties header
1192 std::string edge_prop_header;
1193 // Data point header
1194 std::string point_data_header;
1195 // Ids point
1196 std::string point_ids;
1197 // Data point
1198 std::string point_data;
1199 // Cell data header
1200 std::string cell_data_header;
1201 // Cell data
1202 std::string cell_data;
1203
1204 // VTK header
1205 vtk_header = "# vtk DataFile Version 3.0\n" + graph_name + "\n";
1206
1207 // Choose if binary or ASCII
1208 if (ft == file_type::ASCII)
1209 {
1210 vtk_header += "ASCII\n";
1211 }
1212 else
1213 {
1214 vtk_header += "BINARY\n";
1215 }
1216
1217 // Data type for graph is DATASET POLYDATA
1218 vtk_header += "DATASET POLYDATA\n";
1219
1220 // point properties header
1221 point_prop_header = get_point_properties_list();
1222
1223 // Get point list
1224 point_list = get_point_list<has_attributes<typename Graph::V_type>::value>();
1225
1226 // vertex properties header
1227 vertex_prop_header = get_vertex_properties_list();
1228
1229 // Get vertex list
1230 vertex_list = get_vertex_list();
1231
1232 // Edge properties header
1233 edge_prop_header = get_edge_properties_list();
1234
1235 // Get the edge graph list
1236 edge_list = get_edge_list();
1237
1238 // Get the point data header
1239 point_data_header = get_point_data_header();
1240
1241 // Get the point info
1242 point_ids = get_point_info();
1243
1244 // Get the cell data header
1245 cell_data_header = get_cell_data_header();
1246
1247 // For each property in the vertex type produce a point data
1248
1249 dist_prop_out_vertex<Graph> pp(point_data, g);
1250
1251 if (prp == -1)
1252 boost::mpl::for_each<boost::mpl::range_c<int, 0, Graph::V_type::max_prop> >(pp);
1253 else
1254 boost::mpl::for_each<boost::mpl::range_c<int, prp, prp> >(pp);
1255
1256 // For each property in the edge type produce a point data
1257
1258 dist_prop_out_edge<Graph> ep(cell_data, g);
1259
1260 if (prp == -1)
1261 boost::mpl::for_each<boost::mpl::range_c<int, 0, Graph::E_type::max_prop> >(ep);
1262 else
1263 boost::mpl::for_each<boost::mpl::range_c<int, prp, prp> >(ep);
1264
1265 // write the file
1266 std::ofstream ofs(file);
1267
1268 // Check if the file is open
1269 if (ofs.is_open() == false)
1270 {
1271 std::cerr << "Error cannot create the VTK file: " + file;
1272 }
1273
1274 ofs << vtk_header << point_prop_header << point_list << vertex_prop_header << vertex_list << edge_prop_header << edge_list << point_data_header << point_ids << point_data << cell_data_header << cell_data;
1275
1276 // Close the file
1277
1278 ofs.close();
1279
1280 }
1281
1282 g.deleteGhosts();
1283
1284 // Completed succefully
1285 return true;
1286 }
1287};
1288
1289#endif /* VTKWRITER_GRAPH_HPP_ */
1290