SemiDiscreteOT 1.0
Semi-Discrete Optimal Transport Library
Loading...
Searching...
No Matches
VtkHandler.cc
Go to the documentation of this file.
2
3#include <vtkXMLUnstructuredGridReader.h>
4#include <vtkUnstructuredGridReader.h>
5#include <vtkGenericCell.h>
6#include <vtkTransform.h>
7#include <vtkTransformFilter.h>
8
9#include <stdexcept>
10#include <filesystem>
11#include <string>
12#include <algorithm>
13
14template <int dim, int spacedim>
15VTKHandler<dim, spacedim>::VTKHandler(const std::string& filename,
16 const bool is_binary,
17 const double scaling_factor)
18 : Function<spacedim>(1) // scalar function
19 , filename(filename)
20 , is_binary(is_binary)
21 , scaling_factor(scaling_factor)
22 , selected_component(0)
23{
24 // Check if file exists
25 if (!std::filesystem::exists(filename)) {
26 throw std::runtime_error("VTK file not found: " + filename);
27 }
28
29 read_file();
30}
31
32template <int dim, int spacedim>
34{
35 // Get file extension
36 std::string extension = std::filesystem::path(filename).extension().string();
37 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
38
39 if (extension == ".vtu") {
40 // For VTU files (XML format)
41 auto reader = vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
42 reader->SetFileName(filename.c_str());
43 reader->Update();
44 vtk_grid = reader->GetOutput();
45
46 if (!vtk_grid || vtk_grid->GetNumberOfPoints() == 0) {
47 throw std::runtime_error("Failed to read VTU file or file is empty");
48 }
49 } else if (extension == ".vtk") {
50 // For legacy VTK files
51 auto reader = vtkSmartPointer<vtkUnstructuredGridReader>::New();
52 reader->SetFileName(filename.c_str());
53 reader->Update();
54 vtk_grid = reader->GetOutput();
55
56 if (!vtk_grid || vtk_grid->GetNumberOfPoints() == 0) {
57 throw std::runtime_error("Failed to read VTK file or file is empty");
58 }
59 } else {
60 throw std::runtime_error("Unsupported file extension: " + extension +
61 ". Supported extensions are .vtk and .vtu");
62 }
63
64 // Apply scaling if needed
65 if (scaling_factor != 1.0) {
66 auto transform = vtkSmartPointer<vtkTransform>::New();
67 transform->Scale(scaling_factor, scaling_factor, scaling_factor);
68
69 auto transform_filter = vtkSmartPointer<vtkTransformFilter>::New();
70 transform_filter->SetInputData(vtk_grid);
71 transform_filter->SetTransform(transform);
72 transform_filter->Update();
73
74 vtk_grid = transform_filter->GetUnstructuredGridOutput();
75 }
76
77 // Print some information about the loaded grid
78 std::cout << "Loaded VTK grid with:" << std::endl
79 << " Points: " << vtk_grid->GetNumberOfPoints() << std::endl
80 << " Cells: " << vtk_grid->GetNumberOfCells() << std::endl;
81
82 // Print available point data arrays
83 vtkPointData* point_data = vtk_grid->GetPointData();
84 std::cout << "Available point data arrays:" << std::endl;
85 for (int i = 0; i < point_data->GetNumberOfArrays(); ++i) {
86 vtkDataArray* array = point_data->GetArray(i);
87 std::cout << " - " << array->GetName()
88 << " (components: " << array->GetNumberOfComponents() << ")"
89 << std::endl;
90 }
91}
92
93template <int dim, int spacedim>
94void VTKHandler<dim, spacedim>::setup_field(const std::string& field_name_,
95 const DataLocation data_location_,
96 const unsigned int component)
97{
98 field_name = field_name_;
99 data_location = data_location_;
100 selected_component = component;
101
102 // Get the field data based on location
103 if (data_location == DataLocation::PointData) {
104 field_data = vtk_grid->GetPointData()->GetArray(field_name.c_str());
105 if (!field_data) {
106 throw std::runtime_error("Point data array '" + field_name + "' not found");
107 }
108
109 // Setup point locator
110 point_locator = vtkSmartPointer<vtkPointLocator>::New();
111 point_locator->SetDataSet(vtk_grid);
112 point_locator->BuildLocator();
113 } else {
114 field_data = vtk_grid->GetCellData()->GetArray(field_name.c_str());
115 if (!field_data) {
116 throw std::runtime_error("Cell data array '" + field_name + "' not found");
117 }
118
119 // Setup cell locator
120 cell_locator = vtkSmartPointer<vtkCellLocator>::New();
121 cell_locator->SetDataSet(vtk_grid);
122 cell_locator->BuildLocator();
123 }
124
125 // Check if the component is valid
126 if (selected_component >= static_cast<unsigned int>(field_data->GetNumberOfComponents())) {
127 throw std::runtime_error("Invalid component index " + std::to_string(selected_component) +
128 " for field '" + field_name + "' with " +
129 std::to_string(field_data->GetNumberOfComponents()) + " components");
130 }
131}
132
133template <int dim, int spacedim>
134double VTKHandler<dim, spacedim>::value(const Point<spacedim>& p, const unsigned int /*component*/) const
135{
136 double closest_point[3];
137 vtkIdType closest_id;
138 double closest_dist2;
139 double value = 0.0;
140
141 if (data_location == DataLocation::PointData) {
142 // Convert dealii::Point to double array for VTK
143 double point[3] = {p[0], p[1], p[2]};
144 closest_id = point_locator->FindClosestPoint(point);
145
146 // Get the selected component from the field data
147 double tuple[3]; // Assuming max 3 components
148 field_data->GetTuple(closest_id, tuple);
149 value = tuple[selected_component];
150 } else {
151 // Find closest cell
152 auto cell = vtkSmartPointer<vtkGenericCell>::New();
153 double x[3] = {p[0], p[1], p[2]};
154 int subId;
155
156 cell_locator->FindClosestPoint(x, closest_point, cell, closest_id,
157 subId, closest_dist2);
158
159 // Get the selected component from the field data
160 double tuple[3]; // Assuming max 3 components
161 field_data->GetTuple(closest_id, tuple);
162 value = tuple[selected_component];
163 }
164
165 return value;
166}
167
168// Explicit template instantiations
169template class VTKHandler<2, 2>;
170template class VTKHandler<2, 3>;
171template class VTKHandler<3, 3>;
A handler class for reading and interpolating data from VTK files.
Definition VtkHandler.h:34
virtual double value(const Point< spacedim > &p, const unsigned int component=0) const override
Interpolates the value of the selected field at a given point.
void read_file()
Reads the VTK file and initializes the internal data structures.
Definition VtkHandler.cc:33
VTKHandler(const std::string &filename, const bool is_binary=false, const double scaling_factor=1.0)
Constructor for the VTKHandler.
Definition VtkHandler.cc:15
void setup_field(const std::string &field_name, const DataLocation data_location=DataLocation::PointData, const unsigned int component=0)
Sets up the field to be used for interpolation.
Definition VtkHandler.cc:94
DataLocation
Enum to specify whether the data is associated with points or cells.
Definition VtkHandler.h:39
std::string filename
Definition VtkHandler.h:103