GridFormat 0.5.0
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
vtp_writer.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2// SPDX-License-Identifier: MIT
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
26
27namespace GridFormat {
28
29#ifndef DOXYGEN
30namespace 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 bool operator()(const Cell<Grid>& cell) const {
38 return std::ranges::any_of(cell_types, [&] (const CellType& _ct) {
39 return _ct == type(grid.get(), cell);
40 });
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
56template<Concepts::UnstructuredGrid Grid>
57class VTPWriter : public 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 explicit VTPWriter(LValueReferenceOf<const Grid> grid,
71 VTK::XMLOptions xml_opts = {})
72 : ParentType(grid.get(), ".vtp", false, std::move(xml_opts))
73 {}
74
75 private:
76 VTPWriter _with(VTK::XMLOptions xml_opts) const override {
77 return VTPWriter{this->grid(), std::move(xml_opts)};
78 }
79
80 void _write(std::ostream& s) const override {
81 FilteredGrid verts{this->grid(), Detail::CellTypesPredicate{this->grid(), zero_d_types}};
82 FilteredGrid lines{this->grid(), Detail::CellTypesPredicate{this->grid(), one_d_types}};
83 FilteredGrid polys{this->grid(), Detail::CellTypesPredicate{this->grid(), two_d_types}};
84 FilteredGrid unsupported{
85 this->grid(),
86 [p=Detail::CellTypesPredicate{
87 this->grid(), Ranges::merged(Ranges::merged(zero_d_types, one_d_types), two_d_types)
88 }] (const Cell<Grid>& cell) {
89 return !p(cell);
90 }
91 };
92
93 auto verts_range = cells(verts);
94 auto lines_range = cells(lines);
95 auto polys_range = cells(polys);
96 auto unsupported_range = cells(unsupported);
97
98 if (Ranges::size(unsupported_range) > 0)
99 this->_log_warning("Grid contains cell types not supported by .vtp; These will be ignored.");
100 if (!std::ranges::empty(this->_cell_field_names())
101 && !std::ranges::empty(verts_range)
102 + !std::ranges::empty(lines_range)
103 + !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 const auto num_verts = Ranges::size(verts_range);
113 const auto num_lines = Ranges::size(lines_range);
114 const auto num_polys = Ranges::size(polys_range);
115
116 auto context = this->_get_write_context("PolyData");
117 this->_set_attribute(context, "Piece", "NumberOfPoints", number_of_points(this->grid()));
118 this->_set_attribute(context, "Piece", "NumberOfVerts", num_verts);
119 this->_set_attribute(context, "Piece", "NumberOfLines", num_lines);
120 this->_set_attribute(context, "Piece", "NumberOfStrips", "0");
121 this->_set_attribute(context, "Piece", "NumberOfPolys", num_polys);
122
123 FieldStorage vtk_point_fields;
124 FieldStorage vtk_cell_fields;
125 std::ranges::for_each(this->_point_field_names(), [&] (const std::string& name) {
126 vtk_point_fields.set(name, VTK::make_vtk_field(this->_get_point_field_ptr(name)));
127 this->_set_data_array(context, "Piece/PointData", name, vtk_point_fields.get(name));
128 });
129 std::ranges::for_each(this->_cell_field_names(), [&] (const std::string& name) {
130 vtk_cell_fields.set(name, VTK::make_vtk_field(this->_get_cell_field_ptr(name)));
131 this->_set_data_array(context, "Piece/CellData", name, vtk_cell_fields.get(name));
132 });
133
134 const FieldPtr coords_field = std::visit([&] <typename T> (const Precision<T>&) {
135 return VTK::make_coordinates_field<T>(this->grid(), false);
136 }, this->_xml_settings.coordinate_precision);
137 this->_set_data_array(context, "Piece/Points", "Coordinates", *coords_field);
138
139 const auto point_id_map = make_point_id_map(this->grid());
140 const auto verts_connectivity_field = _make_connectivity_field(verts, point_id_map);
141 const auto verts_offsets_field = _make_offsets_field(verts);
142 this->_set_data_array(context, "Piece/Verts", "connectivity", *verts_connectivity_field);
143 this->_set_data_array(context, "Piece/Verts", "offsets", *verts_offsets_field);
144
145 const auto lines_connectivity_field = _make_connectivity_field(lines, point_id_map);
146 const auto lines_offsets_field = _make_offsets_field(lines);
147 this->_set_data_array(context, "Piece/Lines", "connectivity", *lines_connectivity_field);
148 this->_set_data_array(context, "Piece/Lines", "offsets", *lines_offsets_field);
149
150 const auto polys_connectivity_field = _make_connectivity_field(polys, point_id_map);
151 const auto polys_offsets_field = _make_offsets_field(polys);
152 this->_set_data_array(context, "Piece/Polys", "connectivity", *polys_connectivity_field);
153 this->_set_data_array(context, "Piece/Polys", "offsets", *polys_offsets_field);
154
155 this->_write_xml(std::move(context), s);
156 }
157
158 template<typename G, typename PointMap>
159 FieldPtr _make_connectivity_field(G&& grid, const PointMap& point_id_map) const {
160 return std::visit([&] <typename T> (const Precision<T>&) {
161 return VTK::make_connectivity_field<T>(grid, point_id_map);
162 }, this->_xml_settings.header_precision);
163 }
164
165 template<typename G>
166 FieldPtr _make_offsets_field(G&& grid) const {
167 return std::visit([&] <typename T> (const Precision<T>&) {
168 return VTK::make_offsets_field<T>(grid);
169 }, this->_xml_settings.header_precision);
170 }
171};
172
173template<typename G>
174VTPWriter(G&&, VTK::XMLOptions = {}) -> VTPWriter<std::remove_cvref_t<G>>;
175
176} // namespace GridFormat
177
178#endif // GRIDFORMAT_VTK_VTP_WRITER_HPP_
Base class for VTK-XML Writer implementations.
Definition: xml.hpp:190
Writer for .vtu file format.
Definition: vtp_writer.hpp:57
std::shared_ptr< const Field > FieldPtr
Pointer type used by writers/readers for fields.
Definition: field.hpp:186
Options for VTK-XML files for setting the desired encoding, data format and compression.
Definition: xml.hpp:99
Common functionality for VTK writers.
Helper classes and functions for VTK XML-type file format writers & readers.