forked from KeckCAVES/LidarViewer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ReadPlyFile.cpp
892 lines (805 loc) · 22.2 KB
/
ReadPlyFile.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
/***********************************************************************
ReadPlyFile - Function to read 3D polygon files in PLY format.
Copyright (c) 2004-2011 Oliver Kreylos
This file is part of the LiDAR processing and analysis package.
The LiDAR processing and analysis package is free software; you can
redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
The LiDAR processing and analysis package is distributed in the hope
that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with the LiDAR processing and analysis package; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
***********************************************************************/
#include "ReadPlyFile.h"
#include <string.h>
#include <string>
#include <vector>
#include <iostream>
#include <Misc/SelfDestructPointer.h>
#include <Misc/ThrowStdErr.h>
#include <IO/File.h>
#include <IO/OpenFile.h>
#include <IO/ValueSource.h>
#include "LidarTypes.h"
#include "PointAccumulator.h"
namespace {
/*********************************************
Enumerated type for basic PLY file data types:
*********************************************/
enum DataType
{
CHAR,UCHAR,SHORT,USHORT,INT,UINT,FLOAT,DOUBLE
};
/******************************************************
Templatized class to define PLY file value type traits:
******************************************************/
template <int dataTypeParam>
class DataValueTypes
{
};
template <>
class DataValueTypes<CHAR>
{
/* Embedded classes: */
public:
static const int dataType=CHAR;
typedef char FileType;
typedef int MemoryType;
};
template <>
class DataValueTypes<UCHAR>
{
/* Embedded classes: */
public:
static const int dataType=UCHAR;
typedef unsigned char FileType;
typedef unsigned int MemoryType;
};
template <>
class DataValueTypes<SHORT>
{
/* Embedded classes: */
public:
static const int dataType=SHORT;
typedef short FileType;
typedef int MemoryType;
};
template <>
class DataValueTypes<USHORT>
{
/* Embedded classes: */
public:
static const int dataType=USHORT;
typedef unsigned short FileType;
typedef unsigned int MemoryType;
};
template <>
class DataValueTypes<INT>
{
/* Embedded classes: */
public:
static const int dataType=INT;
typedef int FileType;
typedef int MemoryType;
};
template <>
class DataValueTypes<UINT>
{
/* Embedded classes: */
public:
static const int dataType=UINT;
typedef unsigned int FileType;
typedef unsigned int MemoryType;
};
template <>
class DataValueTypes<FLOAT>
{
/* Embedded classes: */
public:
static const int dataType=FLOAT;
typedef float FileType;
typedef double MemoryType;
};
template <>
class DataValueTypes<DOUBLE>
{
/* Embedded classes: */
public:
static const int dataType=DOUBLE;
typedef double FileType;
typedef double MemoryType;
};
/************************************************************
Templatized helper class to read values from ASCII PLY files:
************************************************************/
template <typename MemoryTypeParam>
class AsciiFileReader
{
};
template <>
class AsciiFileReader<int>
{
/* Methods: */
public:
static int readValue(IO::ValueSource& asciiFile)
{
return asciiFile.readInteger();
}
};
template <>
class AsciiFileReader<unsigned int>
{
/* Methods: */
public:
static unsigned int readValue(IO::ValueSource& asciiFile)
{
return asciiFile.readUnsignedInteger();
}
};
template <>
class AsciiFileReader<double>
{
/* Methods: */
public:
static double readValue(IO::ValueSource& asciiFile)
{
return asciiFile.readNumber();
}
};
/**********************************************
Base class for data values read from PLY files:
**********************************************/
class DataValue
{
/* Constructors and destructors: */
public:
virtual ~DataValue(void)
{
}
/* Methods: */
virtual DataValue* clone(void) const =0;
virtual size_t getFileSize(void) const =0;
virtual size_t getMemorySize(void) const =0;
virtual void read(IO::File& binaryPlyFile) =0;
virtual void read(IO::ValueSource& asciiPlyFile) =0;
virtual int getInt(void) const =0;
virtual unsigned int getUnsignedInt(void) const =0;
virtual double getDouble(void) const =0;
};
/*****************************************************
Templatized class for data values read from PLY files:
*****************************************************/
template <int dataTypeParam>
class DataValueTemplate:public DataValue,public DataValueTypes<dataTypeParam>
{
/* Embedded classes: */
public:
typedef DataValue Base1;
typedef DataValueTypes<dataTypeParam> Base2;
/* Elements: */
private:
typename Base2::MemoryType value; // Data value
/* Methods: */
virtual DataValue* clone(void) const
{
return new DataValueTemplate(*this);
}
virtual size_t getFileSize(void) const
{
return sizeof(typename Base2::FileType);
}
virtual size_t getMemorySize(void) const
{
return sizeof(typename Base2::MemoryType);
}
virtual void read(IO::File& binaryPlyFile)
{
value=typename Base2::MemoryType(binaryPlyFile.read<typename Base2::FileType>());
}
virtual void read(IO::ValueSource& asciiPlyFile)
{
value=AsciiFileReader<typename Base2::MemoryType>::readValue(asciiPlyFile);
}
virtual int getInt(void) const
{
return int(value);
}
virtual unsigned int getUnsignedInt(void) const
{
return (unsigned int)(value);
}
virtual double getDouble(void) const
{
return double(value);
}
};
/******************************************
Factory class to create data value readers:
******************************************/
class DataValueFactory
{
/* Methods: */
public:
static DataValue* newDataValue(DataType dataType)
{
switch(dataType)
{
case CHAR:
return new DataValueTemplate<CHAR>;
case UCHAR:
return new DataValueTemplate<UCHAR>;
case SHORT:
return new DataValueTemplate<SHORT>;
case USHORT:
return new DataValueTemplate<USHORT>;
case INT:
return new DataValueTemplate<INT>;
case UINT:
return new DataValueTemplate<UINT>;
case FLOAT:
return new DataValueTemplate<FLOAT>;
case DOUBLE:
return new DataValueTemplate<DOUBLE>;
}
}
};
/*****************************
Class for PLY file properties:
*****************************/
class Property
{
/* Embedded classes: */
public:
enum PropertyType
{
SCALAR,LIST
};
class Value
{
/* Elements: */
private:
PropertyType propertyType; // Type of the value's property
DataValue* scalar; // Pointer to scalar value for scalar properties
DataValue* listSize; // List size value for list properties
std::vector<DataValue*> listElements; // Vector of pointers to list elements for list properties
/* Constructors and destructors: */
public:
Value(const Property& property) // Creates empty value structure for the given property
:propertyType(property.getPropertyType()),
scalar(0),
listSize(0)
{
if(propertyType==Property::SCALAR)
{
/* Allocate space for scalar: */
scalar=DataValueFactory::newDataValue(property.getScalarType());
}
else
{
/* Allocate space for list size: */
listSize=DataValueFactory::newDataValue(property.getListSizeType());
/* Create one list element to get started: */
listElements.push_back(DataValueFactory::newDataValue(property.getListElementType()));
}
}
private:
Value(const Value& source); // Prohibit copy constructor
Value& operator=(const Value& source); // Prohibit assignment operator
public:
~Value(void)
{
delete scalar;
delete listSize;
for(std::vector<DataValue*>::iterator eIt=listElements.begin();eIt!=listElements.end();++eIt)
delete *eIt;
}
/* Methods: */
size_t getFileSize(void) const // Returns value's size in binary files (returns minimal file size for list values)
{
if(propertyType==SCALAR)
return scalar->getFileSize();
else
return listSize->getFileSize();
}
void skip(IO::ValueSource& plyFile) // Skips value from ASCII PLY file (never used)
{
if(propertyType==Property::SCALAR)
{
/* Skip scalar: */
scalar->read(plyFile);
}
else
{
/* Read list size: */
listSize->read(plyFile);
unsigned int listSizeValue=listSize->getUnsignedInt();
/* Skip all list elements: */
for(unsigned int i=0;i<listSizeValue;++i)
listElements[0]->read(plyFile);
}
}
void skip(IO::File& plyFile) // Skips value from binary PLY file
{
if(propertyType==Property::SCALAR)
{
/* Skip scalar: */
plyFile.skip<char>(scalar->getFileSize());
}
else
{
/* Read list size: */
listSize->read(plyFile);
unsigned int listSizeValue=listSize->getUnsignedInt();
/* Skip all list elements: */
plyFile.skip<char>(listElements[0]->getFileSize()*listSizeValue);
}
}
template <class PlyFileParam>
void read(PlyFileParam& plyFile) // Reads value from binary or ASCII PLY file
{
if(propertyType==Property::SCALAR)
{
/* Read scalar: */
scalar->read(plyFile);
}
else
{
/* Read list size: */
listSize->read(plyFile);
unsigned int listSizeValue=listSize->getUnsignedInt();
/* Ensure the list storage is long enough: */
unsigned int currentListSize=listElements.size();
while(currentListSize<listSizeValue)
{
listElements.push_back(listElements[0]->clone());
++currentListSize;
}
/* Read all list elements: */
for(unsigned int i=0;i<listSizeValue;++i)
listElements[i]->read(plyFile);
}
}
const DataValue* getScalar(void) const
{
return scalar;
}
const DataValue* getListSize(void) const
{
return listSize;
}
const DataValue* getListElement(unsigned int listElementIndex) const
{
return listElements[listElementIndex];
}
};
/* Elements: */
private:
PropertyType propertyType; // Type of this property (scalar/list)
DataType scalarType; // Data type for scalar properties
DataType listSizeType; // Data type for list sizes for list properties
DataType listElementType; // Data type for list elements for list properties
std::string name; // Property name
/* Private methods: */
static DataType parseDataType(const std::string& tag)
{
static const char* dataTypeTags[]={"char","uchar","short","ushort","int","uint","float","double"};
static const DataType dataTypes[]={CHAR,UCHAR,SHORT,USHORT,INT,UINT,FLOAT,DOUBLE};
int i;
for(i=0;i<8;++i)
if(tag==dataTypeTags[i])
break;
if(i>=8)
Misc::throwStdErr("Unknown data type %s",tag.c_str());
return dataTypes[i];
}
/* Constructors and destructors: */
public:
Property(IO::ValueSource& plyFile)
{
/* Read the property type: */
std::string tag=plyFile.readString();
if(tag=="list")
{
/* Parse a list property: */
propertyType=LIST;
listSizeType=parseDataType(plyFile.readString());
listElementType=parseDataType(plyFile.readString());
}
else
{
/* Parse a scalar property: */
propertyType=SCALAR;
scalarType=parseDataType(tag);
}
/* Read the property name: */
name=plyFile.readLine();
plyFile.skipWs();
}
/* Methods: */
PropertyType getPropertyType(void) const // Returns property's type
{
return propertyType;
}
DataType getScalarType(void) const // Returns scalar property's scalar type
{
return scalarType;
}
DataType getListSizeType(void) const // Returns list property's size type
{
return listSizeType;
}
DataType getListElementType(void) const // Returns list property's element type
{
return listElementType;
}
std::string getName(void) const // Returns property's name
{
return name;
}
};
/***************************
Class for PLY file elements:
***************************/
class Element
{
/* Embedded classes: */
public:
typedef std::vector<Property> PropertyList;
class Value
{
/* Embedded classes: */
public:
typedef std::vector<Property::Value*> PropertyValueList;
/* Elements: */
private:
const Element& element; // Pointer to element definition for this value
PropertyValueList propertyValues; // Vector of values for the properties of this element
/* Constructors and destructors: */
public:
Value(const Element& sElement)
:element(sElement)
{
/* Initialize vector of property values: */
for(PropertyList::const_iterator plIt=element.propertiesBegin();plIt!=element.propertiesEnd();++plIt)
propertyValues.push_back(new Property::Value(*plIt));
}
private:
Value(const Value& source); // Prohibit copy constructor
Value& operator=(const Value& source); // Prohibit assignment operator
public:
~Value(void)
{
/* Destroy vector of property values: */
for(PropertyValueList::iterator pvIt=propertyValues.begin();pvIt!=propertyValues.end();++pvIt)
delete *pvIt;
}
/* Methods: */
public:
size_t getFileSize(void) const // Returns the total file size of all property values (returns minimal file size for any included list values)
{
size_t result=0;
for(PropertyValueList::const_iterator pvIt=propertyValues.begin();pvIt!=propertyValues.end();++pvIt)
result+=(*pvIt)->getFileSize();
return result;
}
template <class PlyFileParam>
void skip(PlyFileParam& plyFile) // Skips element value from binary or ASCII PLY file
{
for(PropertyValueList::iterator pvIt=propertyValues.begin();pvIt!=propertyValues.end();++pvIt)
(*pvIt)->skip(plyFile);
}
template <class PlyFileParam>
void read(PlyFileParam& plyFile) // Reads element value from binary or ASCII PLY file
{
for(PropertyValueList::iterator pvIt=propertyValues.begin();pvIt!=propertyValues.end();++pvIt)
(*pvIt)->read(plyFile);
}
const Property::Value& getValue(unsigned int propertyIndex) const // Returns value of one of the element's properties
{
return *propertyValues[propertyIndex];
}
};
/* Elements: */
private:
std::string name; // Name of this element
size_t numValues; // Number of values of this element in the file
PropertyList properties; // Vector of properties of this element
/* Constructors and destructors: */
public:
Element(std::string sName,size_t sNumValues)
:name(sName),numValues(sNumValues)
{
}
/* Methods: */
bool isElement(const char* elementName) const // Returns true if the element's name matches the given string
{
return name==elementName;
}
size_t getNumValues(void) const
{
return numValues;
}
void addProperty(IO::ValueSource& plyFile)
{
properties.push_back(Property(plyFile));
}
bool hasListProperty(void) const // Returns true if the element has at least one list property
{
bool result=false;
for(PropertyList::const_iterator pIt=properties.begin();!result&&pIt!=properties.end();++pIt,++result)
result=pIt->getPropertyType()==Property::LIST;
return result;
}
size_t getNumProperties(void) const
{
return properties.size();
}
PropertyList::const_iterator propertiesBegin(void) const
{
return properties.begin();
}
PropertyList::const_iterator propertiesEnd(void) const
{
return properties.end();
}
unsigned int getPropertyIndex(const char* propertyName) const
{
unsigned int result=0;
for(PropertyList::const_iterator pIt=properties.begin();pIt!=properties.end();++pIt,++result)
if(pIt->getName()==propertyName)
break;
return result;
}
};
/**************************************
Helper class to parse PLY file headers:
**************************************/
struct PlyFileHeader // Structure containing relevant information from a PLY file's header
{
/* Embedded classes: */
public:
enum FileType
{
Unknown,Ascii,Binary
};
/* Elements: */
private:
bool valid; // Flag if the file is a valid PLY file (as much as determined by parsing the header)
FileType fileType; // ASCII or binary
Misc::Endianness fileEndianness; // Endianness of binary PLY file
std::vector<Element> elements; // List of elements in the file, in the order in which they appear in the file
/* Constructors and destructors: */
public:
PlyFileHeader(void)
:valid(false),fileType(Unknown),fileEndianness(Misc::HostEndianness)
{
}
PlyFileHeader(IO::File& plyFile)
:valid(false),fileType(Unknown),fileEndianness(Misc::HostEndianness)
{
parseHeader(plyFile);
}
/* Methods: */
bool parseHeader(IO::File& plyFile) // Creates header structure by parsing a PLY file's header
{
/* Attach a new value source to the PLY file: */
IO::ValueSource ply(&plyFile);
ply.skipWs();
/* Process the PLY file header: */
std::vector<Element>::iterator currentElement=elements.end();
bool isPly=false;
bool haveEndHeader=false;
while(!ply.eof())
{
/* Read the next tag: */
std::string tag=ply.readString();
if(tag=="ply")
isPly=true;
else if(tag=="format")
{
/* Read the format type and version number: */
std::string format=ply.readString();
if(format=="ascii")
fileType=Ascii;
else if(format=="binary_little_endian")
{
fileType=Binary;
fileEndianness=Misc::LittleEndian;
}
else if(format=="binary_big_endian")
{
fileType=Binary;
fileEndianness=Misc::BigEndian;
}
else
{
/* Unknown format; bail out: */
break;
}
double version=ply.readNumber();
if(version!=1.0)
break;
}
else if(tag=="comment")
{
/* Skip the rest of the line: */
ply.skipLine();
ply.skipWs();
}
else if(tag=="element")
{
/* Read the element type and number of elements: */
std::string elementType=ply.readString();
size_t numElements=ply.readUnsignedInteger();
/* Append a new element: */
elements.push_back(Element(elementType,numElements));
currentElement=elements.end()-1;
}
else if(tag=="property")
{
if(currentElement!=elements.end())
{
/* Parse a property: */
currentElement->addProperty(ply);
}
else
{
/* Skip the property: */
ply.skipLine();
ply.skipWs();
}
}
else if(tag=="end_header")
{
haveEndHeader=true;
break;
}
else
{
/* Skip the unknown tag: */
ply.skipLine();
ply.skipWs();
}
}
/* Check if the header was read completely: */
valid=isPly&&haveEndHeader&&fileType!=Unknown;
return valid;
}
bool isValid(void) const // Returns true if the header described a valid PLY file
{
return valid;
}
FileType getFileType(void) const // Returns the file's type
{
return fileType;
}
Misc::Endianness getFileEndianness(void) const // Returns the endianness for binary PLY files
{
return fileEndianness;
}
size_t getNumElements(void) const // Returns the number of elements in the PLY file
{
return elements.size();
}
const Element& getElement(size_t index) const // Returns the element of the given index
{
return elements[index];
}
};
template <class PlyFileParam>
void readPlyFileVertices(const Element& vertex,PlyFileParam& ply,PointAccumulator& pa)
{
/* Get the indices of all relevant vertex value components: */
unsigned int posIndex[3];
posIndex[0]=vertex.getPropertyIndex("x");
posIndex[1]=vertex.getPropertyIndex("y");
posIndex[2]=vertex.getPropertyIndex("z");
unsigned int colIndex[3];
colIndex[0]=vertex.getPropertyIndex("red");
colIndex[1]=vertex.getPropertyIndex("green");
colIndex[2]=vertex.getPropertyIndex("blue");
bool hasColor=colIndex[0]<vertex.getNumProperties()&&colIndex[1]<vertex.getNumProperties()&&colIndex[2]<vertex.getNumProperties();
/* Read all vertices: */
Element::Value vertexValue(vertex);
for(unsigned int i=0;i<vertex.getNumValues();++i)
{
/* Read vertex element from file: */
vertexValue.read(ply);
/* Extract vertex coordinates from vertex element: */
PointAccumulator::Point p;
for(int j=0;j<3;++j)
p[j]=vertexValue.getValue(posIndex[j]).getScalar()->getDouble();
/* Extract vertex color from vertex element: */
PointAccumulator::Color c;
if(hasColor)
{
for(int j=0;j<3;++j)
c[j]=float(vertexValue.getValue(colIndex[j]).getScalar()->getDouble());
}
else
{
for(int j=0;j<3;++j)
c[j]=255.0f;
}
/* Store the point: */
pa.addPoint(p,c);
}
}
void skipElement(const Element& element,IO::File& ply)
{
/* Check if the element has variable size: */
Element::Value value(element);
if(element.hasListProperty())
{
/* Need to skip each value separately: */
for(size_t i=0;i<element.getNumValues();++i)
value.skip(ply);
}
else
{
/* Calculate the file size of each value of the element: */
size_t valueSize=value.getFileSize();
ply.skip<char>(valueSize*element.getNumValues());
}
}
void skipElement(const Element& element,IO::ValueSource& ply)
{
/* Skip one line for each value of the element: */
for(size_t i=0;i<element.getNumValues();++i)
ply.skipLine();
ply.skipWs();
}
template <class PlyFileParam>
void readPlyFileElements(const PlyFileHeader& header,PlyFileParam& ply,PointAccumulator& pa)
{
/* Process all elements in order: */
for(size_t elementIndex=0;elementIndex<header.getNumElements();++elementIndex)
{
/* Get the next element: */
const Element& element=header.getElement(elementIndex);
/* Check if it's the vertex element: */
if(element.isElement("vertex"))
{
/* Read the vertex element: */
readPlyFileVertices(element,ply,pa);
}
else
{
/* Skip the entire element: */
skipElement(element,ply);
}
}
}
}
void readPlyFile(PointAccumulator& pa,const char* fileName)
{
/* Open the PLY file: */
IO::FilePtr plyFile(IO::openFile(fileName));
/* Read the PLY file's header: */
PlyFileHeader header(*plyFile);
if(!header.isValid())
{
std::cerr<<"Error: File "<<fileName<<" is not a valid PLY file"<<std::endl;
return;
}
/* Read the PLY file in ASCII or binary mode: */
if(header.getFileType()==PlyFileHeader::Ascii)
{
/* Attach a value source to the PLY file: */
IO::ValueSource ply(plyFile);
/* Read the PLY file in ASCII mode: */
readPlyFileElements(header,ply,pa);
}
else if(header.getFileType()==PlyFileHeader::Binary)
{
/* Set the PLY file's endianness: */
plyFile->setEndianness(header.getFileEndianness());
/* Read the PLY file in binary mode: */
readPlyFileElements(header,*plyFile,pa);
}
}