UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
ply.hpp
1
42#ifndef UFO_CLOUD_IO_PLY_HPP
43#define UFO_CLOUD_IO_PLY_HPP
44
45// UFO
46#include <ufo/cloud/point_cloud.hpp>
47#include <ufo/core/intensity.hpp>
48#include <ufo/core/normal.hpp>
49#include <ufo/io/cloud_properties.hpp>
50#include <ufo/io/file_handler.hpp>
51#include <ufo/numeric/vec.hpp>
52#include <ufo/vision/color.hpp>
53
54// STL
55#include <cstdio>
56#include <filesystem>
57#include <span>
58#include <vector>
59
60namespace ufo
61{
62namespace detail
63{
64bool readPLY(std::filesystem::path const& file, std::vector<Vec3f>& points,
65 std::vector<SmallRGB>* colors, std::vector<SmallRGBA>* colors_with_alpha,
66 std::vector<Normal>* normals, std::vector<Intensity>* intensities);
67
68bool writePLY(std::filesystem::path const& file, std::span<Vec3f const> points,
69 std::span<SmallRGB const> colors,
70 std::span<SmallRGBA const> colors_with_alpha,
71 std::span<Normal const> normals, std::span<Intensity const> intensities,
72 bool ascii);
73} // namespace detail
74
75[[nodiscard]] CloudProperties cloudPropertiesPLY(std::filesystem::path const& file);
76
77template <std::size_t Dim, class T, class... Ts>
78bool readPLY(std::filesystem::path const& file, PointCloud<Dim, T, Ts...>& pc)
79{
80 std::vector<Vec3f> points;
81 std::vector<SmallRGB> colors;
82 std::vector<SmallRGBA> colors_with_alpha;
83 std::vector<Normal> normals;
84 std::vector<Intensity> intensities;
85
86 std::vector<SmallRGB>* p_colors = nullptr;
87 std::vector<SmallRGBA>* p_colors_with_alpha = nullptr;
88 std::vector<Normal>* p_normals = nullptr;
89 std::vector<Intensity>* p_intensities = nullptr;
90
91 if constexpr ((is_color_v<Ts> || ...)) {
92 if constexpr (has_alpha_v<first_color_t<Ts...>>) {
93 p_colors_with_alpha = &colors_with_alpha;
94 } else {
95 p_colors = &colors;
96 }
97 }
98 if constexpr ((is_normal_v<Ts> || ...)) {
99 p_normals = &normals;
100 }
101 if constexpr ((is_intensity_v<Ts> || ...)) {
102 p_intensities = &intensities;
103 }
104
105 if (!detail::readPLY(file, points, p_colors, p_colors_with_alpha, p_normals,
106 p_intensities)) {
107 return false;
108 }
109
110 pc.clear();
111 pc.resize(points.size());
112
113 for (std::size_t i{}; points.size() > i; ++i) {
114 view<Vec<Dim, T>>(pc)[i] = convert<Vec<Dim, T>>(points[i]);
115 if constexpr ((is_color_v<Ts> || ...)) {
116 if constexpr (has_alpha_v<first_color_t<Ts...>>) {
117 view<first_color_t<Ts...>>(pc)[i] =
118 convert<first_color_t<Ts...>>(colors_with_alpha[i]);
119 } else {
120 view<first_color_t<Ts...>>(pc)[i] = convert<first_color_t<Ts...>>(colors[i]);
121 }
122 }
123 if constexpr ((is_normal_v<Ts> || ...)) {
124 view<Normal>(pc)[i] = normals[i];
125 }
126 if constexpr ((is_intensity_v<Ts> || ...)) {
127 view<Intensity>(pc)[i] = intensities[i];
128 }
129 }
130
131 return true;
132}
133
134template <std::size_t Dim, class T, class... Ts>
135bool writePLY(std::filesystem::path const& file, PointCloud<Dim, T, Ts...> const& pc,
136 bool ascii = false)
137{
138 std::vector<Vec3f> points;
139 std::vector<SmallRGB> colors;
140 std::vector<SmallRGBA> colors_with_alpha;
141
142 for (std::size_t i{}; pc.size() > i; ++i) {
143 if constexpr (!std::is_same_v<Vec3f, Vec<Dim, T>>) {
144 points.push_back(convert<Vec3f>(view<Vec<Dim, T>>(pc)[i]));
145 }
146
147 if constexpr ((is_color_v<Ts> || ...)) {
148 if constexpr (has_alpha_v<first_color_t<Ts...>>) {
149 if constexpr (!std::is_same_v<SmallRGBA, first_color_t<Ts...>>) {
150 colors_with_alpha.push_back(
151 convert<SmallRGBA>(view<first_color_t<Ts...>>(pc)[i]));
152 }
153 } else {
154 if constexpr (!std::is_same_v<SmallRGB, first_color_t<Ts...>>) {
155 colors.push_back(convert<SmallRGB>(view<first_color_t<Ts...>>(pc)[i]));
156 }
157 }
158 }
159 }
160
161 std::span<Vec3f const> points_span;
162 std::span<SmallRGB const> colors_span;
163 std::span<SmallRGBA const> colors_with_alpha_span;
164 std::span<Normal const> normals_span;
165 std::span<Intensity const> intensities_span;
166
167 if constexpr (std::is_same_v<Vec3f, Vec<Dim, T>>) {
168 points_span = view<Vec3f>(pc);
169 } else {
170 points_span = std::span<Vec3f>(points);
171 }
172
173 if constexpr ((is_color_v<Ts> || ...)) {
174 if constexpr (std::is_same_v<SmallRGBA, first_color_t<Ts...>>) {
175 colors_with_alpha_span = view<SmallRGBA>(pc);
176 colors_span = std::span<SmallRGB>(colors);
177 } else if constexpr (std::is_same_v<SmallRGB, first_color_t<Ts...>>) {
178 colors_span = view<SmallRGB>(pc);
179 colors_with_alpha_span = std::span<SmallRGBA>(colors_with_alpha);
180 } else {
181 colors_span = std::span<SmallRGB>(colors);
182 colors_with_alpha_span = std::span<SmallRGBA>(colors_with_alpha);
183 }
184 }
185
186 if constexpr ((is_normal_v<Ts> || ...)) {
187 normals_span = view<Normal>(pc);
188 }
189
190 if constexpr ((is_intensity_v<Ts> || ...)) {
191 intensities_span = view<Intensity>(pc);
192 }
193
194 return detail::writePLY(file, points_span, colors_span, colors_with_alpha_span,
195 normals_span, intensities_span, ascii);
196}
197} // namespace ufo
198
199#endif // UFO_CLOUD_IO_PLY_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