Tatooine
read.h
Go to the documentation of this file.
1#ifndef TATOOINE_AMIRA_READ_H
2#define TATOOINE_AMIRA_READ_H
3//==============================================================================
5#include <tatooine/concepts.h>
7
8#include <cassert>
9#include <stdexcept>
10#include <string>
11#include <vector>
12//==============================================================================
13namespace tatooine::amira {
14//==============================================================================
15static constexpr auto lattice = std::string_view{"define Lattice"};
16static constexpr auto boundingbox = std::string_view{"BoundingBox"};
17static constexpr auto lattice_size = std::string_view{"Lattice { float["};
18static constexpr auto data_follows = std::string_view{"# Data section follows"};
19static constexpr auto num_bytes_header = std::size_t(2048);
20//==============================================================================
21inline auto read_header(std::ifstream& file) {
22 auto const cur_cursor_pos = file.tellg();
23 // We read the first 2048 bytes into memory to parse the header.
24 auto buf = std::string(
25 num_bytes_header / sizeof(typename std::string::value_type), ' ');
26 file.read(buf.data(), num_bytes_header);
27
28 // remove eof flag if read all data
29 if (file.eof()) {
30 file.clear();
31 }
32 file.seekg(0, std::ios_base::beg);
33 auto buffer = std::istringstream{std::move(buf)};
34
35 // Find the Lattice definition, i.e., the dimensions of the uniform grid
36 auto dims = std::array<std::size_t, 3>{};
37 auto const lattice_pos =
38 static_cast<std::streamoff>(buffer.str().find(lattice));
39 buffer.seekg(lattice_pos, std::ios_base::beg);
40 buffer.seekg(static_cast<std::istringstream::off_type>(lattice.size()),
41 std::ios_base::cur);
42 buffer >> dims[0] >> dims[1] >> dims[2];
43
44 // Find the boundingbox
46 auto const boundingbox_pos =
47 static_cast<std::istringstream::off_type>(buffer.str().find(boundingbox));
48 buffer.seekg(boundingbox_pos,
49 std::ios_base::beg);
50 buffer.seekg(static_cast<std::istringstream::off_type>(boundingbox.size()),
51 std::ios_base::cur);
52 buffer >> aabb.min(0) >> aabb.max(0) >> aabb.min(1) >> aabb.max(1) >>
53 aabb.min(2) >> aabb.max(2);
54
55 // Is it a uniform grid? We need this only for the sanity check below.
56 auto const is_uniform =
57 buffer.str().find("CoordType \"uniform\"") != std::string::npos;
58
59 // Type of the field: scalar, vector
60 auto num_components = std::size_t{};
61 if (buffer.str().find("Lattice { float Data }") != std::string::npos) {
62 // Scalar field
63 num_components = 1;
64 } else {
65 // A field with more than one component, i.e., a vector field
66 auto const pos = buffer.str().find(lattice_size);
67 buffer.seekg(static_cast<std::istringstream::off_type>(pos), std::ios_base::beg);
68 buffer.seekg(static_cast<std::istringstream::off_type>(lattice_size.size()), std::ios_base::cur);
69 buffer >> num_components;
70 }
71
72 // Sanity check
73 if (dims[0] <= 0 || dims[1] <= 0 || dims[2] <= 0 ||
74 aabb.min(0) > aabb.max(0) || aabb.min(1) > aabb.max(1) ||
75 aabb.min(2) > aabb.max(2) || !is_uniform || num_components <= 0) {
76 throw std::runtime_error("something went wrong");
77 }
78
79 // Find the beginning of the data section
80 auto const data_follows_pos = buffer.str().find(data_follows);
81 auto break_pos = static_cast<std::string::size_type>(buffer.str().find(
82 '\n', static_cast<std::string::size_type>(data_follows_pos)));
83 break_pos = static_cast<std::string::size_type>(
84 buffer.str().find('\n', break_pos + 1));
85 auto data_begin_pos = std::streamoff{};
86 if (data_follows_pos != std::string::npos) {
87 data_begin_pos = static_cast<std::streamoff>(break_pos + 1);
88 }
89 file.seekg(cur_cursor_pos);
90 return std::tuple{dims, std::move(aabb), num_components, data_begin_pos};
91}
92//------------------------------------------------------------------------------
93inline auto read_header(filesystem::path const& path) {
94 auto file = std::ifstream{path};
95 if (!file.is_open()) {
96 throw std::runtime_error("could not open file " + path.string());
97 }
98 return read_header(file);
99}
100//==============================================================================
103template <floating_point T = float>
104auto read(std::ifstream& file) {
105 auto [dims, aabb, num_components, data_begin_pos] = read_header(file);
106 auto const num_to_read = dims[0] * dims[1] * dims[2] * num_components;
107 auto data = std::vector<float>(num_to_read);
108
109 file.seekg(data_begin_pos, std::ios_base::beg);
110 file.read(reinterpret_cast<char*>(data.data()),
111 static_cast<std::streamsize>(sizeof(float) * num_to_read));
112
113 if constexpr (is_float<T>) {
114 return std::tuple{std::move(data), dims, std::move(aabb), num_components};
115 } else {
116 return std::tuple{std::vector<T>(begin(data), end(data)), dims,
117 std::move(aabb), num_components};
118 }
119}
120//------------------------------------------------------------------------------
121template <floating_point T = float>
122auto read(filesystem::path const& path) {
123 auto file = std::ifstream{path};
124 if (!file.is_open()) {
125 throw std::runtime_error("could not open file " + path.string());
126 }
127 return read<T>(file);
128}
129//==============================================================================
130} // namespace tatooine::amira
131//==============================================================================
132#endif
Definition: read.h:13
static constexpr auto num_bytes_header
Definition: read.h:19
static constexpr auto boundingbox
Definition: read.h:16
static constexpr auto lattice_size
Definition: read.h:17
static constexpr auto lattice
Definition: read.h:15
auto read_header(std::ifstream &file)
Definition: read.h:21
static constexpr auto data_follows
Definition: read.h:18
auto read(std::ifstream &file)
Definition: read.h:104
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
axis_aligned_bounding_box< Real, NumDimensions > aabb
Definition: axis_aligned_bounding_box.h:553
Definition: axis_aligned_bounding_box.h:103
auto constexpr max() const -> auto const &
Definition: axis_aligned_bounding_box.h:156
auto constexpr min() const -> auto const &
Definition: axis_aligned_bounding_box.h:151