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::texnumber: mod.setPerVertexMaterialIndex(); break;
208 case ply::unknown:
209 if (p.type <= ply::PropertyType::DOUBLE) {
210 mod.addPerVertexCustomComponent(
211 p.unknownPropertyName, (MeshInfo::DataType) p.type);
212 }
213 default: break;
214 }
215 }
216 }
217 if (mFaceElemPos != UINT_NULL) {
218 mod.setFaces();
219 for (const PlyProperty& p : mElements[mFaceElemPos].properties) {
220 switch (p.name) {
221 case ply::vertex_indices:
222 mod.setPerFaceVertexReferences();
223 break;
224 case ply::nx:
225 case ply::ny:
226 case ply::nz: mod.setPerFaceNormal(); break;
227 case ply::red:
228 case ply::green:
229 case ply::blue:
230 case ply::alpha: mod.setPerFaceColor(); break;
231 case ply::quality: mod.setPerFaceQuality(); break;
232 case ply::texnumber: mod.setPerFaceMaterialIndex(); break;
233 case ply::texcoord: mod.setPerFaceWedgeTexCoords(); break;
234 case ply::unknown:
235 if (p.type <= ply::PropertyType::DOUBLE) {
236 mod.addPerFaceCustomComponent(
237 p.unknownPropertyName, (MeshInfo::DataType) p.type);
238 }
239 default: break;
240 }
241 }
242 }
243 if (mTriStripElemPos != UINT_NULL) {
244 mod.setFaces();
245 for (const PlyProperty& p :
246 mElements[mTriStripElemPos].properties) {
247 switch (p.name) {
248 case ply::vertex_indices:
249 mod.setPerFaceVertexReferences();
250 break;
251 case ply::nx:
252 case ply::ny:
253 case ply::nz: mod.setPerFaceNormal(); break;
254 case ply::red:
255 case ply::green:
256 case ply::blue:
257 case ply::alpha: mod.setPerFaceColor(); break;
258 case ply::quality: mod.setPerFaceQuality(); break;
259 case ply::texcoord: mod.setPerFaceWedgeTexCoords(); break;
260 default: break;
261 }
262 }
263 }
264 if (mEdgeElemPos != UINT_NULL) {
265 mod.setEdges();
266 for (const PlyProperty& p : mElements[mEdgeElemPos].properties) {
267 switch (p.name) {
268 case ply::vertex_indices:
269 mod.setPerEdgeVertexReferences();
270 break;
271 case ply::nx:
272 case ply::ny:
273 case ply::nz: mod.setPerEdgeNormal(); break;
274 case ply::red:
275 case ply::green:
276 case ply::blue:
277 case ply::alpha: mod.setPerEdgeColor(); break;
278 case ply::quality: mod.setPerEdgeQuality(); break;
279 default: break;
280 }
281 }
282 }
283 if (mTextureFiles.size() > 0) {
284 mod.setMaterials();
285 }
286 return mod;
287 }
288
289 bool hasVertices() const { return mVertElemPos != UINT_NULL; }
290
291 bool hasFaces() const { return mFaceElemPos != UINT_NULL; }
292
293 bool hasEdges() const { return mEdgeElemPos != UINT_NULL; }
294
295 bool hasTriStrips() const { return mTriStripElemPos != UINT_NULL; }
296
297 bool hasTextureFileNames() const { return mTextureFiles.size() > 0; }
298
299 uint numberVertices() const
300 {
301 assert(hasVertices());
302 return mElements[mVertElemPos].numberElements;
303 }
304
305 uint numberFaces() const
306 {
307 assert(hasFaces());
308 return mElements[mFaceElemPos].numberElements;
309 }
310
311 uint numberEdges() const
312 {
313 assert(hasEdges());
314 return mElements[mEdgeElemPos].numberElements;
315 }
316
317 uint numberTriStrips() const
318 {
319 assert(hasTriStrips());
320 return mElements[mTriStripElemPos].numberElements;
321 }
322
323 uint numberTextureFileNames() const { return mTextureFiles.size(); }
324
325 const std::list<PlyProperty>& vertexProperties() const
326 {
327 assert(hasVertices());
328 return mElements[mVertElemPos].properties;
329 }
330
331 const std::list<PlyProperty>& faceProperties() const
332 {
333 assert(hasFaces());
334 return mElements[mFaceElemPos].properties;
335 }
336
337 const std::list<PlyProperty>& edgeProperties() const
338 {
339 assert(hasEdges());
340 return mElements[mEdgeElemPos].properties;
341 }
342
343 const std::list<PlyProperty>& triStripsProperties() const
344 {
345 assert(hasTriStrips());
346 return mElements[mTriStripElemPos].properties;
347 }
348
349 const std::vector<std::string>& textureFileNames() const
350 {
351 return mTextureFiles;
352 }
353
354 bool errorWhileLoading() const { return !mValid; }
355
356 void setNumberVertices(unsigned long int nV)
357 {
358 assert(hasVertices());
359 mElements[mVertElemPos].numberElements = nV;
360 }
361
362 void setNumberFaces(unsigned long int nF)
363 {
364 assert(hasFaces());
365 mElements[mFaceElemPos].numberElements = nF;
366 }
367
368 void setNumberEdges(unsigned long int nE)
369 {
370 assert(hasEdges());
371 mElements[mEdgeElemPos].numberElements = nE;
372 }
373
374 void pushTextureFileName(const std::string& tn)
375 {
376 mTextureFiles.push_back(tn);
377 }
378
379 void setInfo(
380 const MeshInfo& info,
381 std::vector<std::string> textureFileNames = std::vector<std::string>(),
382 ply::Format format = ply::BINARY_LITTLE_ENDIAN)
383 {
384 clear();
385 mFormat = format;
386 mValid = true;
387 mTextureFiles = textureFileNames;
388 if (info.hasVertices()) {
389 mVertElemPos = mElements.size();
390 PlyElement vElem;
391 vElem.type = ply::VERTEX;
392 if (info.hasPerVertexPosition()) {
393 PlyProperty px, py, pz;
394 px.name = ply::x;
395 px.type = info.perVertexPositionType();
396 py.name = ply::y;
397 py.type = info.perVertexPositionType();
398 pz.name = ply::z;
399 pz.type = info.perVertexPositionType();
400 vElem.properties.push_back(px);
401 vElem.properties.push_back(py);
402 vElem.properties.push_back(pz);
403 }
404 if (info.hasPerVertexNormal()) {
405 PlyProperty vnx, vny, vnz;
406 vnx.name = ply::nx;
407 vnx.type = info.perVertexNormalType();
408 vny.name = ply::ny;
409 vny.type = info.perVertexNormalType();
410 vnz.name = ply::nz;
411 vnz.type = info.perVertexNormalType();
412 vElem.properties.push_back(vnx);
413 vElem.properties.push_back(vny);
414 vElem.properties.push_back(vnz);
415 }
416 if (info.hasPerVertexColor()) {
417 PlyProperty vcr, vcg, vcb, vca;
418 vcr.name = ply::red;
419 vcr.type = info.perVertexColorType();
420 vcg.name = ply::green;
421 vcg.type = info.perVertexColorType();
422 vcb.name = ply::blue;
423 vcb.type = info.perVertexColorType();
424 vca.name = ply::alpha;
425 vca.type = info.perVertexColorType();
426 vElem.properties.push_back(vcr);
427 vElem.properties.push_back(vcg);
428 vElem.properties.push_back(vcb);
429 vElem.properties.push_back(vca);
430 }
431 if (info.hasPerVertexQuality()) {
432 PlyProperty vs;
433 vs.name = ply::quality;
434 vs.type = info.perVertexQualityType();
435 vElem.properties.push_back(vs);
436 }
437 if (info.hasPerVertexTexCoord()) {
438 PlyProperty tcu, tcv;
439 tcu.name = ply::texture_u;
440 tcu.type = info.perVertexTexCoordType();
441 tcv.name = ply::texture_v;
442 tcv.type = info.perVertexTexCoordType();
443 vElem.properties.push_back(tcu);
444 vElem.properties.push_back(tcv);
445 }
446 if (info.hasPerVertexMaterialIndex()) {
447 PlyProperty tcn;
448 tcn.name = ply::texnumber;
449 tcn.type = info.perVertexMaterialIndexType();
450 vElem.properties.push_back(tcn);
451 }
452 if (info.hasPerVertexCustomComponents()) {
453 for (const auto& cc : info.perVertexCustomComponents()) {
454 if (cc.type <= PrimitiveType::DOUBLE) {
455 PlyProperty pp;
456 pp.name = ply::unknown;
457 pp.unknownPropertyName = cc.name;
458 pp.type = cc.type;
459 vElem.properties.push_back(pp);
460 }
461 }
462 }
463 mElements.push_back(vElem);
464 }
465 if (info.hasFaces()) {
466 mFaceElemPos = mElements.size();
467 PlyElement fElem;
468 fElem.type = ply::FACE;
469 if (info.hasPerFaceVertexReferences()) {
470 PlyProperty vids;
471 vids.list = true;
472 vids.name = ply::vertex_indices;
473 vids.type = PrimitiveType::UINT;
474 vids.listSizeType = PrimitiveType::UCHAR;
475 fElem.properties.push_back(vids);
476 }
477 if (info.hasPerFaceNormal()) {
478 PlyProperty fnx, fny, fnz;
479 fnx.name = ply::nx;
480 fnx.type = info.perFaceNormalType();
481 fny.name = ply::ny;
482 fny.type = info.perFaceNormalType();
483 fnz.name = ply::nz;
484 fnz.type = info.perFaceNormalType();
485 fElem.properties.push_back(fnx);
486 fElem.properties.push_back(fny);
487 fElem.properties.push_back(fnz);
488 }
489 if (info.hasPerFaceColor()) {
490 PlyProperty fcr, fcg, fcb, fca;
491 fcr.name = ply::red;
492 fcr.type = info.perFaceColorType();
493 fcg.name = ply::green;
494 fcg.type = info.perFaceColorType();
495 fcb.name = ply::blue;
496 fcb.type = info.perFaceColorType();
497 fca.name = ply::alpha;
498 fca.type = info.perFaceColorType();
499 fElem.properties.push_back(fcr);
500 fElem.properties.push_back(fcg);
501 fElem.properties.push_back(fcb);
502 fElem.properties.push_back(fca);
503 }
504 if (info.hasPerFaceQuality()) {
505 PlyProperty fs;
506 fs.name = ply::quality;
507 fs.type = info.perFaceQualityType();
508 fElem.properties.push_back(fs);
509 }
510 if (info.hasPerFaceWedgeTexCoords()) {
511 PlyProperty tc;
512 tc.list = true;
513 tc.listSizeType = PrimitiveType::UCHAR;
514 tc.name = ply::texcoord;
515 tc.type = info.perFaceWedgeTexCoordsType();
516 fElem.properties.push_back(tc);
517 }
518 if (info.hasPerFaceMaterialIndex()) {
519 PlyProperty tn;
520 tn.name = ply::texnumber;
521 tn.type = info.perFaceMaterialIndexType();
522 fElem.properties.push_back(tn);
523 }
524 if (info.hasPerFaceCustomComponents()) {
525 for (const auto& cc : info.perFaceCustomComponents()) {
526 if (cc.type <= PrimitiveType::DOUBLE) {
527 PlyProperty pp;
528 pp.name = ply::unknown;
529 pp.unknownPropertyName = cc.name;
530 pp.type = cc.type;
531 fElem.properties.push_back(pp);
532 }
533 }
534 }
535 mElements.push_back(fElem);
536 }
537 if (info.hasEdges()) {
538 mEdgeElemPos = mElements.size();
539 PlyElement eElem;
540 eElem.type = ply::EDGE;
541 if (info.hasPerEdgeVertexReferences()) {
542 PlyProperty v1;
543 v1.name = ply::vertex1;
544 v1.type = PrimitiveType::UINT;
545 eElem.properties.push_back(v1);
546 PlyProperty v2;
547 v2.name = ply::vertex2;
548 v2.type = PrimitiveType::UINT;
549 eElem.properties.push_back(v2);
550 }
551 mElements.push_back(eElem);
552 }
553 }
554
555 std::string toString() const
556 {
557 std::string s;
558
559 s += "ply\nformat ";
560
561 switch (mFormat) {
562 case ply::ASCII: s += "ascii 1.0\n"; break;
563 case ply::BINARY_BIG_ENDIAN: s += "binary_big_endian 1.0\n"; break;
564 default: s += "binary_little_endian 1.0\n"; break;
565 }
566
567 s += "comment Generated by vclib\n";
568 for (const std::string& str : mTextureFiles) {
569 s += "comment TextureFile " + str + "\n";
570 }
571 for (const PlyElement& e : mElements) {
572 s += "element ";
573 switch (e.type) {
574 case ply::VERTEX:
575 s += "vertex " + std::to_string(e.numberElements) + "\n";
576 break;
577 case ply::FACE:
578 s += "face " + std::to_string(e.numberElements) + "\n";
579 break;
580 case ply::EDGE:
581 s += "edge " + std::to_string(e.numberElements) + "\n";
582 break;
583 case ply::TRISTRIP:
584 s += "tristrips " + std::to_string(e.numberElements) + "\n";
585 break;
586 case ply::MATERIAL:
587 s += "material " + std::to_string(e.numberElements) + "\n";
588 break;
589 case ply::OTHER:
590 s += e.unknownElementType + " " +
591 std::to_string(e.numberElements) + "\n";
592 break;
593 }
594 for (const PlyProperty& p : e.properties) {
595 s += "property ";
596 if (p.list) {
597 s += "list ";
598 s += typeToString(p.listSizeType) + " ";
599 }
600 s += typeToString(p.type) + " ";
601 if (p.name == ply::unknown)
602 s += p.unknownPropertyName + "\n";
603 else
604 s += nameToString(p.name) + "\n";
605 }
606 }
607 s += "end_header\n";
608
609 return s;
610 }
611
612 void setFormat(ply::Format f) { mFormat = f; }
613
614 iterator begin() const { return mElements.begin(); }
615
616 iterator end() const { return mElements.end(); }
617
618private:
619 PlyElement readElement(const Tokenizer& lineTokenizer) const
620 {
621 PlyElement e;
622 Tokenizer::iterator token = lineTokenizer.begin();
623 std::string s = *(++token);
624 if (s == "vertex") {
625 e.type = ply::VERTEX;
626 e.numberElements = std::stoi(*(++token));
627 }
628 else if (s == "face") {
629 e.type = ply::FACE;
630 e.numberElements = std::stoi(*(++token));
631 }
632 else if (s == "edge") {
633 e.type = ply::EDGE;
634 e.numberElements = std::stoi(*(++token));
635 }
636 else if (s == "tristrips") {
637 e.type = ply::TRISTRIP;
638 e.numberElements = std::stoi(*(++token));
639 }
640 else {
641 e.type = ply::OTHER;
642 e.numberElements = std::stoi(*(++token));
643 e.unknownElementType = s;
644 }
645 return e;
646 }
647
648 PlyProperty readProperty(const Tokenizer& lineTokenizer) const
649 {
650 PlyProperty p;
651 Tokenizer::iterator token = lineTokenizer.begin();
652 std::string type = *(++token);
653 if (type == "list") {
654 p.list = true;
655 std::string typeSize = *(++token);
656 std::string typeData = *(++token);
657 std::string name = *(++token);
658 p.listSizeType = stringToType(typeSize);
659 p.type = stringToType(typeData);
660 p.name = stringToName(name);
661 if (p.name == ply::unknown)
662 p.unknownPropertyName = name;
663 }
664 else {
665 p.list = false;
666 std::string name = *(++token);
667 p.type = stringToType(type);
668 p.name = stringToName(name);
669 if (p.name == ply::unknown)
670 p.unknownPropertyName = name;
671 }
672
673 return p;
674 }
675
676 ply::PropertyName stringToName(const std::string& name) const
677 {
678 ply::PropertyName pn = ply::unknown;
679 if (name == "x")
680 pn = ply::x;
681 if (name == "y")
682 pn = ply::y;
683 if (name == "z")
684 pn = ply::z;
685 if (name == "nx")
686 pn = ply::nx;
687 if (name == "ny")
688 pn = ply::ny;
689 if (name == "nz")
690 pn = ply::nz;
691 if (name == "red")
692 pn = ply::red;
693 if (name == "green")
694 pn = ply::green;
695 if (name == "blue")
696 pn = ply::blue;
697 if (name == "alpha")
698 pn = ply::alpha;
699 if (name == "quality" || name == "scalar")
700 pn = ply::quality;
701 if (name == "texture_u" || name == "s" || name == "u")
702 pn = ply::texture_u;
703 if (name == "texture_v" || name == "t" || name == "v")
704 pn = ply::texture_v;
705 if (name == "texnumber")
706 pn = ply::texnumber;
707 if (name == "vertex_indices")
708 pn = ply::vertex_indices;
709 if (name == "texcoord")
710 pn = ply::texcoord;
711 if (name == "vertex1")
712 pn = ply::vertex1;
713 if (name == "vertex2")
714 pn = ply::vertex2;
715
716 return pn;
717 }
718
719 ply::PropertyType stringToType(const std::string& type) const
720 {
721 ply::PropertyType pt = ply::PropertyType::UCHAR;
722 if (type == "char")
723 pt = ply::PropertyType::CHAR;
724 if (type == "uchar")
725 pt = ply::PropertyType::UCHAR;
726 if (type == "short")
727 pt = ply::PropertyType::SHORT;
728 if (type == "ushort")
729 pt = ply::PropertyType::USHORT;
730 if (type == "int")
731 pt = ply::PropertyType::INT;
732 if (type == "uint")
733 pt = ply::PropertyType::UINT;
734 if (type == "float")
735 pt = ply::PropertyType::FLOAT;
736 if (type == "double")
737 pt = ply::PropertyType::DOUBLE;
738 return pt;
739 }
740
741 std::string nameToString(ply::PropertyName n) const
742 {
743 switch (n) {
744 case ply::x: return "x";
745 case ply::y: return "y";
746 case ply::z: return "z";
747 case ply::nx: return "nx";
748 case ply::ny: return "ny";
749 case ply::nz: return "nz";
750 case ply::red: return "red";
751 case ply::green: return "green";
752 case ply::blue: return "blue";
753 case ply::alpha: return "alpha";
754 case ply::quality: return "quality";
755 case ply::texture_u: return "texture_u";
756 case ply::texture_v: return "texture_v";
757 case ply::texnumber: return "texnumber";
758 case ply::vertex_indices: return "vertex_indices";
759 case ply::texcoord: return "texcoord";
760 case ply::vertex1: return "vertex1";
761 case ply::vertex2: return "vertex2";
762 default: return "unknown";
763 }
764 }
765
766 std::string typeToString(ply::PropertyType t) const
767 {
768 switch (t) {
769 case ply::PropertyType::CHAR: return "char";
770 case ply::PropertyType::UCHAR: return "uchar";
771 case ply::PropertyType::SHORT: return "short";
772 case ply::PropertyType::USHORT: return "ushort";
773 case ply::PropertyType::INT: return "int";
774 case ply::PropertyType::UINT: return "uint";
775 case ply::PropertyType::FLOAT: return "float";
776 case ply::PropertyType::DOUBLE: return "double";
777 case ply::PropertyType::NONE: return "";
778 }
779 return "";
780 }
781};
782
783} // namespace vcl::detail
784
785#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:114
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