Line | Branch | Exec | Source |
---|---|---|---|
1 | // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de> | ||
2 | // SPDX-License-Identifier: MIT | ||
3 | /*! | ||
4 | * \file | ||
5 | * \ingroup VTK | ||
6 | * \copydoc GridFormat::VTPWriter | ||
7 | */ | ||
8 | #ifndef GRIDFORMAT_VTK_VTP_WRITER_HPP_ | ||
9 | #define GRIDFORMAT_VTK_VTP_WRITER_HPP_ | ||
10 | |||
11 | #include <ranges> | ||
12 | #include <ostream> | ||
13 | #include <iostream> | ||
14 | #include <algorithm> | ||
15 | #include <functional> | ||
16 | |||
17 | #include <gridformat/common/ranges.hpp> | ||
18 | #include <gridformat/common/field_storage.hpp> | ||
19 | #include <gridformat/common/lvalue_reference.hpp> | ||
20 | |||
21 | #include <gridformat/grid/grid.hpp> | ||
22 | #include <gridformat/grid/filtered.hpp> | ||
23 | |||
24 | #include <gridformat/vtk/common.hpp> | ||
25 | #include <gridformat/vtk/xml.hpp> | ||
26 | |||
27 | namespace GridFormat { | ||
28 | |||
29 | #ifndef DOXYGEN | ||
30 | namespace Detail { | ||
31 | |||
32 | template<typename Grid, std::size_t size> | ||
33 | struct CellTypesPredicate { | ||
34 | std::reference_wrapper<const Grid> grid; | ||
35 | std::array<CellType, size> cell_types; | ||
36 | |||
37 | 166672 | bool operator()(const Cell<Grid>& cell) const { | |
38 | 311886 | return std::ranges::any_of(cell_types, [&] (const CellType& _ct) { | |
39 | 145214 | return _ct == type(grid.get(), cell); | |
40 | 166672 | }); | |
41 | } | ||
42 | }; | ||
43 | |||
44 | template<typename G, std::size_t s> | ||
45 | CellTypesPredicate(G&&, std::array<CellType, s>&&) -> CellTypesPredicate<std::remove_cvref_t<G>, s>; | ||
46 | template<typename G, std::size_t s> | ||
47 | CellTypesPredicate(G&&, const std::array<CellType, s>&) -> CellTypesPredicate<std::remove_cvref_t<G>, s>; | ||
48 | |||
49 | } // namespace Detail | ||
50 | #endif // DOXYGEN | ||
51 | |||
52 | /*! | ||
53 | * \ingroup VTK | ||
54 | * \brief Writer for .vtu file format | ||
55 | */ | ||
56 | template<Concepts::UnstructuredGrid Grid> | ||
57 | class VTPWriter : public VTK::XMLWriterBase<Grid, VTPWriter<Grid>> { | ||
58 | using ParentType = VTK::XMLWriterBase<Grid, VTPWriter<Grid>>; | ||
59 | |||
60 | static constexpr std::array zero_d_types{CellType::vertex}; | ||
61 | static constexpr std::array one_d_types{CellType::segment}; | ||
62 | static constexpr std::array two_d_types{ | ||
63 | CellType::quadrilateral, | ||
64 | CellType::pixel, | ||
65 | CellType::polygon, | ||
66 | CellType::triangle | ||
67 | }; | ||
68 | |||
69 | public: | ||
70 | 909 | explicit VTPWriter(LValueReferenceOf<const Grid> grid, | |
71 | VTK::XMLOptions xml_opts = {}) | ||
72 |
2/4✓ Branch 2 taken 496 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 496 times.
✗ Branch 7 not taken.
|
1818 | : ParentType(grid.get(), ".vtp", false, std::move(xml_opts)) |
73 | 909 | {} | |
74 | |||
75 | private: | ||
76 | 562 | VTPWriter _with(VTK::XMLOptions xml_opts) const override { | |
77 |
1/2✓ Branch 4 taken 282 times.
✗ Branch 5 not taken.
|
562 | return VTPWriter{this->grid(), std::move(xml_opts)}; |
78 | } | ||
79 | |||
80 | 372 | void _write(std::ostream& s) const override { | |
81 | 372 | FilteredGrid verts{this->grid(), Detail::CellTypesPredicate{this->grid(), zero_d_types}}; | |
82 | 372 | FilteredGrid lines{this->grid(), Detail::CellTypesPredicate{this->grid(), one_d_types}}; | |
83 | 372 | FilteredGrid polys{this->grid(), Detail::CellTypesPredicate{this->grid(), two_d_types}}; | |
84 | 372 | FilteredGrid unsupported{ | |
85 | 372 | this->grid(), | |
86 | 3114 | [p=Detail::CellTypesPredicate{ | |
87 |
2/4✓ Branch 2 taken 231 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 231 times.
✗ Branch 6 not taken.
|
744 | this->grid(), Ranges::merged(Ranges::merged(zero_d_types, one_d_types), two_d_types) |
88 | }] (const Cell<Grid>& cell) { | ||
89 | 8456 | return !p(cell); | |
90 | } | ||
91 | }; | ||
92 | |||
93 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | auto verts_range = cells(verts); |
94 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | auto lines_range = cells(lines); |
95 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | auto polys_range = cells(polys); |
96 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | auto unsupported_range = cells(unsupported); |
97 | |||
98 |
3/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 228 times.
|
372 | if (Ranges::size(unsupported_range) > 0) |
99 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
4 | this->_log_warning("Grid contains cell types not supported by .vtp; These will be ignored."); |
100 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 231 times.
✗ Branch 5 not taken.
|
372 | if (!std::ranges::empty(this->_cell_field_names()) |
101 |
4/6✓ Branch 0 taken 206 times.
✓ Branch 1 taken 25 times.
✓ Branch 3 taken 206 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 231 times.
|
701 | && !std::ranges::empty(verts_range) |
102 |
1/2✓ Branch 1 taken 206 times.
✗ Branch 2 not taken.
|
329 | + !std::ranges::empty(lines_range) |
103 |
2/4✓ Branch 1 taken 206 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 206 times.
|
329 | + !std::ranges::empty(polys_range) |
104 | > 1) | ||
105 | ✗ | this->_log_warning( | |
106 | "You appear to have cell data defined and your grid consists of multiple cell types " | ||
107 | "(vertices, lines, polys).\nNote that for correct cell data visualization with vtk, " | ||
108 | "your cell iterator must be such that it iterates over the cell types in order " | ||
109 | "(vertices -> lines -> polys)." | ||
110 | ); | ||
111 | |||
112 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | const auto num_verts = Ranges::size(verts_range); |
113 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | const auto num_lines = Ranges::size(lines_range); |
114 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | const auto num_polys = Ranges::size(polys_range); |
115 | |||
116 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 231 times.
✗ Branch 5 not taken.
|
744 | auto context = this->_get_write_context("PolyData"); |
117 |
5/9✓ Branch 2 taken 20 times.
✓ Branch 3 taken 211 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 211 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
|
744 | this->_set_attribute(context, "Piece", "NumberOfPoints", number_of_points(this->grid())); |
118 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 231 times.
✗ Branch 6 not taken.
|
744 | this->_set_attribute(context, "Piece", "NumberOfVerts", num_verts); |
119 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 231 times.
✗ Branch 6 not taken.
|
744 | this->_set_attribute(context, "Piece", "NumberOfLines", num_lines); |
120 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 231 times.
✗ Branch 6 not taken.
|
744 | this->_set_attribute(context, "Piece", "NumberOfStrips", "0"); |
121 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 231 times.
✗ Branch 6 not taken.
|
744 | this->_set_attribute(context, "Piece", "NumberOfPolys", num_polys); |
122 | |||
123 | 372 | FieldStorage vtk_point_fields; | |
124 | 372 | FieldStorage vtk_cell_fields; | |
125 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 231 times.
✗ Branch 5 not taken.
|
1822 | std::ranges::for_each(this->_point_field_names(), [&] (const std::string& name) { |
126 |
24/48✓ Branch 1 taken 518 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 518 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 518 times.
✗ Branch 8 not taken.
✓ Branch 15 taken 92 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 92 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 92 times.
✗ Branch 22 not taken.
✓ Branch 29 taken 91 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 91 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 91 times.
✗ Branch 36 not taken.
✓ Branch 43 taken 90 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 90 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 90 times.
✗ Branch 50 not taken.
✓ Branch 57 taken 90 times.
✗ Branch 58 not taken.
✓ Branch 60 taken 90 times.
✗ Branch 61 not taken.
✓ Branch 63 taken 90 times.
✗ Branch 64 not taken.
✓ Branch 71 taken 90 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 90 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 90 times.
✗ Branch 78 not taken.
✓ Branch 85 taken 90 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 90 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 90 times.
✗ Branch 92 not taken.
✓ Branch 99 taken 90 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 90 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 90 times.
✗ Branch 106 not taken.
|
1151 | vtk_point_fields.set(name, VTK::make_vtk_field(this->_get_point_field_ptr(name))); |
127 |
16/32✓ Branch 2 taken 518 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 518 times.
✗ Branch 7 not taken.
✓ Branch 12 taken 92 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 92 times.
✗ Branch 17 not taken.
✓ Branch 22 taken 91 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 91 times.
✗ Branch 27 not taken.
✓ Branch 32 taken 90 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 90 times.
✗ Branch 37 not taken.
✓ Branch 42 taken 90 times.
✗ Branch 43 not taken.
✓ Branch 46 taken 90 times.
✗ Branch 47 not taken.
✓ Branch 52 taken 90 times.
✗ Branch 53 not taken.
✓ Branch 56 taken 90 times.
✗ Branch 57 not taken.
✓ Branch 62 taken 90 times.
✗ Branch 63 not taken.
✓ Branch 66 taken 90 times.
✗ Branch 67 not taken.
✓ Branch 72 taken 90 times.
✗ Branch 73 not taken.
✓ Branch 76 taken 90 times.
✗ Branch 77 not taken.
|
1151 | this->_set_data_array(context, "Piece/PointData", name, vtk_point_fields.get(name)); |
128 | }); | ||
129 |
2/4✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 231 times.
✗ Branch 5 not taken.
|
1818 | std::ranges::for_each(this->_cell_field_names(), [&] (const std::string& name) { |
130 |
24/48✓ Branch 1 taken 516 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 516 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 516 times.
✗ Branch 8 not taken.
✓ Branch 15 taken 91 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 91 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 91 times.
✗ Branch 22 not taken.
✓ Branch 29 taken 90 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 90 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 90 times.
✗ Branch 36 not taken.
✓ Branch 43 taken 90 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 90 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 90 times.
✗ Branch 50 not taken.
✓ Branch 57 taken 90 times.
✗ Branch 58 not taken.
✓ Branch 60 taken 90 times.
✗ Branch 61 not taken.
✓ Branch 63 taken 90 times.
✗ Branch 64 not taken.
✓ Branch 71 taken 90 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 90 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 90 times.
✗ Branch 78 not taken.
✓ Branch 85 taken 90 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 90 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 90 times.
✗ Branch 92 not taken.
✓ Branch 99 taken 90 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 90 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 90 times.
✗ Branch 106 not taken.
|
1147 | vtk_cell_fields.set(name, VTK::make_vtk_field(this->_get_cell_field_ptr(name))); |
131 |
16/32✓ Branch 2 taken 516 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 516 times.
✗ Branch 7 not taken.
✓ Branch 12 taken 91 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 91 times.
✗ Branch 17 not taken.
✓ Branch 22 taken 90 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 90 times.
✗ Branch 27 not taken.
✓ Branch 32 taken 90 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 90 times.
✗ Branch 37 not taken.
✓ Branch 42 taken 90 times.
✗ Branch 43 not taken.
✓ Branch 46 taken 90 times.
✗ Branch 47 not taken.
✓ Branch 52 taken 90 times.
✗ Branch 53 not taken.
✓ Branch 56 taken 90 times.
✗ Branch 57 not taken.
✓ Branch 62 taken 90 times.
✗ Branch 63 not taken.
✓ Branch 66 taken 90 times.
✗ Branch 67 not taken.
✓ Branch 72 taken 90 times.
✗ Branch 73 not taken.
✓ Branch 76 taken 90 times.
✗ Branch 77 not taken.
|
1147 | this->_set_data_array(context, "Piece/CellData", name, vtk_cell_fields.get(name)); |
132 | }); | ||
133 | |||
134 | 321 | const FieldPtr coords_field = std::visit([&] <typename T> (const Precision<T>&) { | |
135 | 231 | return VTK::make_coordinates_field<T>(this->grid(), false); | |
136 |
1/2✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
|
372 | }, this->_xml_settings.coordinate_precision); |
137 |
3/4✓ Branch 2 taken 231 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✓ Branch 7 taken 20 times.
|
780 | this->_set_data_array(context, "Piece/Points", "Coordinates", *coords_field); |
138 | |||
139 |
1/2✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
|
336 | const auto point_id_map = make_point_id_map(this->grid()); |
140 |
1/2✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
|
336 | const auto verts_connectivity_field = _make_connectivity_field(verts, point_id_map); |
141 |
1/2✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
|
336 | const auto verts_offsets_field = _make_offsets_field(verts); |
142 |
2/4✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✗ Branch 7 not taken.
|
672 | this->_set_data_array(context, "Piece/Verts", "connectivity", *verts_connectivity_field); |
143 |
2/4✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✗ Branch 7 not taken.
|
672 | this->_set_data_array(context, "Piece/Verts", "offsets", *verts_offsets_field); |
144 | |||
145 |
1/2✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
|
336 | const auto lines_connectivity_field = _make_connectivity_field(lines, point_id_map); |
146 |
1/2✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
|
336 | const auto lines_offsets_field = _make_offsets_field(lines); |
147 |
2/4✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✗ Branch 7 not taken.
|
672 | this->_set_data_array(context, "Piece/Lines", "connectivity", *lines_connectivity_field); |
148 |
2/4✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✗ Branch 7 not taken.
|
672 | this->_set_data_array(context, "Piece/Lines", "offsets", *lines_offsets_field); |
149 | |||
150 |
1/2✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
|
336 | const auto polys_connectivity_field = _make_connectivity_field(polys, point_id_map); |
151 |
1/2✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
|
336 | const auto polys_offsets_field = _make_offsets_field(polys); |
152 |
2/4✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✗ Branch 7 not taken.
|
672 | this->_set_data_array(context, "Piece/Polys", "connectivity", *polys_connectivity_field); |
153 |
2/4✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 211 times.
✗ Branch 7 not taken.
|
672 | this->_set_data_array(context, "Piece/Polys", "offsets", *polys_offsets_field); |
154 | |||
155 |
1/2✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
|
336 | this->_write_xml(std::move(context), s); |
156 | 480 | } | |
157 | |||
158 | template<typename G, typename PointMap> | ||
159 | 1266 | FieldPtr _make_connectivity_field(G&& grid, const PointMap& point_id_map) const { | |
160 | 1899 | return std::visit([&] <typename T> (const Precision<T>&) { | |
161 | 633 | return VTK::make_connectivity_field<T>(grid, point_id_map); | |
162 |
1/2✓ Branch 1 taken 633 times.
✗ Branch 2 not taken.
|
2532 | }, this->_xml_settings.header_precision); |
163 | } | ||
164 | |||
165 | template<typename G> | ||
166 | 633 | FieldPtr _make_offsets_field(G&& grid) const { | |
167 | 1266 | return std::visit([&] <typename T> (const Precision<T>&) { | |
168 | 633 | return VTK::make_offsets_field<T>(grid); | |
169 | 1266 | }, this->_xml_settings.header_precision); | |
170 | } | ||
171 | }; | ||
172 | |||
173 | template<typename G> | ||
174 | VTPWriter(G&&, VTK::XMLOptions = {}) -> VTPWriter<std::remove_cvref_t<G>>; | ||
175 | |||
176 | } // namespace GridFormat | ||
177 | |||
178 | #endif // GRIDFORMAT_VTK_VTP_WRITER_HPP_ | ||
179 |