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