63 #define PLY_BINARY_BE 2 64 #define PLY_BINARY_LE 3 100 int external_type = 0;
101 int internal_type = 0;
105 int count_external = 0;
106 int count_internal = 0;
107 int count_offset = 0;
119 int other_offset = 0;
136 string(
"invalid"), string(
"char"), string(
"short"),
137 string(
"int"), string(
"uchar"), string(
"ushort"),
138 string(
"uint"), string(
"float"), string(
"double"),
152 vector<string>
get_words(FILE*,
string&);
168 void store_item(
char*,
int,
int,
unsigned int,
double);
177 void get_ascii_item(
const char*,
int,
int*,
unsigned int*,
double*);
179 FILE*,
int,
int,
int*,
unsigned int*,
double*);
206 if (fp ==
nullptr)
return (
nullptr);
209 auto* plyfile =
new PlyFile(fp);
211 plyfile->file_type = file_type;
212 plyfile->version = 1.0;
217 plyfile->elems.resize(elem_names.size());
218 for (
size_t i = 0; i < elem_names.size(); i++)
220 plyfile->elems[i].name = elem_names[i];
242 const char* name,
const vector<string>& elem_names,
int file_type,
250 fp =
fopen(name,
"w");
258 plyfile =
ply_write(fp, elem_names, file_type);
259 if (plyfile ==
nullptr)
return (
nullptr);
281 PlyFile* plyfile,
const string& elem_name,
int nelems,
282 vector<PlyProperty>& prop_list)
287 throw std::runtime_error(
format(
288 "ply_describe_element: can't find element '%s'",
295 const size_t nprops = prop_list.size();
296 elem->
props.resize(nprops);
299 for (
size_t i = 0; i < nprops; i++)
301 elem->
props[i] = prop_list[i];
323 stderr,
"ply_describe_property: can't find element '%s'\n",
329 elem->
props.push_back(*prop);
351 throw std::runtime_error(
format(
352 "ply_element_count: can't find element '%s'", elem_name.c_str()));
367 FILE* fp = plyfile->
fp;
374 fprintf(fp,
"format ascii 1.0\n");
377 fprintf(fp,
"format binary_big_endian 1.0\n");
380 fprintf(fp,
"format binary_little_endian 1.0\n");
383 throw std::runtime_error(
format(
384 "ply_header_complete: bad file type = %d", plyfile->
file_type));
389 for (
auto& comment : plyfile->
comments)
390 fprintf(fp,
"comment %s\n", comment.c_str());
394 for (
auto& i : plyfile->
obj_info)
fprintf(fp,
"obj_info %s\n", i.c_str());
398 for (
auto& i : plyfile->
elems)
404 for (
const auto& j : elem->
props)
442 throw std::runtime_error(
format(
443 "ply_elements_setup: can't find element '%s'", elem_name.c_str()));
460 FILE* fp = plyfile->
fp;
461 char *elem_data, *item;
465 unsigned int uint_val;
470 elem_data = (
char*)elem_ptr;
471 other_ptr = (
char**)(((
char*)elem_ptr) + elem->
other_offset);
480 for (
size_t j = 0; j < elem->
props.size(); j++)
484 elem_data = *other_ptr;
486 elem_data = (
char*)elem_ptr;
495 const size_t list_count = uint_val;
496 item_ptr = (
char**)(elem_data + prop->
offset);
499 for (
size_t k = 0; k < list_count; k++)
511 item = elem_data + prop->
offset;
527 for (
size_t j = 0; j < elem->
props.size(); j++)
531 elem_data = *other_ptr;
533 elem_data = (
char*)elem_ptr;
543 const size_t list_count = uint_val;
544 item_ptr = (
char**)(elem_data + prop->
offset);
547 for (
size_t k = 0; k < list_count; k++)
559 item = elem_data + prop->
offset;
581 plyfile->
comments.push_back(comment);
595 plyfile->
obj_info.push_back(obj_info);
620 if (fp ==
nullptr)
return (
nullptr);
623 auto* plyfile =
new PlyFile(fp);
627 vector<string> words =
get_words(plyfile->fp, orig_line);
629 if (words.empty() || words[0] !=
"ply")
return nullptr;
631 while (!words.empty())
635 if (words[0] ==
"format")
637 if (words.size() != 3)
return (
nullptr);
638 if (words[1] ==
"ascii")
640 else if (words[1] ==
"binary_big_endian")
642 else if (words[1] ==
"binary_little_endian")
646 plyfile->version =
d2f(atof(words[2].c_str()));
649 else if (words[0] ==
"element")
651 else if (words[0] ==
"property")
653 else if (words[0] ==
"comment")
655 else if (words[0] ==
"obj_info")
657 else if (words[0] ==
"end_header")
660 words =
get_words(plyfile->fp, orig_line);
666 for (
auto& i : plyfile->elems)
676 for (
auto& elem : plyfile->elems) elem_names.push_back(elem.name);
698 const char* filename, vector<string>& elem_names,
int* file_type,
706 fp =
fopen(filename,
"r");
707 if (fp ==
nullptr)
return (
nullptr);
739 PlyFile* plyfile,
const string& elem_name,
int& nelems,
int& nprops)
743 if (elem ==
nullptr)
return vector<PlyProperty>();
746 nprops = elem->
props.size();
778 if (prop_ptr ==
nullptr)
781 stderr,
"Warning: Can't find property '%s' in element '%s'\n",
782 prop->
name.c_str(), elem_name.c_str());
877 if (ply ==
nullptr)
return;
896 for (
auto& elem : plyfile->
elems)
897 if (element == elem.name)
return &elem;
915 PlyElement* elem,
const std::string& prop_name,
int* index)
917 for (
size_t i = 0; i < elem->
props.size(); i++)
918 if (
string(prop_name) == elem->
props[i].name)
921 return &elem->
props[i];
939 char *elem_data, *item =
nullptr;
943 unsigned int uint_val;
948 char* other_data =
nullptr;
971 vector<string> words =
get_words(plyfile->
fp, orig_line);
974 throw std::runtime_error(
"ply_get_element: unexpected end of file");
978 for (
size_t j = 0; j < elem->
props.size(); j++)
981 store_it = (elem->
store_prop[j] | other_flag);
985 elem_data = elem_ptr;
987 elem_data = other_data;
995 &uint_val, &double_val);
1005 list_count = int_val;
1007 store_array = (
char**)(elem_data + prop->
offset);
1009 if (list_count == 0)
1011 if (store_it) *store_array =
nullptr;
1018 (
char*)malloc(
sizeof(
char) * item_size * list_count);
1020 *store_array = item_ptr;
1024 for (
int k = 0; k < list_count; k++)
1028 &int_val, &uint_val, &double_val);
1043 &uint_val, &double_val);
1046 item = elem_data + prop->
offset;
1064 FILE* fp = plyfile->
fp;
1065 char *elem_data, *item =
nullptr;
1069 unsigned int uint_val;
1074 char* other_data =
nullptr;
1089 other_data = (
char*)malloc(elem->
other_size);
1099 for (
size_t j = 0; j < elem->
props.size(); j++)
1102 store_it = (elem->
store_prop[j] | other_flag);
1106 elem_data = elem_ptr;
1108 elem_data = other_data;
1116 &uint_val, &double_val))
1121 "RPly::binary_get_element: Error reading binary file!\n");
1133 list_count = int_val;
1142 store_array = (
char**)(elem_data + prop->
offset);
1143 if (list_count == 0)
1145 if (store_it) *store_array =
nullptr;
1152 (
char*)malloc(
sizeof(
char) * item_size * list_count);
1154 *store_array = item_ptr;
1158 for (
int k = 0; k < list_count; k++)
1162 &uint_val, &double_val))
1167 "RPly::binary_get_element: Error reading binary " 1184 fp, bin_file_type, prop->
external_type, &int_val, &uint_val,
1190 "RPly::binary_get_element: Error reading binary file!\n");
1195 item = elem_data + prop->
offset;
1216 throw std::runtime_error(
1217 format(
"write_scalar_type: bad data code = %d", code));
1241 #define BIG_STRING 4096 1244 vector<string> words;
1250 if (result ==
nullptr)
1252 orig_line = string();
1256 orig_line = string(str);
1275 unsigned char* puchar;
1278 unsigned short int* pushort;
1280 unsigned int* puint;
1284 unsigned int uint_value;
1285 double double_value;
1290 pchar = (
char*)item;
1292 return ((
double)int_value);
1294 puchar = (
unsigned char*)item;
1295 int_value = *puchar;
1296 return ((
double)int_value);
1298 pshort = (
short int*)item;
1299 int_value = *pshort;
1300 return ((
double)int_value);
1302 pushort = (
unsigned short int*)item;
1303 int_value = *pushort;
1304 return ((
double)int_value);
1308 return ((
double)int_value);
1310 puint = (
unsigned int*)item;
1311 uint_value = *puint;
1312 return ((
double)uint_value);
1314 pfloat = (
float*)item;
1315 double_value = *pfloat;
1316 return (double_value);
1318 pdouble = (
double*)item;
1319 double_value = *pdouble;
1320 return (double_value);
1322 throw std::runtime_error(
1323 format(
"get_item_value: bad type = %d", type));
1339 FILE* fp,
int int_val,
unsigned int uint_val,
double double_val,
int type)
1341 unsigned char uchar_val;
1343 unsigned short ushort_val;
1351 fwrite(&char_val, 1, 1, fp);
1354 short_val = int_val;
1355 fwrite(&short_val, 2, 1, fp);
1358 fwrite(&int_val, 4, 1, fp);
1361 uchar_val = uint_val;
1362 fwrite(&uchar_val, 1, 1, fp);
1365 ushort_val = uint_val;
1366 fwrite(&ushort_val, 2, 1, fp);
1369 fwrite(&uint_val, 4, 1, fp);
1372 float_val =
d2f(double_val);
1373 fwrite(&float_val, 4, 1, fp);
1376 fwrite(&double_val, 8, 1, fp);
1379 throw std::runtime_error(
1380 format(
"write_binary_item: bad type = %d", type));
1396 FILE* fp,
int int_val,
unsigned int uint_val,
double double_val,
int type)
1412 fprintf(fp,
"%g ", double_val);
1415 throw std::runtime_error(
1416 format(
"write_ascii_item: bad type = %d", type));
1435 void* ptr,
int type,
int* int_val,
unsigned int* uint_val,
1441 *int_val = *((
char*)ptr);
1442 *uint_val = *int_val;
1443 *double_val = *int_val;
1446 *uint_val = *((
unsigned char*)ptr);
1447 *int_val = *uint_val;
1448 *double_val = *uint_val;
1451 *int_val = *((
short int*)ptr);
1452 *uint_val = *int_val;
1453 *double_val = *int_val;
1456 *uint_val = *((
unsigned short int*)ptr);
1457 *int_val = *uint_val;
1458 *double_val = *uint_val;
1461 *int_val = *((
int*)ptr);
1462 *uint_val = *int_val;
1463 *double_val = *int_val;
1466 *uint_val = *((
unsigned int*)ptr);
1467 *int_val = *uint_val;
1468 *double_val = *uint_val;
1471 *double_val = *((
float*)ptr);
1472 *int_val =
static_cast<int>(*double_val);
1473 *uint_val =
static_cast<unsigned int>(*double_val);
1476 *double_val = *((
double*)ptr);
1477 *int_val =
static_cast<int>(*double_val);
1478 *uint_val =
static_cast<unsigned int>(*double_val);
1481 throw std::runtime_error(
1482 format(
"get_stored_item: bad type = %d", type));
1503 FILE* fp,
int bin_file_type,
int type,
int* int_val,
unsigned int* uint_val,
1514 if (fread(ptr, 1, 1, fp) != 1)
return 0;
1515 *int_val = *((
char*)ptr);
1516 *uint_val = *int_val;
1517 *double_val = *int_val;
1520 if (fread(ptr, 1, 1, fp) != 1)
return 0;
1521 *uint_val = *((
unsigned char*)ptr);
1522 *int_val = *uint_val;
1523 *double_val = *uint_val;
1526 if (fread(ptr, 2, 1, fp) != 1)
return 0;
1527 *int_val = *((
short int*)ptr);
1528 *uint_val = *int_val;
1529 *double_val = *int_val;
1532 if (fread(ptr, 2, 1, fp) != 1)
return 0;
1533 *uint_val = *((
unsigned short int*)ptr);
1534 *int_val = *uint_val;
1535 *double_val = *uint_val;
1538 if (fread(ptr, 4, 1, fp) != 1)
return 0;
1539 *int_val = *((
int*)ptr);
1540 *uint_val = *int_val;
1541 *double_val = *int_val;
1544 if (fread(ptr, 4, 1, fp) != 1)
return 0;
1545 *uint_val = *((
unsigned int*)ptr);
1546 *int_val = *uint_val;
1547 *double_val = *uint_val;
1550 if (fread(ptr, 4, 1, fp) != 1)
return 0;
1551 *double_val = *((
float*)ptr);
1552 *int_val =
static_cast<int>(*double_val);
1553 *uint_val =
static_cast<unsigned int>(*double_val);
1556 if (fread(ptr, 8, 1, fp) != 1)
return 0;
1557 *double_val = *((
double*)ptr);
1558 *int_val =
static_cast<int>(*double_val);
1559 *uint_val =
static_cast<unsigned int>(*double_val);
1562 throw std::runtime_error(
1563 format(
"get_binary_item: bad type = %d", type));
1569 #if MRPT_IS_BIG_ENDIAN 1577 int int_val2 = *int_val;
1578 unsigned int uint_val2 = *uint_val;
1579 double double_val2 = *double_val;
1603 const char* word,
int type,
int* int_val,
unsigned int* uint_val,
1613 *int_val = atoi(word);
1614 *uint_val = *int_val;
1615 *double_val = *int_val;
1619 *uint_val = strtoul(word, (
char**)
nullptr, 10);
1620 *int_val = *uint_val;
1621 *double_val = *uint_val;
1626 *double_val = atof(word);
1627 *int_val = (int)*double_val;
1628 *uint_val = (
unsigned int)*double_val;
1632 throw std::runtime_error(
1633 format(
"get_ascii_item: bad type = %d", type));
1652 char* item,
int type,
int int_val,
unsigned int uint_val,
double double_val)
1654 unsigned char* puchar;
1656 unsigned short int* pushort;
1658 unsigned int* puint;
1668 puchar = (
unsigned char*)item;
1672 pshort = (
short*)item;
1676 pushort = (
unsigned short*)item;
1677 *pushort = uint_val;
1684 puint = (
unsigned int*)item;
1688 pfloat = (
float*)item;
1689 *pfloat =
d2f(double_val);
1692 pdouble = (
double*)item;
1693 *pdouble = double_val;
1696 throw std::runtime_error(
format(
"store_item: bad type = %d", type));
1712 plyfile->
elems.emplace_back();
1715 elem->
name = words[1];
1716 elem->
num = atoi(words[2].c_str());
1754 elem->
props.emplace_back();
1760 if (words[1] ==
"list")
1764 prop->
name = words[4];
1770 prop->
name = words[2];
1812 float x{0}, y{0}, z{0};
1813 float r{0}, g{0}, b{0};
1844 bool PLY_Importer::loadFromPlyFile(
1845 const std::string& filename, std::vector<std::string>* file_comments,
1846 std::vector<std::string>* file_obj_info)
1851 vector<string> elist;
1860 for (
const auto& elem_name : elist)
1863 int num_elems = 0, nprops = 0;
1872 if (
"vertex" == elem_name)
1879 this->PLY_import_set_vertex_count(num_elems);
1880 for (
int j = 0; j < num_elems; j++)
1893 this->PLY_import_set_vertex(j, xyz, &col);
1900 this->PLY_import_set_vertex(j, xyz, &col);
1904 this->PLY_import_set_vertex(j, xyz);
1917 vector<string> strs;
1919 *file_comments = std::vector<std::string>(strs);
1925 vector<string> strs;
1927 *file_obj_info = std::vector<std::string>(strs);
1934 m_ply_import_last_error = std::string();
1937 catch (
const std::exception& e)
1940 m_ply_import_last_error = std::string(e.what());
1945 bool PLY_Exporter::saveToPlyFile(
1946 const std::string& filename,
bool save_in_binary,
1947 const std::vector<std::string>& file_comments,
1948 const std::vector<std::string>& file_obj_info)
const 1953 vector<string> elem_names;
1954 elem_names.emplace_back(
"vertex");
1955 elem_names.emplace_back(
"face");
1967 filename.c_str(), elem_names,
1969 #if MRPT_IS_BIG_ENDIAN 1979 const size_t nverts = this->PLY_export_get_vertex_count();
1980 const size_t nfaces = this->PLY_export_get_face_count();
1988 this->PLY_export_get_vertex(0, pt, pt_has_color, pt_color);
2005 for (
const auto& file_comment : file_comments)
2016 for (
size_t i = 0; i < nverts; i++)
2021 this->PLY_export_get_vertex(i, pt, pt_has_color, pt_color);
2030 (1.0f / 3.0f) * (pt_color.
R + pt_color.
G + pt_color.
B);
2050 m_ply_export_last_error = std::string();
2053 catch (
const std::exception& e)
2056 m_ply_export_last_error = std::string(e.what());
const char DONT_STORE_PROP
void ply_put_obj_info(PlyFile *plyfile, const string &obj_info)
void get_ascii_item(const char *, int, int *, unsigned int *, double *)
vector< string > comments
vector< PlyProperty > props
PlyElement * find_element(PlyFile *, const std::string &s)
std::string std::string format(std::string_view fmt, ARGS &&... args)
size_t size(const MATRIXLIKE &m, const int dim)
int void fclose(FILE *f)
An OS-independent version of fclose.
const PlyProperty vert_props[]
void reverseBytes(const T &v_in, T &v_out)
Reverse the order of the bytes of a given type (useful for transforming btw little/big endian) ...
vector< char > store_prop
void ply_get_obj_info(PlyFile *plyfile, vector< string > &obj_info)
struct PlyProperty PlyProperty
PlyFile * ply_open_for_writing(const char *name, const vector< string > &elem_names, int file_type, float *version)
int get_binary_item(FILE *, int, int, int *, unsigned int *, double *)
void add_property(PlyFile *, const vector< string > &)
void tokenize(const std::string &inString, const std::string &inDelimiters, OUT_CONTAINER &outTokens, bool skipBlankTokens=true) noexcept
Tokenizes a string according to a set of delimiting characters.
#define ASSERT_(f)
Defines an assertion mechanism.
float d2f(const double d)
shortcut for static_cast<float>(double)
const int ply_type_size[]
This base provides a set of functions for maths stuff.
double get_item_value(const char *, int)
PlyFile(FILE *_fp=nullptr)
void ply_put_element_setup(PlyFile *plyfile, const string &elem_name)
void add_comment(PlyFile *, const string &)
void ply_describe_element(PlyFile *plyfile, const string &elem_name, int nelems, vector< PlyProperty > &prop_list)
const PlyProperty face_props[]
void ply_describe_property(PlyFile *plyfile, const char *elem_name, const PlyProperty *prop)
PlyFile * ply_read(FILE *fp, vector< string > &elem_names)
void add_element(PlyFile *, const vector< string > &)
int get_prop_type(const string &type_name)
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
const std::string type_names[]
vector< PlyProperty > ply_get_element_description(PlyFile *plyfile, const string &elem_name, int &nelems, int &nprops)
void add_obj_info(PlyFile *, const string &)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void write_binary_item(FILE *, int, unsigned int, double, int)
void ply_close(PlyFile *plyfile)
void ply_put_comment(PlyFile *plyfile, const string &comment)
void ply_get_element(PlyFile *plyfile, void *elem_ptr)
void write_scalar_type(FILE *, int)
void write_ascii_item(FILE *, int, unsigned int, double, int)
PlyFile * ply_write(FILE *fp, const vector< string > &elem_names, int file_type)
PlyProperty * find_property(PlyElement *, const std::string &s, int *)
void get_stored_item(void *, int, int *, unsigned int *, double *)
An RGBA color - floats in the range [0,1].
The namespace for 3D scene representation and rendering.
void ascii_get_element(PlyFile *, char *)
void copy_property(PlyProperty *, const PlyProperty *)
vector< string > get_words(FILE *, string &)
void binary_get_element(PlyFile *, char *)
std::string trim(const std::string &str)
Removes leading and trailing spaces.
vector< PlyElement > elems
struct PlyElement PlyElement
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
void ply_get_property(PlyFile *plyfile, const string &elem_name, const PlyProperty *prop)
void store_item(char *, int, int, unsigned int, double)
void ply_header_complete(PlyFile *plyfile)
void ply_get_info(PlyFile *ply, float *version, int *file_type)
vector< string > obj_info
void ply_element_count(PlyFile *plyfile, const string &elem_name, int nelems)
void ply_get_comments(PlyFile *plyfile, vector< string > &comments)
PlyFile * ply_open_for_reading(const char *filename, vector< string > &elem_names, int *file_type, float *version)
void ply_put_element(PlyFile *plyfile, void *elem_ptr)