UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
pts.hpp
1
42#ifndef UFO_CLOUD_IO_PTS_HPP
43#define UFO_CLOUD_IO_PTS_HPP
44
45// UFO
46#include <ufo/cloud/point_cloud.hpp>
47#include <ufo/core/intensity.hpp>
48#include <ufo/io/cloud_properties.hpp>
49#include <ufo/io/file_handler.hpp>
50#include <ufo/numeric/vec.hpp>
51#include <ufo/vision/color.hpp>
52
53// STL
54#include <cstdio>
55#include <filesystem>
56#include <print>
57
58namespace ufo
59{
60[[nodiscard]] CloudProperties cloudPropertiesPTS(std::filesystem::path const& file);
61
62template <std::size_t Dim, class T, class... Ts>
63bool readPTS(std::filesystem::path const& file, PointCloud<Dim, T, Ts...>& pc)
64{
65 FileHandler fp(file.c_str(), "rb");
66
67 if (!fp) {
68 std::println(stderr, "[UFO | Read PTS] Failed to open file: {}", file.string());
69 return false;
70 }
71
72 char line[1024];
73 std::size_t size{};
74 if (nullptr != std::fgets(line, sizeof line, fp.get())) {
75 std::sscanf(line, "%zu", &size);
76 }
77
78 if (0 == size) {
79 std::println(stderr, "[UFO | Read PTS] Unable to read header");
80 return false;
81 }
82
83 pc.clear();
84 pc.resize(size);
85
86 std::size_t i{};
87 std::array<double, 7> fields;
88 do {
89 auto num_fields =
90 std::sscanf(line, "%lf %lf %lf %lf %lf %lf %lf", &fields[0], &fields[1],
91 &fields[2], &fields[3], &fields[4], &fields[5], &fields[6]);
92
93 if (3 != num_fields && 4 != num_fields && 6 != num_fields && 7 != num_fields) {
94 std::println(stderr, "[UFO | Read PTS] Unknown format of line: {}", line);
95 return false;
96 }
97
98 view<Vec<Dim, T>>(pc)[i] =
99 convert<Vec<Dim, T>>(Vec3d{fields[0], fields[1], fields[2]});
100
101 if constexpr ((is_intensity_v<Ts> || ...)) {
102 if (4 == num_fields || 7 == num_fields) {
103 view<Intensity>(pc)[i] = fields[3];
104 }
105 }
106
107 if constexpr ((is_color_v<Ts> || ...)) {
108 if (6 == num_fields || 7 == num_fields) {
109 view<first_color_t<Ts...>>(pc)[i] = convert<first_color_t<Ts...>>(
110 SmallRGB{static_cast<std::uint8_t>(fields[num_fields - 3]),
111 static_cast<std::uint8_t>(fields[num_fields - 2]),
112 static_cast<std::uint8_t>(fields[num_fields - 1])});
113 }
114 }
115
116 ++i;
117 } while (nullptr != std::fgets(line, sizeof line, fp.get()));
118
119 return true;
120}
121
122template <std::size_t Dim, class T, class... Ts>
123bool writePTS(std::filesystem::path const& file, PointCloud<Dim, T, Ts...> const& pc)
124{
125 FileHandler fp(file.c_str(), "wb");
126
127 if (!fp) {
128 std::println(stderr, "[UFO | Write PTS] Failed to create file: {}", file.string());
129 return false;
130 }
131
132 std::size_t size = pc.size();
133 std::println(fp.get(), "{}", size);
134
135 auto points = view<Vec<Dim, T>>(pc);
136 for (std::size_t i{}; size > i; ++i) {
137 auto p = convert<Vec<3, T>>(points[i]);
138 if constexpr (std::is_same_v<T, float>) {
139 std::print(fp.get(), "{:.6} {:.6} {:.6}", p.x, p.y, p.z);
140 } else if constexpr (std::is_floating_point_v<T>) {
141 std::print(fp.get(), "{:.10} {:.10} {:.10}", p.x, p.y, p.z);
142 } else {
143 std::print(fp.get(), "{} {} {}", p.x, p.y, p.z);
144 }
145 if constexpr ((is_intensity_v<Ts> || ...)) {
146 auto intensity = view<Intensity>(pc)[i];
147 std::print(fp.get(), "{:.6}", intensity.intensity);
148 }
149 if constexpr ((is_color_v<Ts> || ...)) {
150 auto c = convert<SmallRGB>(view<first_color_t<Ts...>>(pc)[i]);
151 std::println(fp.get(), " {} {} {}", static_cast<int>(c.red),
152 static_cast<int>(c.green), static_cast<int>(c.blue));
153 } else {
154 std::print(fp.get(), "\n");
155 }
156 }
157
158 return true;
159}
160} // namespace ufo
161
162#endif // UFO_CLOUD_IO_PTS_HPP
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr To convert(Vec< Dim, U > const &v) noexcept
Converts a vector to a different Vec type, truncating or zero-padding dimensions.
Definition vec.hpp:1059