42#ifndef UFO_CLOUD_IO_UFO_HPP
43#define UFO_CLOUD_IO_UFO_HPP
46#include <ufo/cloud/cloud.hpp>
47#include <ufo/execution/execution.hpp>
48#include <ufo/io/cloud_properties.hpp>
49#include <ufo/numeric/transform.hpp>
50#include <ufo/numeric/vec.hpp>
51#include <ufo/vision/color.hpp>
66[[nodiscard]] CloudProperties cloudPropertiesUFO(std::filesystem::path
const& file);
70 float timestamp = 0.0f;
76template <std::
size_t Dim,
class T>
77bool readUFOData(std::istream& in, SoAView<
Vec<Dim, T>> data, std::string
const& type,
80 if (
"point" != type) {
82 }
else if ((data.size() *
sizeof(Vec3f)) != size) {
87 if constexpr (std::is_same_v<Vec3f, Vec<Dim, T>>) {
88 in.read(
reinterpret_cast<char*
>(data.data()), data.size_bytes());
91 for (
auto& c : data) {
92 in.read(
reinterpret_cast<char*
>(&tmp),
sizeof(tmp));
93 c =
static_cast<Vec<Dim, T>
>(tmp);
100template <ColorType CT,
class T,
bool Alpha,
bool Weight>
101bool readUFOData(std::istream& in, SoAView<Color<CT, T, Alpha, Weight>> data,
102 std::string
const& type, std::uint64_t size)
104 if (
"color" != type) {
106 }
else if ((data.size() *
sizeof(SmallRGBA)) != size) {
111 if constexpr (std::is_same_v<SmallRGBA, Color<CT, T, Alpha, Weight>>) {
112 in.read(
reinterpret_cast<char*
>(data.data()), data.size_bytes());
115 for (
auto& c : data) {
116 in.read(
reinterpret_cast<char*
>(&tmp),
sizeof(tmp));
125bool readUFOData([[maybe_unused]] std::istream& in, [[maybe_unused]] SoAView<T> data,
126 [[maybe_unused]] std::string
const& type,
127 [[maybe_unused]] std::uint64_t size)
132template <std::
size_t Dim,
class T>
133void writeUFOData(std::ostream& out, SoAView<Vec<Dim, T>
const> data)
135 out <<
"point: " << (data.size() *
sizeof(Vec3f)) <<
'\n';
137 if constexpr (std::is_same_v<Vec3f, Vec<Dim, T>>) {
138 out.write(
reinterpret_cast<char const*
>(data.data()), data.size_bytes());
140 for (
auto const& p : data) {
142 out.write(
reinterpret_cast<char const*
>(&tmp),
sizeof(tmp));
147template <ColorType CT,
class T,
bool Alpha,
bool Weight>
148void writeUFOData(std::ostream& out, SoAView<Color<CT, T, Alpha, Weight>
const> data)
150 out <<
"color: " << (data.size() *
sizeof(SmallRGBA)) <<
'\n';
152 if constexpr (std::is_same_v<SmallRGBA, Color<CT, T, Alpha, Weight>>) {
153 out.write(
reinterpret_cast<char const*
>(data.data()), data.size_bytes());
156 for (
auto const& c : data) {
158 out.write(
reinterpret_cast<char const*
>(&tmp),
sizeof(tmp));
164void writeUFOData([[maybe_unused]] std::ostream& out,
165 [[maybe_unused]] SoAView<T const> data)
170template <
class... Ts>
171inline bool readUFO(std::istream& in,
Cloud<Ts...>& cloud)
177 std::getline(in, line);
178 if (
"# UFO cloud file" != line) {
182 while (std::getline(in, line) && in.good()) {
183 if (line.starts_with(
'#')) {
187 std::string type = line.substr(0, line.find(
':'));
188 std::string value = line.substr(line.find(
':') + 1);
190 if (
"version" == type) {
191 if (
" 1.0" != value) {
194 }
else if (
"width" == type) {
195 std::size_t v = std::stoull(value);
197 }
else if (
"height" == type) {
199 }
else if (
"pose" == type) {
201 }
else if (
"timestamp" == type) {
203 }
else if (
"data" == type) {
212 while (std::getline(in, line) && in.good()) {
213 auto pos = line.find(
':');
215 type = line.substr(0, pos);
218 std::from_chars(line.data() + pos + 2, line.data() + line.size(), size);
220 if (ec == std::errc()) {
222 }
else if (ec == std::errc::invalid_argument) {
225 }
else if (ec == std::errc::result_out_of_range) {
230 if ((detail::readUFOData(in, view<Ts>(cloud), type, size) || ...)) {
233 in.seekg(size, std::ios::cur);
240template <
class... Ts>
241bool readUFO(std::filesystem::path
const& file,
Cloud<Ts...>& cloud)
244 ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
245 ifs.imbue(std::locale());
246 ifs.open(file, std::ios::in | std::ios::binary);
247 return readUFO(ifs, cloud);
250template <
class... Ts>
251bool writeUFO(std::ostream& out,
Cloud<Ts...> const& cloud,
252 CloudUFOOptions
const& options = CloudUFOOptions())
254 out <<
"# UFO cloud file\n";
256 out <<
"# Generated by UFO\n";
258 out <<
"version: 1.0\n";
259 out <<
"width: " << cloud.size() <<
'\n';
261 out <<
"height: 1\n";
262 out <<
"# pose: x y z qw qx qy qz\n";
263 auto t = options.pose.translation;
264 auto q =
static_cast<Quatf
>(options.pose.rotation);
265 out <<
"pose: " << t.x <<
' ' << t.y <<
' ' << t.z <<
' ' << q.w <<
' ' << q.x <<
' '
266 << q.y <<
' ' << q.z <<
'\n';
268 out <<
"# timestamp: seconds nanoseconds\n";
269 out <<
"timestamp: " << options.timestamp <<
'\n';
272 (detail::writeUFOData(out, view<Ts>(cloud)), ...);
277template <
class... Ts>
278bool writeUFO(std::filesystem::path
const& file,
Cloud<Ts...> const& cloud,
279 CloudUFOOptions
const& options = CloudUFOOptions())
282 ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit);
283 ofs.imbue(std::locale());
284 ofs.open(file, std::ios::out | std::ios::binary);
285 return writeUFO(ofs, cloud, options);
All vision-related classes and functions.
constexpr To convert(Vec< Dim, U > const &v) noexcept
Converts a vector to a different Vec type, truncating or zero-padding dimensions.
A fixed-size arithmetic vector of up to 4 dimensions.