ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PlyFile.cpp
Go to the documentation of this file.
1 /*
2 
3  The interface routines for reading and writing PLY polygon files.
4 
5  Greg Turk, February 1994
6 
7  ---------------------------------------------------------------
8 
9  A PLY file contains a single polygonal _object_.
10 
11  An object is composed of lists of _elements_. Typical elements are
12  vertices, faces, edges and materials.
13 
14  Each type of element for a given object has one or more _properties_
15  associated with the element type. For instance, a vertex element may
16  have as properties the floating-point values x,y,z and the three unsigned
17  chars representing red, green and blue.
18 
19  ---------------------------------------------------------------
20 
21  Copyright (c) 1994 The Board of Trustees of The Leland Stanford
22  Junior University. All rights reserved.
23 
24  Permission to use, copy, modify and distribute this software and its
25  documentation for any purpose is hereby granted without fee, provided
26  that the above copyright notice and this permission notice appear in
27  all copies of this software and that you do not sell the software.
28 
29  THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
30  EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
31  WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
32 
33 */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <math.h>
38 #include <string.h>
39 #include "Ply.h"
40 
41 const char *type_names[] = {
42  "invalid",
43  "char",
44  "short",
45  "int",
46  "uchar",
47  "ushort",
48  "uint",
49  "float",
50  "double",
51 
52  "int8", // character 1
53  "uint8", // unsigned character 1
54  "int16", // short integer 2
55  "uint16", // unsigned short integer 2
56  "int32", // integer 4
57  "uint32", // unsigned integer 4
58  "float32", // single-precision float 4
59  "float64", // double-precision float 8
60 
61 };
62 
63 int ply_type_size[] = {
64  0,
65  1,
66  2,
67  4,
68  1,
69  2,
70  4,
71  4,
72  8,
73  1,
74  1,
75  2,
76  2,
77  4,
78  4,
79  4,
80  8
81 };
82 
83 typedef union
84 {
85  int int_value;
86  char byte_values[sizeof(int)];
88 
89 
90 static int native_binary_type = -1;
91 static int types_checked = 0;
92 
93 #define NO_OTHER_PROPS -1
94 
95 #define DONT_STORE_PROP 0
96 #define STORE_PROP 1
97 
98 #define OTHER_PROP 0
99 #define NAMED_PROP 1
100 
101 
102 /* returns 1 if strings are equal, 0 if not */
103 int equal_strings(const char *, const char *);
104 
105 /* find an element in a plyfile's list */
106 PlyElement *find_element(PlyFile *, const char *);
107 
108 /* find a property in an element's list */
109 PlyProperty *find_property(PlyElement *, const char *, int *);
110 
111 /* write to a file the word describing a PLY file data type */
112 void write_scalar_type (FILE *, int);
113 
114 /* read a line from a file and break it up into separate words */
115 char **get_words(FILE *, int *, char **);
116 char **old_get_words(FILE *, int *);
117 
118 /* write an item to a file */
119 void write_binary_item(FILE *, int, int, unsigned int, double, int);
120 void write_ascii_item(FILE *, int, unsigned int, double, int);
121 double old_write_ascii_item(FILE *, char *, int);
122 
123 /* add information to a PLY file descriptor */
124 void add_element(PlyFile *, char **);
125 void add_property(PlyFile *, char **);
126 void add_comment(PlyFile *, char *);
127 void add_obj_info(PlyFile *, char *);
128 
129 /* copy a property */
131 
132 /* store a value into where a pointer and a type specify */
133 void store_item(char *, int, int, unsigned int, double);
134 
135 /* return the value of a stored item */
136 void get_stored_item( void *, int, int *, unsigned int *, double *);
137 
138 /* return the value stored in an item, given ptr to it and its type */
139 double get_item_value(char *, int);
140 
141 /* get binary or ascii item and store it according to ptr and type */
142 void get_ascii_item(char *, int, int *, unsigned int *, double *);
143 void get_binary_item(FILE *, int, int, int *, unsigned int *, double *);
144 
145 /* get a bunch of elements from a file */
146 void ascii_get_element(PlyFile *, char *);
147 void binary_get_element(PlyFile *, char *);
148 
149 /* memory allocation */
150 char *my_alloc(int, int, const char *);
151 
152 /* byte ordering */
154 void swap_bytes(char *, int);
155 
156 void check_types();
157 
158 /*************/
159 /* Writing */
160 /*************/
161 
162 
163 /******************************************************************************
164 Given a file pointer, get ready to write PLY data to the file.
165 
166  Entry:
167  fp - the given file pointer
168  nelems - number of elements in object
169  elem_names - list of element names
170  file_type - file type, either ascii or binary
171 
172  Exit:
173  returns a pointer to a PlyFile, used to refer to this file, or NULL if error
174 ******************************************************************************/
175 
177  FILE *fp,
178  int nelems,
179  const char **elem_names,
180  int file_type
181  )
182 {
183  int i;
184  PlyFile *plyfile;
185  PlyElement *elem;
186 
187  /* check for NULL file pointer */
188  if (fp == NULL)
189  return (NULL);
190 
191  if (native_binary_type == -1)
193  if (!types_checked)
194  check_types();
195 
196  /* create a record for this object */
197 
198  plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
199  if (file_type == PLY_BINARY_NATIVE)
200  plyfile->file_type = native_binary_type;
201  else
202  plyfile->file_type = file_type;
203  plyfile->num_comments = 0;
204  plyfile->num_obj_info = 0;
205  plyfile->nelems = nelems;
206  plyfile->version = 1.0;
207  plyfile->fp = fp;
208  plyfile->other_elems = NULL;
209 
210  /* tuck aside the names of the elements */
211 
212  plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
213  for (i = 0; i < nelems; i++) {
214  elem = (PlyElement *) myalloc (sizeof (PlyElement));
215  plyfile->elems[i] = elem;
216  elem->name = _strdup (elem_names[i]);
217  elem->num = 0;
218  elem->nprops = 0;
219  }
220 
221  /* return pointer to the file descriptor */
222  return (plyfile);
223 }
224 
225 
226 /******************************************************************************
227 Open a polygon file for writing.
228 
229  Entry:
230  filename - name of file to read from
231  nelems - number of elements in object
232  elem_names - list of element names
233  file_type - file type, either ascii or binary
234 
235  Exit:
236  version - version number of PLY file
237  returns a file identifier, used to refer to this file, or NULL if error
238 ******************************************************************************/
239 
241  char *filename,
242  int nelems,
243  const char **elem_names,
244  int file_type,
245  float *version
246  )
247 {
248  PlyFile *plyfile;
249  char *name;
250  FILE *fp;
251 
252  /* tack on the extension .ply, if necessary */
253 
254  name = (char *) myalloc (int(sizeof (char) * (strlen (filename)) + 5));
255  strcpy (name, filename);
256  if (strlen (name) < 4 ||
257  strcmp (name + strlen (name) - 4, ".ply") != 0)
258  strcat (name, ".ply");
259 
260  /* open the file for writing */
261 
262  fp = fopen (name, "wb");
263  free(name);
264  if (fp == NULL) {
265  return (NULL);
266  }
267 
268  /* create the actual PlyFile structure */
269 
270  plyfile = ply_write_custom (fp, nelems, elem_names, file_type);
271  if (plyfile == NULL)
272  return (NULL);
273 
274  /* say what PLY file version number we're writing */
275  *version = plyfile->version;
276 
277  /* return pointer to the file descriptor */
278  return (plyfile);
279 }
280 
281 
282 /******************************************************************************
283 Describe an element, including its properties and how many will be written
284 to the file.
285 
286  Entry:
287  plyfile - file identifier
288  elem_name - name of element that information is being specified about
289  nelems - number of elements of this type to be written
290  nprops - number of properties contained in the element
291  prop_list - list of properties
292 ******************************************************************************/
293 
295  PlyFile *plyfile,
296  char *elem_name,
297  int nelems,
298  int nprops,
299  PlyProperty *prop_list
300  )
301 {
302  int i;
303  PlyElement *elem;
304  PlyProperty *prop;
305 
306  /* look for appropriate element */
307  elem = find_element (plyfile, elem_name);
308  if (elem == NULL) {
309  fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
310  exit (-1);
311  }
312 
313  elem->num = nelems;
314 
315  /* copy the list of properties */
316 
317  elem->nprops = nprops;
318  elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
319  elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
320 
321  for (i = 0; i < nprops; i++) {
322  prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
323  elem->props[i] = prop;
324  elem->store_prop[i] = NAMED_PROP;
325  copy_property (prop, &prop_list[i]);
326  }
327 }
328 
329 
330 /******************************************************************************
331 Describe a property of an element.
332 
333  Entry:
334  plyfile - file identifier
335  elem_name - name of element that information is being specified about
336  prop - the new property
337 ******************************************************************************/
338 
340  PlyFile *plyfile,
341  const char *elem_name,
342  PlyProperty *prop
343  )
344 {
345  PlyElement *elem;
346  PlyProperty *elem_prop;
347 
348  /* look for appropriate element */
349  elem = find_element (plyfile, elem_name);
350  if (elem == NULL) {
351  fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
352  elem_name);
353  return;
354  }
355 
356  /* create room for new property */
357 
358  if (elem->nprops == 0) {
359  elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
360  elem->store_prop = (char *) myalloc (sizeof (char));
361  elem->nprops = 1;
362  }
363  else {
364  elem->nprops++;
365  elem->props = (PlyProperty **)
366  realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
367  elem->store_prop = (char *)
368  realloc (elem->store_prop, sizeof (char) * elem->nprops);
369  }
370 
371  /* copy the new property */
372 
373  elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
374  elem->props[elem->nprops - 1] = elem_prop;
375  elem->store_prop[elem->nprops - 1] = NAMED_PROP;
376  copy_property (elem_prop, prop);
377 }
378 
379 
380 /******************************************************************************
381 Describe what the "other" properties are that are to be stored, and where
382 they are in an element.
383 ******************************************************************************/
384 
386  PlyFile *plyfile,
387  PlyOtherProp *other,
388  int offset
389  )
390 {
391  int i;
392  PlyElement *elem;
393  PlyProperty *prop;
394 
395  /* look for appropriate element */
396  elem = find_element (plyfile, other->name);
397  if (elem == NULL) {
398  fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
399  other->name);
400  return;
401  }
402 
403  /* create room for other properties */
404 
405  if (elem->nprops == 0) {
406  elem->props = (PlyProperty **)
407  myalloc (sizeof (PlyProperty *) * other->nprops);
408  elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
409  elem->nprops = 0;
410  }
411  else {
412  int newsize;
413  newsize = elem->nprops + other->nprops;
414  elem->props = (PlyProperty **)
415  realloc (elem->props, sizeof (PlyProperty *) * newsize);
416  elem->store_prop = (char *)
417  realloc (elem->store_prop, sizeof (char) * newsize);
418  }
419 
420  /* copy the other properties */
421 
422  for (i = 0; i < other->nprops; i++) {
423  prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
424  copy_property (prop, other->props[i]);
425  elem->props[elem->nprops] = prop;
426  elem->store_prop[elem->nprops] = OTHER_PROP;
427  elem->nprops++;
428  }
429 
430  /* save other info about other properties */
431  elem->other_size = other->size;
432  elem->other_offset = offset;
433 }
434 
435 
436 /******************************************************************************
437 State how many of a given element will be written.
438 
439  Entry:
440  plyfile - file identifier
441  elem_name - name of element that information is being specified about
442  nelems - number of elements of this type to be written
443 ******************************************************************************/
444 
446  PlyFile *plyfile,
447  const char *elem_name,
448  int nelems
449  )
450 {
451  PlyElement *elem;
452 
453  /* look for appropriate element */
454  elem = find_element (plyfile, elem_name);
455  if (elem == NULL) {
456  fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
457  exit (-1);
458  }
459 
460  elem->num = nelems;
461 }
462 
463 
464 /******************************************************************************
465 Signal that we've described everything a PLY file's header and that the
466 header should be written to the file.
467 
468  Entry:
469  plyfile - file identifier
470 ******************************************************************************/
471 
473 {
474  int i,j;
475  FILE *fp = plyfile->fp;
476  PlyElement *elem;
477  PlyProperty *prop;
478 
479  fprintf (fp, "ply\n");
480 
481  switch (plyfile->file_type) {
482  case PLY_ASCII:
483  fprintf (fp, "format ascii 1.0\n");
484  break;
485  case PLY_BINARY_BE:
486  fprintf (fp, "format binary_big_endian 1.0\n");
487  break;
488  case PLY_BINARY_LE:
489  fprintf (fp, "format binary_little_endian 1.0\n");
490  break;
491  default:
492  fprintf (stderr, "ply_header_complete: bad file type = %d\n",
493  plyfile->file_type);
494  exit (-1);
495  }
496 
497  /* write out the comments */
498 
499  for (i = 0; i < plyfile->num_comments; i++)
500  fprintf (fp, "comment %s\n", plyfile->comments[i]);
501 
502  /* write out object information */
503 
504  for (i = 0; i < plyfile->num_obj_info; i++)
505  fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
506 
507  /* write out information about each element */
508 
509  for (i = 0; i < plyfile->nelems; i++) {
510 
511  elem = plyfile->elems[i];
512  fprintf (fp, "element %s %d\n", elem->name, elem->num);
513 
514  /* write out each property */
515  for (j = 0; j < elem->nprops; j++) {
516  prop = elem->props[j];
517  if (prop->is_list) {
518  fprintf (fp, "property list ");
519  write_scalar_type (fp, prop->count_external);
520  fprintf (fp, " ");
521  write_scalar_type (fp, prop->external_type);
522  fprintf (fp, " %s\n", prop->name);
523  }
524  else {
525  fprintf (fp, "property ");
526  write_scalar_type (fp, prop->external_type);
527  fprintf (fp, " %s\n", prop->name);
528  }
529  }
530  }
531 
532  fprintf (fp, "end_header\n");
533 }
534 
535 
536 /******************************************************************************
537 Specify which elements are going to be written. This should be called
538 before a call to the routine ply_put_element().
539 
540  Entry:
541  plyfile - file identifier
542  elem_name - name of element we're talking about
543 ******************************************************************************/
544 
545 void ply_put_element_setup(PlyFile *plyfile, const char *elem_name)
546 {
547  PlyElement *elem;
548 
549  elem = find_element (plyfile, elem_name);
550  if (elem == NULL) {
551  fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
552  exit (-1);
553  }
554 
555  plyfile->which_elem = elem;
556 }
557 
558 
559 /******************************************************************************
560 Write an element to the file. This routine assumes that we're
561 writing the type of element specified in the last call to the routine
562 ply_put_element_setup().
563 
564  Entry:
565  plyfile - file identifier
566  elem_ptr - pointer to the element
567 ******************************************************************************/
568 
569 void ply_put_element(PlyFile *plyfile, void *elem_ptr)
570 {
571  int j,k;
572  FILE *fp = plyfile->fp;
573  PlyElement *elem;
574  PlyProperty *prop;
575  char *elem_data,*item;
576  char **item_ptr;
577  int list_count;
578  int item_size;
579  int int_val;
580  unsigned int uint_val;
581  double double_val;
582  char **other_ptr;
583 
584  elem = plyfile->which_elem;
585  elem_data = (char *)elem_ptr;
586  other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
587 
588  /* write out either to an ascii or binary file */
589 
590  if (plyfile->file_type == PLY_ASCII) {
591 
592  /* write an ascii file */
593 
594  /* write out each property of the element */
595  for (j = 0; j < elem->nprops; j++) {
596  prop = elem->props[j];
597  if (elem->store_prop[j] == OTHER_PROP)
598  elem_data = *other_ptr;
599  else
600  elem_data = (char *)elem_ptr;
601  if (prop->is_list) {
602  item = elem_data + prop->count_offset;
603  get_stored_item ((void *) item, prop->count_internal,
604  &int_val, &uint_val, &double_val);
605  write_ascii_item (fp, int_val, uint_val, double_val,
606  prop->count_external);
607  list_count = uint_val;
608  item_ptr = (char **) (elem_data + prop->offset);
609  item = item_ptr[0];
610  item_size = ply_type_size[prop->internal_type];
611  for (k = 0; k < list_count; k++) {
612  get_stored_item ((void *) item, prop->internal_type,
613  &int_val, &uint_val, &double_val);
614  write_ascii_item (fp, int_val, uint_val, double_val,
615  prop->external_type);
616  item += item_size;
617  }
618  }
619  else {
620  item = elem_data + prop->offset;
621  get_stored_item ((void *) item, prop->internal_type,
622  &int_val, &uint_val, &double_val);
623  write_ascii_item (fp, int_val, uint_val, double_val,
624  prop->external_type);
625  }
626  }
627 
628  fprintf (fp, "\n");
629  }
630  else {
631 
632  /* write a binary file */
633 
634  /* write out each property of the element */
635  for (j = 0; j < elem->nprops; j++) {
636  prop = elem->props[j];
637  if (elem->store_prop[j] == OTHER_PROP)
638  elem_data = *other_ptr;
639  else
640  elem_data = (char *)elem_ptr;
641  if (prop->is_list) {
642  item = elem_data + prop->count_offset;
643  item_size = ply_type_size[prop->count_internal];
644  get_stored_item ((void *) item, prop->count_internal,
645  &int_val, &uint_val, &double_val);
646  write_binary_item (fp, plyfile->file_type, int_val, uint_val,
647  double_val, prop->count_external);
648  list_count = uint_val;
649  item_ptr = (char **) (elem_data + prop->offset);
650  item = item_ptr[0];
651  item_size = ply_type_size[prop->internal_type];
652  for (k = 0; k < list_count; k++) {
653  get_stored_item ((void *) item, prop->internal_type,
654  &int_val, &uint_val, &double_val);
655  write_binary_item (fp, plyfile->file_type, int_val, uint_val,
656  double_val, prop->external_type);
657  item += item_size;
658  }
659  }
660  else {
661  item = elem_data + prop->offset;
662  item_size = ply_type_size[prop->internal_type];
663  get_stored_item ((void *) item, prop->internal_type,
664  &int_val, &uint_val, &double_val);
665  write_binary_item (fp, plyfile->file_type, int_val, uint_val,
666  double_val, prop->external_type);
667  }
668  }
669 
670  }
671 }
672 
673 
674 /******************************************************************************
675 Specify a comment that will be written in the header.
676 
677  Entry:
678  plyfile - file identifier
679  comment - the comment to be written
680  ******************************************************************************/
681 
682  void ply_put_comment(PlyFile *plyfile, char *comment)
683  {
684  /* (re)allocate space for new comment */
685  if (plyfile->num_comments == 0)
686  plyfile->comments = (char **) myalloc (sizeof (char *));
687  else
688  plyfile->comments = (char **) realloc (plyfile->comments,
689  sizeof (char *) * (plyfile->num_comments + 1));
690 
691  /* add comment to list */
692  plyfile->comments[plyfile->num_comments] = _strdup (comment);
693  plyfile->num_comments++;
694  }
695 
696 
697  /******************************************************************************
698  Specify a piece of object information (arbitrary text) that will be written
699  in the header.
700 
701  Entry:
702  plyfile - file identifier
703  obj_info - the text information to be written
704  ******************************************************************************/
705 
706  void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
707  {
708  /* (re)allocate space for new info */
709  if (plyfile->num_obj_info == 0)
710  plyfile->obj_info = (char **) myalloc (sizeof (char *));
711  else
712  plyfile->obj_info = (char **) realloc (plyfile->obj_info,
713  sizeof (char *) * (plyfile->num_obj_info + 1));
714 
715  /* add info to list */
716  plyfile->obj_info[plyfile->num_obj_info] = _strdup (obj_info);
717  plyfile->num_obj_info++;
718  }
719 
720 
721 
722 
723 
724 
725 
726  /*************/
727  /* Reading */
728  /*************/
729 
730 
731 
732  /******************************************************************************
733  Given a file pointer, get ready to read PLY data from the file.
734 
735  Entry:
736  fp - the given file pointer
737 
738  Exit:
739  nelems - number of elements in object
740  elem_names - list of element names
741  returns a pointer to a PlyFile, used to refer to this file, or NULL if error
742  ******************************************************************************/
743 
744  PlyFile *ply_read_custom(FILE *fp, int *nelems, char ***elem_names)
745  {
746  int i,j;
747  PlyFile *plyfile;
748  int nwords;
749  char **words;
750  char **elist;
751  PlyElement *elem;
752  char *orig_line;
753  /* check for NULL file pointer */
754  if (fp == NULL)
755  return (NULL);
756 
757  if (native_binary_type == -1)
759  if (!types_checked)
760  check_types();
761  /* create record for this object */
762 
763  plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
764  plyfile->nelems = 0;
765  plyfile->comments = NULL;
766  plyfile->num_comments = 0;
767  plyfile->obj_info = NULL;
768  plyfile->num_obj_info = 0;
769  plyfile->fp = fp;
770  plyfile->other_elems = NULL;
771 
772  /* read and parse the file's header */
773 
774  words = get_words (plyfile->fp, &nwords, &orig_line);
775  if (!words || !equal_strings (words[0], "ply"))
776  {
777  if (words)
778  free(words);
779  return (NULL);
780  }
781  while (words) {
782  /* parse words */
783 
784  if (equal_strings (words[0], "format")) {
785  if (nwords != 3) {
786  free(words);
787  return (NULL);
788  }
789  if (equal_strings (words[1], "ascii"))
790  plyfile->file_type = PLY_ASCII;
791  else if (equal_strings (words[1], "binary_big_endian"))
792  plyfile->file_type = PLY_BINARY_BE;
793  else if (equal_strings (words[1], "binary_little_endian"))
794  plyfile->file_type = PLY_BINARY_LE;
795  else {
796  free(words);
797  return (NULL);
798  }
799  plyfile->version = (float)atof (words[2]);
800  }
801  else if (equal_strings (words[0], "element"))
802  add_element (plyfile, words);
803  else if (equal_strings (words[0], "property"))
804  add_property (plyfile, words);
805  else if (equal_strings (words[0], "comment"))
806  add_comment (plyfile, orig_line);
807  else if (equal_strings (words[0], "obj_info"))
808  add_obj_info (plyfile, orig_line);
809  else if (equal_strings (words[0], "end_header")) {
810  free(words);
811  break;
812  }
813 
814  /* free up words space */
815  free (words);
816 
817  words = get_words (plyfile->fp, &nwords, &orig_line);
818  }
819 
820  /* create tags for each property of each element, to be used */
821  /* later to say whether or not to store each property for the user */
822 
823  for (i = 0; i < plyfile->nelems; i++) {
824  elem = plyfile->elems[i];
825  elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
826  for (j = 0; j < elem->nprops; j++)
827  elem->store_prop[j] = DONT_STORE_PROP;
828  elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
829  }
830 
831  /* set return values about the elements */
832 
833  elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
834  for (i = 0; i < plyfile->nelems; i++)
835  elist[i] = _strdup (plyfile->elems[i]->name);
836 
837  *elem_names = elist;
838  *nelems = plyfile->nelems;
839 
840  /* return a pointer to the file's information */
841 
842  return (plyfile);
843 }
844 
845 
846 /******************************************************************************
847 Open a polygon file for reading.
848 
849  Entry:
850  filename - name of file to read from
851 
852  Exit:
853  nelems - number of elements in object
854  elem_names - list of element names
855  file_type - file type, either ascii or binary
856  version - version number of PLY file
857  returns a file identifier, used to refer to this file, or NULL if error
858  ******************************************************************************/
859 
861  char *filename,
862  int *nelems,
863  char ***elem_names,
864  int *file_type,
865  float *version
866  )
867  {
868  FILE *fp;
869  PlyFile *plyfile;
870  char *name;
871 
872  /* tack on the extension .ply, if necessary */
873 
874  name = (char *) myalloc (int(sizeof (char) * (strlen (filename) + 5)));
875  strcpy (name, filename);
876  if (strlen (name) < 4 ||
877  strcmp (name + strlen (name) - 4, ".ply") != 0)
878  strcat (name, ".ply");
879 
880  /* open the file for reading */
881 
882  fp = fopen (name, "rb");
883  free(name);
884  if (fp == NULL)
885  return (NULL);
886 
887  /* create the PlyFile data structure */
888 
889  plyfile = ply_read_custom (fp, nelems, elem_names);
890 
891  /* determine the file type and version */
892 
893  *file_type = plyfile->file_type;
894  *version = plyfile->version;
895 
896  /* return a pointer to the file's information */
897 
898  return (plyfile);
899  }
900 
901 
902  /******************************************************************************
903  Get information about a particular element.
904 
905  Entry:
906  plyfile - file identifier
907  elem_name - name of element to get information about
908 
909  Exit:
910  nelems - number of elements of this type in the file
911  nprops - number of properties
912  returns a list of properties, or NULL if the file doesn't contain that elem
913  ******************************************************************************/
914 
916  PlyFile *plyfile,
917  char *elem_name,
918  int *nelems,
919  int *nprops
920  )
921  {
922  int i;
923  PlyElement *elem;
924  PlyProperty *prop;
925  PlyProperty **prop_list;
926 
927  /* find information about the element */
928  elem = find_element (plyfile, elem_name);
929  if (elem == NULL)
930  return (NULL);
931 
932  *nelems = elem->num;
933  *nprops = elem->nprops;
934 
935  /* make a copy of the element's property list */
936  prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
937  for (i = 0; i < elem->nprops; i++) {
938  prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
939  copy_property (prop, elem->props[i]);
940  prop_list[i] = prop;
941  }
942 
943  /* return this duplicate property list */
944  return (prop_list);
945  }
946 
947 
948  /******************************************************************************
949  Specify which properties of an element are to be returned. This should be
950  called before a call to the routine ply_get_element().
951 
952  Entry:
953  plyfile - file identifier
954  elem_name - which element we're talking about
955  nprops - number of properties
956  prop_list - list of properties
957  ******************************************************************************/
958 
960  PlyFile *plyfile,
961  char *elem_name,
962  int nprops,
963  PlyProperty *prop_list
964  )
965  {
966  int i;
967  PlyElement *elem;
968  PlyProperty *prop;
969  int index;
970 
971  /* find information about the element */
972  elem = find_element (plyfile, elem_name);
973  plyfile->which_elem = elem;
974 
975  /* deposit the property information into the element's description */
976  for (i = 0; i < nprops; i++) {
977 
978  /* look for actual property */
979  prop = find_property (elem, prop_list[i].name, &index);
980  if (prop == NULL) {
981  fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
982  prop_list[i].name, elem_name);
983  continue;
984  }
985 
986  /* store its description */
987  prop->internal_type = prop_list[i].internal_type;
988  prop->offset = prop_list[i].offset;
989  prop->count_internal = prop_list[i].count_internal;
990  prop->count_offset = prop_list[i].count_offset;
991 
992  /* specify that the user wants this property */
993  elem->store_prop[index] = STORE_PROP;
994  }
995  }
996 
997 
998  /******************************************************************************
999  Specify a property of an element that is to be returned. This should be
1000  called (usually multiple times) before a call to the routine ply_get_element().
1001  This routine should be used in preference to the less flexible old routine
1002  called ply_get_element_setup().
1003 
1004  Entry:
1005  plyfile - file identifier
1006  elem_name - which element we're talking about
1007  prop - property to add to those that will be returned
1008  ******************************************************************************/
1009 
1011  PlyFile *plyfile,
1012  char *elem_name,
1013  PlyProperty *prop
1014  )
1015  {
1016  PlyElement *elem;
1017  PlyProperty *prop_ptr;
1018  int index;
1019 
1020  /* find information about the element */
1021  elem = find_element (plyfile, elem_name);
1022  plyfile->which_elem = elem;
1023 
1024  /* deposit the property information into the element's description */
1025 
1026  prop_ptr = find_property (elem, prop->name, &index);
1027  if (prop_ptr == NULL) {
1028 // fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
1029 // prop->name, elem_name);
1030 // return;
1031  return 0;
1032  }
1033  prop_ptr->internal_type = prop->internal_type;
1034  prop_ptr->offset = prop->offset;
1035  prop_ptr->count_internal = prop->count_internal;
1036  prop_ptr->count_offset = prop->count_offset;
1037 
1038  /* specify that the user wants this property */
1039  elem->store_prop[index] = STORE_PROP;
1040  return 1;
1041  }
1042 
1043 
1044  /******************************************************************************
1045  Read one element from the file. This routine assumes that we're reading
1046  the type of element specified in the last call to the routine
1047  ply_get_element_setup().
1048 
1049  Entry:
1050  plyfile - file identifier
1051  elem_ptr - pointer to location where the element information should be put
1052  ******************************************************************************/
1053 
1054  void ply_get_element(PlyFile *plyfile, void *elem_ptr)
1055  {
1056  if (plyfile->file_type == PLY_ASCII)
1057  ascii_get_element (plyfile, (char *) elem_ptr);
1058  else
1059  binary_get_element (plyfile, (char *) elem_ptr);
1060  }
1061 
1062 
1063  /******************************************************************************
1064  Extract the comments from the header information of a PLY file.
1065 
1066  Entry:
1067  plyfile - file identifier
1068 
1069  Exit:
1070  num_comments - number of comments returned
1071  returns a pointer to a list of comments
1072  ******************************************************************************/
1073 
1074  char **ply_get_comments(PlyFile *plyfile, int *num_comments)
1075  {
1076  *num_comments = plyfile->num_comments;
1077  return (plyfile->comments);
1078  }
1079 
1080 
1081  /******************************************************************************
1082  Extract the object information (arbitrary text) from the header information
1083  of a PLY file.
1084 
1085  Entry:
1086  plyfile - file identifier
1087 
1088  Exit:
1089  num_obj_info - number of lines of text information returned
1090  returns a pointer to a list of object info lines
1091  ******************************************************************************/
1092 
1093  char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
1094  {
1095  *num_obj_info = plyfile->num_obj_info;
1096  return (plyfile->obj_info);
1097  }
1098 
1099 
1100  /******************************************************************************
1101  Make ready for "other" properties of an element-- those properties that
1102  the user has not explicitly asked for, but that are to be stashed away
1103  in a special structure to be carried along with the element's other
1104  information.
1105 
1106  Entry:
1107  plyfile - file identifier
1108  elem - element for which we want to save away other properties
1109  ******************************************************************************/
1110 
1112  {
1113  int i;
1114  PlyProperty *prop;
1115  int size = 0;
1116  int type_size;
1117 
1118  /* Examine each property in decreasing order of size. */
1119  /* We do this so that all data types will be aligned by */
1120  /* word, half-word, or whatever within the structure. */
1121 
1122  for (type_size = 8; type_size > 0; type_size /= 2) {
1123 
1124  /* add up the space taken by each property, and save this information */
1125  /* away in the property descriptor */
1126 
1127  for (i = 0; i < elem->nprops; i++) {
1128 
1129  /* don't bother with properties we've been asked to store explicitly */
1130  if (elem->store_prop[i])
1131  continue;
1132 
1133  prop = elem->props[i];
1134 
1135  /* internal types will be same as external */
1136  prop->internal_type = prop->external_type;
1137  prop->count_internal = prop->count_external;
1138 
1139  /* check list case */
1140  if (prop->is_list) {
1141 
1142  /* pointer to list */
1143  if (type_size == sizeof (void *)) {
1144  prop->offset = size;
1145  size += sizeof (void *); /* always use size of a pointer here */
1146  }
1147 
1148  /* count of number of list elements */
1149  if (type_size == ply_type_size[prop->count_external]) {
1150  prop->count_offset = size;
1151  size += ply_type_size[prop->count_external];
1152  }
1153  }
1154  /* not list */
1155  else if (type_size == ply_type_size[prop->external_type]) {
1156  prop->offset = size;
1157  size += ply_type_size[prop->external_type];
1158  }
1159  }
1160 
1161  }
1162 
1163  /* save the size for the other_props structure */
1164  elem->other_size = size;
1165  }
1166 
1167 
1168  /******************************************************************************
1169  Specify that we want the "other" properties of an element to be tucked
1170  away within the user's structure. The user needn't be concerned for how
1171  these properties are stored.
1172 
1173  Entry:
1174  plyfile - file identifier
1175  elem_name - name of element that we want to store other_props in
1176  offset - offset to where other_props will be stored inside user's structure
1177 
1178  Exit:
1179  returns pointer to structure containing description of other_props
1180  ******************************************************************************/
1181 
1183  PlyFile *plyfile,
1184  char *elem_name,
1185  int offset
1186  )
1187  {
1188  int i;
1189  PlyElement *elem;
1190  PlyOtherProp *other;
1191  PlyProperty *prop;
1192  int nprops;
1193 
1194  /* find information about the element */
1195  elem = find_element (plyfile, elem_name);
1196  if (elem == NULL) {
1197  fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
1198  elem_name);
1199  return (NULL);
1200  }
1201 
1202  /* remember that this is the "current" element */
1203  plyfile->which_elem = elem;
1204 
1205  /* save the offset to where to store the other_props */
1206  elem->other_offset = offset;
1207 
1208  /* place the appropriate pointers, etc. in the element's property list */
1209  setup_other_props (elem);
1210 
1211  /* create structure for describing other_props */
1212  other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
1213  other->name = _strdup (elem_name);
1214  other->size = elem->other_size;
1215  other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
1216 
1217  /* save descriptions of each "other" property */
1218  nprops = 0;
1219  for (i = 0; i < elem->nprops; i++) {
1220  if (elem->store_prop[i])
1221  continue;
1222  prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
1223  copy_property (prop, elem->props[i]);
1224  other->props[nprops] = prop;
1225  nprops++;
1226  }
1227  other->nprops = nprops;
1228 
1229  /* set other_offset pointer appropriately if there are NO other properties */
1230  if (other->nprops == 0) {
1231  elem->other_offset = NO_OTHER_PROPS;
1232  }
1233 
1234  /* return structure */
1235  return (other);
1236  }
1237 
1238 
1239 
1240 
1241  /*************************/
1242  /* Other Element Stuff */
1243  /*************************/
1244 
1245 
1246 
1247 
1248  /******************************************************************************
1249  Grab all the data for an element that a user does not want to explicitly
1250  read in.
1251 
1252  Entry:
1253  plyfile - pointer to file
1254  elem_name - name of element whose data is to be read in
1255  elem_count - number of instances of this element stored in the file
1256 
1257  Exit:
1258  returns pointer to ALL the "other" element data for this PLY file
1259  ******************************************************************************/
1260 
1262  PlyFile *plyfile,
1263  char *elem_name,
1264  int elem_count
1265  )
1266  {
1267  int i;
1268  PlyElement *elem;
1269  PlyOtherElems *other_elems;
1270  OtherElem *other;
1271 
1272  /* look for appropriate element */
1273  elem = find_element (plyfile, elem_name);
1274  if (elem == NULL) {
1275  fprintf (stderr,
1276  "ply_get_other_element: can't find element '%s'\n", elem_name);
1277  exit (-1);
1278  }
1279 
1280  /* create room for the new "other" element, initializing the */
1281  /* other data structure if necessary */
1282 
1283  if (plyfile->other_elems == NULL) {
1284  plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
1285  other_elems = plyfile->other_elems;
1286  other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
1287  other = &(other_elems->other_list[0]);
1288  other_elems->num_elems = 1;
1289  }
1290  else {
1291  other_elems = plyfile->other_elems;
1292  other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
1293  sizeof (OtherElem) * other_elems->num_elems + 1);
1294  other = &(other_elems->other_list[other_elems->num_elems]);
1295  other_elems->num_elems++;
1296  }
1297 
1298  /* count of element instances in file */
1299  other->elem_count = elem_count;
1300 
1301  /* save name of element */
1302  other->elem_name = _strdup (elem_name);
1303 
1304  /* create a list to hold all the current elements */
1305  other->other_data = (OtherData **)
1306  malloc (sizeof (OtherData *) * other->elem_count);
1307 
1308  /* set up for getting elements */
1309  other->other_props = ply_get_other_properties (plyfile, elem_name,
1310  offsetof(OtherData,other_props));
1311 
1312  /* grab all these elements */
1313  for (i = 0; i < other->elem_count; i++) {
1314  /* grab and element from the file */
1315  other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
1316  ply_get_element (plyfile, (void *) other->other_data[i]);
1317  }
1318 
1319  /* return pointer to the other elements data */
1320  return (other_elems);
1321  }
1322 
1323 
1324  /******************************************************************************
1325  Pass along a pointer to "other" elements that we want to save in a given
1326  PLY file. These other elements were presumably read from another PLY file.
1327 
1328  Entry:
1329  plyfile - file pointer in which to store this other element info
1330  other_elems - info about other elements that we want to store
1331  ******************************************************************************/
1332 
1334  PlyFile *plyfile,
1335  PlyOtherElems *other_elems
1336  )
1337  {
1338  int i;
1339  OtherElem *other;
1340  PlyElement *elem;
1341 
1342  /* ignore this call if there is no other element */
1343  if (other_elems == NULL)
1344  return;
1345 
1346  /* save pointer to this information */
1347  plyfile->other_elems = other_elems;
1348 
1349  /* describe the other properties of this element */
1350  /* store them in the main element list as elements with
1351  only other properties */
1352 
1353  REALLOCN(plyfile->elems, PlyElement *,
1354  plyfile->nelems, plyfile->nelems + other_elems->num_elems);
1355  for (i = 0; i < other_elems->num_elems; i++) {
1356  other = &(other_elems->other_list[i]);
1357  elem = (PlyElement *) myalloc (sizeof (PlyElement));
1358  plyfile->elems[plyfile->nelems++] = elem;
1359  elem->name = _strdup (other->elem_name);
1360  elem->num = other->elem_count;
1361  elem->nprops = 0;
1362  ply_describe_other_properties (plyfile, other->other_props,
1363  offsetof(OtherData,other_props));
1364  }
1365  }
1366 
1367 
1368  /******************************************************************************
1369  Write out the "other" elements specified for this PLY file.
1370 
1371  Entry:
1372  plyfile - pointer to PLY file to write out other elements for
1373  ******************************************************************************/
1374 
1376  {
1377  int i,j;
1378  OtherElem *other;
1379 
1380  /* make sure we have other elements to write */
1381  if (plyfile->other_elems == NULL)
1382  return;
1383 
1384  /* write out the data for each "other" element */
1385 
1386  for (i = 0; i < plyfile->other_elems->num_elems; i++) {
1387 
1388  other = &(plyfile->other_elems->other_list[i]);
1389  ply_put_element_setup (plyfile, other->elem_name);
1390 
1391  /* write out each instance of the current element */
1392  for (j = 0; j < other->elem_count; j++)
1393  ply_put_element (plyfile, (void *) other->other_data[j]);
1394  }
1395  }
1396 
1397 
1398  /******************************************************************************
1399  Free up storage used by an "other" elements data structure.
1400 
1401  Entry:
1402  other_elems - data structure to free up
1403  ******************************************************************************/
1404 
1406  {
1407  other_elems = other_elems;
1408  }
1409 
1410 
1411 
1412  /*******************/
1413  /* Miscellaneous */
1414  /*******************/
1415 
1416 
1417 
1418  /******************************************************************************
1419  Close a PLY file.
1420 
1421  Entry:
1422  plyfile - identifier of file to close
1423  ******************************************************************************/
1424 
1425  void ply_close_custom(PlyFile *plyfile)
1426  {
1427  fclose (plyfile->fp);
1428 
1429  /* free up memory associated with the PLY file */
1430  free (plyfile);
1431  }
1432 
1433 
1434  /******************************************************************************
1435  Get version number and file type of a PlyFile.
1436 
1437  Entry:
1438  ply - pointer to PLY file
1439 
1440  Exit:
1441  version - version of the file
1442  file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
1443  ******************************************************************************/
1444 
1445  void ply_get_info(PlyFile *ply, float *version, int *file_type)
1446  {
1447  if (ply == NULL)
1448  return;
1449 
1450  *version = ply->version;
1451  *file_type = ply->file_type;
1452  }
1453 
1454 
1455  /******************************************************************************
1456  Compare two strings. Returns 1 if they are the same, 0 if not.
1457  ******************************************************************************/
1458 
1459  int equal_strings(const char *s1, const char *s2)
1460  {
1461 
1462  while (*s1 && *s2)
1463  if (*s1++ != *s2++)
1464  return (0);
1465 
1466  if (*s1 != *s2)
1467  return (0);
1468  else
1469  return (1);
1470  }
1471 
1472 
1473  /******************************************************************************
1474  Find an element from the element list of a given PLY object.
1475 
1476  Entry:
1477  plyfile - file id for PLY file
1478  element - name of element we're looking for
1479 
1480  Exit:
1481  returns the element, or NULL if not found
1482  ******************************************************************************/
1483 
1484  PlyElement *find_element(PlyFile *plyfile, const char *element)
1485  {
1486  int i;
1487 
1488  for (i = 0; i < plyfile->nelems; i++)
1489  if (equal_strings (element, plyfile->elems[i]->name))
1490  return (plyfile->elems[i]);
1491 
1492  return (NULL);
1493  }
1494 
1495 
1496  /******************************************************************************
1497  Find a property in the list of properties of a given element.
1498 
1499  Entry:
1500  elem - pointer to element in which we want to find the property
1501  prop_name - name of property to find
1502 
1503  Exit:
1504  index - index to position in list
1505  returns a pointer to the property, or NULL if not found
1506  ******************************************************************************/
1507 
1508  PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index)
1509  {
1510  int i;
1511 
1512  for (i = 0; i < elem->nprops; i++)
1513  if (equal_strings (prop_name, elem->props[i]->name)) {
1514  *index = i;
1515  return (elem->props[i]);
1516  }
1517 
1518  *index = -1;
1519  return (NULL);
1520  }
1521 
1522 
1523  /******************************************************************************
1524  Read an element from an ascii file.
1525 
1526  Entry:
1527  plyfile - file identifier
1528  elem_ptr - pointer to element
1529  ******************************************************************************/
1530 
1531  void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
1532  {
1533  int j,k;
1534  PlyElement *elem;
1535  PlyProperty *prop;
1536  char **words;
1537  int nwords;
1538  int which_word;
1539  char *elem_data,*item=NULL;
1540  char *item_ptr;
1541  int item_size;
1542  int int_val;
1543  unsigned int uint_val;
1544  double double_val;
1545  int list_count;
1546  int store_it;
1547  char **store_array;
1548  char *orig_line;
1549  char *other_data=NULL;
1550  int other_flag;
1551 
1552  /* the kind of element we're reading currently */
1553  elem = plyfile->which_elem;
1554 
1555  /* do we need to setup for other_props? */
1556 
1557  if (elem->other_offset != NO_OTHER_PROPS) {
1558  char **ptr;
1559  other_flag = 1;
1560  /* make room for other_props */
1561  other_data = (char *) myalloc (elem->other_size);
1562  /* store pointer in user's structure to the other_props */
1563  ptr = (char **) (elem_ptr + elem->other_offset);
1564  *ptr = other_data;
1565  }
1566  else
1567  other_flag = 0;
1568 
1569  /* read in the element */
1570 
1571  words = get_words (plyfile->fp, &nwords, &orig_line);
1572  if (words == NULL) {
1573  fprintf (stderr, "ply_get_element: unexpected end of file\n");
1574  exit (-1);
1575  }
1576 
1577  which_word = 0;
1578 
1579  for (j = 0; j < elem->nprops; j++) {
1580 
1581  prop = elem->props[j];
1582  store_it = (elem->store_prop[j] | other_flag);
1583 
1584  /* store either in the user's structure or in other_props */
1585  if (elem->store_prop[j])
1586  elem_data = elem_ptr;
1587  else
1588  elem_data = other_data;
1589 
1590  if (prop->is_list) { /* a list */
1591 
1592  /* get and store the number of items in the list */
1593  get_ascii_item (words[which_word++], prop->count_external,
1594  &int_val, &uint_val, &double_val);
1595  if (store_it) {
1596  item = elem_data + prop->count_offset;
1597  store_item(item, prop->count_internal, int_val, uint_val, double_val);
1598  }
1599 
1600  /* allocate space for an array of items and store a ptr to the array */
1601  list_count = int_val;
1602  item_size = ply_type_size[prop->internal_type];
1603  store_array = (char **) (elem_data + prop->offset);
1604 
1605  if (list_count == 0) {
1606  if (store_it)
1607  *store_array = NULL;
1608  }
1609  else {
1610  if (store_it) {
1611  item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
1612  item = item_ptr;
1613  *store_array = item_ptr;
1614  }
1615 
1616  /* read items and store them into the array */
1617  for (k = 0; k < list_count; k++) {
1618  get_ascii_item (words[which_word++], prop->external_type,
1619  &int_val, &uint_val, &double_val);
1620  if (store_it) {
1621  store_item (item, prop->internal_type,
1622  int_val, uint_val, double_val);
1623  item += item_size;
1624  }
1625  }
1626  }
1627 
1628  }
1629  else { /* not a list */
1630  get_ascii_item (words[which_word++], prop->external_type,
1631  &int_val, &uint_val, &double_val);
1632  if (store_it) {
1633  item = elem_data + prop->offset;
1634  store_item (item, prop->internal_type, int_val, uint_val, double_val);
1635  }
1636  }
1637 
1638  }
1639 
1640  free (words);
1641 }
1642 
1643 
1644 /******************************************************************************
1645 Read an element from a binary file.
1646 
1647  Entry:
1648  plyfile - file identifier
1649  elem_ptr - pointer to an element
1650  ******************************************************************************/
1651 
1652  void binary_get_element(PlyFile *plyfile, char *elem_ptr)
1653  {
1654  int j,k;
1655  PlyElement *elem;
1656  PlyProperty *prop;
1657  FILE *fp = plyfile->fp;
1658  char *elem_data,*item=NULL;
1659  char *item_ptr;
1660  int item_size;
1661  int int_val;
1662  unsigned int uint_val;
1663  double double_val;
1664  int list_count;
1665  int store_it;
1666  char **store_array;
1667  char *other_data=NULL;
1668  int other_flag;
1669 
1670  /* the kind of element we're reading currently */
1671  elem = plyfile->which_elem;
1672 
1673  /* do we need to setup for other_props? */
1674 
1675  if (elem->other_offset != NO_OTHER_PROPS) {
1676  char **ptr;
1677  other_flag = 1;
1678  /* make room for other_props */
1679  other_data = (char *) myalloc (elem->other_size);
1680  /* store pointer in user's structure to the other_props */
1681  ptr = (char **) (elem_ptr + elem->other_offset);
1682  *ptr = other_data;
1683  }
1684  else
1685  other_flag = 0;
1686 
1687  /* read in a number of elements */
1688 
1689  for (j = 0; j < elem->nprops; j++) {
1690 
1691  prop = elem->props[j];
1692  store_it = (elem->store_prop[j] | other_flag);
1693 
1694  /* store either in the user's structure or in other_props */
1695  if (elem->store_prop[j])
1696  elem_data = elem_ptr;
1697  else
1698  elem_data = other_data;
1699 
1700  if (prop->is_list) { /* a list */
1701 
1702  /* get and store the number of items in the list */
1703  get_binary_item (fp, plyfile->file_type, prop->count_external,
1704  &int_val, &uint_val, &double_val);
1705  if (store_it) {
1706  item = elem_data + prop->count_offset;
1707  store_item(item, prop->count_internal, int_val, uint_val, double_val);
1708  }
1709 
1710  /* allocate space for an array of items and store a ptr to the array */
1711  list_count = int_val;
1712  item_size = ply_type_size[prop->internal_type];
1713  store_array = (char **) (elem_data + prop->offset);
1714  if (list_count == 0) {
1715  if (store_it)
1716  *store_array = NULL;
1717  }
1718  else {
1719  if (store_it) {
1720  item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
1721  item = item_ptr;
1722  *store_array = item_ptr;
1723  }
1724 
1725  /* read items and store them into the array */
1726  for (k = 0; k < list_count; k++) {
1727  get_binary_item (fp, plyfile->file_type, prop->external_type,
1728  &int_val, &uint_val, &double_val);
1729  if (store_it) {
1730  store_item (item, prop->internal_type,
1731  int_val, uint_val, double_val);
1732  item += item_size;
1733  }
1734  }
1735  }
1736 
1737  }
1738  else { /* not a list */
1739  get_binary_item (fp, plyfile->file_type, prop->external_type,
1740  &int_val, &uint_val, &double_val);
1741  if (store_it) {
1742  item = elem_data + prop->offset;
1743  store_item (item, prop->internal_type, int_val, uint_val, double_val);
1744  }
1745  }
1746 
1747  }
1748  }
1749 
1750 
1751  /******************************************************************************
1752  Write to a file the word that represents a PLY data type.
1753 
1754  Entry:
1755  fp - file pointer
1756  code - code for type
1757  ******************************************************************************/
1758 
1759  void write_scalar_type (FILE *fp, int code)
1760  {
1761  /* make sure this is a valid code */
1762 
1763  if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
1764  fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
1765  exit (-1);
1766  }
1767 
1768  /* write the code to a file */
1769 
1770  fprintf (fp, "%s", type_names[code]);
1771  }
1772 
1773  /******************************************************************************
1774  Reverse the order in an array of bytes. This is the conversion from big
1775  endian to little endian and vice versa
1776 
1777  Entry:
1778  bytes - array of bytes to reverse (in place)
1779  num_bytes - number of bytes in array
1780  ******************************************************************************/
1781 
1782  void swap_bytes(char *bytes, int num_bytes)
1783  {
1784  int i;
1785  char temp;
1786 
1787  for (i=0; i < num_bytes/2; i++)
1788  {
1789  temp = bytes[i];
1790  bytes[i] = bytes[(num_bytes-1)-i];
1791  bytes[(num_bytes-1)-i] = temp;
1792  }
1793  }
1794 
1795  /******************************************************************************
1796  Find out if this machine is big endian or little endian
1797 
1798  Exit:
1799  set global variable, native_binary_type =
1800  either PLY_BINARY_BE or PLY_BINARY_LE
1801 
1802  ******************************************************************************/
1803 
1805  {
1806  endian_test_type test;
1807 
1808  test.int_value = 0;
1809  test.int_value = 1;
1810  if (test.byte_values[0] == 1)
1812  else if (test.byte_values[sizeof(int)-1] == 1)
1814  else
1815  {
1816  fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
1817  fprintf(stderr, "ply: Exiting...\n");
1818  exit(1);
1819  }
1820  }
1821 
1822  /******************************************************************************
1823  Verify that all the native types are the sizes we need
1824 
1825 
1826  ******************************************************************************/
1827 
1829  {
1830  if ((ply_type_size[PLY_CHAR] != sizeof(char)) ||
1831  (ply_type_size[PLY_SHORT] != sizeof(short)) ||
1832  (ply_type_size[PLY_INT] != sizeof(int)) ||
1833  (ply_type_size[PLY_UCHAR] != sizeof(unsigned char)) ||
1834  (ply_type_size[PLY_USHORT] != sizeof(unsigned short)) ||
1835  (ply_type_size[PLY_UINT] != sizeof(unsigned int)) ||
1836  (ply_type_size[PLY_FLOAT] != sizeof(float)) ||
1837  (ply_type_size[PLY_DOUBLE] != sizeof(double)))
1838  {
1839  fprintf(stderr, "ply: Type sizes do not match built-in types\n");
1840  fprintf(stderr, "ply: Exiting...\n");
1841  exit(1);
1842  }
1843 
1844  types_checked = 1;
1845  }
1846 
1847  /******************************************************************************
1848  Get a text line from a file and break it up into words.
1849 
1850  IMPORTANT: The calling routine call "free" on the returned pointer once
1851  finished with it.
1852 
1853  Entry:
1854  fp - file to read from
1855 
1856  Exit:
1857  nwords - number of words returned
1858  orig_line - the original line of characters
1859  returns a list of words from the line, or NULL if end-of-file
1860  ******************************************************************************/
1861 
1862  char **get_words(FILE *fp, int *nwords, char **orig_line)
1863  {
1864 #define BIG_STRING 4096
1865  static char str[BIG_STRING];
1866  static char str_copy[BIG_STRING];
1867  char **words;
1868  int max_words = 10;
1869  int num_words = 0;
1870  char *ptr,*ptr2;
1871  char *result;
1872 
1873  words = (char **) myalloc (sizeof (char *) * max_words);
1874 
1875  /* read in a line */
1876  result = fgets (str, BIG_STRING, fp);
1877  if (result == NULL) {
1878  free(words);
1879  *nwords = 0;
1880  *orig_line = NULL;
1881  return (NULL);
1882  }
1883  /* convert line-feed and tabs into spaces */
1884  /* (this guarentees that there will be a space before the */
1885  /* null character at the end of the string) */
1886 
1887  str[BIG_STRING-2] = ' ';
1888  str[BIG_STRING-1] = '\0';
1889 
1890  for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
1891  *ptr2 = *ptr;
1892  // Added line here to manage carriage returns
1893  if (*ptr == '\t' || *ptr == '\r') {
1894  *ptr = ' ';
1895  *ptr2 = ' ';
1896  }
1897  else if (*ptr == '\n') {
1898  *ptr = ' ';
1899  *ptr2 = '\0';
1900  break;
1901  }
1902  }
1903 
1904  /* find the words in the line */
1905 
1906  ptr = str;
1907  while (*ptr != '\0') {
1908 
1909  /* jump over leading spaces */
1910  while (*ptr == ' ')
1911  ptr++;
1912 
1913  /* break if we reach the end */
1914  if (*ptr == '\0')
1915  break;
1916 
1917  /* save pointer to beginning of word */
1918  if (num_words >= max_words) {
1919  max_words += 10;
1920  words = (char **) realloc (words, sizeof (char *) * max_words);
1921  }
1922  words[num_words++] = ptr;
1923 
1924  /* jump over non-spaces */
1925  while (*ptr != ' ')
1926  ptr++;
1927 
1928  /* place a null character here to mark the end of the word */
1929  *ptr++ = '\0';
1930  }
1931 
1932  /* return the list of words */
1933  *nwords = num_words;
1934  *orig_line = str_copy;
1935  return (words);
1936  }
1937 
1938 
1939  /******************************************************************************
1940  Return the value of an item, given a pointer to it and its type.
1941 
1942  Entry:
1943  item - pointer to item
1944  type - data type that "item" points to
1945 
1946  Exit:
1947  returns a double-precision float that contains the value of the item
1948  ******************************************************************************/
1949 
1950  double get_item_value(char *item, int type)
1951  {
1952  unsigned char *puchar;
1953  char *pchar;
1954  short int *pshort;
1955  unsigned short int *pushort;
1956  int *pint;
1957  unsigned int *puint;
1958  float *pfloat;
1959  double *pdouble;
1960  int int_value;
1961  unsigned int uint_value;
1962  double double_value;
1963 
1964  switch (type) {
1965  case PLY_CHAR:
1966  case PLY_INT_8:
1967  pchar = (char *) item;
1968  int_value = *pchar;
1969  return ((double) int_value);
1970  case PLY_UCHAR:
1971  case PLY_UINT_8:
1972  puchar = (unsigned char *) item;
1973  int_value = *puchar;
1974  return ((double) int_value);
1975  case PLY_SHORT:
1976  case PLY_INT_16:
1977  pshort = (short int *) item;
1978  int_value = *pshort;
1979  return ((double) int_value);
1980  case PLY_USHORT:
1981  case PLY_UINT_16:
1982  pushort = (unsigned short int *) item;
1983  int_value = *pushort;
1984  return ((double) int_value);
1985  case PLY_INT:
1986  case PLY_INT_32:
1987  pint = (int *) item;
1988  int_value = *pint;
1989  return ((double) int_value);
1990  case PLY_UINT:
1991  case PLY_UINT_32:
1992  puint = (unsigned int *) item;
1993  uint_value = *puint;
1994  return ((double) uint_value);
1995  case PLY_FLOAT:
1996  case PLY_FLOAT_32:
1997  pfloat = (float *) item;
1998  double_value = *pfloat;
1999  return (double_value);
2000  case PLY_DOUBLE:
2001  case PLY_FLOAT_64:
2002  pdouble = (double *) item;
2003  double_value = *pdouble;
2004  return (double_value);
2005  default:
2006  fprintf (stderr, "get_item_value: bad type = %d\n", type);
2007  exit (-1);
2008  }
2009  }
2010 
2011 
2012  /******************************************************************************
2013  Write out an item to a file as raw binary bytes.
2014 
2015  Entry:
2016  fp - file to write to
2017  int_val - integer version of item
2018  uint_val - unsigned integer version of item
2019  double_val - double-precision float version of item
2020  type - data type to write out
2021  ******************************************************************************/
2022 
2024  FILE *fp,
2025  int file_type,
2026  int int_val,
2027  unsigned int uint_val,
2028  double double_val,
2029  int type
2030  )
2031  {
2032  unsigned char uchar_val;
2033  char char_val;
2034  unsigned short ushort_val;
2035  short short_val;
2036  float float_val;
2037  void *value;
2038 
2039  switch (type) {
2040  case PLY_CHAR:
2041  case PLY_INT_8:
2042  char_val = char(int_val);
2043  value = &char_val;
2044  break;
2045  case PLY_SHORT:
2046  case PLY_INT_16:
2047  short_val = short(int_val);
2048  value = &short_val;
2049  break;
2050  case PLY_INT:
2051  case PLY_INT_32:
2052  value = &int_val;
2053  break;
2054  case PLY_UCHAR:
2055  case PLY_UINT_8:
2056  uchar_val = (unsigned char)(uint_val);
2057  value = &uchar_val;
2058  break;
2059  case PLY_USHORT:
2060  case PLY_UINT_16:
2061  ushort_val = (unsigned short)(uint_val);
2062  value = &ushort_val;
2063  break;
2064  case PLY_UINT:
2065  case PLY_UINT_32:
2066  value = &uint_val;
2067  break;
2068  case PLY_FLOAT:
2069  case PLY_FLOAT_32:
2070  float_val = (float)double_val;
2071  value = &float_val;
2072  break;
2073  case PLY_DOUBLE:
2074  case PLY_FLOAT_64:
2075  value = &double_val;
2076  break;
2077  default:
2078  fprintf (stderr, "write_binary_item: bad type = %d\n", type);
2079  exit (-1);
2080  }
2081 
2082 
2083  if ((file_type != native_binary_type) && (ply_type_size[type] > 1))
2084  swap_bytes((char *)value, ply_type_size[type]);
2085 
2086  if (fwrite (value, ply_type_size[type], 1, fp) != 1)
2087  {
2088  fprintf(stderr, "PLY ERROR: fwrite() failed -- aborting.\n");
2089  exit(1);
2090  }
2091  }
2092 
2093 
2094  /******************************************************************************
2095  Write out an item to a file as ascii characters.
2096 
2097  Entry:
2098  fp - file to write to
2099  int_val - integer version of item
2100  uint_val - unsigned integer version of item
2101  double_val - double-precision float version of item
2102  type - data type to write out
2103  ******************************************************************************/
2104 
2106  FILE *fp,
2107  int int_val,
2108  unsigned int uint_val,
2109  double double_val,
2110  int type
2111  )
2112  {
2113  switch (type) {
2114  case PLY_CHAR:
2115  case PLY_INT_8:
2116  case PLY_SHORT:
2117  case PLY_INT_16:
2118  case PLY_INT:
2119  case PLY_INT_32:
2120  if (fprintf (fp, "%d ", int_val) <= 0)
2121  {
2122  fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2123  exit(1);
2124  }
2125  break;
2126  case PLY_UCHAR:
2127  case PLY_UINT_8:
2128  case PLY_USHORT:
2129  case PLY_UINT_16:
2130  case PLY_UINT:
2131  case PLY_UINT_32:
2132 
2133  if (fprintf (fp, "%u ", uint_val) <= 0)
2134  {
2135  fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2136  exit(1);
2137  }
2138  break;
2139  case PLY_FLOAT:
2140  case PLY_FLOAT_32:
2141  case PLY_DOUBLE:
2142  case PLY_FLOAT_64:
2143  if (fprintf (fp, "%g ", double_val) <= 0)
2144  {
2145  fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2146  exit(1);
2147  }
2148  break;
2149  default:
2150  fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
2151  exit (-1);
2152  }
2153  }
2154 
2155 
2156  /******************************************************************************
2157  Write out an item to a file as ascii characters.
2158 
2159  Entry:
2160  fp - file to write to
2161  item - pointer to item to write
2162  type - data type that "item" points to
2163 
2164  Exit:
2165  returns a double-precision float that contains the value of the written item
2166  ******************************************************************************/
2167 
2168  double old_write_ascii_item(FILE *fp, char *item, int type)
2169  {
2170  unsigned char *puchar;
2171  char *pchar;
2172  short int *pshort;
2173  unsigned short int *pushort;
2174  int *pint;
2175  unsigned int *puint;
2176  float *pfloat;
2177  double *pdouble;
2178  int int_value;
2179  unsigned int uint_value;
2180  double double_value;
2181 
2182  switch (type) {
2183  case PLY_CHAR:
2184  case PLY_INT_8:
2185  pchar = (char *) item;
2186  int_value = *pchar;
2187  fprintf (fp, "%d ", int_value);
2188  return ((double) int_value);
2189  case PLY_UCHAR:
2190  case PLY_UINT_8:
2191  puchar = (unsigned char *) item;
2192  int_value = *puchar;
2193  fprintf (fp, "%d ", int_value);
2194  return ((double) int_value);
2195  case PLY_SHORT:
2196  case PLY_INT_16:
2197  pshort = (short int *) item;
2198  int_value = *pshort;
2199  fprintf (fp, "%d ", int_value);
2200  return ((double) int_value);
2201  case PLY_USHORT:
2202  case PLY_UINT_16:
2203  pushort = (unsigned short int *) item;
2204  int_value = *pushort;
2205  fprintf (fp, "%d ", int_value);
2206  return ((double) int_value);
2207  case PLY_INT:
2208  case PLY_INT_32:
2209  pint = (int *) item;
2210  int_value = *pint;
2211  fprintf (fp, "%d ", int_value);
2212  return ((double) int_value);
2213  case PLY_UINT:
2214  case PLY_UINT_32:
2215  puint = (unsigned int *) item;
2216  uint_value = *puint;
2217  fprintf (fp, "%u ", uint_value);
2218  return ((double) uint_value);
2219  case PLY_FLOAT:
2220  case PLY_FLOAT_32:
2221  pfloat = (float *) item;
2222  double_value = *pfloat;
2223  fprintf (fp, "%g ", double_value);
2224  return (double_value);
2225  case PLY_DOUBLE:
2226  case PLY_FLOAT_64:
2227  pdouble = (double *) item;
2228  double_value = *pdouble;
2229  fprintf (fp, "%g ", double_value);
2230  return (double_value);
2231  default:
2232  fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type);
2233  exit (-1);
2234  }
2235  }
2236 
2237 
2238  /******************************************************************************
2239  Get the value of an item that is in memory, and place the result
2240  into an integer, an unsigned integer and a double.
2241 
2242  Entry:
2243  ptr - pointer to the item
2244  type - data type supposedly in the item
2245 
2246  Exit:
2247  int_val - integer value
2248  uint_val - unsigned integer value
2249  double_val - double-precision floating point value
2250  ******************************************************************************/
2251 
2253  void *ptr,
2254  int type,
2255  int *int_val,
2256  unsigned int *uint_val,
2257  double *double_val
2258  )
2259  {
2260  switch (type) {
2261  case PLY_CHAR:
2262  case PLY_INT_8:
2263  *int_val = *((char *) ptr);
2264  *uint_val = *int_val;
2265  *double_val = *int_val;
2266  break;
2267  case PLY_UCHAR:
2268  case PLY_UINT_8:
2269  *uint_val = *((unsigned char *) ptr);
2270  *int_val = *uint_val;
2271  *double_val = *uint_val;
2272  break;
2273  case PLY_SHORT:
2274  case PLY_INT_16:
2275  *int_val = *((short int *) ptr);
2276  *uint_val = *int_val;
2277  *double_val = *int_val;
2278  break;
2279  case PLY_USHORT:
2280  case PLY_UINT_16:
2281  *uint_val = *((unsigned short int *) ptr);
2282  *int_val = *uint_val;
2283  *double_val = *uint_val;
2284  break;
2285  case PLY_INT:
2286  case PLY_INT_32:
2287  *int_val = *((int *) ptr);
2288  *uint_val = *int_val;
2289  *double_val = *int_val;
2290  break;
2291  case PLY_UINT:
2292  case PLY_UINT_32:
2293  *uint_val = *((unsigned int *) ptr);
2294  *int_val = *uint_val;
2295  *double_val = *uint_val;
2296  break;
2297  case PLY_FLOAT:
2298  case PLY_FLOAT_32:
2299  *double_val = *((float *) ptr);
2300  *int_val = (int) *double_val;
2301  *uint_val = (unsigned int) *double_val;
2302  break;
2303  case PLY_DOUBLE:
2304  case PLY_FLOAT_64:
2305  *double_val = *((double *) ptr);
2306  *int_val = (int) *double_val;
2307  *uint_val = (unsigned int) *double_val;
2308  break;
2309  default:
2310  fprintf (stderr, "get_stored_item: bad type = %d\n", type);
2311  exit (-1);
2312  }
2313  }
2314 
2315 
2316  /******************************************************************************
2317  Get the value of an item from a binary file, and place the result
2318  into an integer, an unsigned integer and a double.
2319 
2320  Entry:
2321  fp - file to get item from
2322  type - data type supposedly in the word
2323 
2324  Exit:
2325  int_val - integer value
2326  uint_val - unsigned integer value
2327  double_val - double-precision floating point value
2328  ******************************************************************************/
2329 
2331  FILE *fp,
2332  int file_type,
2333  int type,
2334  int *int_val,
2335  unsigned int *uint_val,
2336  double *double_val
2337  )
2338  {
2339  char c[8];
2340  void *ptr;
2341 
2342  ptr = (void *) c;
2343 
2344  if (fread (ptr, ply_type_size[type], 1, fp) != 1)
2345  {
2346  fprintf(stderr, "PLY ERROR: fread() failed -- aborting.\n");
2347  exit(1);
2348  }
2349 
2350 
2351  if ((file_type != native_binary_type) && (ply_type_size[type] > 1))
2352  swap_bytes((char *)ptr, ply_type_size[type]);
2353 
2354  switch (type) {
2355  case PLY_CHAR:
2356  case PLY_INT_8:
2357  *int_val = *((char *) ptr);
2358  *uint_val = *int_val;
2359  *double_val = *int_val;
2360  break;
2361  case PLY_UCHAR:
2362  case PLY_UINT_8:
2363  *uint_val = *((unsigned char *) ptr);
2364  *int_val = *uint_val;
2365  *double_val = *uint_val;
2366  break;
2367  case PLY_SHORT:
2368  case PLY_INT_16:
2369  *int_val = *((short int *) ptr);
2370  *uint_val = *int_val;
2371  *double_val = *int_val;
2372  break;
2373  case PLY_USHORT:
2374  case PLY_UINT_16:
2375  *uint_val = *((unsigned short int *) ptr);
2376  *int_val = *uint_val;
2377  *double_val = *uint_val;
2378  break;
2379  case PLY_INT:
2380  case PLY_INT_32:
2381  *int_val = *((int *) ptr);
2382  *uint_val = *int_val;
2383  *double_val = *int_val;
2384  break;
2385  case PLY_UINT:
2386  case PLY_UINT_32:
2387  *uint_val = *((unsigned int *) ptr);
2388  *int_val = *uint_val;
2389  *double_val = *uint_val;
2390  break;
2391  case PLY_FLOAT:
2392  case PLY_FLOAT_32:
2393  *double_val = *((float *) ptr);
2394  *int_val = (int) *double_val;
2395  *uint_val = (unsigned int) *double_val;
2396  break;
2397  case PLY_DOUBLE:
2398  case PLY_FLOAT_64:
2399  *double_val = *((double *) ptr);
2400  *int_val = (int) *double_val;
2401  *uint_val = (unsigned int) *double_val;
2402  break;
2403  default:
2404  fprintf (stderr, "get_binary_item: bad type = %d\n", type);
2405  exit (-1);
2406  }
2407  }
2408 
2409 
2410  /******************************************************************************
2411  Extract the value of an item from an ascii word, and place the result
2412  into an integer, an unsigned integer and a double.
2413 
2414  Entry:
2415  word - word to extract value from
2416  type - data type supposedly in the word
2417 
2418  Exit:
2419  int_val - integer value
2420  uint_val - unsigned integer value
2421  double_val - double-precision floating point value
2422  ******************************************************************************/
2423 
2425  char *word,
2426  int type,
2427  int *int_val,
2428  unsigned int *uint_val,
2429  double *double_val
2430  )
2431  {
2432  switch (type) {
2433  case PLY_CHAR:
2434  case PLY_INT_8:
2435  case PLY_UCHAR:
2436  case PLY_UINT_8:
2437  case PLY_SHORT:
2438  case PLY_INT_16:
2439  case PLY_USHORT:
2440  case PLY_UINT_16:
2441  case PLY_INT:
2442  case PLY_INT_32:
2443  *int_val = atoi (word);
2444  *uint_val = (unsigned int) *int_val;
2445  *double_val = (double) *int_val;
2446  break;
2447 
2448  case PLY_UINT:
2449  case PLY_UINT_32:
2450  *uint_val = strtol (word, (char **) NULL, 10);
2451  *int_val = (int) *uint_val;
2452  *double_val = (double) *uint_val;
2453  break;
2454 
2455  case PLY_FLOAT:
2456  case PLY_FLOAT_32:
2457  case PLY_DOUBLE:
2458  case PLY_FLOAT_64:
2459  *double_val = atof (word);
2460  *int_val = (int) *double_val;
2461  *uint_val = (unsigned int) *double_val;
2462  break;
2463 
2464  default:
2465  fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
2466  exit (-1);
2467  }
2468  }
2469 
2470 
2471  /******************************************************************************
2472  Store a value into a place being pointed to, guided by a data type.
2473 
2474  Entry:
2475  item - place to store value
2476  type - data type
2477  int_val - integer version of value
2478  uint_val - unsigned integer version of value
2479  double_val - double version of value
2480 
2481  Exit:
2482  item - pointer to stored value
2483  ******************************************************************************/
2484 
2485  void store_item (
2486  char *item,
2487  int type,
2488  int int_val,
2489  unsigned int uint_val,
2490  double double_val
2491  )
2492  {
2493  unsigned char *puchar;
2494  short int *pshort;
2495  unsigned short int *pushort;
2496  int *pint;
2497  unsigned int *puint;
2498  float *pfloat;
2499  double *pdouble;
2500 
2501 
2502  switch (type) {
2503  case PLY_CHAR:
2504  case PLY_INT_8:
2505  *item = char(int_val);
2506  break;
2507  case PLY_UCHAR:
2508  case PLY_UINT_8:
2509  puchar = (unsigned char *) item;
2510  *puchar = (unsigned char)(uint_val);
2511  break;
2512  case PLY_SHORT:
2513  case PLY_INT_16:
2514  pshort = (short *) item;
2515  *pshort = short(int_val);
2516  break;
2517  case PLY_USHORT:
2518  case PLY_UINT_16:
2519  pushort = (unsigned short *) item;
2520  *pushort = (unsigned short)(uint_val);
2521  break;
2522  case PLY_INT:
2523  case PLY_INT_32:
2524  pint = (int *) item;
2525  *pint = int_val;
2526  break;
2527  case PLY_UINT:
2528  case PLY_UINT_32:
2529  puint = (unsigned int *) item;
2530  *puint = uint_val;
2531  break;
2532  case PLY_FLOAT:
2533  case PLY_FLOAT_32:
2534  pfloat = (float *) item;
2535  *pfloat = (float)double_val;
2536  break;
2537  case PLY_DOUBLE:
2538  case PLY_FLOAT_64:
2539  pdouble = (double *) item;
2540  *pdouble = double_val;
2541  break;
2542  default:
2543  fprintf (stderr, "store_item: bad type = %d\n", type);
2544  exit (-1);
2545  }
2546  }
2547 
2548 
2549  /******************************************************************************
2550  Add an element to a PLY file descriptor.
2551 
2552  Entry:
2553  plyfile - PLY file descriptor
2554  words - list of words describing the element
2555  nwords - number of words in the list
2556  ******************************************************************************/
2557 
2558  void add_element (PlyFile *plyfile, char **words)
2559  {
2560  PlyElement *elem;
2561 
2562  /* create the new element */
2563  elem = (PlyElement *) myalloc (sizeof (PlyElement));
2564  elem->name = _strdup (words[1]);
2565  elem->num = atoi (words[2]);
2566  elem->nprops = 0;
2567 
2568  /* make room for new element in the object's list of elements */
2569  if (plyfile->nelems == 0)
2570  plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
2571  else
2572  plyfile->elems = (PlyElement **) realloc (plyfile->elems,
2573  sizeof (PlyElement *) * (plyfile->nelems + 1));
2574 
2575  /* add the new element to the object's list */
2576  plyfile->elems[plyfile->nelems] = elem;
2577  plyfile->nelems++;
2578  }
2579 
2580 
2581  /******************************************************************************
2582  Return the type of a property, given the name of the property.
2583 
2584  Entry:
2585  name - name of property type
2586 
2587  Exit:
2588  returns integer code for property, or 0 if not found
2589  ******************************************************************************/
2590 
2591  int get_prop_type(char *type_name)
2592  {
2593  int i;
2594 
2595  for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
2596  if (equal_strings (type_name, type_names[i]))
2597  return (i);
2598 
2599  /* if we get here, we didn't find the type */
2600  return (0);
2601  }
2602 
2603 
2604  /******************************************************************************
2605  Add a property to a PLY file descriptor.
2606 
2607  Entry:
2608  plyfile - PLY file descriptor
2609  words - list of words describing the property
2610  nwords - number of words in the list
2611  ******************************************************************************/
2612 
2613  void add_property (PlyFile *plyfile, char **words)
2614  {
2615  PlyProperty *prop;
2616  PlyElement *elem;
2617 
2618  /* create the new property */
2619 
2620  prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
2621 
2622  if (equal_strings (words[1], "list")) { /* is a list */
2623  prop->count_external = get_prop_type (words[2]);
2624  prop->external_type = get_prop_type (words[3]);
2625  prop->name = _strdup (words[4]);
2626  prop->is_list = 1;
2627  }
2628  else { /* not a list */
2629  prop->external_type = get_prop_type (words[1]);
2630  prop->name = _strdup (words[2]);
2631  prop->is_list = 0;
2632  }
2633 
2634  /* add this property to the list of properties of the current element */
2635 
2636  elem = plyfile->elems[plyfile->nelems - 1];
2637 
2638  if (elem->nprops == 0)
2639  elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
2640  else
2641  elem->props = (PlyProperty **) realloc (elem->props,
2642  sizeof (PlyProperty *) * (elem->nprops + 1));
2643 
2644  elem->props[elem->nprops] = prop;
2645  elem->nprops++;
2646  }
2647 
2648 
2649  /******************************************************************************
2650  Add a comment to a PLY file descriptor.
2651 
2652  Entry:
2653  plyfile - PLY file descriptor
2654  line - line containing comment
2655  ******************************************************************************/
2656 
2657  void add_comment (PlyFile *plyfile, char *line)
2658  {
2659  int i;
2660 
2661  /* skip over "comment" and leading spaces and tabs */
2662  i = 7;
2663  while (line[i] == ' ' || line[i] == '\t')
2664  i++;
2665 
2666  ply_put_comment (plyfile, &line[i]);
2667  }
2668 
2669 
2670  /******************************************************************************
2671  Add a some object information to a PLY file descriptor.
2672 
2673  Entry:
2674  plyfile - PLY file descriptor
2675  line - line containing text info
2676  ******************************************************************************/
2677 
2678  void add_obj_info (PlyFile *plyfile, char *line)
2679  {
2680  int i;
2681 
2682  /* skip over "obj_info" and leading spaces and tabs */
2683  i = 8;
2684  while (line[i] == ' ' || line[i] == '\t')
2685  i++;
2686 
2687  ply_put_obj_info (plyfile, &line[i]);
2688  }
2689 
2690 
2691  /******************************************************************************
2692  Copy a property.
2693  ******************************************************************************/
2694 
2696  {
2697  dest->name = _strdup (src->name);
2698  dest->external_type = src->external_type;
2699  dest->internal_type = src->internal_type;
2700  dest->offset = src->offset;
2701 
2702  dest->is_list = src->is_list;
2703  dest->count_external = src->count_external;
2704  dest->count_internal = src->count_internal;
2705  dest->count_offset = src->count_offset;
2706  }
2707 
2708 
2709  /******************************************************************************
2710  Allocate some memory.
2711 
2712  Entry:
2713  size - amount of memory requested (in bytes)
2714  lnum - line number from which memory was requested
2715  fname - file name from which memory was requested
2716  ******************************************************************************/
2717 
2718  char *my_alloc(int size, int lnum, const char *fname)
2719  {
2720  char *ptr;
2721 
2722  ptr = (char *) malloc (size);
2723 
2724  if (ptr == 0) {
2725  fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname);
2726  }
2727 
2728  return (ptr);
2729  }
2730 
std::string filename
int size
std::string version
std::string name
int offset
char type
void store_item(char *, int, int, unsigned int, double)
Definition: PlyFile.cpp:2485
void write_ascii_item(FILE *, int, unsigned int, double, int)
Definition: PlyFile.cpp:2105
void swap_bytes(char *, int)
Definition: PlyFile.cpp:1782
void ply_free_other_elements(PlyOtherElems *other_elems)
Definition: PlyFile.cpp:1405
PlyFile * ply_open_for_writing(char *filename, int nelems, const char **elem_names, int file_type, float *version)
Definition: PlyFile.cpp:240
#define NO_OTHER_PROPS
Definition: PlyFile.cpp:93
void ply_element_count(PlyFile *plyfile, const char *elem_name, int nelems)
Definition: PlyFile.cpp:445
void ply_describe_element(PlyFile *plyfile, char *elem_name, int nelems, int nprops, PlyProperty *prop_list)
Definition: PlyFile.cpp:294
char ** get_words(FILE *, int *, char **)
Definition: PlyFile.cpp:1862
#define OTHER_PROP
Definition: PlyFile.cpp:98
char ** ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
Definition: PlyFile.cpp:1093
void ply_put_element(PlyFile *plyfile, void *elem_ptr)
Definition: PlyFile.cpp:569
void ply_describe_other_properties(PlyFile *plyfile, PlyOtherProp *other, int offset)
Definition: PlyFile.cpp:385
PlyElement * find_element(PlyFile *, const char *)
Definition: PlyFile.cpp:1484
void ply_describe_other_elements(PlyFile *plyfile, PlyOtherElems *other_elems)
Definition: PlyFile.cpp:1333
PlyOtherElems * ply_get_other_element(PlyFile *plyfile, char *elem_name, int elem_count)
Definition: PlyFile.cpp:1261
void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
Definition: PlyFile.cpp:706
int get_prop_type(char *type_name)
Definition: PlyFile.cpp:2591
void get_native_binary_type()
Definition: PlyFile.cpp:1804
void get_stored_item(void *, int, int *, unsigned int *, double *)
Definition: PlyFile.cpp:2252
int ply_get_property(PlyFile *plyfile, char *elem_name, PlyProperty *prop)
Definition: PlyFile.cpp:1010
#define STORE_PROP
Definition: PlyFile.cpp:96
void ply_get_element_setup(PlyFile *plyfile, char *elem_name, int nprops, PlyProperty *prop_list)
Definition: PlyFile.cpp:959
void write_scalar_type(FILE *, int)
Definition: PlyFile.cpp:1759
double get_item_value(char *, int)
Definition: PlyFile.cpp:1950
void ply_close_custom(PlyFile *plyfile)
Definition: PlyFile.cpp:1425
PlyOtherProp * ply_get_other_properties(PlyFile *plyfile, char *elem_name, int offset)
Definition: PlyFile.cpp:1182
void write_binary_item(FILE *, int, int, unsigned int, double, int)
Definition: PlyFile.cpp:2023
static int types_checked
Definition: PlyFile.cpp:91
PlyFile * ply_read_custom(FILE *fp, int *nelems, char ***elem_names)
Definition: PlyFile.cpp:744
#define BIG_STRING
void copy_property(PlyProperty *, PlyProperty *)
Definition: PlyFile.cpp:2695
void add_element(PlyFile *, char **)
Definition: PlyFile.cpp:2558
PlyFile * ply_write_custom(FILE *fp, int nelems, const char **elem_names, int file_type)
Definition: PlyFile.cpp:176
void ply_put_other_elements(PlyFile *plyfile)
Definition: PlyFile.cpp:1375
int ply_type_size[]
Definition: PlyFile.cpp:63
void ascii_get_element(PlyFile *, char *)
Definition: PlyFile.cpp:1531
void ply_header_complete(PlyFile *plyfile)
Definition: PlyFile.cpp:472
void add_comment(PlyFile *, char *)
Definition: PlyFile.cpp:2657
#define NAMED_PROP
Definition: PlyFile.cpp:99
void ply_describe_property(PlyFile *plyfile, const char *elem_name, PlyProperty *prop)
Definition: PlyFile.cpp:339
void ply_put_comment(PlyFile *plyfile, char *comment)
Definition: PlyFile.cpp:682
void ply_get_info(PlyFile *ply, float *version, int *file_type)
Definition: PlyFile.cpp:1445
void add_obj_info(PlyFile *, char *)
Definition: PlyFile.cpp:2678
void check_types()
Definition: PlyFile.cpp:1828
void setup_other_props(PlyElement *elem)
Definition: PlyFile.cpp:1111
int equal_strings(const char *, const char *)
Definition: PlyFile.cpp:1459
void binary_get_element(PlyFile *, char *)
Definition: PlyFile.cpp:1652
void ply_get_element(PlyFile *plyfile, void *elem_ptr)
Definition: PlyFile.cpp:1054
PlyProperty * find_property(PlyElement *, const char *, int *)
Definition: PlyFile.cpp:1508
void get_ascii_item(char *, int, int *, unsigned int *, double *)
Definition: PlyFile.cpp:2424
char * my_alloc(int, int, const char *)
Definition: PlyFile.cpp:2718
static int native_binary_type
Definition: PlyFile.cpp:90
const char * type_names[]
Definition: PlyFile.cpp:41
void add_property(PlyFile *, char **)
Definition: PlyFile.cpp:2613
double old_write_ascii_item(FILE *, char *, int)
Definition: PlyFile.cpp:2168
void get_binary_item(FILE *, int, int, int *, unsigned int *, double *)
Definition: PlyFile.cpp:2330
char ** old_get_words(FILE *, int *)
#define DONT_STORE_PROP
Definition: PlyFile.cpp:95
char ** ply_get_comments(PlyFile *plyfile, int *num_comments)
Definition: PlyFile.cpp:1074
PlyFile * ply_open_for_reading(char *filename, int *nelems, char ***elem_names, int *file_type, float *version)
Definition: PlyFile.cpp:860
void ply_put_element_setup(PlyFile *plyfile, const char *elem_name)
Definition: PlyFile.cpp:545
PlyProperty ** ply_get_element_description(PlyFile *plyfile, char *elem_name, int *nelems, int *nprops)
Definition: PlyFile.cpp:915
#define PLY_UINT_32
Definition: Ply.h:75
#define PLY_UINT
Definition: Ply.h:67
#define PLY_UINT_16
Definition: Ply.h:73
#define PLY_ASCII
Definition: Ply.h:51
#define PLY_FLOAT
Definition: Ply.h:68
#define myalloc(mem_size)
Definition: Ply.h:150
#define PLY_INT
Definition: Ply.h:64
#define PLY_FLOAT_32
Definition: Ply.h:76
#define PLY_DOUBLE
Definition: Ply.h:69
#define PLY_BINARY_LE
Definition: Ply.h:53
#define PLY_UCHAR
Definition: Ply.h:65
#define PLY_USHORT
Definition: Ply.h:66
#define PLY_END_TYPE
Definition: Ply.h:79
#define PLY_BINARY_BE
Definition: Ply.h:52
#define PLY_FLOAT_64
Definition: Ply.h:77
#define _strdup
Definition: Ply.h:39
#define PLY_INT_16
Definition: Ply.h:72
#define PLY_SHORT
Definition: Ply.h:63
#define PLY_UINT_8
Definition: Ply.h:71
#define REALLOCN(PTR, TYPE, OLD_N, NEW_N)
Definition: Ply.h:153
#define PLY_CHAR
Definition: Ply.h:62
#define PLY_BINARY_NATIVE
Definition: Ply.h:54
#define PLY_INT_8
Definition: Ply.h:70
#define PLY_INT_32
Definition: Ply.h:74
#define PLY_START_TYPE
Definition: Ply.h:61
void * bytes
#define NULL
core::Tensor result
Definition: VtkUtils.cpp:76
#define offsetof(STRUCTURE, FIELD)
Definition: sqlite3.c:14241
Definition: Ply.h:118
Definition: Ply.h:122
OtherData ** other_data
Definition: Ply.h:125
char * elem_name
Definition: Ply.h:123
PlyOtherProp * other_props
Definition: Ply.h:126
int elem_count
Definition: Ply.h:124
int other_offset
Definition: Ply.h:107
int num
Definition: Ply.h:102
int other_size
Definition: Ply.h:108
char * name
Definition: Ply.h:101
char * store_prop
Definition: Ply.h:106
PlyProperty ** props
Definition: Ply.h:105
int nprops
Definition: Ply.h:104
Definition: Ply.h:134
int num_comments
Definition: Ply.h:140
int nelems
Definition: Ply.h:138
float version
Definition: Ply.h:137
char ** obj_info
Definition: Ply.h:143
PlyElement * which_elem
Definition: Ply.h:144
PlyElement ** elems
Definition: Ply.h:139
int num_obj_info
Definition: Ply.h:142
int file_type
Definition: Ply.h:136
PlyOtherElems * other_elems
Definition: Ply.h:145
char ** comments
Definition: Ply.h:141
FILE * fp
Definition: Ply.h:135
OtherElem * other_list
Definition: Ply.h:131
int num_elems
Definition: Ply.h:130
char * name
Definition: Ply.h:112
PlyProperty ** props
Definition: Ply.h:115
int size
Definition: Ply.h:113
int nprops
Definition: Ply.h:114
int external_type
Definition: Ply.h:89
int count_offset
Definition: Ply.h:96
int count_external
Definition: Ply.h:94
char * name
Definition: Ply.h:88
int count_internal
Definition: Ply.h:95
int internal_type
Definition: Ply.h:90
int is_list
Definition: Ply.h:93
int offset
Definition: Ply.h:91
char byte_values[sizeof(int)]
Definition: PlyFile.cpp:86