flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
sdf_reader.cpp
Go to the documentation of this file.
1
3#include "sdf_reader.h"
4
5#include <algorithm>
6#include <cstring>
7#include <filesystem>
8#include <fstream>
9#include <iostream>
10#include <sstream>
11#include <stdexcept>
12
13// A simple string helper to find value of an XML attribute
14// e.g. WholeExtent="0 10 0 10 0 10"
15std::string get_attribute_value(const std::string &content, const std::string &attr_name) {
16 size_t pos = content.find(attr_name + "=\"");
17 if (pos == std::string::npos)
18 return "";
19
20 size_t start = pos + attr_name.length() + 2;
21 size_t end = content.find("\"", start);
22 if (end == std::string::npos)
23 return "";
24
25 return content.substr(start, end - start);
26}
27
28SDFData SDFReader::read_vti(const std::string &filename) {
29 std::ifstream file(filename, std::ios::binary);
30 if (!file.is_open()) {
31 throw std::runtime_error("Could not open file: " + filename);
32 }
33
34 SDFData data;
35
36 // Read file content line by line until we find AppendedData or similar
37 // We assume the header is small enough to read comfortably
38 // BUT we need to be careful not to read the binary part as text
39 // Strategy: Read chunks or just locate the "<AppendedData encoding=\"raw\">"
40 // tag.
41
42 // A clearer approach for mixed text/binary:
43 // Read the file into a string buffer until we see the start of binary marker.
44 // The user said: "Appended Raw Binary".
45 // Usually VTK VTI structure is:
46 // <VTKFile ...> ... <AppendedData
47 // encoding="raw">_LENGTH_DATA...</AppendedData></VTKFile>
48
49 // We will scan for the underscore `_` identifying the start of raw data,
50 // but we must first parse the header info which appears before.
51
52 std::string header_buffer;
53 char c;
54 bool found_marker = false;
55
56 // We'll read until we see the sequence `_` immediately following
57 // "<AppendedData encoding=\"raw\">" Actually, often it's just
58 // `...<AppendedData encoding="raw">` then newline then `_`. Let's read the
59 // first 4KB, it should contain the header.
60
61 // Better: Read whole file into memory? No, could be large.
62 // Let's read until "</InAppendedData>" is not useful because it's at the end.
63 // We search for the offset=0 in the AppendedData.
64
65 // Implementation:
66 // 1. Read header text until `header_type="UInt64"` (verification) or just
67 // parse specific tags.
68 // 2. Find "WholeExtent", "Origin", "Spacing".
69
70 // Let's read a chunk (e.g. 8KB) to parse XML.
71 std::vector<char> buffer(8192);
72 file.read(buffer.data(), buffer.size());
73 std::string header(buffer.data(), file.gcount());
74
75 // Parse WholeExtent
76 std::string extent_str = get_attribute_value(header, "WholeExtent");
77 if (extent_str.empty())
78 throw std::runtime_error("Could not find WholeExtent in VTI header");
79
80 int x1, x2, y1, y2, z1, z2;
81 std::stringstream ss_ext(extent_str);
82 ss_ext >> x1 >> x2 >> y1 >> y2 >> z1 >> z2;
83 data.resolution = {x2 - x1 + 1, y2 - y1 + 1, z2 - z1 + 1};
84
85 // Parse Origin
86 std::string origin_str = get_attribute_value(header, "Origin");
87 std::stringstream ss_org(origin_str);
88 ss_org >> data.origin[0] >> data.origin[1] >> data.origin[2];
89
90 // Parse Spacing
91 std::string spacing_str = get_attribute_value(header, "Spacing");
92 std::stringstream ss_spc(spacing_str);
93 ss_spc >> data.spacing[0] >> data.spacing[1] >> data.spacing[2];
94
95 // Find binary data start
96 // Look for "<AppendedData encoding=\"raw\">"
97 std::string appended_tag = "<AppendedData encoding=\"raw\">";
98 size_t tag_pos = header.find(appended_tag);
99 if (tag_pos == std::string::npos)
100 throw std::runtime_error("Could not find AppendedData tag");
101
102 // The binary data starts after the tag. It typically starts with an
103 // underscore `_` followed by the length (UInt64). Let's search for `_` after
104 // the tag.
105 size_t underscore_pos = header.find("_", tag_pos);
106 if (underscore_pos == std::string::npos) {
107 // Maybe we didn't read enough?
108 // If the header is larger than 8KB, we are in trouble.
109 // Realistically headers are small.
110 throw std::runtime_error("Could not find binary data marker '_' in first 8KB");
111 }
112
113 // Seek file to the position of the length (immediately after `_`)
114 file.clear(); // Clear EOF flag if we read past end in buffer
115 file.seekg(underscore_pos + 1, std::ios::beg);
116
117 // Read length (UInt64)
118 uint64_t data_bytes = 0;
119 file.read(reinterpret_cast<char *>(&data_bytes), sizeof(uint64_t));
120
121 // Check for read failure
122 if (!file) {
123 throw std::runtime_error("Failed to read data_bytes (UInt64) from file.");
124 }
125
126 std::cout << "Read data length: " << data_bytes << std::endl;
127
128 size_t attempts = 0;
129 // Check if expected size matches our resolution
130 // Float32 = 4 bytes
131 size_t expected_bytes = data.size() * sizeof(float);
132 if (data_bytes != expected_bytes) {
133 std::cerr << "Warning: Data length in file (" << data_bytes
134 << ") does not match expected size from resolution (" << expected_bytes << ")."
135 << std::endl;
136 // Proceeding anyway but this is suspicious.
137 // It might be that the file size includes some padding or we misread
138 // resolution. Or maybe its compressed (zlib)? User said: "Appended Raw
139 // Binary". This implies uncompressed.
140 }
141
142 // Read Data
143 data.sdf_values.resize(data.size());
144 file.read(reinterpret_cast<char *>(data.sdf_values.data()), data_bytes);
145
146 if (file.gcount() != static_cast<std::streamsize>(data_bytes)) {
147 std::cerr << "Warning: Could not read all data. Read " << file.gcount() << " bytes."
148 << std::endl;
149 }
150
151 return data;
152}
static SDFData read_vti(const std::string &filename)
std::string get_attribute_value(const std::string &content, const std::string &attr_name)
Reader for SDF / VTI geometry (interface).
std::array< int, 3 > resolution
Definition sdf_reader.h:12
std::array< float, 3 > spacing
Definition sdf_reader.h:14
std::vector< float > sdf_values
Definition sdf_reader.h:11
size_t size() const
Definition sdf_reader.h:17
std::array< float, 3 > origin
Definition sdf_reader.h:13