Super4PCS Library  V1.1.2(719f5c0)
io_ply.h
1 #ifndef _SUPER4PCS_IO_PLY_H
2 #define _SUPER4PCS_IO_PLY_H
3 
4 #include <cstdarg>
5 
6 typedef enum {
7  BINARY_BIG_ENDIAN_1,
8  BINARY_LITTLE_ENDIAN_1,
9  ASCII_1
10 } PLYFormat;
11 
12 static const unsigned int MAX_COMMENT_SIZE = 256;
13 
14 
15 unsigned int
16 readHeader ( const char *filename,
17  unsigned int & numOfVertices,
18  unsigned int & numOfFaces,
19  PLYFormat & format,
20  unsigned int & numOfVertexProperties,
21  bool & haveColor )
22 {
23  using namespace std;
24 
25  // use binary mode to preserve end line symbols on linux and windows
26  ifstream in (filename, std::ios_base::in | std::ios_base::binary);
27  if (!in){
28  cerr << "(PLY) error opening file" << endl;
29  return 0;
30  }
31 
32  numOfVertexProperties = 0;
33  numOfVertices = 0;
34  numOfFaces = 0;
35  haveColor = false;
36 
37  string current, currentelement;
38  in >> current;
39  if (current != "ply"){
40  cerr << "(PLY) not a PLY file" << endl;
41  return 0;
42  }
43  in >> current;
44  int lid = 0;
45  while (current != "end_header") {
46  if (current == "format") {
47  in >> current;
48  if (current == "binary_big_endian") {
49  in >> current;
50  if (current == "1.0")
51  format = BINARY_BIG_ENDIAN_1;
52  else{
53  cerr << "(PLY) error parsing header - bad binary big endian version" << endl;
54  return 0;
55  }
56  } else if (current == "binary_little_endian") {
57  in >> current;
58  if (current == "1.0")
59  format = BINARY_LITTLE_ENDIAN_1;
60  else{
61  cerr << "(PLY) error parsing header - bad binary little endian version" << endl;
62  return 0;
63  }
64  } else if (current == "ascii") {
65  in >> current;
66  if (current == "1.0")
67  format = ASCII_1;
68  else{
69  cerr << "(PLY) error parsing header - bad ascii version" << endl;
70  return 0;
71  }
72  } else {
73  cerr << "(PLY) error parsing header (format)" << endl;
74  return 0;
75  }
76  } else if (current == "element") {
77  in >> current;
78  if (current == "vertex"){
79  currentelement = current;
80  in >> numOfVertices;
81  }
82  else if (current == "face"){
83  currentelement = current;
84  in >> numOfFaces;
85  }
86  else{
87  cerr << "(PLY) ignoring unknown element " << current << endl;
88  currentelement = "";
89  }
90  } else if (currentelement != "" && current == "property") {
91  in >> current;
92  if (current == "float" || current == "double") {
93  numOfVertexProperties++;
94  in >> current;
95  }
96  else if (current == "uchar") { // color
97  numOfVertexProperties++;
98  haveColor = true;
99  in >> current;
100  }
101  else if (current == "list") {
102  in >> current;
103  in >> current;
104  in >> current;
105  } else {
106  cerr << "(PLY) error parsing header (property)" << endl;
107  return 0;
108  }
109  } else if ( (current == "comment") || (current.find("obj_info") != std::string::npos) ) {
110  char comment[MAX_COMMENT_SIZE];
111  in.getline (comment, MAX_COMMENT_SIZE);
112  } else {
113  ;
114  //cerr << "(PLY) ignoring line: " << current << endl;
115  //return 0;
116  }
117  in >> current;
118  lid++;
119  }
120 
121  unsigned int headerSize = in.tellg ();
122  in.close ();
123  return headerSize+1;
124 }
125 
126 
127 template <class T>
128 void
129 bigLittleEndianSwap (T * v, unsigned int numOfElements)
130 {
131  char * tmp = (char*)v;
132  for (unsigned int j = 0; j < numOfElements; j++){
133  unsigned int offset = 4*j;
134  char c = tmp[offset];
135  tmp[offset] = tmp[offset+3];
136  tmp[offset+3] = c;
137  c = tmp[offset+1];
138  tmp[offset+1] = tmp[offset+2];
139  tmp[offset+2] = c;
140  }
141 }
142 
143 inline bool
144 almostsafefread ( void * ptr, size_t size, size_t count, FILE * stream ){
145  size_t result = fread (ptr,size,count,stream);
146  return (result == count);
147 }
148 
149 template<int targetCount, typename... Args>
150 inline bool
151 almostsafefscanf ( FILE * stream, const char * format, Args&&... args ){
152  int count = fscanf (stream,format, std::forward<Args>(args)...);
153  return (count == targetCount);
154 }
155 
156 
157 bool
158 readBinary1Body (const std::string & filename,
159  unsigned int headerSize,
160  unsigned int numOfVertices,
161  unsigned int numOfFaces,
162  unsigned int numOfVertexProperties,
163  bool haveColor,
164  bool bigEndian,
165  std::vector<GlobalRegistration::Point3D>& vertex,
166  std::vector<typename GlobalRegistration::Point3D::VectorType>& normal,
167  std::vector<tripple>& face )
168 {
169  using namespace std;
170  using namespace GlobalRegistration;
171 
172  FILE * in = fopen (filename.c_str (), "r");
173  if (!in){
174  cerr << "(PLY) error opening file" << endl;
175  return false;
176  }
177 
178  char c;
179  for (unsigned int i = 0; i < headerSize; i++) {
180  almostsafefread (&c, 1, 1, in);
181  }
182 
183  // *****************
184  // Reading geometry.
185  // *****************
186  typename Point3D::VectorType n;
187  typename Point3D::VectorType rgb;
188  float * v = new float[numOfVertexProperties];
189  unsigned char rgb_buff [4];
190 
191  for (unsigned int i = 0; i < numOfVertices && !feof (in); i++) {
192  if (numOfVertexProperties==10){
193  almostsafefread (v, 4, 6, in);
194  almostsafefread (rgb_buff, sizeof(unsigned char), 4, in);
195  }else if (numOfVertexProperties==9){
196  almostsafefread (v, 4, 6, in);
197  almostsafefread (rgb_buff, sizeof(unsigned char), 3, in);
198  }else if (numOfVertexProperties==6 && haveColor){
199  almostsafefread (v, 4, 3, in);
200  almostsafefread (rgb_buff, sizeof(unsigned char), 3, in);
201  }else if (numOfVertexProperties==7 ){
202  almostsafefread (v, 4, 3, in);
203  almostsafefread (rgb_buff, sizeof(unsigned char), 4, in);
204  }
205  else
206  almostsafefread (v, 4, numOfVertexProperties, in);
207  if (bigEndian == true)
208  bigLittleEndianSwap (v, numOfVertexProperties);
209  vertex.emplace_back( v[0],v[1],v[2] );
210 
211  if (numOfVertexProperties == 6){
212  if (haveColor){
213  rgb << rgb_buff[0], rgb_buff[1], rgb_buff[2];
214  vertex.back().set_rgb(rgb);
215  }else{
216  n << v[3], v[4], v[5];
217  normal.push_back (n);
218  vertex.back().set_normal(n);
219  }
220  }else if (numOfVertexProperties == 7){
221  rgb << rgb_buff[0], rgb_buff[1], rgb_buff[2];
222  vertex.back().set_rgb(rgb);
223  }else if (numOfVertexProperties == 9 || numOfVertexProperties == 10){
224  n << v[3], v[4], v[5];
225  rgb << rgb_buff[0], rgb_buff[1], rgb_buff[2];
226  normal.push_back (n);
227  vertex.back().set_normal(n);
228  vertex.back().set_rgb(rgb);
229  }
230  }
231  delete [] v;
232 
233  if (numOfFaces != 0){
234  if (feof (in)){
235  cerr << "(PLY) incomplete file" << endl;
236  return false;
237  }
238 
239  // *****************
240  // Reading topology.
241  // *****************
242  for (unsigned int i = 0; i < numOfFaces && !feof (in); i++) {
243  unsigned int f[4];
244  char polygonSize;
245  almostsafefread (&polygonSize, 1, 1, in);
246  almostsafefread (f, 4, 3, in);
247  if (bigEndian == true)
248  bigLittleEndianSwap (f, 3);
249  face.emplace_back(f[0],f[1],f[2]);
250  }
251  }
252 
253  return true;
254 }
255 
256 
257 bool
258 readASCII1Body (const std::string & filename,
259  unsigned int headerSize,
260  unsigned int numOfVertices,
261  unsigned int numOfFaces,
262  unsigned int numOfVertexProperties,
263  bool haveColor,
264  std::vector<GlobalRegistration::Point3D>& vertex,
265  std::vector<typename GlobalRegistration::Point3D::VectorType>& normal,
266  std::vector<tripple>& face )
267 {
268  using namespace std;
269  using namespace GlobalRegistration;
270 
271  FILE * in = fopen (filename.c_str (), "r");
272  if (!in){
273  cerr << "(PLY) error opening file" << endl;
274  return false;
275  }
276 
277  char c;
278  for (unsigned int i = 0; i < headerSize; i++) {
279  almostsafefread (&c, 1, 1, in);
280  }
281 
282  // *****************
283  // Reading geometry.
284  // *****************
285  typename Point3D::VectorType n;
286  typename Point3D::VectorType rgb;
287  unsigned int rgb_buff [4];
288  for (unsigned int i = 0; i < numOfVertices && !feof (in); i++) {
289  std::vector<float> v(numOfVertexProperties);
290 
291  if (numOfVertexProperties==10){
292  for (unsigned int j = 0; j < 6; j++)
293  almostsafefscanf<1> (in, "%f", &v[j]);
294  for (unsigned int j = 0; j < 4; j++)
295  almostsafefscanf<1> (in, "%i", &rgb_buff[j]);
296  }
297  else if (numOfVertexProperties==9){
298  for (unsigned int j = 0; j < 6; j++)
299  almostsafefscanf<1> (in, "%f", &v[j]);
300  for (unsigned int j = 0; j < 3; j++)
301  almostsafefscanf<1> (in, "%i", &rgb_buff[j]);
302  }else if (numOfVertexProperties==6 && haveColor){
303  for (unsigned int j = 0; j < 3; j++)
304  almostsafefscanf<1> (in, "%f", &v[j]);
305  for (unsigned int j = 0; j < 3; j++)
306  almostsafefscanf<1> (in, "%i", &rgb_buff[j]);
307  }else if (numOfVertexProperties==7){
308  for (unsigned int j = 0; j < 3; j++)
309  almostsafefscanf<1> (in, "%f", &v[j]);
310  for (unsigned int j = 0; j < 4; j++)
311  almostsafefscanf<1> (in, "%i", &rgb_buff[j]);
312  }
313  else
314  for (unsigned int j = 0; j < numOfVertexProperties; j++)
315  almostsafefscanf<1> (in, "%f", &v[j]);
316 
317  vertex.emplace_back( v[0],v[1],v[2] );
318 
319  if (numOfVertexProperties == 6){
320  if (haveColor){
321  rgb << rgb_buff[0], rgb_buff[1], rgb_buff[2];
322  vertex.back().set_rgb(rgb);
323 
324  }else{
325  n << v[3], v[4], v[5];
326  normal.push_back (n);
327  vertex.back().set_normal(n);
328  }
329  }else if (numOfVertexProperties == 7){
330  rgb << rgb_buff[0], rgb_buff[1], rgb_buff[2];
331  vertex.back().set_rgb(rgb);
332  }else if (numOfVertexProperties == 9 || numOfVertexProperties == 10){
333  n << v[3], v[4], v[5];
334  rgb << rgb_buff[0], rgb_buff[1], rgb_buff[2];
335  normal.push_back (n);
336  vertex.back().set_normal(n);
337  vertex.back().set_rgb(rgb);
338  }
339  }
340 
341  if (numOfFaces != 0){
342  if (feof (in)){
343  cerr << "(PLY) incomplete file" << endl;
344  return false;
345  }
346 
347  // *****************
348  // Reading topology.
349  // *****************
350  for (unsigned int i = 0; i < numOfFaces && !feof (in); i++) {
351  int f[3];
352  int polygonSize;
353  almostsafefscanf<4> (in, "%d %d %d %d", &polygonSize, &f[0], &f[1], &f[2]);
354  face.emplace_back(f[0],f[1],f[2]);
355  }
356  }
357 
358  return true;
359 }
360 
361 #endif //IO_PLY_H
Definition: bbox.h:54
Eigen::Matrix< Scalar, 3, 1 > VectorType
Definition: shared4pcs.h:64
STL namespace.