13 #include <liblzf/lzf.h>
21 #include "io/PointCloudIO.h"
42 namespace ply_pointcloud_reader {
44 struct PLYReaderState {
56 int ReadVertexCallback(p_ply_argument argument) {
57 PLYReaderState *state_ptr;
59 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
61 if (state_ptr->vertex_index >= state_ptr->vertex_num) {
65 double value = ply_get_argument_value(argument);
66 CCVector3 &P = *state_ptr->pointcloud_ptr->getPointPtr(
67 static_cast<size_t>(state_ptr->vertex_index));
70 state_ptr->vertex_index++;
71 ++(*state_ptr->progress_bar);
76 int ReadNormalCallback(p_ply_argument argument) {
77 PLYReaderState *state_ptr;
79 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
81 if (state_ptr->normal_index >= state_ptr->normal_num) {
85 double value = ply_get_argument_value(argument);
86 state_ptr->normal[index] = value;
89 state_ptr->pointcloud_ptr->addEigenNorm(
90 Eigen::Vector3d(state_ptr->normal[0], state_ptr->normal[1],
91 state_ptr->normal[2]));
92 state_ptr->normal_index++;
97 int ReadColorCallback(p_ply_argument argument) {
98 PLYReaderState *state_ptr;
100 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
102 if (state_ptr->color_index >= state_ptr->color_num) {
106 double value = ply_get_argument_value(argument);
107 ecvColor::Rgb &C = state_ptr->pointcloud_ptr->getPointColorPtr(
108 static_cast<size_t>(state_ptr->color_index));
112 state_ptr->color_index++;
124 PCD_DATA_BINARY_COMPRESSED = 2
127 struct PCLPointField {
157 bool CheckHeader(PCDHeader &header) {
158 if (header.points <= 0 || header.pointsize <= 0) {
162 if (header.fields.size() == 0 || header.pointsize <= 0) {
166 header.has_points =
false;
167 header.has_normals =
false;
168 header.has_colors =
false;
169 header.has_ring =
false;
170 header.has_intensity =
false;
174 bool has_normal_x =
false;
175 bool has_normal_y =
false;
176 bool has_normal_z =
false;
177 bool has_rgb =
false;
178 bool has_rgba =
false;
181 for (
const auto &field : header.fields) {
182 if (field.name ==
"x") {
184 }
else if (field.name ==
"y") {
186 }
else if (field.name ==
"z") {
188 }
else if (field.name ==
"normal_x") {
190 }
else if (field.name ==
"normal_y") {
192 }
else if (field.name ==
"normal_z") {
194 }
else if (field.name ==
"rgb") {
196 }
else if (field.name ==
"rgba") {
198 }
else if (field.name ==
"intensity") {
200 }
else if (field.name ==
"ring") {
204 header.has_points = (has_x && has_y && has_z);
205 header.has_normals = (has_normal_x && has_normal_y && has_normal_z);
206 header.has_colors = (has_rgb || has_rgba);
209 if (header.has_points ==
false) {
211 "[CheckHeader] Fields for point data are not complete.");
219 size_t specified_channel_count = 0;
222 std::string line(line_buffer);
226 std::vector<std::string> st;
228 std::stringstream sstream(line);
229 sstream.imbue(std::locale::classic());
230 std::string line_type;
231 sstream >> line_type;
232 if (line_type.substr(0, 1) ==
"#") {
233 }
else if (line_type.substr(0, 7) ==
"VERSION") {
234 if (st.size() >= 2) {
235 header.version = st[1];
237 }
else if (line_type.substr(0, 6) ==
"FIELDS" ||
238 line_type.substr(0, 7) ==
"COLUMNS") {
239 specified_channel_count = st.size() - 1;
240 if (specified_channel_count == 0) {
244 header.fields.resize(specified_channel_count);
246 for (
size_t i = 0; i < specified_channel_count;
248 header.fields[i].name = st[i + 1];
249 header.fields[i].size = 4;
250 header.fields[i].type =
'F';
251 header.fields[i].count = 1;
253 header.fields[i].offset =
offset;
256 header.pointsize =
offset;
257 }
else if (line_type.substr(0, 4) ==
"SIZE") {
258 if (specified_channel_count != st.size() - 1) {
262 int offset = 0, col_type = 0;
263 for (
size_t i = 0; i < specified_channel_count;
264 i++,
offset += col_type) {
266 header.fields[i].size = col_type;
267 header.fields[i].offset =
offset;
269 header.pointsize =
offset;
270 }
else if (line_type.substr(0, 4) ==
"TYPE") {
271 if (specified_channel_count != st.size() - 1) {
275 for (
size_t i = 0; i < specified_channel_count; i++) {
276 header.fields[i].type = st[i + 1].c_str()[0];
278 }
else if (line_type.substr(0, 5) ==
"COUNT") {
279 if (specified_channel_count != st.size() - 1) {
284 for (
size_t i = 0; i < specified_channel_count; i++) {
285 sstream >> col_count;
286 header.fields[i].count = col_count;
288 header.fields[i].offset =
offset;
290 offset += col_count * header.fields[i].size;
293 header.pointsize =
offset;
294 }
else if (line_type.substr(0, 5) ==
"WIDTH") {
295 sstream >> header.width;
296 }
else if (line_type.substr(0, 6) ==
"HEIGHT") {
297 sstream >> header.height;
298 header.points = header.width * header.height;
299 }
else if (line_type.substr(0, 9) ==
"VIEWPOINT") {
300 if (st.size() >= 2) {
301 header.viewpoint = st[1];
303 }
else if (line_type.substr(0, 6) ==
"POINTS") {
304 sstream >> header.points;
305 }
else if (line_type.substr(0, 4) ==
"DATA") {
306 header.datatype = PCD_DATA_ASCII;
307 if (st.size() >= 2) {
308 if (st[1].substr(0, 17) ==
"binary_compressed") {
309 header.datatype = PCD_DATA_BINARY_COMPRESSED;
310 }
else if (st[1].substr(0, 6) ==
"binary") {
311 header.datatype = PCD_DATA_BINARY;
317 if (CheckHeader(header) ==
false) {
326 const char type_uppercase = std::toupper(
type, std::locale());
327 if (type_uppercase ==
'I') {
330 memcpy(&data, data_ptr,
sizeof(data));
332 }
else if (
size == 2) {
334 memcpy(&data, data_ptr,
sizeof(data));
336 }
else if (
size == 4) {
338 memcpy(&data, data_ptr,
sizeof(data));
343 }
else if (type_uppercase ==
'U') {
346 memcpy(&data, data_ptr,
sizeof(data));
348 }
else if (
size == 2) {
350 memcpy(&data, data_ptr,
sizeof(data));
352 }
else if (
size == 4) {
354 memcpy(&data, data_ptr,
sizeof(data));
359 }
else if (type_uppercase ==
'F') {
362 memcpy(&data, data_ptr,
sizeof(data));
375 std::uint8_t data[4];
376 memcpy(data, data_ptr, 4);
384 ScalarType UnpackBinaryPCDScalar(
const char *data_ptr,
389 memcpy(&data, data_ptr, 1);
390 ScalarType scalar =
static_cast<ScalarType
>(data);
393 return static_cast<ScalarType
>(0);
401 const char type_uppercase = std::toupper(
type, std::locale());
402 if (type_uppercase ==
'I') {
404 }
else if (type_uppercase ==
'U') {
406 std::strtoul(data_ptr, &end, 0));
407 }
else if (type_uppercase ==
'F') {
417 std::uint8_t data[4] = {0, 0, 0, 0};
419 const char type_uppercase = std::toupper(
type, std::locale());
420 if (type_uppercase ==
'I') {
421 std::int32_t value = std::strtol(data_ptr, &end, 0);
422 memcpy(data, &value, 4);
423 }
else if (type_uppercase ==
'U') {
424 std::uint32_t value = std::strtoul(data_ptr, &end, 0);
425 memcpy(data, &value, 4);
426 }
else if (type_uppercase ==
'F') {
427 float value = std::strtof(data_ptr, &end);
428 memcpy(data, &value, 4);
436 ScalarType UnpackASCIIPCDScalar(
const char *data_ptr,
440 std::uint8_t data = 0;
443 std::int32_t value = std::strtol(data_ptr, &end, 0);
444 memcpy(&data, &value, 1);
445 }
else if (
type ==
'U') {
446 std::uint32_t value = std::strtoul(data_ptr, &end, 0);
447 memcpy(&data, &value, 1);
448 }
else if (
type ==
'F') {
449 float value = std::strtof(data_ptr, &end);
450 memcpy(&data, &value, 1);
452 ScalarType scalar =
static_cast<ScalarType
>(data);
455 return static_cast<ScalarType
>(0);
460 const PCDHeader &header,
465 if (header.has_points) {
466 pointcloud.
resize(
static_cast<unsigned int>(header.points));
469 "[ReadPCDData] Fields for point data are not complete.");
472 if (header.has_normals) {
475 if (header.has_colors) {
480 size_t pointCount =
static_cast<size_t>(header.points);
484 if (header.has_intensity) {
492 static_cast<unsigned>(pointCount))) {
498 if (header.has_ring) {
504 if (!cc_ring_field->
reserveSafe(
static_cast<unsigned>(pointCount))) {
511 reporter.SetTotal(header.points);
517 ScalarType intensity;
519 if (header.datatype == PCD_DATA_ASCII) {
521 unsigned int idx = 0;
523 idx < (
unsigned int)header.points) {
524 std::string line(line_buffer);
525 std::vector<std::string> strs;
527 if ((
int)strs.size() < header.elementnum) {
531 bool find_point =
false;
532 bool find_normal =
false;
533 bool find_color =
false;
534 bool find_ring =
false;
535 bool find_intensity =
false;
536 for (
size_t i = 0; i < header.fields.size(); i++) {
537 const auto &field = header.fields[i];
538 if (field.name ==
"x") {
541 strs[field.count_offset].c_str(), field.type,
543 }
else if (field.name ==
"y") {
546 strs[field.count_offset].c_str(), field.type,
548 }
else if (field.name ==
"z") {
551 strs[field.count_offset].c_str(), field.type,
553 }
else if (field.name ==
"normal_x") {
556 strs[field.count_offset].c_str(), field.type,
558 }
else if (field.name ==
"normal_y") {
561 strs[field.count_offset].c_str(), field.type,
563 }
else if (field.name ==
"normal_z") {
566 strs[field.count_offset].c_str(), field.type,
568 }
else if (field.name ==
"rgb" || field.name ==
"rgba") {
570 col = UnpackASCIIPCDColor(strs[field.count_offset].c_str(),
571 field.type, field.size);
572 }
else if (field.name ==
"intensity") {
573 find_intensity =
true;
574 intensity = UnpackASCIIPCDScalar(
575 strs[field.count_offset].c_str(), field.type,
577 }
else if (field.name ==
"ring") {
579 ring = UnpackASCIIPCDScalar(
580 strs[field.count_offset].c_str(), field.type,
588 if (header.has_normals && find_normal) {
591 if (header.has_colors && find_color) {
594 if (header.has_intensity && find_intensity) {
597 if (header.has_ring && find_ring) {
602 if (idx % 1000 == 0) {
603 reporter.Update(idx);
606 }
else if (header.datatype == PCD_DATA_BINARY) {
607 std::unique_ptr<char[]> buffer(
new char[header.pointsize]);
608 for (
unsigned int i = 0; i < (
unsigned int)header.points; i++) {
609 if (fread(buffer.get(), header.pointsize, 1, file) != 1) {
611 "[ReadPCDData] Failed to read data record.");
616 bool find_point =
false;
617 bool find_normal =
false;
618 bool find_color =
false;
619 bool find_ring =
false;
620 bool find_intensity =
false;
621 for (
const auto &field : header.fields) {
622 if (field.name ==
"x") {
624 P.
x = UnpackBinaryPCDElement(buffer.get() + field.offset,
625 field.type, field.size);
626 }
else if (field.name ==
"y") {
628 P.
y = UnpackBinaryPCDElement(buffer.get() + field.offset,
629 field.type, field.size);
630 }
else if (field.name ==
"z") {
632 P.
z = UnpackBinaryPCDElement(buffer.get() + field.offset,
633 field.type, field.size);
634 }
else if (field.name ==
"normal_x") {
636 N.x = UnpackBinaryPCDElement(buffer.get() + field.offset,
637 field.type, field.size);
638 }
else if (field.name ==
"normal_y") {
640 N.y = UnpackBinaryPCDElement(buffer.get() + field.offset,
641 field.type, field.size);
642 }
else if (field.name ==
"normal_z") {
644 N.z = UnpackBinaryPCDElement(buffer.get() + field.offset,
645 field.type, field.size);
646 }
else if (field.name ==
"rgb" || field.name ==
"rgba") {
648 col = UnpackBinaryPCDColor(buffer.get() + field.offset,
649 field.type, field.size);
650 }
else if (field.name ==
"intensity") {
651 find_intensity =
true;
653 UnpackBinaryPCDScalar(buffer.get() + field.offset,
654 field.type, field.size);
655 }
else if (field.name ==
"ring") {
657 ring = UnpackBinaryPCDScalar(buffer.get() + field.offset,
658 field.type, field.size);
665 if (header.has_normals && find_normal) {
668 if (header.has_colors && find_color) {
671 if (header.has_intensity && find_intensity) {
674 if (header.has_ring && find_ring) {
682 }
else if (header.datatype == PCD_DATA_BINARY_COMPRESSED) {
683 double reporter_total = 100.0;
684 reporter.SetTotal(
int(reporter_total));
685 reporter.Update(
int(reporter_total * 0.01));
687 std::uint32_t compressed_size;
688 std::uint32_t uncompressed_size;
689 if (fread(&compressed_size,
sizeof(compressed_size), 1, file) != 1) {
694 if (fread(&uncompressed_size,
sizeof(uncompressed_size), 1, file) !=
701 "PCD data with {:d} compressed size, and {:d} uncompressed "
703 compressed_size, uncompressed_size);
704 std::unique_ptr<char[]> buffer_compressed(
new char[compressed_size]);
705 reporter.Update(
int(reporter_total * .1));
706 if (fread(buffer_compressed.get(), 1, compressed_size, file) !=
712 std::unique_ptr<char[]> buffer(
new char[uncompressed_size]);
713 reporter.Update(
int(reporter_total * .2));
714 if (lzf_decompress(buffer_compressed.get(),
715 (
unsigned int)compressed_size, buffer.get(),
716 (
unsigned int)uncompressed_size) !=
723 std::vector<CCVector3>
normals;
724 if (header.has_normals) {
725 normals.resize(
static_cast<unsigned int>(header.points));
728 for (
const auto &field : header.fields) {
729 const char *base_ptr = buffer.get() + field.offset * header.points;
731 double(base_ptr - buffer.get()) / uncompressed_size;
732 reporter.Update(
int(reporter_total * (progress + .2)));
734 if (field.name ==
"x") {
735 for (
size_t i = 0; i < (size_t)header.points; i++) {
737 base_ptr + i * field.size * field.count, field.type,
740 }
else if (field.name ==
"y") {
741 for (
size_t i = 0; i < (size_t)header.points; i++) {
743 base_ptr + i * field.size * field.count, field.type,
746 }
else if (field.name ==
"z") {
747 for (
size_t i = 0; i < (size_t)header.points; i++) {
749 base_ptr + i * field.size * field.count, field.type,
752 }
else if (field.name ==
"normal_x") {
753 for (
size_t i = 0; i < (size_t)header.points; i++) {
754 normals[i].x = UnpackBinaryPCDElement(
755 base_ptr + i * field.size * field.count, field.type,
758 }
else if (field.name ==
"normal_y") {
759 for (
size_t i = 0; i < (size_t)header.points; i++) {
760 normals[i].y = UnpackBinaryPCDElement(
761 base_ptr + i * field.size * field.count, field.type,
764 }
else if (field.name ==
"normal_z") {
765 for (
size_t i = 0; i < (size_t)header.points; i++) {
766 normals[i].z = UnpackBinaryPCDElement(
767 base_ptr + i * field.size * field.count, field.type,
770 }
else if (field.name ==
"rgb" || field.name ==
"rgba") {
771 for (
unsigned int i = 0; i < (
unsigned int)header.points; i++) {
773 base_ptr + i * field.size * field.count, field.type,
777 }
else if (field.name ==
"intensity") {
778 for (
unsigned int i = 0; i < (
unsigned int)header.points; i++) {
779 ScalarType intensity = UnpackBinaryPCDScalar(
780 base_ptr + i * field.size * field.count, field.type,
784 }
else if (field.name ==
"ring") {
785 for (
unsigned int i = 0; i < (
unsigned int)header.points; i++) {
786 ScalarType ring = UnpackBinaryPCDScalar(
787 base_ptr + i * field.size * field.count, field.type,
794 if (header.has_normals) {
799 if (header.has_intensity && cc_intensity_field) {
806 if (header.has_ring && cc_ring_field) {
825 header.version =
"0.7";
826 header.width = (int)pointcloud.
size();
828 header.points = header.width;
829 header.fields.clear();
835 header.fields.push_back(field);
837 header.fields.push_back(field);
839 header.fields.push_back(field);
840 header.elementnum = 3;
841 header.pointsize = 12;
843 field.name =
"normal_x";
844 header.fields.push_back(field);
845 field.name =
"normal_y";
846 header.fields.push_back(field);
847 field.name =
"normal_z";
848 header.fields.push_back(field);
849 header.elementnum += 3;
850 header.pointsize += 12;
854 header.fields.push_back(field);
856 header.pointsize += 4;
859 header.datatype = PCD_DATA_ASCII;
862 header.datatype = PCD_DATA_BINARY_COMPRESSED;
864 header.datatype = PCD_DATA_BINARY;
871 fprintf(file,
"# .PCD v%s - Point Cloud Data file format\n",
872 header.version.c_str());
873 fprintf(file,
"VERSION %s\n", header.version.c_str());
874 fprintf(file,
"FIELDS");
875 for (
const auto &field : header.fields) {
876 fprintf(file,
" %s", field.name.c_str());
879 fprintf(file,
"SIZE");
880 for (
const auto &field : header.fields) {
881 fprintf(file,
" %d", field.size);
884 fprintf(file,
"TYPE");
885 for (
const auto &field : header.fields) {
886 fprintf(file,
" %c", field.type);
889 fprintf(file,
"COUNT");
890 for (
const auto &field : header.fields) {
891 fprintf(file,
" %d", field.count);
894 fprintf(file,
"WIDTH %d\n", header.width);
895 fprintf(file,
"HEIGHT %d\n", header.height);
896 fprintf(file,
"VIEWPOINT 0 0 0 1 0 0 0\n");
897 fprintf(file,
"POINTS %d\n", header.points);
899 switch (header.datatype) {
900 case PCD_DATA_BINARY:
901 fprintf(file,
"DATA binary\n");
903 case PCD_DATA_BINARY_COMPRESSED:
904 fprintf(file,
"DATA binary_compressed\n");
908 fprintf(file,
"DATA ascii\n");
915 std::uint8_t rgba[4] = {0, 0, 0, 0};
920 memcpy(&value, rgba, 4);
925 const PCDHeader &header,
932 reporter.SetTotal(pointcloud.
size());
934 if (header.datatype == PCD_DATA_ASCII) {
935 for (
unsigned int i = 0; i < pointcloud.
size(); i++) {
945 fprintf(file,
" %.10g", ConvertRGBToFloat(
color));
952 }
else if (header.datatype == PCD_DATA_BINARY) {
953 std::unique_ptr<float[]> data(
new float[header.elementnum]);
954 for (
unsigned int i = 0; i < pointcloud.
size(); i++) {
956 data[0] = (float)
point[0];
957 data[1] = (float)
point[1];
958 data[2] = (float)
point[2];
962 data[idx + 0] = (float)
normal[0];
963 data[idx + 1] = (float)
normal[1];
964 data[idx + 2] = (float)
normal[2];
969 data[idx] = ConvertRGBToFloat(
color);
971 fwrite(data.get(),
sizeof(
float), header.elementnum, file);
976 }
else if (header.datatype == PCD_DATA_BINARY_COMPRESSED) {
977 double report_total = double(pointcloud.
size() * 2);
981 reporter.SetTotal(
int(report_total));
983 int strip_size = header.points;
984 std::uint32_t buffer_size =
985 (std::uint32_t)(header.elementnum * header.points);
986 std::unique_ptr<float[]> buffer(
new float[buffer_size]);
987 std::unique_ptr<float[]> buffer_compressed(
new float[buffer_size * 2]);
988 for (
unsigned int i = 0; i < pointcloud.
size(); i++) {
990 buffer[0 * strip_size + i] = (float)
point(0);
991 buffer[1 * strip_size + i] = (float)
point(1);
992 buffer[2 * strip_size + i] = (float)
point(2);
996 buffer[(idx + 0) * strip_size + i] = (
float)
normal(0);
997 buffer[(idx + 1) * strip_size + i] = (
float)
normal(1);
998 buffer[(idx + 2) * strip_size + i] = (
float)
normal(2);
1003 buffer[idx * strip_size + i] = ConvertRGBToFloat(
color);
1005 if (i % 1000 == 0) {
1009 std::uint32_t buffer_size_in_bytes = buffer_size *
sizeof(float);
1010 std::uint32_t size_compressed =
1011 lzf_compress(buffer.get(), buffer_size_in_bytes,
1012 buffer_compressed.get(), buffer_size_in_bytes * 2);
1013 if (size_compressed == 0) {
1018 "[WritePCDData] {:d} bytes data compressed into {:d} bytes.",
1019 buffer_size_in_bytes, size_compressed);
1020 reporter.Update(
int(report_total * 0.75));
1021 fwrite(&size_compressed,
sizeof(size_compressed), 1, file);
1022 fwrite(&buffer_size_in_bytes,
sizeof(buffer_size_in_bytes), 1, file);
1023 fwrite(buffer_compressed.get(), 1, size_compressed, file);
1057 "PCD header indicates {:d} fields, {:d} bytes per point, and {:d} "
1059 (
int)header.fields.size(), header.pointsize, header.points);
1060 for (
const auto &field : header.fields) {
1062 field.type, field.size, field.count, field.offset);
1066 header.has_points ?
"yes" :
"no",
1067 header.has_normals ?
"yes" :
"no",
1068 header.has_colors ?
"yes" :
"no");
1083 bool(
params.compressed), header)) {
1129 const char *line_buffer;
1130 while ((line_buffer = file.
ReadLine())) {
1131 if (sscanf(line_buffer,
"%lf %lf %lf", &x, &y, &z) == 3) {
1134 if (++i % 1000 == 0) {
1141 }
catch (
const std::exception &e) {
1155 std::string content(
reinterpret_cast<const char *
>(buffer),
length);
1156 std::istringstream ibs(content);
1161 while (std::getline(ibs, line)) {
1162 if (sscanf(line.c_str(),
"%lf %lf %lf", &x, &y, &z) == 3) {
1165 if (++i % 1000 == 0) {
1166 reporter.
Update(ibs.tellg());
1172 }
catch (
const std::exception &e) {
1191 for (
size_t i = 0; i < pointcloud.
size(); i++) {
1193 if (fprintf(file.
GetFILE(),
"%.10f %.10f %.10f\n",
point(0),
1196 "Write XYZ failed: unable to write file: {}",
filename);
1199 if (i % 1000 == 0) {
1205 }
catch (
const std::exception &e) {
1219 std::string content;
1220 for (
size_t i = 0; i < pointcloud.
size(); i++) {
1224 content.append(line);
1225 if (i % 1000 == 0) {
1230 if (content.length() == 0) {
1234 length = content.length();
1235 buffer =
new unsigned char[
length];
1236 std::memcpy(buffer, content.c_str(),
length);
1240 }
catch (
const std::exception &e) {
1268 double x, y, z, nx, ny, nz;
1269 const char *line_buffer;
1270 while ((line_buffer = file.
ReadLine())) {
1271 if (sscanf(line_buffer,
"%lf %lf %lf %lf %lf %lf", &x, &y, &z, &nx,
1276 if (++i % 1000 == 0) {
1283 }
catch (
const std::exception &e) {
1306 for (
size_t i = 0; i < pointcloud.
size(); i++) {
1309 if (fprintf(file.
GetFILE(),
"%.10f %.10f %.10f %.10f %.10f %.10f\n",
1313 "Write XYZN failed: unable to write file: {}",
1317 if (i % 1000 == 0) {
1323 }
catch (
const std::exception &e) {
1352 double x, y, z, r, g, b;
1353 const char *line_buffer;
1354 while ((line_buffer = file.
ReadLine())) {
1355 if (sscanf(line_buffer,
"%lf %lf %lf %lf %lf %lf", &x, &y, &z, &r,
1360 if (++i % 1000 == 0) {
1367 }
catch (
const std::exception &e) {
1390 for (
size_t i = 0; i < pointcloud.
size(); i++) {
1393 if (fprintf(file.
GetFILE(),
"%.10f %.10f %.10f %.10f %.10f %.10f\n",
1397 "Write XYZRGB failed: unable to write file: {}",
1401 if (i % 1000 == 0) {
1407 }
catch (
const std::exception &e) {
1417 p_ply ply_file = ply_open(
path.c_str(),
NULL, 0,
NULL);
1421 if (!ply_read_header(ply_file)) {
1422 ply_close(ply_file);
1427 ply_set_read_cb(ply_file,
"vertex",
"x",
nullptr,
nullptr, 0);
1429 ply_set_read_cb(ply_file,
"edge",
"vertex1",
nullptr,
nullptr, 0);
1430 auto nFaces = ply_set_read_cb(ply_file,
"face",
"vertex_indices",
nullptr,
1433 nFaces = ply_set_read_cb(ply_file,
"face",
"vertex_index",
nullptr,
1436 ply_close(ply_file);
1441 }
else if (nLines > 0) {
1443 }
else if (nVertices > 0) {
1452 using namespace ply_pointcloud_reader;
1460 if (!ply_read_header(ply_file)) {
1462 ply_close(ply_file);
1466 PLYReaderState state;
1467 state.pointcloud_ptr = &pointcloud;
1468 state.vertex_num = ply_set_read_cb(ply_file,
"vertex",
"x",
1469 ReadVertexCallback, &state, 0);
1470 ply_set_read_cb(ply_file,
"vertex",
"y", ReadVertexCallback, &state, 1);
1471 ply_set_read_cb(ply_file,
"vertex",
"z", ReadVertexCallback, &state, 2);
1473 state.normal_num = ply_set_read_cb(ply_file,
"vertex",
"nx",
1474 ReadNormalCallback, &state, 0);
1475 ply_set_read_cb(ply_file,
"vertex",
"ny", ReadNormalCallback, &state, 1);
1476 ply_set_read_cb(ply_file,
"vertex",
"nz", ReadNormalCallback, &state, 2);
1478 state.color_num = ply_set_read_cb(ply_file,
"vertex",
"red",
1479 ReadColorCallback, &state, 0);
1480 ply_set_read_cb(ply_file,
"vertex",
"green", ReadColorCallback, &state, 1);
1481 ply_set_read_cb(ply_file,
"vertex",
"blue", ReadColorCallback, &state, 2);
1483 if (state.vertex_num <= 0) {
1485 ply_close(ply_file);
1489 state.vertex_index = 0;
1490 state.normal_index = 0;
1491 state.color_index = 0;
1494 pointcloud.
resize(state.vertex_num);
1496 if (state.color_num > 1) {
1500 if (state.normal_num > 1) {
1505 reporter.
SetTotal(state.vertex_num);
1506 state.progress_bar = &reporter;
1508 if (!ply_read(ply_file)) {
1511 ply_close(ply_file);
1515 ply_close(ply_file);
1537 ply_add_comment(ply_file,
"Created by CloudViewer");
1538 ply_add_element(ply_file,
"vertex",
static_cast<long>(pointcloud.
size()));
1552 if (!ply_write_header(ply_file)) {
1554 ply_close(ply_file);
1561 bool printed_color_warning =
false;
1562 for (
size_t i = 0; i < pointcloud.
size(); i++) {
1564 ply_write(ply_file,
point(0));
1565 ply_write(ply_file,
point(1));
1566 ply_write(ply_file,
point(2));
1569 ply_write(ply_file,
normal(0));
1570 ply_write(ply_file,
normal(1));
1571 ply_write(ply_file,
normal(2));
1575 if (!printed_color_warning &&
1579 "Write Ply clamped color value to valid range");
1580 printed_color_warning =
true;
1583 ply_write(ply_file, rgb(0));
1584 ply_write(ply_file, rgb(1));
1585 ply_write(ply_file, rgb(2));
1587 if (i % 1000 == 0) {
1593 ply_close(ply_file);
1613 size_t num_of_pts = 0;
1614 int num_of_fields = 0;
1615 const char *line_buffer;
1616 if ((line_buffer = file.
ReadLine())) {
1617 sscanf(line_buffer,
"%zu", &num_of_pts);
1619 if (num_of_pts <= 0) {
1628 while (idx < num_of_pts && (line_buffer = file.
ReadLine())) {
1629 if (num_of_fields == 0) {
1630 std::vector<std::string> st;
1632 num_of_fields = (int)st.size();
1633 if (num_of_fields < 3) {
1635 "Read PTS failed: insufficient data fields.");
1638 pointcloud.
resize(
static_cast<unsigned>(num_of_pts));
1639 if (num_of_fields >= 7) {
1646 if (num_of_fields < 7) {
1647 if (sscanf(line_buffer,
"%lf %lf %lf", &x, &y, &z) == 3) {
1648 pointcloud.
setPoint(idx, Eigen::Vector3d(x, y, z));
1651 if (sscanf(line_buffer,
"%lf %lf %lf %d %d %d %d", &x, &y, &z,
1652 &i, &r, &g, &b) == 7) {
1653 pointcloud.
setPoint(idx, Eigen::Vector3d(x, y, z));
1659 if (idx % 1000 == 0) {
1666 }
catch (
const std::exception &e) {
1685 if (fprintf(file.
GetFILE(),
"%zu\r\n", (
size_t)pointcloud.
size()) < 0) {
1690 for (
size_t i = 0; i < pointcloud.
size(); i++) {
1693 if (fprintf(file.
GetFILE(),
"%.10f %.10f %.10f\r\n",
point(0),
1696 "Write PTS failed: unable to write file: {}",
1702 if (fprintf(file.
GetFILE(),
"%.10f %.10f %.10f %d %d %d %d\r\n",
1706 "Write PTS failed: unable to write file: {}",
1711 if (i % 1000 == 0) {
1717 }
catch (
const std::exception &e) {
float PointCoordinateType
Type of the coordinates of a (N-D) point.
ccPointCloud * pointcloud_ptr
utility::CountingProgressReporter * progress_bar
std::vector< PCLPointField > fields
cmdLineReadable * params[]
virtual void release()
Decrease counter and deletes object when 0.
virtual void showSF(bool state)
Sets active scalarfield visibility.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addEigenNorm(const Eigen::Vector3d &N)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
void addNorms(const std::vector< CCVector3 > &Ns)
void addEigenColor(const Eigen::Vector3d &color)
Eigen::Vector3d getEigenNormal(size_t index) const
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
bool hasNormals() const override
Returns whether normals are enabled or not.
virtual bool IsEmpty() const override
bool resizeTheRGBTable(bool fillWithWhite=false)
Resizes the RGB colors array.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
void clear() override
Clears the entity from all its points and features.
bool hasColors() const override
Returns whether colors are enabled or not.
bool resize(unsigned numberOfPoints) override
Resizes all the active features arrays.
void deleteScalarField(int index) override
Deletes a specific scalar field.
void setPointColor(size_t pointIndex, const ecvColor::Rgb &col)
Sets a particular point color.
const ecvColor::Rgb & getPointColor(unsigned pointIndex) const override
Returns color corresponding to a given point.
Eigen::Vector3d getEigenColor(size_t index) const
const CCVector3 & getPointNormal(unsigned pointIndex) const override
Returns normal corresponding to a given point.
A scalar field associated to display-related parameters.
void computeMinAndMax() override
Determines the min and max values.
virtual bool hasPoints() const
void addEigenPoint(const Eigen::Vector3d &point)
int getScalarFieldIndexByName(const char *name) const
Returns the index of a scalar field represented by its name.
CCVector3 * getPointPtr(size_t index)
unsigned size() const override
Eigen::Vector3d getEigenPoint(size_t index) const
void setPoint(size_t index, const CCVector3 &P)
const CCVector3 * getPoint(unsigned index) const override
void addElement(ScalarType value)
bool reserveSafe(std::size_t count)
Reserves memory (no exception thrown)
void SetTotal(int64_t total)
bool Update(int64_t count)
bool Open(const std::string &filename, const std::string &mode)
Open a file.
int64_t CurPos()
Returns current position in the file (ftell).
FILE * GetFILE()
Returns the underlying C FILE pointer.
int64_t GetFileSize()
Returns the file size in bytes.
#define DEFAULT_IO_BUFFER_SIZE
__host__ __device__ float length(float2 v)
unsigned char ColorCompType
Default color components type (R,G and B)
Helper functions for the ml ops.
bool ReadPointCloudFromPLY(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
bool ReadPointCloudFromXYZN(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
bool WritePointCloudToPCD(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
FileGeometry ReadFileGeometryTypePCD(const std::string &path)
FileGeometry ReadFileGeometryTypePTS(const std::string &path)
bool WritePointCloudToPTS(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
bool ReadPointCloudFromPCD(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
bool ReadPointCloudFromXYZ(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
bool ReadPointCloudFromXYZRGB(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
bool WritePointCloudToXYZ(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
bool WritePointCloudToPLY(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
FileGeometry ReadFileGeometryTypeXYZ(const std::string &path)
bool WritePointCloudToXYZN(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
FileGeometry ReadFileGeometryTypeXYZN(const std::string &path)
FileGeometry ReadFileGeometryTypePLY(const std::string &path)
bool WritePointCloudToXYZRGB(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
bool WritePointCloudInMemoryToXYZ(unsigned char *&buffer, size_t &length, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
bool ReadPointCloudFromPTS(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
bool ReadPointCloudInMemoryFromXYZ(const unsigned char *buffer, const size_t length, ccPointCloud &pointcloud, const ReadPointCloudOption ¶ms)
FileGeometry ReadFileGeometryTypeXYZRGB(const std::string &path)
static const std::string path
static bool ReadPCDData(FILE *file, PCDHeader &header, t::geometry::PointCloud &pointcloud, const ReadPointCloudOption ¶ms)
static bool GenerateHeader(const t::geometry::PointCloud &pointcloud, const bool write_ascii, const bool compressed, PCDHeader &header)
static bool WritePCDHeader(FILE *file, const PCDHeader &header)
static bool ReadPCDHeader(FILE *file, PCDHeader &header)
static bool WritePCDData(FILE *file, const PCDHeader &header, const geometry::PointCloud &pointcloud, const WritePointCloudOption ¶ms)
static void UnpackASCIIPCDElement(scalar_t &data, const char *data_ptr)=delete
FILE * FOpen(const std::string &filename, const std::string &mode)
void SplitString(std::vector< std::string > &tokens, const std::string &str, const std::string &delimiters=" ", bool trim_empty_str=true)
Eigen::Vector3uint8 ColorToUint8(const Eigen::Vector3d &color)
std::string FastFormatString(const std::string &format, Args... args)
Format string fast (Unix / BSD Only)
Generic file read and write utility for python interface.
RgbTpl< ColorCompType > Rgb
3 components, default type
Optional parameters to ReadPointCloud.
Optional parameters to WritePointCloud.