BinaryIO.h
Go to the documentation of this file.
1#pragma once
2
3#include <fstream>
4#include <istream>
5#include <ostream>
6
7#include "../VoxelGrid.hpp"
8#include "exceptions.h"
9
11{
13 {
14 public:
15 // VOXEL READ/WRITE
16
17 /**
18 * @brief Read a voxel from the out stream.
19 *
20 * This is a free template method used by voxel_grid_io::read(),
21 * so you can specialize it if necessary.
22 */
23 template <typename VoxelT>
24 static void readVoxel(std::istream& is, VoxelT& voxel);
25
26
27 /**
28 * @brief Write a voxel to the out stream.
29 *
30 * This is a free template method used by voxel_grid_io::write(),
31 * so you can specialize it if necessary.
32 */
33 template <typename VoxelT>
34 static void writeVoxel(std::ostream& os, const VoxelT& voxel);
35
36
37 // VOXEL GRID READ
38
39 /**
40 * @brief Read a voxel grid from the file.
41 *
42 * Sets `voxelGrid`'s layout and fills the voxel data.
43 */
44 template <typename VoxelT>
45 static void read(VoxelGrid<VoxelT>& voxelGrid, const std::string& filename);
46
47 /**
48 * @brief Read a voxel grid from the in-stream.
49 *
50 * Sets `voxelGrid`'s layout and fills the voxel data.
51 * `is` must be open in binary mode with a valid voxel grid file.
52 */
53 template <typename VoxelT>
54 static void read(VoxelGrid<VoxelT>& voxelGrid, std::istream& is);
55
56
57 /**
58 * @brief Read a voxel grid from the filename.
59 *
60 * The specified voxel grid type `VoxelGridT` must provide a default constructor.
61 * Sets `voxelGrid`'s layout and fills the voxel data.
62 * `is` must be open in binary mode with a valid voxel grid file.
63 */
64 template <typename VoxelGridT>
65 static VoxelGridT read(const std::string& filename);
66
67 /**
68 * @brief Read a voxel grid from the in-stream.
69 *
70 * The specified voxel grid type `VoxelGridT` must provide a default constructor.
71 * Sets `voxelGrid`'s layout and fills the voxel data.
72 * `is` must be open in binary mode with a valid voxel grid file.
73 */
74 template <typename VoxelGridT>
75 static VoxelGridT read(std::istream& is);
76
77
78 // VOXEL GRID WRITE
79
80 /**
81 * @brief Write a voxel grid to a file.
82 */
83 template <typename VoxelT>
84 static void write(const VoxelGrid<VoxelT>& voxelGrid, const std::string& filename);
85
86 /**
87 * @brief Write a voxel grid to an out-stream.
88 *
89 * The out-stream `os` must be open in binary mode.
90 */
91 template <typename VoxelT>
92 static void write(const VoxelGrid<VoxelT>& voxelGrid, std::ostream& os);
93
94
95 private:
96 /// Throws an exception if value is not positive 0.
97 static void checkPositive(int value);
98 static void checkPositive(float value);
99 };
100} // namespace visionx::voxelgrid::io
101
102// IMPLEMENTATIONS
103
105{
106
107 template <typename DataT>
108 void
109 readData(std::istream& is, DataT& data)
110 {
111 is.read(reinterpret_cast<char*>(&data), sizeof(DataT));
112 }
113
114 template <typename DataT>
115 void
116 writeData(std::ostream& os, const DataT& data)
117 {
118 os.write(reinterpret_cast<const char*>(&data), sizeof(DataT));
119 }
120
121 template <typename ReadT, typename Derived>
122 void
123 readEigen(std::istream& is, Eigen::MatrixBase<Derived>& matrix)
124 {
125 using Scalar = typename Eigen::MatrixBase<Derived>::Scalar;
126
127 auto cast = matrix.template cast<ReadT>().eval();
128 is.read(reinterpret_cast<char*>(cast.data()), cast.size() * sizeof(Scalar));
129
130 matrix = cast.template cast<Scalar>();
131 }
132
133 template <typename WriteT, typename Derived>
134 void
135 writeEigen(std::ostream& os, const Eigen::MatrixBase<Derived>& matrix)
136 {
137 auto eval = matrix.template cast<WriteT>().eval();
138 os.write(reinterpret_cast<const char*>(eval.data()), eval.size() * sizeof(WriteT));
139 }
140
141} // namespace visionx::voxelgrid::io::detail
142
144{
145 template <typename VoxelT>
146 void
147 BinaryIO::readVoxel(std::istream& is, VoxelT& voxel)
148 {
149 detail::readData<VoxelT>(is, voxel);
150 }
151
152 template <typename VoxelT>
153 void
154 BinaryIO::writeVoxel(std::ostream& os, const VoxelT& voxel)
155 {
156 detail::writeData<VoxelT>(os, voxel);
157 }
158
159 template <typename VoxelGridT>
160 VoxelGridT
161 BinaryIO::read(const std::string& filename)
162 {
163 VoxelGridT grid;
164 read(grid, filename);
165 return grid;
166 }
167
168 template <typename VoxelGridT>
169 VoxelGridT
170 BinaryIO::read(std::istream& is)
171 {
172 VoxelGridT grid;
173 read(grid, is);
174 return grid;
175 }
176
177 template <typename VoxelT>
178 void
179 BinaryIO::read(VoxelGrid<VoxelT>& voxelGrid, const std::string& filename)
180 {
181 std::ifstream ifs;
182 ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
183
184 try
185 {
186 ifs.open(filename, std::ios_base::binary | std::ios_base::in);
187 }
188 catch (const std::ios_base::failure& e)
189 {
190 throw error::io::BinaryIOError("read", filename, "Failed to open file.", e);
191 }
192
193 try
194 {
195 read(voxelGrid, ifs);
196 }
197 catch (const std::ios_base::failure& e)
198 {
199 throw error::io::BinaryIOError("read", filename, "Error while reading file.", e);
200 }
201 }
202
203 template <typename VoxelT>
204 void
205 BinaryIO::read(VoxelGrid<VoxelT>& voxelGrid, std::istream& is)
206 {
207 Eigen::Vector3f voxelSizes = Eigen::Vector3f::Zero();
208 Eigen::Vector3f gridSizes = Eigen::Vector3f::Zero();
209 Eigen::Vector3f origin = Eigen::Vector3f::Zero();
210 Eigen::Vector4f orientationCoeffs = Eigen::Vector4f::Zero();
211
212 try
213 {
214 // read voxel sizes
215 detail::readEigen<float>(is, voxelSizes);
216 // read grid sizes (as float to be uniform)
217 detail::readEigen<float>(is, gridSizes);
218 // read grid origin
219 detail::readEigen<float>(is, origin);
220 // read orientation coeffs in [w x y z] order
221 detail::readEigen<float>(is, orientationCoeffs);
222 }
223 catch (const std::ios_base::failure& e)
224 {
225 throw error::io::BinaryReadError("Failed to read voxel grid structure.", e);
226 }
227
228 checkPositive(voxelSizes.minCoeff());
229 checkPositive(gridSizes.minCoeff());
230
231 Eigen::Quaternionf orientation;
232 orientation.w() = orientationCoeffs(0);
233 orientation.coeffs().head<3>() = orientationCoeffs.tail<3>();
234
235 voxelGrid.setVoxelSizes(voxelSizes);
236 voxelGrid.setGridSizes(gridSizes.cast<int>());
237 voxelGrid.setOrigin(origin);
238 voxelGrid.setOrientation(orientation);
239
240 // read voxel data
241 for (std::size_t i = 0; i < voxelGrid.numVoxels(); ++i)
242 {
243 try
244 {
245 readVoxel<VoxelT>(is, voxelGrid.getVoxel(i));
246 }
247 catch (const std::ios_base::failure& e)
248 {
249 std::stringstream ss;
250 ss << "Failed to read voxel " << i << " of " << voxelGrid.numVoxels() << ".";
251 throw error::io::BinaryReadError(ss.str(), e);
252 }
253 }
254 }
255
256 template <typename VoxelT>
257 void
258 BinaryIO::write(const VoxelGrid<VoxelT>& voxelGrid, const std::string& filename)
259 {
260 std::ofstream ofs;
261 ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit);
262
263 try
264 {
265 ofs.open(filename, std::ios_base::binary | std::ios_base::out);
266 }
267 catch (const std::ios_base::failure& e)
268 {
269 throw error::io::BinaryIOError("write", filename, "Failed to open file.", e);
270 }
271
272 try
273 {
274 write(voxelGrid, ofs);
275 }
276 catch (const std::ios_base::failure& e)
277 {
278 throw error::io::BinaryIOError("write", filename, "Error while reading file.", e);
279 }
280 }
281
282 template <typename VoxelT>
283 void
284 BinaryIO::write(const VoxelGrid<VoxelT>& voxelGrid, std::ostream& os)
285 {
286 const Eigen::Vector3f voxelSizes = voxelGrid.getVoxelSizes();
287 const Eigen::Vector3i gridSizes = voxelGrid.getGridSizes();
288 const Eigen::Vector3f origin = voxelGrid.getOrigin();
289 const Eigen::Quaternionf orientation = voxelGrid.getOrientation();
290
291 // orientation in [w x y z] order
292 Eigen::Vector4f orientationCoeffs;
293 orientationCoeffs(0) = orientation.w();
294 orientationCoeffs.tail<3>() = orientation.coeffs().head<3>();
295
296 // write voxel sizes
297 detail::writeEigen<float>(os, voxelSizes);
298 // write grid sizes (as float to be uniform)
299 detail::writeEigen<float>(os, gridSizes.cast<float>());
300 // write grid origin
301 detail::writeEigen<float>(os, origin);
302 // write grid orientation
303 detail::writeEigen<float>(os, orientationCoeffs);
304
305 // write voxel data
306 for (std::size_t i = 0; i < voxelGrid.numVoxels(); ++i)
307 {
308 writeVoxel<VoxelT>(os, voxelGrid.getVoxel(i));
309 }
310 }
311
312} // namespace visionx::voxelgrid::io
uint8_t data[1]
float Scalar
Definition basic.h:15
A 3D grid of voxels of type _VoxelT.
Definition VoxelGrid.hpp:50
Eigen::Vector3f getOrigin() const
Get the grid origin in the world frame (center of voxel [0 0 0]).
void setVoxelSizes(float voxelSize)
Set the voxel size of cubic voxels. The grid data is not updated.
VoxelT & getVoxel(std::size_t index)
Get the voxel with the given index.
void setOrientation(const Eigen::Quaternionf &value)
Set the grid orienation in the world frame.
void setOrigin(const Eigen::Vector3f &value)
Set the grid origin the world frame (center of voxel [0 0 0]).
std::size_t numVoxels() const
Get the number of voxels in the grid.
Eigen::Vector3i getGridSizes() const
Get the grid size.
Eigen::Vector3f getVoxelSizes() const
Get the voxel size.
void setGridSizes(float gridSizes)
Set the grid size for a cubic grid. Resets the grid data.
Eigen::Quaternionf getOrientation() const
Get the grid orienation in the world frame.
Indicates that voxel data with an invalid number of voxels has been passed to a VoxelGrid.
Definition exceptions.h:24
static void read(VoxelGrid< VoxelT > &voxelGrid, const std::string &filename)
Read a voxel grid from the file.
Definition BinaryIO.h:179
static void writeVoxel(std::ostream &os, const VoxelT &voxel)
Write a voxel to the out stream.
Definition BinaryIO.h:154
static void write(const VoxelGrid< VoxelT > &voxelGrid, const std::string &filename)
Write a voxel grid to a file.
Definition BinaryIO.h:258
static void readVoxel(std::istream &is, VoxelT &voxel)
Read a voxel from the out stream.
Definition BinaryIO.h:147
Quaternion< float, 0 > Quaternionf
void readData(std::istream &is, DataT &data)
Definition BinaryIO.h:109
void readEigen(std::istream &is, Eigen::MatrixBase< Derived > &matrix)
Definition BinaryIO.h:123
void writeEigen(std::ostream &os, const Eigen::MatrixBase< Derived > &matrix)
Definition BinaryIO.h:135
void writeData(std::ostream &os, const DataT &data)
Definition BinaryIO.h:116