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/filtered_range.hpp> | ||
19 | #include <gridformat/common/field_storage.hpp> | ||
20 | #include <gridformat/common/lvalue_reference.hpp> | ||
21 | |||
22 | #include <gridformat/grid/grid.hpp> | ||
23 | #include <gridformat/vtk/common.hpp> | ||
24 | #include <gridformat/vtk/xml.hpp> | ||
25 | |||
26 | namespace GridFormat { | ||
27 | |||
28 | #ifndef DOXYGEN | ||
29 | namespace Detail { | ||
30 | |||
31 | template<typename Grid, std::size_t size> | ||
32 | struct CellTypesPredicate { | ||
33 | std::reference_wrapper<const Grid> grid; | ||
34 | std::array<CellType, size> cell_types; | ||
35 | |||
36 | 148306 | bool operator()(const Cell<Grid>& cell) const { | |
37 | 268966 | return std::ranges::any_of(cell_types, [&] (const CellType& _ct) { | |
38 | 120660 | return _ct == type(grid.get(), cell); | |
39 | 148306 | }); | |
40 | } | ||
41 | }; | ||
42 | |||
43 | template<typename G, std::size_t s> | ||
44 | CellTypesPredicate(G&&, std::array<CellType, s>&&) -> CellTypesPredicate<std::remove_cvref_t<G>, s>; | ||
45 | template<typename G, std::size_t s> | ||
46 | CellTypesPredicate(G&&, const std::array<CellType, s>&) -> CellTypesPredicate<std::remove_cvref_t<G>, s>; | ||
47 | |||
48 | } // namespace Detail | ||
49 | #endif // DOXYGEN | ||
50 | |||
51 | /*! | ||
52 | * \ingroup VTK | ||
53 | * \brief Writer for .vtu file format | ||
54 | */ | ||
55 | template<Concepts::UnstructuredGrid Grid> | ||
56 | class VTPWriter : public VTK::XMLWriterBase<Grid, VTPWriter<Grid>> { | ||
57 | using ParentType = VTK::XMLWriterBase<Grid, VTPWriter<Grid>>; | ||
58 | |||
59 | static constexpr std::array zero_d_types{CellType::vertex}; | ||
60 | static constexpr std::array one_d_types{CellType::segment}; | ||
61 | static constexpr std::array two_d_types{ | ||
62 | CellType::quadrilateral, | ||
63 | CellType::pixel, | ||
64 | CellType::polygon, | ||
65 | CellType::triangle | ||
66 | }; | ||
67 | |||
68 | public: | ||
69 | 905 | explicit VTPWriter(LValueReferenceOf<const Grid> grid, | |
70 | VTK::XMLOptions xml_opts = {}) | ||
71 |
2/4✓ Branch 2 taken 492 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 492 times.
✗ Branch 7 not taken.
|
1810 | : ParentType(grid.get(), ".vtp", false, std::move(xml_opts)) |
72 | 905 | {} | |
73 | |||
74 | private: | ||
75 | 560 | VTPWriter _with(VTK::XMLOptions xml_opts) const override { | |
76 |
1/2✓ Branch 4 taken 280 times.
✗ Branch 5 not taken.
|
560 | return VTPWriter{this->grid(), std::move(xml_opts)}; |
77 | } | ||
78 | |||
79 | 370 | void _write(std::ostream& s) const override { | |
80 |
1/2✓ Branch 3 taken 229 times.
✗ Branch 4 not taken.
|
370 | auto verts_range = _get_cell_range(Detail::CellTypesPredicate{this->grid(), zero_d_types}); |
81 |
1/2✓ Branch 3 taken 229 times.
✗ Branch 4 not taken.
|
370 | auto lines_range = _get_cell_range(Detail::CellTypesPredicate{this->grid(), one_d_types}); |
82 |
1/2✓ Branch 3 taken 229 times.
✗ Branch 4 not taken.
|
370 | auto polys_range = _get_cell_range(Detail::CellTypesPredicate{this->grid(), two_d_types}); |
83 |
1/2✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
|
370 | auto unsupported_range = _get_cell_range( |
84 | 1741 | [p=Detail::CellTypesPredicate{ | |
85 |
2/4✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 229 times.
✗ Branch 6 not taken.
|
740 | this->grid(), Ranges::merged(Ranges::merged(zero_d_types, one_d_types), two_d_types) |
86 | }] (const Cell<Grid>& cell) { | ||
87 | 4208 | return !p(cell); | |
88 | } | ||
89 | ); | ||
90 | |||
91 |
3/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 226 times.
|
370 | if (Ranges::size(unsupported_range) > 0) |
92 |
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."); |
93 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 229 times.
✗ Branch 5 not taken.
|
370 | if (!std::ranges::empty(this->_cell_field_names()) |
94 |
4/6✓ Branch 0 taken 204 times.
✓ Branch 1 taken 25 times.
✓ Branch 3 taken 204 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 229 times.
|
697 | && !std::ranges::empty(verts_range) |
95 |
1/2✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
|
327 | + !std::ranges::empty(lines_range) |
96 |
2/4✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 204 times.
|
327 | + !std::ranges::empty(polys_range) |
97 | > 1) | ||
98 | ✗ | this->_log_warning( | |
99 | "You appear to have cell data defined and your grid consists of multiple cell types " | ||
100 | "(vertices, lines, polys).\nNote that for correct cell data visualization with vtk, " | ||
101 | "your cell iterator must be such that it iterates over the cell types in order " | ||
102 | "(vertices -> lines -> polys)." | ||
103 | ); | ||
104 | |||
105 |
1/2✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
|
370 | const auto num_verts = Ranges::size(verts_range); |
106 |
1/2✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
|
370 | const auto num_lines = Ranges::size(lines_range); |
107 |
1/2✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
|
370 | const auto num_polys = Ranges::size(polys_range); |
108 | |||
109 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 229 times.
✗ Branch 5 not taken.
|
740 | auto context = this->_get_write_context("PolyData"); |
110 |
5/9✓ Branch 2 taken 20 times.
✓ Branch 3 taken 209 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 209 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
|
740 | this->_set_attribute(context, "Piece", "NumberOfPoints", number_of_points(this->grid())); |
111 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 229 times.
✗ Branch 6 not taken.
|
740 | this->_set_attribute(context, "Piece", "NumberOfVerts", num_verts); |
112 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 229 times.
✗ Branch 6 not taken.
|
740 | this->_set_attribute(context, "Piece", "NumberOfLines", num_lines); |
113 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 229 times.
✗ Branch 6 not taken.
|
740 | this->_set_attribute(context, "Piece", "NumberOfStrips", "0"); |
114 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 229 times.
✗ Branch 6 not taken.
|
740 | this->_set_attribute(context, "Piece", "NumberOfPolys", num_polys); |
115 | |||
116 | 370 | FieldStorage vtk_point_fields; | |
117 | 370 | FieldStorage vtk_cell_fields; | |
118 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 229 times.
✗ Branch 5 not taken.
|
1820 | std::ranges::for_each(this->_point_field_names(), [&] (const std::string& name) { |
119 |
24/48✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 506 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 506 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.
|
1139 | vtk_point_fields.set(name, VTK::make_vtk_field(this->_get_point_field_ptr(name))); |
120 |
16/32✓ Branch 2 taken 506 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 506 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.
|
1139 | this->_set_data_array(context, "Piece/PointData", name, vtk_point_fields.get(name)); |
121 | }); | ||
122 |
2/4✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 229 times.
✗ Branch 5 not taken.
|
1816 | std::ranges::for_each(this->_cell_field_names(), [&] (const std::string& name) { |
123 |
24/48✓ Branch 1 taken 504 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 504 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 504 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.
|
1135 | vtk_cell_fields.set(name, VTK::make_vtk_field(this->_get_cell_field_ptr(name))); |
124 |
16/32✓ Branch 2 taken 504 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 504 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.
|
1135 | this->_set_data_array(context, "Piece/CellData", name, vtk_cell_fields.get(name)); |
125 | }); | ||
126 | |||
127 | 317 | const FieldPtr coords_field = std::visit([&] <typename T> (const Precision<T>&) { | |
128 | 229 | return VTK::make_coordinates_field<T>(this->grid(), false); | |
129 |
1/2✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
|
370 | }, this->_xml_settings.coordinate_precision); |
130 |
3/4✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✓ Branch 7 taken 20 times.
|
776 | this->_set_data_array(context, "Piece/Points", "Coordinates", *coords_field); |
131 | |||
132 |
1/2✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
|
334 | const auto point_id_map = make_point_id_map(this->grid()); |
133 |
1/2✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
|
334 | const auto verts_connectivity_field = _make_connectivity_field(verts_range, point_id_map); |
134 |
1/2✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
|
334 | const auto verts_offsets_field = _make_offsets_field(verts_range); |
135 |
2/4✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✗ Branch 7 not taken.
|
668 | this->_set_data_array(context, "Piece/Verts", "connectivity", *verts_connectivity_field); |
136 |
2/4✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✗ Branch 7 not taken.
|
668 | this->_set_data_array(context, "Piece/Verts", "offsets", *verts_offsets_field); |
137 | |||
138 |
1/2✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
|
334 | const auto lines_connectivity_field = _make_connectivity_field(lines_range, point_id_map); |
139 |
1/2✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
|
334 | const auto lines_offsets_field = _make_offsets_field(lines_range); |
140 |
2/4✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✗ Branch 7 not taken.
|
668 | this->_set_data_array(context, "Piece/Lines", "connectivity", *lines_connectivity_field); |
141 |
2/4✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✗ Branch 7 not taken.
|
668 | this->_set_data_array(context, "Piece/Lines", "offsets", *lines_offsets_field); |
142 | |||
143 |
1/2✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
|
334 | const auto polys_connectivity_field = _make_connectivity_field(polys_range, point_id_map); |
144 |
1/2✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
|
334 | const auto polys_offsets_field = _make_offsets_field(polys_range); |
145 |
2/4✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✗ Branch 7 not taken.
|
668 | this->_set_data_array(context, "Piece/Polys", "connectivity", *polys_connectivity_field); |
146 |
2/4✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 209 times.
✗ Branch 7 not taken.
|
668 | this->_set_data_array(context, "Piece/Polys", "offsets", *polys_offsets_field); |
147 | |||
148 |
1/2✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
|
334 | this->_write_xml(std::move(context), s); |
149 | 478 | } | |
150 | |||
151 | template<typename Predicate> | ||
152 | 1832 | std::ranges::forward_range auto _get_cell_range(Predicate&& pred) const { | |
153 |
3/6✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 824 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 92 times.
✗ Branch 7 not taken.
|
1832 | return Ranges::filter_by(std::forward<Predicate>(pred), cells(this->grid())); |
154 | } | ||
155 | |||
156 | template<typename CellsRange, typename PointMap> | ||
157 | 1254 | FieldPtr _make_connectivity_field(CellsRange&& cells, const PointMap& point_id_map) const { | |
158 | 1881 | return std::visit([&] <typename T> (const Precision<T>&) { | |
159 | 627 | return VTK::make_connectivity_field<T>(this->grid(), cells, point_id_map); | |
160 |
1/2✓ Branch 1 taken 627 times.
✗ Branch 2 not taken.
|
2508 | }, this->_xml_settings.header_precision); |
161 | } | ||
162 | |||
163 | template<typename CellsRange> | ||
164 | 627 | FieldPtr _make_offsets_field(CellsRange&& cells) const { | |
165 | 1254 | return std::visit([&] <typename T> (const Precision<T>&) { | |
166 | 627 | return VTK::make_offsets_field<T>(this->grid(), cells); | |
167 | 1254 | }, this->_xml_settings.header_precision); | |
168 | } | ||
169 | }; | ||
170 | |||
171 | template<typename G> | ||
172 | VTPWriter(G&&, VTK::XMLOptions = {}) -> VTPWriter<std::remove_cvref_t<G>>; | ||
173 | |||
174 | } // namespace GridFormat | ||
175 | |||
176 | #endif // GRIDFORMAT_VTK_VTP_WRITER_HPP_ | ||
177 |