| 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::VTPReader | ||
| 7 | */ | ||
| 8 | #ifndef GRIDFORMAT_VTK_VTP_READER_HPP_ | ||
| 9 | #define GRIDFORMAT_VTK_VTP_READER_HPP_ | ||
| 10 | |||
| 11 | #include <string> | ||
| 12 | #include <optional> | ||
| 13 | #include <iterator> | ||
| 14 | #include <utility> | ||
| 15 | |||
| 16 | #include <gridformat/common/string_conversion.hpp> | ||
| 17 | #include <gridformat/common/exceptions.hpp> | ||
| 18 | #include <gridformat/common/field.hpp> | ||
| 19 | |||
| 20 | #include <gridformat/grid/cell_type.hpp> | ||
| 21 | #include <gridformat/grid/reader.hpp> | ||
| 22 | #include <gridformat/vtk/xml.hpp> | ||
| 23 | |||
| 24 | namespace GridFormat { | ||
| 25 | |||
| 26 | /*! | ||
| 27 | * \ingroup VTK | ||
| 28 | * \brief Reader for .vtp file format | ||
| 29 | */ | ||
| 30 | class VTPReader : public GridReader { | ||
| 31 | private: | ||
| 32 | 235 | void _open(const std::string& filename, typename GridReader::FieldNames& fields) override { | |
| 33 |
1/2✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
|
235 | auto helper = VTK::XMLReaderHelper::make_from(filename, "PolyData"); |
| 34 | |||
| 35 |
3/6✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 235 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 235 times.
✗ Branch 10 not taken.
|
235 | _num_points = from_string<std::size_t>(helper.get("PolyData/Piece").get_attribute("NumberOfPoints")); |
| 36 |
2/4✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 235 times.
✗ Branch 7 not taken.
|
235 | _num_verts = helper.get("PolyData/Piece").get_attribute_or(std::size_t{0}, "NumberOfVerts"); |
| 37 |
2/4✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 235 times.
✗ Branch 7 not taken.
|
235 | _num_lines = helper.get("PolyData/Piece").get_attribute_or(std::size_t{0}, "NumberOfLines"); |
| 38 |
2/4✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 235 times.
✗ Branch 7 not taken.
|
235 | _num_strips = helper.get("PolyData/Piece").get_attribute_or(std::size_t{0}, "NumberOfStrips"); |
| 39 |
2/4✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 235 times.
✗ Branch 7 not taken.
|
235 | _num_polys = helper.get("PolyData/Piece").get_attribute_or(std::size_t{0}, "NumberOfPolys"); |
| 40 | |||
| 41 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
|
235 | if (_num_strips > 0) |
| 42 | ✗ | throw NotImplemented("Triangle strips are not (yet) supported"); | |
| 43 | |||
| 44 |
2/4✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 235 times.
✗ Branch 6 not taken.
|
235 | VTK::XMLDetail::copy_field_names_from(helper.get("PolyData"), fields); |
| 45 | 235 | _helper.emplace(std::move(helper)); | |
| 46 | 235 | } | |
| 47 | |||
| 48 | 43 | void _close() override { | |
| 49 | 43 | _helper.reset(); | |
| 50 | 43 | _num_points = 0; | |
| 51 | 43 | _num_verts = 0; | |
| 52 | 43 | _num_lines = 0; | |
| 53 | 43 | _num_strips = 0; | |
| 54 | 43 | _num_polys = 0; | |
| 55 | 43 | } | |
| 56 | |||
| 57 | 1 | std::string _name() const override { | |
| 58 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | return "VTPReader"; |
| 59 | } | ||
| 60 | |||
| 61 | 921 | std::size_t _number_of_cells() const override { | |
| 62 | 921 | return _num_verts + _num_lines + _num_strips + _num_polys; | |
| 63 | } | ||
| 64 | |||
| 65 | 1317 | std::size_t _number_of_points() const override { | |
| 66 | 1317 | return _num_points; | |
| 67 | } | ||
| 68 | |||
| 69 | 7 | std::size_t _number_of_pieces() const override { | |
| 70 | 7 | return 1; | |
| 71 | } | ||
| 72 | |||
| 73 | 85 | bool _is_sequence() const override { | |
| 74 | 85 | return false; | |
| 75 | } | ||
| 76 | |||
| 77 | 161 | FieldPtr _points() const override { | |
| 78 |
1/2✓ Branch 4 taken 161 times.
✗ Branch 5 not taken.
|
161 | return _helper.value().make_points_field("PolyData/Piece/Points", _number_of_points()); |
| 79 | } | ||
| 80 | |||
| 81 | 295 | void _visit_cells(const typename GridReader::CellVisitor& visitor) const override { | |
| 82 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 295 times.
|
295 | if (_num_verts > 0) |
| 83 | ✗ | _visit_cells("Verts", CellType::vertex, _num_verts, visitor); | |
| 84 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 269 times.
|
295 | if (_num_lines > 0) |
| 85 |
1/2✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
26 | _visit_cells("Lines", CellType::polyline, _num_lines, visitor); |
| 86 |
2/2✓ Branch 0 taken 269 times.
✓ Branch 1 taken 26 times.
|
295 | if (_num_polys > 0) |
| 87 |
1/2✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
|
269 | _visit_cells("Polys", CellType::polygon, _num_polys, visitor); |
| 88 | 295 | } | |
| 89 | |||
| 90 | 655 | FieldPtr _cell_field(std::string_view name) const override { | |
| 91 |
2/4✓ Branch 2 taken 655 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 655 times.
✗ Branch 8 not taken.
|
655 | return _helper.value().make_data_array_field(name, "PolyData/Piece/CellData", _number_of_cells()); |
| 92 | } | ||
| 93 | |||
| 94 | 658 | FieldPtr _point_field(std::string_view name) const override { | |
| 95 |
2/4✓ Branch 2 taken 658 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 658 times.
✗ Branch 8 not taken.
|
658 | return _helper.value().make_data_array_field(name, "PolyData/Piece/PointData", _number_of_points()); |
| 96 | } | ||
| 97 | |||
| 98 | 66 | FieldPtr _meta_data_field(std::string_view name) const override { | |
| 99 |
1/2✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
|
66 | return _helper.value().make_data_array_field(name, "PolyData/FieldData"); |
| 100 | } | ||
| 101 | |||
| 102 | 295 | void _visit_cells(std::string_view type_name, | |
| 103 | const CellType& cell_type, | ||
| 104 | const std::size_t expected_size, | ||
| 105 | const typename GridReader::CellVisitor& visitor) const { | ||
| 106 |
2/4✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 295 times.
✗ Branch 5 not taken.
|
295 | const std::string path = "PolyData/Piece/" + std::string{type_name}; |
| 107 |
2/4✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 295 times.
✗ Branch 8 not taken.
|
590 | const auto offsets = _helper.value().make_data_array_field( |
| 108 | "offsets", path, expected_size | ||
| 109 |
1/2✓ Branch 2 taken 295 times.
✗ Branch 3 not taken.
|
295 | )->template export_to<std::vector<std::size_t>>(); |
| 110 |
2/4✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 295 times.
✗ Branch 8 not taken.
|
590 | const auto connectivity = _helper.value().make_data_array_field( |
| 111 | "connectivity", path | ||
| 112 |
1/2✓ Branch 2 taken 295 times.
✗ Branch 3 not taken.
|
295 | )->template export_to<std::vector<std::size_t>>(); |
| 113 | |||
| 114 | 295 | std::vector<std::size_t> corners; | |
| 115 |
2/2✓ Branch 0 taken 6392 times.
✓ Branch 1 taken 295 times.
|
6687 | for (std::size_t i = 0; i < expected_size; ++i) { |
| 116 | 6392 | corners.clear(); | |
| 117 |
3/4✓ Branch 0 taken 6097 times.
✓ Branch 1 taken 295 times.
✓ Branch 3 taken 6097 times.
✗ Branch 4 not taken.
|
6392 | const std::size_t offset_begin = (i == 0 ? 0 : offsets.at(i-1)); |
| 118 |
1/2✓ Branch 1 taken 6392 times.
✗ Branch 2 not taken.
|
6392 | const std::size_t offset_end = offsets.at(i); |
| 119 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6392 times.
|
6392 | if (connectivity.size() < offset_end) |
| 120 | ✗ | throw SizeError("Connectivity array read from the file is too small"); | |
| 121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6392 times.
|
6392 | if (offset_end < offset_begin) |
| 122 | ✗ | throw ValueError("Invalid offset array"); | |
| 123 |
2/4✓ Branch 1 taken 6392 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 6392 times.
✗ Branch 7 not taken.
|
6392 | std::copy_n(connectivity.begin() + offset_begin, offset_end - offset_begin, std::back_inserter(corners)); |
| 124 | |||
| 125 | // look for cell types that allow for a more specific classification | ||
| 126 |
2/2✓ Branch 0 taken 6132 times.
✓ Branch 1 taken 260 times.
|
12784 | const CellType ct = cell_type == CellType::polygon ? ( |
| 127 |
2/2✓ Branch 1 taken 6131 times.
✓ Branch 2 taken 1 times.
|
12263 | corners.size() == 3 ? CellType::triangle |
| 128 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6130 times.
|
6131 | : (corners.size() == 4 ? CellType::quadrilateral : cell_type) |
| 129 |
1/2✓ Branch 0 taken 260 times.
✗ Branch 1 not taken.
|
520 | ) : (cell_type == CellType::polyline ? ( |
| 130 |
2/2✓ Branch 1 taken 130 times.
✓ Branch 2 taken 130 times.
|
260 | corners.size() == 2 ? CellType::segment |
| 131 | : cell_type | ||
| 132 | 6392 | ) : cell_type); | |
| 133 |
1/2✓ Branch 1 taken 6392 times.
✗ Branch 2 not taken.
|
6392 | visitor(ct, corners); |
| 134 | } | ||
| 135 | 295 | } | |
| 136 | |||
| 137 | std::optional<VTK::XMLReaderHelper> _helper; | ||
| 138 | std::size_t _num_points; | ||
| 139 | std::size_t _num_verts; | ||
| 140 | std::size_t _num_lines; | ||
| 141 | std::size_t _num_strips; | ||
| 142 | std::size_t _num_polys; | ||
| 143 | }; | ||
| 144 | |||
| 145 | } // namespace GridFormat | ||
| 146 | |||
| 147 | #endif // GRIDFORMAT_VTK_VTP_READER_HPP_ | ||
| 148 |