2#include <ufo/io/file_handler.hpp>
3#include <ufo/io/ply.hpp>
18int pointCallback(p_ply_argument argument)
20 std::vector<Vec3f>* points;
22 ply_get_argument_user_data(argument,
reinterpret_cast<void**
>(&points), &index);
24 auto value =
static_cast<float>(ply_get_argument_value(argument));
26 points->emplace_back(value, 0.0f, 0.0f);
28 points->back()[index] = value;
35int colorCallback(p_ply_argument argument)
37 std::vector<Color>* colors;
39 ply_get_argument_user_data(argument,
reinterpret_cast<void**
>(&colors), &index);
41 auto value =
static_cast<std::uint8_t
>(ply_get_argument_value(argument));
43 colors->emplace_back(value, 0u, 0u);
44 }
else if (1 == index) {
45 colors->back().green = value;
46 }
else if (2 == index) {
47 colors->back().blue = value;
48 }
else if (3 == index) {
49 if constexpr (has_alpha_v<Color>) {
50 colors->back().alpha = value;
57int normalCallback(p_ply_argument argument)
59 std::vector<Normal>* normals;
61 ply_get_argument_user_data(argument,
reinterpret_cast<void**
>(&normals), &index);
63 auto value =
static_cast<float>(ply_get_argument_value(argument));
65 normals->emplace_back(value, 0.0f, 0.0f);
66 }
else if (1 == index) {
67 normals->back().y = value;
68 }
else if (2 == index) {
69 normals->back().z = value;
75int intensityCallback(p_ply_argument argument)
77 std::vector<Intensity>* intensities;
79 ply_get_argument_user_data(argument,
reinterpret_cast<void**
>(&intensities), &index);
81 auto value =
static_cast<float>(ply_get_argument_value(argument));
82 intensities->emplace_back(value);
87bool readPLY(std::filesystem::path
const& file, std::vector<Vec3f>& points,
88 std::vector<SmallRGB>* colors, std::vector<SmallRGBA>* colors_with_alpha,
89 std::vector<Normal>* normals, std::vector<Intensity>* intensities)
91 p_ply fp = ply_open(file.c_str(),
nullptr, 0,
nullptr);
94 std::println(stderr,
"[UFO | Read PLY] Failed to open file: {}", file.string());
98 if (!ply_read_header(fp)) {
99 std::println(stderr,
"[UFO | Read PLY] Failed to read header: {}", file.string());
106 long num_normals = 0;
107 long num_intensities = 0;
109 num_points = ply_set_read_cb(fp,
"vertex",
"x", pointCallback, &points, 0);
110 ply_set_read_cb(fp,
"vertex",
"y", pointCallback, &points, 1);
111 ply_set_read_cb(fp,
"vertex",
"z", pointCallback, &points, 2);
113 if (
nullptr != colors) {
114 num_colors = ply_set_read_cb(fp,
"vertex",
"red", colorCallback<SmallRGB>, colors, 0);
115 ply_set_read_cb(fp,
"vertex",
"green", colorCallback<SmallRGB>, colors, 1);
116 ply_set_read_cb(fp,
"vertex",
"blue", colorCallback<SmallRGB>, colors, 2);
117 }
else if (
nullptr != colors_with_alpha) {
118 num_colors = ply_set_read_cb(fp,
"vertex",
"red", colorCallback<SmallRGBA>,
119 colors_with_alpha, 0);
120 ply_set_read_cb(fp,
"vertex",
"green", colorCallback<SmallRGBA>, colors_with_alpha,
122 ply_set_read_cb(fp,
"vertex",
"blue", colorCallback<SmallRGBA>, colors_with_alpha, 2);
123 ply_set_read_cb(fp,
"vertex",
"alpha", colorCallback<SmallRGBA>, colors_with_alpha,
127 if (
nullptr != normals) {
128 num_normals = ply_set_read_cb(fp,
"vertex",
"nx", normalCallback, normals, 0);
129 ply_set_read_cb(fp,
"vertex",
"ny", normalCallback, normals, 1);
130 ply_set_read_cb(fp,
"vertex",
"nz", normalCallback, normals, 2);
133 if (
nullptr != intensities) {
135 ply_set_read_cb(fp,
"vertex",
"intensity", intensityCallback, intensities, 0);
138 if (0 >= num_points) {
139 std::println(stderr,
"[UFO | Read PLY] Number of vertices <= 0");
144 long total = std::max({num_points, num_colors, num_normals, num_intensities});
146 points.reserve(total);
147 if (
nullptr != colors) {
148 colors->reserve(total);
149 }
else if (
nullptr != colors_with_alpha) {
150 colors_with_alpha->reserve(total);
152 if (
nullptr != normals) {
153 normals->reserve(total);
155 if (
nullptr != intensities) {
156 intensities->reserve(total);
160 std::println(stderr,
"[UFO | Read PLY] Failed to read file: {}", file.string());
166 std::max({points.size(),
nullptr != colors ? colors->size() : 0,
167 nullptr != colors_with_alpha ? colors_with_alpha->size() : 0,
168 nullptr != normals ? normals->size() : 0,
169 nullptr != intensities ? intensities->size() : 0});
171 if (actual_size !=
static_cast<std::size_t
>(num_points)) {
173 if (
nullptr != colors) {
175 }
else if (
nullptr != colors_with_alpha) {
176 colors_with_alpha->clear();
178 if (
nullptr != normals) {
181 if (
nullptr != intensities) {
182 intensities->clear();
185 "[UFO | Read PLY] Mismatch in number of points: expected {}, got {}",
186 num_points, actual_size);
191 points.resize(total);
192 if (
nullptr != colors) {
193 colors->resize(total);
194 }
else if (
nullptr != colors_with_alpha) {
195 colors_with_alpha->resize(total);
197 if (
nullptr != normals) {
198 normals->resize(total);
200 if (
nullptr != intensities) {
201 intensities->resize(total);
209bool writePLY(std::filesystem::path
const& file, std::span<Vec3f const> points,
210 std::span<SmallRGB const> colors,
211 std::span<SmallRGBA const> colors_with_alpha,
212 std::span<Normal const> normals, std::span<Intensity const> intensities,
215 p_ply fp = ply_create(file.c_str(), ascii ? PLY_ASCII : PLY_LITTLE_ENDIAN, nullptr, 0,
219 std::println(stderr,
"[UFO | Write PLY] Failed to create file: {}", file.string());
223 ply_add_comment(fp,
"Created by UFO");
225 ply_add_element(fp,
"vertex",
static_cast<long>(points.size()));
226 ply_add_property(fp,
"x", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
227 ply_add_property(fp,
"y", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
228 ply_add_property(fp,
"z", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
230 if (!colors.empty()) {
231 ply_add_property(fp,
"red", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
232 ply_add_property(fp,
"green", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
233 ply_add_property(fp,
"blue", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
234 }
else if (!colors_with_alpha.empty()) {
235 ply_add_property(fp,
"red", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
236 ply_add_property(fp,
"green", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
237 ply_add_property(fp,
"blue", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
238 ply_add_property(fp,
"alpha", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
241 if (!normals.empty()) {
242 ply_add_property(fp,
"nx", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
243 ply_add_property(fp,
"ny", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
244 ply_add_property(fp,
"nz", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
247 if (!intensities.empty()) {
248 ply_add_property(fp,
"intensity", PLY_FLOAT32, PLY_FLOAT32, PLY_FLOAT32);
251 if (!ply_write_header(fp)) {
252 std::println(stderr,
"[UFO | Write PLY] Failed to write header");
257 for (std::size_t i{}; points.size() > i; ++i) {
258 ply_write(fp, points[i].x);
259 ply_write(fp, points[i].y);
260 ply_write(fp, points[i].z);
262 if (!colors.empty()) {
263 ply_write(fp,
static_cast<unsigned char>(colors[i].
red));
264 ply_write(fp,
static_cast<unsigned char>(colors[i].
green));
265 ply_write(fp,
static_cast<unsigned char>(colors[i].
blue));
266 }
else if (!colors_with_alpha.empty()) {
267 ply_write(fp,
static_cast<unsigned char>(colors_with_alpha[i].
red));
268 ply_write(fp,
static_cast<unsigned char>(colors_with_alpha[i].
green));
269 ply_write(fp,
static_cast<unsigned char>(colors_with_alpha[i].
blue));
270 ply_write(fp,
static_cast<unsigned char>(colors_with_alpha[i].
alpha));
273 if (!normals.empty()) {
274 ply_write(fp,
static_cast<float>(normals[i].x));
275 ply_write(fp,
static_cast<float>(normals[i].y));
276 ply_write(fp,
static_cast<float>(normals[i].z));
279 if (!intensities.empty()) {
280 ply_write(fp,
static_cast<float>(intensities[i].intensity));
290CloudProperties cloudPropertiesPLY(std::filesystem::path
const& file)
292 p_ply fp = ply_open(file.c_str(),
nullptr, 0,
nullptr);
295 throw std::runtime_error(std::format(
296 "[UFO | Cloud Properties PLY] Failed to open file: {}", file.string()));
299 if (!ply_read_header(fp)) {
301 throw std::runtime_error(
302 std::format(
"[UFO | Cloud Properties PLY] Failed to read header"));
305 CloudProperties prop;
307 prop.color = 0 < ply_set_read_cb(fp,
"vertex",
"red",
nullptr,
nullptr, 0);
308 prop.alpha = 0 < ply_set_read_cb(fp,
"vertex",
"alpha",
nullptr,
nullptr, 0);
309 prop.normal = 0 < ply_set_read_cb(fp,
"vertex",
"nx",
nullptr,
nullptr, 0);
310 prop.intensity = 0 < ply_set_read_cb(fp,
"vertex",
"intensity",
nullptr,
nullptr, 0);
All vision-related classes and functions.
constexpr T green(Lrgb< T, Flags > color) noexcept
Returns the un-weighted green channel value.
constexpr T blue(Lrgb< T, Flags > color) noexcept
Returns the un-weighted blue channel value.
constexpr alpha_type_t< C > alpha(C color) noexcept
Returns the un-weighted alpha of color.
constexpr T red(Lrgb< T, Flags > color) noexcept
Returns the un-weighted red channel value.