Visual Computing Library  devel
Loading...
Searching...
No Matches
header.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_IO_MESH_PLY_DETAIL_HEADER_H
24#define VCL_IO_MESH_PLY_DETAIL_HEADER_H
25
26#include "ply.h"
27
28#include <vclib/io/file_info.h>
29#include <vclib/io/read.h>
30
31#include <vclib/space/complex.h>
32
33#include <clocale>
34#include <string>
35#include <vector>
36
37namespace vcl::detail {
38
44class PlyHeader
45{
46 bool mValid = false;
47
48 ply::Format mFormat = ply::UNKNOWN;
49
50 std::vector<PlyElement> mElements;
51 std::vector<std::string> mTextureFiles;
52
53 // for each element, its position in the mElements vector
54 uint mVertElemPos = UINT_NULL;
55 uint mFaceElemPos = UINT_NULL;
56 uint mEdgeElemPos = UINT_NULL;
57 uint mTriStripElemPos = UINT_NULL;
58
59public:
60 using iterator = std::vector<PlyElement>::const_iterator;
61
62 PlyHeader() = default;
63
64 PlyHeader(
65 ply::Format format,
66 const MeshInfo& info,
67 std::vector<std::string> textureFiles = std::vector<std::string>()) :
68 mValid(true), mFormat(format)
69 {
70 setInfo(info, textureFiles, format);
71 }
72
73 PlyHeader(std::istream& file, const std::string& filename = "")
74 {
75 clear();
76
77 std::string line;
78 std::getline(file, line);
79 removeCarriageReturn(line);
80 if (line.compare(0, 3, "ply") == 0) {
81 bool error = false;
82 bool firstElement = true;
83 std::string headerLine;
84 PlyElement element;
85 do {
86 Tokenizer spaceTokenizer =
87 readAndTokenizeNextNonEmptyLine(file);
88 if (!error) {
89 Tokenizer::iterator token = spaceTokenizer.begin();
90 headerLine = *token;
91 if (headerLine == "format") {
92 token++;
93 if (*token == "ascii")
94 mFormat = ply::ASCII;
95 else if (
96 *token == "binary_little_endian" ||
97 *token == "binary")
98 mFormat = ply::BINARY_LITTLE_ENDIAN;
99 else if (*token == "binary_big_endian")
100 mFormat = ply::BINARY_BIG_ENDIAN;
101 }
102 // reading a comment, may be a texture file...
103 else if (headerLine == "comment") {
104 token++;
105 if (token != spaceTokenizer.end()) {
106 if (containsCaseInsensitive(*token, "texture")) {
107 ++token;
108 if (token != spaceTokenizer.end()) {
109 std::string textName = *token;
110 auto it =
111 findCaseInsensitive(textName, "<this>");
112 if (it != textName.end()) {
113 uint pos = it - textName.begin();
114 std::string fn =
116 filename);
117 textName =
118 textName.substr(0, pos) + fn +
119 textName.substr(
120 pos + 6, textName.size());
121 }
122 mTextureFiles.push_back(textName);
123 }
124 }
125 }
126 }
127 // I am reading a new element
128 else if (headerLine == "element") {
129 // if it is not the first element to read, it means that
130 // the previous one needs to be saved
131 if (!firstElement) {
132 // index of each element type in elements vector
133 if (element.type == ply::VERTEX)
134 mVertElemPos = mElements.size();
135 if (element.type == ply::FACE)
136 mFaceElemPos = mElements.size();
137 if (element.type == ply::EDGE)
138 mEdgeElemPos = mElements.size();
139 if (element.type == ply::TRISTRIP)
140 mTriStripElemPos = mElements.size();
141 mElements.push_back(element);
142 element = PlyElement();
143 }
144 element = readElement(spaceTokenizer);
145 firstElement = false;
146 }
147 else if (headerLine == "property") {
148 PlyProperty p = readProperty(spaceTokenizer);
149 element.properties.push_back(p);
150 }
151 // save the last element
152 else if (headerLine == "end_header") {
153 if (element.type == ply::VERTEX)
154 mVertElemPos = mElements.size();
155 if (element.type == ply::FACE)
156 mFaceElemPos = mElements.size();
157 if (element.type == ply::EDGE)
158 mEdgeElemPos = mElements.size();
159 if (element.type == ply::TRISTRIP)
160 mTriStripElemPos = mElements.size();
161 mElements.push_back(element);
162 }
163 }
164 } while (!error && headerLine != "end_header");
165 mValid = !error && hasVertices();
166 }
167 }
168
169 void clear()
170 {
171 mFormat = ply::UNKNOWN;
172 mElements.clear();
173 mTextureFiles.clear();
174 mValid = false;
175
176 mVertElemPos = UINT_NULL;
177 mFaceElemPos = UINT_NULL;
178 mEdgeElemPos = UINT_NULL;
179 mTriStripElemPos = UINT_NULL;
180 }
181
182 bool isValid() const { return mValid; }
183
184 ply::Format format() const { return mFormat; }
185
186 MeshInfo getInfo() const
187 {
188 MeshInfo mod;
189 // x, y, z, nx, ny, nz, red, green, blue, alpha, vertex_indices
190
191 if (mVertElemPos != UINT_NULL) {
192 mod.setVertices();
193 for (const PlyProperty& p : mElements[mVertElemPos].properties) {
194 switch (p.name) {
195 case ply::x:
196 case ply::y:
197 case ply::z: mod.setPerVertexPosition(); break;
198 case ply::nx:
199 case ply::ny:
200 case ply::nz: mod.setPerVertexNormal(); break;
201 case ply::red:
202 case ply::green:
203 case ply::blue:
204 case ply::alpha: mod.setPerVertexColor(); break;
205 case ply::quality: mod.setPerVertexQuality(); break;
206 case ply::texture_u: mod.setPerVertexTexCoord(); break;
207 case ply::unknown:
208 if (p.type <= ply::PropertyType::DOUBLE) {
209 mod.addPerVertexCustomComponent(
210 p.unknownPropertyName, (MeshInfo::DataType) p.type);
211 }
212 default: break;
213 }
214 }
215 }
216 if (mFaceElemPos != UINT_NULL) {
217 mod.setFaces();
218 for (const PlyProperty& p : mElements[mFaceElemPos].properties) {
219 switch (p.name) {
220 case ply::vertex_indices:
221 mod.setPerFaceVertexReferences();
222 break;
223 case ply::nx:
224 case ply::ny:
225 case ply::nz: mod.setPerFaceNormal(); break;
226 case ply::red:
227 case ply::green:
228 case ply::blue:
229 case ply::alpha: mod.setPerFaceColor(); break;
230 case ply::quality: mod.setPerFaceQuality(); break;
231 case ply::texcoord: mod.setPerFaceWedgeTexCoords(); break;
232 case ply::unknown:
233 if (p.type <= ply::PropertyType::DOUBLE) {
234 mod.addPerFaceCustomComponent(
235 p.unknownPropertyName, (MeshInfo::DataType) p.type);
236 }
237 default: break;
238 }
239 }
240 }
241 if (mTriStripElemPos != UINT_NULL) {
242 mod.setFaces();
243 for (const PlyProperty& p :
244 mElements[mTriStripElemPos].properties) {
245 switch (p.name) {
246 case ply::vertex_indices:
247 mod.setPerFaceVertexReferences();
248 break;
249 case ply::nx:
250 case ply::ny:
251 case ply::nz: mod.setPerFaceNormal(); break;
252 case ply::red:
253 case ply::green:
254 case ply::blue:
255 case ply::alpha: mod.setPerFaceColor(); break;
256 case ply::quality: mod.setPerFaceQuality(); break;
257 case ply::texcoord: mod.setPerFaceWedgeTexCoords(); break;
258 default: break;
259 }
260 }
261 }
262 if (mEdgeElemPos != UINT_NULL) {
263 mod.setEdges();
264 for (const PlyProperty& p : mElements[mEdgeElemPos].properties) {
265 switch (p.name) {
266 case ply::vertex_indices:
267 mod.setPerEdgeVertexReferences();
268 break;
269 case ply::nx:
270 case ply::ny:
271 case ply::nz: mod.setPerEdgeNormal(); break;
272 case ply::red:
273 case ply::green:
274 case ply::blue:
275 case ply::alpha: mod.setPerEdgeColor(); break;
276 case ply::quality: mod.setPerEdgeQuality(); break;
277 default: break;
278 }
279 }
280 }
281 if (mTextureFiles.size() > 0) {
282 mod.setTextures(true);
283 }
284 return mod;
285 }
286
287 bool hasVertices() const { return mVertElemPos != UINT_NULL; }
288
289 bool hasFaces() const { return mFaceElemPos != UINT_NULL; }
290
291 bool hasEdges() const { return mEdgeElemPos != UINT_NULL; }
292
293 bool hasTriStrips() const { return mTriStripElemPos != UINT_NULL; }
294
295 bool hasTextureFileNames() const { return mTextureFiles.size() > 0; }
296
297 uint numberVertices() const
298 {
299 assert(hasVertices());
300 return mElements[mVertElemPos].numberElements;
301 }
302
303 uint numberFaces() const
304 {
305 assert(hasFaces());
306 return mElements[mFaceElemPos].numberElements;
307 }
308
309 uint numberEdges() const
310 {
311 assert(hasEdges());
312 return mElements[mEdgeElemPos].numberElements;
313 }
314
315 uint numberTriStrips() const
316 {
317 assert(hasTriStrips());
318 return mElements[mTriStripElemPos].numberElements;
319 }
320
321 uint numberTextureFileNames() const { return mTextureFiles.size(); }
322
323 const std::list<PlyProperty>& vertexProperties() const
324 {
325 assert(hasVertices());
326 return mElements[mVertElemPos].properties;
327 }
328
329 const std::list<PlyProperty>& faceProperties() const
330 {
331 assert(hasFaces());
332 return mElements[mFaceElemPos].properties;
333 }
334
335 const std::list<PlyProperty>& edgeProperties() const
336 {
337 assert(hasEdges());
338 return mElements[mEdgeElemPos].properties;
339 }
340
341 const std::list<PlyProperty>& triStripsProperties() const
342 {
343 assert(hasTriStrips());
344 return mElements[mTriStripElemPos].properties;
345 }
346
347 const std::vector<std::string>& textureFileNames() const
348 {
349 return mTextureFiles;
350 }
351
352 bool errorWhileLoading() const { return !mValid; }
353
354 void setNumberVertices(unsigned long int nV)
355 {
356 assert(hasVertices());
357 mElements[mVertElemPos].numberElements = nV;
358 }
359
360 void setNumberFaces(unsigned long int nF)
361 {
362 assert(hasFaces());
363 mElements[mFaceElemPos].numberElements = nF;
364 }
365
366 void setNumberEdges(unsigned long int nE)
367 {
368 assert(hasEdges());
369 mElements[mEdgeElemPos].numberElements = nE;
370 }
371
372 void pushTextureFileName(const std::string& tn)
373 {
374 mTextureFiles.push_back(tn);
375 }
376
377 void setInfo(
378 const MeshInfo& info,
379 std::vector<std::string> textureFileNames = std::vector<std::string>(),
380 ply::Format format = ply::BINARY_LITTLE_ENDIAN)
381 {
382 clear();
383 mFormat = format;
384 mValid = true;
385 mTextureFiles = textureFileNames;
386 if (info.hasVertices()) {
387 mVertElemPos = mElements.size();
388 PlyElement vElem;
389 vElem.type = ply::VERTEX;
390 if (info.hasPerVertexPosition()) {
391 PlyProperty px, py, pz;
392 px.name = ply::x;
393 px.type = info.perVertexPositionType();
394 py.name = ply::y;
395 py.type = info.perVertexPositionType();
396 pz.name = ply::z;
397 pz.type = info.perVertexPositionType();
398 vElem.properties.push_back(px);
399 vElem.properties.push_back(py);
400 vElem.properties.push_back(pz);
401 }
402 if (info.hasPerVertexNormal()) {
403 PlyProperty vnx, vny, vnz;
404 vnx.name = ply::nx;
405 vnx.type = info.perVertexNormalType();
406 vny.name = ply::ny;
407 vny.type = info.perVertexNormalType();
408 vnz.name = ply::nz;
409 vnz.type = info.perVertexNormalType();
410 vElem.properties.push_back(vnx);
411 vElem.properties.push_back(vny);
412 vElem.properties.push_back(vnz);
413 }
414 if (info.hasPerVertexColor()) {
415 PlyProperty vcr, vcg, vcb, vca;
416 vcr.name = ply::red;
417 vcr.type = info.perVertexColorType();
418 vcg.name = ply::green;
419 vcg.type = info.perVertexColorType();
420 vcb.name = ply::blue;
421 vcb.type = info.perVertexColorType();
422 vca.name = ply::alpha;
423 vca.type = info.perVertexColorType();
424 vElem.properties.push_back(vcr);
425 vElem.properties.push_back(vcg);
426 vElem.properties.push_back(vcb);
427 vElem.properties.push_back(vca);
428 }
429 if (info.hasPerVertexQuality()) {
430 PlyProperty vs;
431 vs.name = ply::quality;
432 vs.type = info.perVertexQualityType();
433 vElem.properties.push_back(vs);
434 }
435 if (info.hasPerVertexTexCoord()) {
436 PlyProperty tcu, tcv, tcn;
437 tcu.name = ply::texture_u;
438 tcu.type = info.perVertexTexCoordType();
439 tcv.name = ply::texture_v;
440 tcv.type = info.perVertexTexCoordType();
441 tcn.name = ply::texnumber;
442 tcn.type = PrimitiveType::USHORT;
443 vElem.properties.push_back(tcu);
444 vElem.properties.push_back(tcv);
445 vElem.properties.push_back(tcn);
446 }
447 if (info.hasPerVertexCustomComponents()) {
448 for (const auto& cc : info.perVertexCustomComponents()) {
449 if (cc.type <= PrimitiveType::DOUBLE) {
450 PlyProperty pp;
451 pp.name = ply::unknown;
452 pp.unknownPropertyName = cc.name;
453 pp.type = cc.type;
454 vElem.properties.push_back(pp);
455 }
456 }
457 }
458 mElements.push_back(vElem);
459 }
460 if (info.hasFaces()) {
461 mFaceElemPos = mElements.size();
462 PlyElement fElem;
463 fElem.type = ply::FACE;
464 if (info.hasPerFaceVertexReferences()) {
465 PlyProperty vids;
466 vids.list = true;
467 vids.name = ply::vertex_indices;
468 vids.type = PrimitiveType::UINT;
469 vids.listSizeType = PrimitiveType::UCHAR;
470 fElem.properties.push_back(vids);
471 }
472 if (info.hasPerFaceNormal()) {
473 PlyProperty fnx, fny, fnz;
474 fnx.name = ply::nx;
475 fnx.type = info.perFaceNormalType();
476 fny.name = ply::ny;
477 fny.type = info.perFaceNormalType();
478 fnz.name = ply::nz;
479 fnz.type = info.perFaceNormalType();
480 fElem.properties.push_back(fnx);
481 fElem.properties.push_back(fny);
482 fElem.properties.push_back(fnz);
483 }
484 if (info.hasPerFaceColor()) {
485 PlyProperty fcr, fcg, fcb, fca;
486 fcr.name = ply::red;
487 fcr.type = info.perFaceColorType();
488 fcg.name = ply::green;
489 fcg.type = info.perFaceColorType();
490 fcb.name = ply::blue;
491 fcb.type = info.perFaceColorType();
492 fca.name = ply::alpha;
493 fca.type = info.perFaceColorType();
494 fElem.properties.push_back(fcr);
495 fElem.properties.push_back(fcg);
496 fElem.properties.push_back(fcb);
497 fElem.properties.push_back(fca);
498 }
499 if (info.hasPerFaceQuality()) {
500 PlyProperty fs;
501 fs.name = ply::quality;
502 fs.type = (ply::PropertyType) info.perFaceQualityType();
503 fElem.properties.push_back(fs);
504 }
505 if (info.hasPerFaceWedgeTexCoords()) {
506 PlyProperty tc, tn;
507 tc.list = true;
508 tc.listSizeType = PrimitiveType::UCHAR;
509 tc.name = ply::texcoord;
510 tc.type = (ply::PropertyType) info.perFaceWedgeTexCoordsType();
511 tn.name = ply::texnumber;
512 tn.type = PrimitiveType::USHORT;
513 fElem.properties.push_back(tc);
514 fElem.properties.push_back(tn);
515 }
516 if (info.hasPerFaceCustomComponents()) {
517 for (const auto& cc : info.perFaceCustomComponents()) {
518 if (cc.type <= PrimitiveType::DOUBLE) {
519 PlyProperty pp;
520 pp.name = ply::unknown;
521 pp.unknownPropertyName = cc.name;
522 pp.type = (ply::PropertyType) cc.type;
523 fElem.properties.push_back(pp);
524 }
525 }
526 }
527 mElements.push_back(fElem);
528 }
529 if (info.hasEdges()) {
530 mEdgeElemPos = mElements.size();
531 PlyElement eElem;
532 eElem.type = ply::EDGE;
533 if (info.hasPerEdgeVertexReferences()) {
534 PlyProperty v1;
535 v1.name = ply::vertex1;
536 v1.type = PrimitiveType::UINT;
537 eElem.properties.push_back(v1);
538 PlyProperty v2;
539 v2.name = ply::vertex2;
540 v2.type = PrimitiveType::UINT;
541 eElem.properties.push_back(v2);
542 }
543 mElements.push_back(eElem);
544 }
545 }
546
547 std::string toString() const
548 {
549 std::string s;
550
551 s += "ply\nformat ";
552
553 switch (mFormat) {
554 case ply::ASCII: s += "ascii 1.0\n"; break;
555 case ply::BINARY_BIG_ENDIAN: s += "binary_big_endian 1.0\n"; break;
556 default: s += "binary_little_endian 1.0\n"; break;
557 }
558
559 s += "comment Generated by vclib\n";
560 for (const std::string& str : mTextureFiles) {
561 s += "comment TextureFile " + str + "\n";
562 }
563 for (const PlyElement& e : mElements) {
564 s += "element ";
565 switch (e.type) {
566 case ply::VERTEX:
567 s += "vertex " + std::to_string(e.numberElements) + "\n";
568 break;
569 case ply::FACE:
570 s += "face " + std::to_string(e.numberElements) + "\n";
571 break;
572 case ply::EDGE:
573 s += "edge " + std::to_string(e.numberElements) + "\n";
574 break;
575 case ply::TRISTRIP:
576 s += "tristrips " + std::to_string(e.numberElements) + "\n";
577 break;
578 case ply::MATERIAL:
579 s += "material " + std::to_string(e.numberElements) + "\n";
580 break;
581 case ply::OTHER:
582 s += e.unknownElementType + " " +
583 std::to_string(e.numberElements) + "\n";
584 break;
585 }
586 for (const PlyProperty& p : e.properties) {
587 s += "property ";
588 if (p.list) {
589 s += "list ";
590 s += typeToString(p.listSizeType) + " ";
591 }
592 s += typeToString(p.type) + " ";
593 if (p.name == ply::unknown)
594 s += p.unknownPropertyName + "\n";
595 else
596 s += nameToString(p.name) + "\n";
597 }
598 }
599 s += "end_header\n";
600
601 return s;
602 }
603
604 void setFormat(ply::Format f) { mFormat = f; }
605
606 iterator begin() const { return mElements.begin(); }
607
608 iterator end() const { return mElements.end(); }
609
610private:
611 PlyElement readElement(const Tokenizer& lineTokenizer) const
612 {
613 PlyElement e;
614 Tokenizer::iterator token = lineTokenizer.begin();
615 std::string s = *(++token);
616 if (s == "vertex") {
617 e.type = ply::VERTEX;
618 e.numberElements = std::stoi(*(++token));
619 }
620 else if (s == "face") {
621 e.type = ply::FACE;
622 e.numberElements = std::stoi(*(++token));
623 }
624 else if (s == "edge") {
625 e.type = ply::EDGE;
626 e.numberElements = std::stoi(*(++token));
627 }
628 else if (s == "tristrips") {
629 e.type = ply::TRISTRIP;
630 e.numberElements = std::stoi(*(++token));
631 }
632 else {
633 e.type = ply::OTHER;
634 e.numberElements = std::stoi(*(++token));
635 e.unknownElementType = s;
636 }
637 return e;
638 }
639
640 PlyProperty readProperty(const Tokenizer& lineTokenizer) const
641 {
642 PlyProperty p;
643 Tokenizer::iterator token = lineTokenizer.begin();
644 std::string type = *(++token);
645 if (type == "list") {
646 p.list = true;
647 std::string typeSize = *(++token);
648 std::string typeData = *(++token);
649 std::string name = *(++token);
650 p.listSizeType = stringToType(typeSize);
651 p.type = stringToType(typeData);
652 p.name = stringToName(name);
653 if (p.name == ply::unknown)
654 p.unknownPropertyName = name;
655 }
656 else {
657 p.list = false;
658 std::string name = *(++token);
659 p.type = stringToType(type);
660 p.name = stringToName(name);
661 if (p.name == ply::unknown)
662 p.unknownPropertyName = name;
663 }
664
665 return p;
666 }
667
668 ply::PropertyName stringToName(const std::string& name) const
669 {
670 ply::PropertyName pn = ply::unknown;
671 if (name == "x")
672 pn = ply::x;
673 if (name == "y")
674 pn = ply::y;
675 if (name == "z")
676 pn = ply::z;
677 if (name == "nx")
678 pn = ply::nx;
679 if (name == "ny")
680 pn = ply::ny;
681 if (name == "nz")
682 pn = ply::nz;
683 if (name == "red")
684 pn = ply::red;
685 if (name == "green")
686 pn = ply::green;
687 if (name == "blue")
688 pn = ply::blue;
689 if (name == "alpha")
690 pn = ply::alpha;
691 if (name == "quality" || name == "scalar")
692 pn = ply::quality;
693 if (name == "texture_u" || name == "s" || name == "u")
694 pn = ply::texture_u;
695 if (name == "texture_v" || name == "t" || name == "v")
696 pn = ply::texture_v;
697 if (name == "texnumber")
698 pn = ply::texnumber;
699 if (name == "vertex_indices")
700 pn = ply::vertex_indices;
701 if (name == "texcoord")
702 pn = ply::texcoord;
703 if (name == "vertex1")
704 pn = ply::vertex1;
705 if (name == "vertex2")
706 pn = ply::vertex2;
707
708 return pn;
709 }
710
711 ply::PropertyType stringToType(const std::string& type) const
712 {
713 ply::PropertyType pt = ply::PropertyType::UCHAR;
714 if (type == "char")
715 pt = ply::PropertyType::CHAR;
716 if (type == "uchar")
717 pt = ply::PropertyType::UCHAR;
718 if (type == "short")
719 pt = ply::PropertyType::SHORT;
720 if (type == "ushort")
721 pt = ply::PropertyType::USHORT;
722 if (type == "int")
723 pt = ply::PropertyType::INT;
724 if (type == "uint")
725 pt = ply::PropertyType::UINT;
726 if (type == "float")
727 pt = ply::PropertyType::FLOAT;
728 if (type == "double")
729 pt = ply::PropertyType::DOUBLE;
730 return pt;
731 }
732
733 std::string nameToString(ply::PropertyName n) const
734 {
735 switch (n) {
736 case ply::x: return "x";
737 case ply::y: return "y";
738 case ply::z: return "z";
739 case ply::nx: return "nx";
740 case ply::ny: return "ny";
741 case ply::nz: return "nz";
742 case ply::red: return "red";
743 case ply::green: return "green";
744 case ply::blue: return "blue";
745 case ply::alpha: return "alpha";
746 case ply::quality: return "quality";
747 case ply::texture_u: return "texture_u";
748 case ply::texture_v: return "texture_v";
749 case ply::texnumber: return "texnumber";
750 case ply::vertex_indices: return "vertex_indices";
751 case ply::texcoord: return "texcoord";
752 case ply::vertex1: return "vertex1";
753 case ply::vertex2: return "vertex2";
754 default: return "unknown";
755 }
756 }
757
758 std::string typeToString(ply::PropertyType t) const
759 {
760 switch (t) {
761 case ply::PropertyType::CHAR: return "char";
762 case ply::PropertyType::UCHAR: return "uchar";
763 case ply::PropertyType::SHORT: return "short";
764 case ply::PropertyType::USHORT: return "ushort";
765 case ply::PropertyType::INT: return "int";
766 case ply::PropertyType::UINT: return "uint";
767 case ply::PropertyType::FLOAT: return "float";
768 case ply::PropertyType::DOUBLE: return "double";
769 case ply::PropertyType::NONE: return "";
770 }
771 return "";
772 }
773};
774
775} // namespace vcl::detail
776
777#endif // VCL_IO_MESH_PLY_DETAIL_HEADER_H
PointT size() const
Computes the size of the box.
Definition box.h:267
static std::string fileNameWithoutExtension(const std::string &fullpath)
Get the file name without extension of a file.
Definition file_info.h:220
PrimitiveType DataType
Enum used to describe the type of Data stored in a component.
Definition mesh_info.h:113
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:48