plyfile.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:60k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. /*
  2. The interface routines for reading and writing PLY polygon files.
  3. - Kari Pulli, April 1998
  4. Modified from PLY library by
  5. - Greg Turk, March 1994
  6. A PLY file contains a single polygonal _object_.
  7. An object is composed of lists of _elements_.  
  8. Typical elements are vertices, faces, edges and materials.
  9. Each type of element for a given object has one or more 
  10. _properties_ associated with the element type.  
  11. For instance, a vertex element may have as properties three 
  12. floating-point values x,y,z and three unsigned
  13. chars for red, green and blue.
  14. ---------------------------------------------------------------
  15. Copyright (c) 1998 The Board of Trustees of The Leland Stanford
  16. Junior University.  All rights reserved.   
  17.   
  18. Permission to use, copy, modify and distribute this software and 
  19. its documentation for any purpose is hereby granted without fee, 
  20. provided that the above copyright notice and this permission 
  21. notice appear in all copies of this software and that you do not 
  22. sell the software.   
  23.   
  24. THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
  25. EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY   
  26. WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   
  27. */
  28. #include <iostream.h>
  29. #include <stdlib.h>
  30. #include <math.h>
  31. #include <string.h>
  32. #ifdef linux
  33. #    define __STL_THROW(x) throw x
  34. #    include <stdexcept>
  35. using std::length_error;
  36. #else
  37. #    include <stdexcept.h>
  38. #endif
  39. #include <assert.h>
  40. #include "ply++.h"
  41. #ifndef WIN32
  42. # include "zlib_fgets.h"
  43. #endif
  44. char *type_names[] = {
  45. "invalid",
  46. "char", "short", "int",
  47. "uchar", "ushort", "uint",
  48. "float", "double",
  49. };
  50. char *new_type_names[] = {
  51. "invalid",
  52. "int8", "int16", "int32",
  53. "uint8", "uint16", "uint32",
  54. "float32", "float64",
  55. };
  56. int ply_type_size[] = {
  57.   0, 1, 2, 4, 1, 2, 4, 4, 8
  58. };
  59. #define NO_OTHER_PROPS  -1
  60. #define DONT_STORE_PROP  0
  61. #define STORE_PROP       1
  62. #define OTHER_PROP       0
  63. #define NAMED_PROP       1
  64. #if defined(WIN32) || defined(i386)
  65. #define NATIVE_ENDIANNES PLY_BINARY_LE
  66. #else
  67. #define NATIVE_ENDIANNES PLY_BINARY_BE
  68. #endif
  69. PlyFile::PlyFile() 
  70.   : fp(NULL)
  71.   fbuf_size = 1024;
  72.   fbuf = new char[fbuf_size];
  73.   fb_s = fb_e = fbuf; 
  74. #ifndef _WIN32
  75.   gzfp = NULL;
  76. #endif
  77. }
  78. PlyFile::~PlyFile() 
  79.   delete[] fbuf;
  80.   close(); 
  81. }
  82. // this is to be called to make sure the buffer has
  83. // enough data for the next read(s)
  84. void
  85. PlyFile::fbuf_need(int n)
  86. {
  87.   int d = fb_e - fb_s; // how much is left
  88.   if (d < n) {
  89.     // not enough, get more
  90.     if (n > fbuf_size) {
  91.       // have to allocate more
  92.       char *tmp = new char[n];
  93.       if (d) {
  94. // there is some unread chars, move them to start
  95. memcpy(tmp, fb_s, d);
  96.       }
  97.       delete[] fbuf;
  98.       fbuf = tmp;
  99.       fbuf_size = n;
  100.     } else {
  101.       // have enough space
  102.       if (d) {
  103. // there is some unread chars, move them to start
  104. memcpy(fbuf, fb_s, d);
  105.       }
  106.     }
  107. #ifdef WIN32
  108.     int i = fread(fbuf + d, 1, fbuf_size - d, fp);
  109. #else
  110.     int i = gzread(gzfp, fbuf+d, fbuf_size-d);
  111. #endif
  112. #ifdef __EXCEPTIONS
  113.     if (!i) {
  114.       __STL_THROW(length_error("ply_file_read"));
  115.     }
  116. #else
  117.     assert(i);
  118. #endif
  119.     fb_s = fbuf;
  120.     fb_e = fb_s + d + i;
  121.   }
  122. }
  123. char
  124. PlyFile::read_char(void)
  125. {
  126.   fbuf_need(1);
  127.   return *(fb_s++);
  128. }
  129. unsigned char
  130. PlyFile::read_uchar(void)
  131. {
  132.   fbuf_need(1);
  133.   return *(fb_s++);
  134. }
  135. short
  136. PlyFile::read_short_BE(void)
  137. {
  138.   fbuf_need(2);
  139.   short s;
  140.   char *p = (char *)&s;
  141.   p[0] = fb_s[0];
  142.   p[1] = fb_s[1];
  143.   fb_s += 2;
  144.   return s;
  145. }
  146. unsigned short
  147. PlyFile::read_ushort_BE(void)
  148. {
  149.   fbuf_need(2);
  150.   unsigned short s;
  151.   char *p = (char *)&s;
  152.   p[0] = fb_s[0];
  153.   p[1] = fb_s[1];
  154.   fb_s += 2;
  155.   return s;
  156. }
  157. int
  158. PlyFile::read_int_BE(void)
  159. {
  160.   fbuf_need(4);
  161.   int s;
  162.   char *p = (char *)&s;
  163.   p[0] = fb_s[0];
  164.   p[1] = fb_s[1];
  165.   p[2] = fb_s[2];
  166.   p[3] = fb_s[3];
  167.   fb_s += 4;
  168.   return s;
  169. }
  170. unsigned int
  171. PlyFile::read_uint_BE(void)
  172. {
  173.   fbuf_need(4);
  174.   unsigned int s;
  175.   char *p = (char *)&s;
  176.   p[0] = fb_s[0];
  177.   p[1] = fb_s[1];
  178.   p[2] = fb_s[2];
  179.   p[3] = fb_s[3];
  180.   fb_s += 4;
  181.   return s;
  182. }
  183. float
  184. PlyFile::read_float_BE(void)
  185. {
  186.   fbuf_need(4);
  187.   float s;
  188.   char *p = (char *)&s;
  189.   p[0] = fb_s[0];
  190.   p[1] = fb_s[1];
  191.   p[2] = fb_s[2];
  192.   p[3] = fb_s[3];
  193.   fb_s += 4;
  194.   return s;
  195. }
  196. double
  197. PlyFile::read_double_BE(void)
  198. {
  199.   fbuf_need(8);
  200.   double s;
  201.   char *p = (char *)&s;
  202.   p[0] = fb_s[0];
  203.   p[1] = fb_s[1];
  204.   p[2] = fb_s[2];
  205.   p[3] = fb_s[3];
  206.   p[4] = fb_s[4];
  207.   p[5] = fb_s[5];
  208.   p[6] = fb_s[6];
  209.   p[7] = fb_s[7];
  210.   fb_s += 8;
  211.   return s;
  212. }
  213. short
  214. PlyFile::read_short_LE(void)
  215. {
  216.   fbuf_need(2);
  217.   short s;
  218.   char *p = (char *)&s;
  219.   p[0] = fb_s[1];
  220.   p[1] = fb_s[0];
  221.   fb_s += 2;
  222.   return s;
  223. }
  224. unsigned short
  225. PlyFile::read_ushort_LE(void)
  226. {
  227.   fbuf_need(2);
  228.   unsigned short s;
  229.   char *p = (char *)&s;
  230.   p[0] = fb_s[1];
  231.   p[1] = fb_s[0];
  232.   fb_s += 2;
  233.   return s;
  234. }
  235. int
  236. PlyFile::read_int_LE(void)
  237. {
  238.   fbuf_need(4);
  239.   int s;
  240.   char *p = (char *)&s;
  241.   p[0] = fb_s[3];
  242.   p[1] = fb_s[2];
  243.   p[2] = fb_s[1];
  244.   p[3] = fb_s[0];
  245.   fb_s += 4;
  246.   return s;
  247. }
  248. unsigned int
  249. PlyFile::read_uint_LE(void)
  250. {
  251.   fbuf_need(4);
  252.   unsigned int s;
  253.   char *p = (char *)&s;
  254.   p[0] = fb_s[3];
  255.   p[1] = fb_s[2];
  256.   p[2] = fb_s[1];
  257.   p[3] = fb_s[0];
  258.   fb_s += 4;
  259.   return s;
  260. }
  261. float
  262. PlyFile::read_float_LE(void)
  263. {
  264.   fbuf_need(4);
  265.   float s;
  266.   char *p = (char *)&s;
  267.   p[0] = fb_s[3];
  268.   p[1] = fb_s[2];
  269.   p[2] = fb_s[1];
  270.   p[3] = fb_s[0];
  271.   fb_s += 4;
  272.   return s;
  273. }
  274. double
  275. PlyFile::read_double_LE(void)
  276. {
  277.   fbuf_need(8);
  278.   double s;
  279.   char *p = (char *)&s;
  280.   p[0] = fb_s[7];
  281.   p[1] = fb_s[6];
  282.   p[2] = fb_s[5];
  283.   p[3] = fb_s[4];
  284.   p[4] = fb_s[3];
  285.   p[5] = fb_s[2];
  286.   p[6] = fb_s[1];
  287.   p[7] = fb_s[0];
  288.   fb_s += 8;
  289.   return s;
  290. }
  291. int
  292. PlyFile::to_int(char *item, int type)
  293. {
  294.   switch (type) {
  295.   case PLY_CHAR:   return *item;
  296.   case PLY_UCHAR:  return *((unsigned char*)item);
  297.   case PLY_SHORT:  return *((short*)item);
  298.   case PLY_USHORT: return *((unsigned short*)item);
  299.   case PLY_INT:    return *((int*)item);
  300.   case PLY_UINT:   return *((unsigned int*)item);
  301.   case PLY_FLOAT:  return *((float*)item);
  302.   case PLY_DOUBLE: return *((double*)item);
  303.   default:         return 0;
  304.   }
  305. }
  306. /*************/
  307. /*  Writing  */
  308. /*************/
  309. /*****************************************************************
  310. Open a polygon file for writing.
  311. Entry:
  312.   filename   - name of file to read from
  313.   nelems     - number of elements in object
  314.   elem_names - list of element names
  315.   file_type  - file type, either ascii or binary
  316. Exit:
  317.   returns 1 if success, 0 if error
  318. ******************************************************************/
  319. int
  320. PlyFile::open_for_writing(const char  *filename,
  321.   int    nelems,
  322.   char **elem_names,
  323.   int    file_type)
  324. {
  325.   /* tack on the extension .ply, if necessary */
  326.   char *name = new char[(strlen(filename) + 5)];
  327.   strcpy (name, filename);
  328.   if (strlen (name) < 4 ||
  329.       strcmp (name + strlen (name) - 4, ".ply") != 0)
  330.       strcat (name, ".ply");
  331.   /* open the file for writing */
  332. #ifdef WIN32
  333.   fp = fopen (name, "wb");
  334. #else
  335.   fp = fopen (name, "w");
  336. #endif
  337.   delete[] name;
  338.   if (fp == NULL)
  339.     return 0;
  340.   /* create a record for this object */
  341.   m_file_type  = file_type;
  342.   m_version    = 1.0;
  343.   other_elems  = NULL;
  344.   /* tuck aside the names of the elements */
  345.   for (int i = 0; i < nelems; i++) {
  346.     elems.push_back(PlyElement(elem_names[i]));
  347.   }
  348.   return 1;
  349. }
  350. /*****************************************************************
  351. Open a polygon file for reading.
  352. Entry:
  353.   filename - name of file to read from
  354. Exit:
  355.   nelems     - number of elements in object
  356.   elem_names - list of element names
  357.   returns 1 if success, 0 if error
  358. ******************************************************************/
  359. int
  360. PlyFile::open_for_reading(const char   *filename,
  361.   int    *nelems,
  362.   char ***elem_names)
  363. {
  364.   char *name = new char[(strlen (filename) + 5)];
  365.   strcpy (name, filename);
  366. #if 0
  367.   /* tack on the extension .ply, if necessary */
  368.   if (strlen (name) < 5 ||
  369.       strcmp (name + strlen (name) - 4, ".ply"))
  370.       strcat (name, ".ply");
  371. #endif
  372.   /* open the file for reading */
  373. #ifdef WIN32
  374.   fp = fopen (name, "rb");
  375. #else
  376.   gzfp = gzopen(name, "rb");
  377. #endif
  378.   delete[] name;
  379. #ifdef WIN32
  380.   if (fp == NULL)
  381. #else
  382.   if (gzfp == NULL)
  383. #endif
  384.     return 0;
  385.   /* create the PlyFile data structure */
  386.   int i,j;
  387.   int nwords;
  388.   char **words;
  389.   char **elist;
  390.   char *orig_line;
  391.   /* create record for this object */
  392.   comments.erase(comments.begin(), comments.end());
  393.   obj_info.erase(obj_info.begin(), obj_info.end());
  394.   other_elems = NULL;
  395.   /* read and parse the file's header */
  396.   words = get_words(&nwords, &orig_line);
  397.   if (!words || !equal_strings (words[0], "ply"))
  398.     return (NULL);
  399.   while (words) {
  400.     /* parse words */
  401.     if (equal_strings (words[0], "format")) {
  402.       if (nwords != 3)
  403.         return (NULL);
  404.       if (equal_strings (words[1], "ascii"))
  405.         m_file_type = PLY_ASCII;
  406.       else if (equal_strings (words[1], "binary_big_endian"))
  407.         m_file_type = PLY_BINARY_BE;
  408.       else if (equal_strings (words[1], "binary_little_endian"))
  409.         m_file_type = PLY_BINARY_LE;
  410.       else
  411.         return 0;
  412.       m_version = atof (words[2]);
  413.     }
  414.     else if (equal_strings (words[0], "element"))
  415.       add_element (words, nwords);
  416.     else if (equal_strings (words[0], "property"))
  417.       add_property (words, nwords);
  418.     else if (equal_strings (words[0], "comment"))
  419.       add_comment (orig_line);
  420.     else if (equal_strings (words[0], "obj_info"))
  421.       add_obj_info (orig_line);
  422.     else if (equal_strings (words[0], "end_header"))
  423.       break;
  424.     delete[] words;
  425.     words = get_words(&nwords, &orig_line);
  426.   }
  427.   /* create tags for each property of each element, to be used */
  428.   /* later to say whether or not to store each property for the user */
  429.   for (i = 0; i < elems.size(); i++) {
  430.     PlyElement &elem = elems[i];
  431.     for (j = 0; j < elem.props.size(); j++)
  432.       elem.store_prop.push_back(DONT_STORE_PROP);
  433.     elem.other_offset = NO_OTHER_PROPS; /* no "other" props by default */
  434.   }
  435.   /* set return values about the elements */
  436.   elist = new char *[elems.size()];
  437.   for (i = 0; i < elems.size(); i++)
  438.     elist[i] = strdup (elems[i].name);
  439.   *elem_names = elist;
  440.   *nelems = elems.size();
  441.   return 1;
  442. }
  443. /*****************************************************************
  444. Describe an element, including its properties and how many will be written
  445. to the file.
  446. Entry:
  447.   elem_name - name of element that information is being specified about
  448.   nelems    - number of elements of this type to be written
  449.   nprops    - number of properties contained in the element
  450.   prop_list - list of properties
  451. ******************************************************************/
  452. void 
  453. PlyFile::describe_element(char *elem_name,
  454.   int   nelems,
  455.   int   nprops,
  456.   PlyProperty *prop_list)
  457. {
  458.   /* look for appropriate element */
  459.   PlyElement *elem = find_element (elem_name);
  460.   if (elem == NULL) {
  461.     fprintf(stderr,"ply_describe_element: can't find element '%s'n",elem_name);
  462.     exit (-1);
  463.   }
  464.   elem->num = nelems;
  465.   /* copy the list of properties */
  466.   for (int i = 0; i < nprops; i++) {
  467.     elem->props.push_back(prop_list[i]);
  468.     elem->store_prop.push_back(NAMED_PROP);
  469.   }
  470. }
  471. /*****************************************************************
  472. Describe a property of an element.
  473. Entry:
  474.   elem_name - name of element that information is being specified about
  475.   prop      - the new property
  476. ******************************************************************/
  477. void 
  478. PlyFile::describe_property(char *elem_name,
  479.    PlyProperty *prop)
  480. {
  481.   /* look for appropriate element */
  482.   PlyElement *elem = find_element (elem_name);
  483.   if (elem == NULL) {
  484.     fprintf(stderr, 
  485.     "ply_describe_property: can't find element '%s'n",
  486.             elem_name);
  487.     return;
  488.   }
  489.   /* copy the new property */
  490.   elem->props.push_back(*prop);
  491.   elem->store_prop.push_back(NAMED_PROP);
  492. }
  493. /*****************************************************************
  494. State how many of a given element will be written.
  495. Entry:
  496.   elem_name - name of element that information is being specified about
  497.   nelems    - number of elements of this type to be written
  498. ******************************************************************/
  499. void 
  500. PlyFile::element_count(char *elem_name,
  501.        int nelems)
  502. {
  503.   // look for appropriate element
  504.   PlyElement *elem = find_element(elem_name);
  505.   if (elem == NULL) {
  506.     fprintf(stderr,"ply_element_count: can't find element '%s'n",
  507.     elem_name);
  508.     exit (-1);
  509.   }
  510.   elem->num = nelems;
  511. }
  512. /*****************************************************************
  513. Pass along a pointer to "other" elements that we want to save in 
  514. a given PLY file.  These other elements were presumably read 
  515. from another PLY file.
  516. Entry:
  517.   o_elems - info about other elements that we want to store
  518. ******************************************************************/
  519. void 
  520. PlyFile::describe_other_elements(PlyOtherElems *o_elems)
  521. {
  522.   int i;
  523.   OtherElem *other;
  524.   /* ignore this call if there is no other element */
  525.   if (o_elems == NULL)
  526.     return;
  527.   /* save pointer to this information */
  528.   other_elems = o_elems;
  529.   /* describe the other properties of this element */
  530.   for (i = 0; i < o_elems->list.size(); i++) {
  531.     other = &(o_elems->list[i]);
  532.     element_count (other->elem_name, other->other_data.size());
  533.     describe_other_properties (other->other_props,
  534.        offsetof(OtherData,other_props));
  535.   }
  536. }
  537. /*****************************************************************
  538. Describe what the "other" properties are that are to be stored, and where
  539. they are in an element.
  540. ******************************************************************/
  541. void 
  542. PlyFile::describe_other_properties(
  543.   PlyOtherProp *other,
  544.   int offset
  545. )
  546. {
  547.   int i;
  548.   PlyElement *elem;
  549.   /* look for appropriate element */
  550.   elem = find_element (other->name);
  551.   if (elem == NULL) {
  552.     fprintf(stderr, "ply_describe_other_properties: "
  553.     "can't find element '%s'n", other->name);
  554.     return;
  555.   }
  556.   /* copy the other properties */
  557.   for (i = 0; i < other->props.size(); i++) {
  558.     elem->props.push_back(other->props[i]);
  559.     elem->store_prop.push_back(OTHER_PROP);
  560.   }
  561.   /* save other info about other properties */
  562.   elem->other_size = other->size;
  563.   elem->other_offset = offset;
  564. }
  565. /*****************************************************************
  566. Signal that we've described everything a PLY file's header and that the
  567. header should be written to the file.
  568. ******************************************************************/
  569. void 
  570. PlyFile::header_complete(void)
  571. {
  572.   int i,j;
  573.   fprintf (fp, "plyn");
  574.   switch (m_file_type) {
  575.     case PLY_ASCII:
  576.       fprintf (fp, "format ascii 1.0n");
  577.       break;
  578.     case PLY_BINARY_BE:
  579.       fprintf (fp, "format binary_big_endian 1.0n");
  580.       break;
  581.     case PLY_BINARY_LE:
  582.       fprintf (fp, "format binary_little_endian 1.0n");
  583.       break;
  584.     default:
  585.       fprintf (stderr, "ply_header_complete: bad file type = %dn",
  586.                m_file_type);
  587.       exit (-1);
  588.   }
  589.   /* write out the comments */
  590.   for (i = 0; i < comments.size(); i++)
  591.     fprintf (fp, "comment %sn", comments[i]);
  592.   /* write out object information */
  593.   for (i = 0; i < obj_info.size(); i++)
  594.     fprintf (fp, "obj_info %sn", obj_info[i]);
  595.   /* write out information about each element */
  596.   for (i = 0; i < elems.size(); i++) {
  597.     PlyElement &elem = elems[i];
  598.     fprintf (fp, "element %s %dn", elem.name, elem.num);
  599.     /* write out each property */
  600.     for (j = 0; j < elem.props.size(); j++) {
  601.       if (elem.props[j].is_list) {
  602.         fprintf (fp, "property list ");
  603.         write_scalar_type (elem.props[j].count_external);
  604.         fprintf (fp, " ");
  605.         write_scalar_type (elem.props[j].external_type);
  606.         fprintf (fp, " %sn", elem.props[j].name);
  607.       }
  608.       else {
  609.         fprintf (fp, "property ");
  610.         write_scalar_type (elem.props[j].external_type);
  611.         fprintf (fp, " %sn", elem.props[j].name);
  612.       }
  613.     }
  614.   }
  615.   fprintf (fp, "end_headern");
  616. }
  617. /*****************************************************************
  618. Specify which elements are going to be written.  This should be called
  619. before a call to the routine ply_put_element().
  620. Entry:
  621.   elem_name - name of element we're talking about
  622. ******************************************************************/
  623. void 
  624. PlyFile::put_element_setup(char *elem_name)
  625. {
  626.   PlyElement *elem = find_element (elem_name);
  627.   if (elem == NULL) {
  628.     fprintf(stderr, "ply_elements_setup: can't find element '%s'n", elem_name);
  629.     exit (-1);
  630.   }
  631.   which_elem = elem;
  632. }
  633. /*****************************************************************
  634. Write an element to the file.  This routine assumes that we're
  635. writing the type of element specified in the last call to the routine
  636. ply_put_element_setup().
  637. Entry:
  638.   plyfile  - file identifier
  639.   elem_ptr - pointer to the element
  640. ******************************************************************/
  641. void 
  642. PlyFile::put_element_static_strg(void *elem_ptr)
  643. { _put_element(elem_ptr, 1); }
  644. void 
  645. PlyFile::put_element(void *elem_ptr)
  646. { _put_element(elem_ptr, 0); }
  647. void 
  648. PlyFile::_put_element(void *elem_ptr, int static_strg)
  649. {
  650.   int j,k;
  651.   char *item;
  652.   int list_count;
  653.   int item_size;
  654.   int int_val;
  655.   unsigned int uint_val;
  656.   double double_val;
  657.   PlyElement *elem = which_elem;
  658.   char *elem_data = (char *) elem_ptr;
  659.   char **other_ptr = (char **) 
  660.     (((char *) elem_ptr) + elem->other_offset);
  661.   // write out each property of the element
  662.   for (j = 0; j < elem->props.size(); j++) {
  663.     PlyProperty &prop = elem->props[j];
  664.     if (elem->store_prop[j] == OTHER_PROP)
  665.       elem_data = *other_ptr;
  666.     else
  667.       elem_data = (char *) elem_ptr;
  668.     if (prop.is_list) {
  669.       item = elem_data + prop.count_offset;
  670.       get_stored_item ((void *) item, prop.count_internal,
  671.        &int_val, &uint_val, &double_val);
  672.       if (m_file_type == PLY_ASCII) {
  673. write_ascii_item (int_val, uint_val, double_val,
  674.   prop.count_external);
  675.       } else if (m_file_type == NATIVE_ENDIANNES) {
  676. write_binary_item_BE (int_val, uint_val, double_val,
  677.       prop.count_external);
  678.       } else {
  679. write_binary_item_LE (int_val, uint_val, double_val,
  680.       prop.count_external);
  681.       };
  682.       list_count = uint_val;
  683.       if (static_strg) {
  684. item = elem_data + prop.offset;
  685.       } else {
  686. // get an array of pointers at data + offset
  687. char **item_ptr = (char **) (elem_data + prop.offset);
  688. // dereference (==take the only pointer there)
  689. item = item_ptr[0];
  690.       }
  691.       item_size = ply_type_size[prop.internal_type];
  692.       if (m_file_type == PLY_ASCII) {
  693. for (k = 0; k < list_count; k++) {
  694.   get_stored_item ((void *) item, prop.internal_type,
  695.    &int_val, &uint_val, &double_val);
  696.   write_ascii_item (int_val, uint_val, double_val,
  697.     prop.external_type);
  698.   item += item_size;
  699. }
  700.       } else if (m_file_type == NATIVE_ENDIANNES) {
  701. for (k = 0; k < list_count; k++) {
  702.   get_stored_item ((void *) item, prop.internal_type,
  703.    &int_val, &uint_val, &double_val);
  704.   write_binary_item_BE (int_val, uint_val, double_val,
  705. prop.external_type);
  706.   item += item_size;
  707. }
  708.       } else {
  709. for (k = 0; k < list_count; k++) {
  710.   get_stored_item ((void *) item, prop.internal_type,
  711.    &int_val, &uint_val, &double_val);
  712.   write_binary_item_LE (int_val, uint_val, double_val,
  713. prop.external_type);
  714.   item += item_size;
  715. }
  716.       }
  717.     }
  718.     else {
  719.       item = elem_data + prop.offset;
  720.       get_stored_item ((void *) item, prop.internal_type,
  721.        &int_val, &uint_val, &double_val);
  722.       if (m_file_type == PLY_ASCII) {
  723. write_ascii_item (int_val, uint_val, double_val,
  724.   prop.external_type);
  725.       } else if (m_file_type == NATIVE_ENDIANNES) {
  726. write_binary_item_BE (int_val, uint_val, double_val,
  727.       prop.external_type);
  728.       } else {
  729. write_binary_item_LE (int_val, uint_val, double_val,
  730.       prop.external_type);
  731.       };
  732.     }
  733.   }
  734.   if (m_file_type == PLY_ASCII) fprintf (fp, "n");
  735. }
  736. /*****************************************************************
  737. Specify a comment that will be written in the header.
  738. Entry:
  739.   plyfile - file identifier
  740.   comment - the comment to be written
  741. ******************************************************************/
  742. void 
  743. PlyFile::put_comment(char *comment)
  744. {
  745.   // add comment to list
  746.   comments.push_back (strdup (comment));
  747. }
  748. /*****************************************************************
  749. Specify a piece of object information (arbitrary text) that will be written
  750. in the header.
  751. Entry:
  752.   o_info - the text information to be written
  753. ******************************************************************/
  754. void 
  755. PlyFile::put_obj_info(char *o_info)
  756. {
  757.   // add info to list
  758.   obj_info.push_back(strdup(o_info));
  759. }
  760. /*************/
  761. /*  Reading  */
  762. /*************/
  763. /*****************************************************************
  764. Get information about a particular element.
  765. Entry:
  766.   elem_name - name of element to get information about
  767. Exit:
  768.   nelems   - number of elements of this type in the file
  769.   nprops   - number of properties
  770.   returns a list of properties, or NULL if the file doesn't contain that elem
  771. ******************************************************************/
  772. PlyProperty **
  773. PlyFile::get_element_description(char *elem_name,
  774.  int  *nelems,
  775.  int  *nprops)
  776. {
  777.   // find information about the element
  778.   PlyElement *elem = find_element(elem_name);
  779.   if (elem == NULL)
  780.     return NULL;
  781.   *nelems = elem->num;
  782.   *nprops = elem->props.size();
  783.   // make a copy of the element's property list
  784.   PlyProperty **prop_list = new PlyProperty *[elem->props.size()];
  785.   PlyProperty *prop;
  786.   for (int i = 0; i < elem->props.size(); i++) {
  787.     prop = new PlyProperty;
  788.     *prop = elem->props[i];
  789.     prop_list[i] = prop;
  790.   }
  791.   // return this duplicate property list
  792.   return prop_list;
  793. }
  794. /*****************************************************************
  795. Specify which properties of an element are to be returned.  
  796. This should be called before a call to the routine 
  797. ply_get_element().
  798. Entry:
  799.   elem_name - which element we're talking about
  800.   nprops    - number of properties
  801.   prop_list - list of properties
  802. ******************************************************************/
  803. void 
  804. PlyFile::get_element_setup(char *elem_name,
  805.    int   nprops,
  806.    PlyProperty *prop_list)
  807. {
  808.   PlyProperty *prop;
  809.   int index;
  810.   // find information about the element
  811.   PlyElement *elem = find_element(elem_name);
  812.   which_elem = elem;
  813.   // deposit the property info into the element's description
  814.   for (int i = 0; i < nprops; i++) {
  815.     // look for actual property
  816.     prop = find_property(elem, prop_list[i].name, &index);
  817.     if (prop == NULL) {
  818.       cerr << "Warning:  Can't find property '"
  819.    << prop_list[i].name << "' in element '"
  820.    << elem_name << "'" << endl;
  821.       continue;
  822.     }
  823.     // store its description
  824.     prop->internal_type  = prop_list[i].internal_type;
  825.     prop->offset         = prop_list[i].offset;
  826.     prop->count_internal = prop_list[i].count_internal;
  827.     prop->count_offset   = prop_list[i].count_offset;
  828.     // specify that the user wants this property
  829.     elem->store_prop[index] = STORE_PROP;
  830.   }
  831. }
  832. /*****************************************************************
  833. Specify a property of an element that is to be returned.  
  834. This should be called (usually multiple times) before a call to 
  835. the routine get_element().
  836. This routine should be used in preference to the less flexible 
  837. old routine called get_element_setup().
  838. Entry:
  839.   elem_name - which element we're talking about
  840.   prop      - property to add to those that will be returned
  841. ******************************************************************/
  842. void 
  843. PlyFile::get_property(char *elem_name,
  844.       PlyProperty *prop)
  845. {
  846.   // find information about the element
  847.   PlyElement *elem = find_element(elem_name);
  848.   which_elem = elem;
  849.   // deposit the property information into the element's description
  850.   int index;
  851.   PlyProperty *prop_ptr = find_property(elem, prop->name, &index);
  852.   if (prop_ptr == NULL) {
  853.     cerr << "Warning:  Can't find property '"
  854.  << prop->name << "' in element '"
  855.  << elem_name << "'" << endl;
  856.     return;
  857.   }
  858.   prop_ptr->internal_type  = prop->internal_type;
  859.   prop_ptr->offset         = prop->offset;
  860.   prop_ptr->count_internal = prop->count_internal;
  861.   prop_ptr->count_offset   = prop->count_offset;
  862.   // specify that the user wants this property
  863.   elem->store_prop[index] = STORE_PROP;
  864. }
  865. /*****************************************************************
  866. Read one element from the file.  
  867. This routine assumes that we're reading
  868. the type of element specified in the last call to the routine
  869. get_element_setup().
  870. Entry:
  871.   elem_ptr - pointer to location where the element information should be put
  872. ******************************************************************/
  873. void
  874. PlyFile::get_element(void *elem_ptr)
  875. {
  876.   if (m_file_type == PLY_ASCII)
  877.     ascii_get_element ((char *) elem_ptr, 0);
  878.   else
  879.     binary_get_element ((char *) elem_ptr, 0);
  880. }
  881. void
  882. PlyFile::get_element_noalloc(void *elem_ptr)
  883. {
  884.   if (m_file_type == PLY_ASCII)
  885.     ascii_get_element ((char *) elem_ptr, 1);
  886.   else
  887.     binary_get_element ((char *) elem_ptr, 1);
  888. }
  889. /*****************************************************************
  890. Extract the comments from the header information of a PLY file.
  891. Entry:
  892. Exit:
  893.   num_comments - number of comments returned
  894.   returns a pointer to a list of comments
  895. ******************************************************************/
  896. char **
  897. PlyFile::get_comments(int *n_comments)
  898. {
  899.   *n_comments = comments.size();
  900.   return &comments[0];
  901. }
  902. /*****************************************************************
  903. Extract the object information (arbitrary text) from the header information
  904. of a PLY file.
  905. Entry:
  906. Exit:
  907.   num_obj_info - number of lines of text information returned
  908.   returns a pointer to a list of object info lines
  909. ******************************************************************/
  910. char **
  911. PlyFile::get_obj_info(int *n_obj_info)
  912. {
  913.   *n_obj_info = obj_info.size();
  914.   return &obj_info[0];
  915. }
  916. /*****************************************************************
  917. Make ready for "other" properties of an element-- those properties that
  918. the user has not explicitly asked for, but that are to be stashed away
  919. in a special structure to be carried along with the element's other
  920. information.
  921. Entry:
  922.   plyfile - file identifier
  923.   elem    - element for which we want to save away other properties
  924. ******************************************************************/
  925. void 
  926. setup_other_props(PlyFile *plyfile, PlyElement *elem)
  927. {
  928.   int i;
  929.   int size = 0;
  930.   int type_size;
  931.   /* Examine each property in decreasing order of size. */
  932.   /* We do this so that all data types will be aligned by */
  933.   /* word, half-word, or whatever within the structure. */
  934.   for (type_size = 8; type_size > 0; type_size /= 2) {
  935.     // add up the space taken by each property, 
  936.     // and save this information away in the property descriptor
  937.     for (i = 0; i < elem->props.size(); i++) {
  938.       /* don't bother with properties we've been asked to store explicitly */
  939.       if (elem->store_prop[i])
  940.         continue;
  941.       PlyProperty &prop = elem->props[i];
  942.       /* internal types will be same as external */
  943.       prop.internal_type = prop.external_type;
  944.       prop.count_internal = prop.count_external;
  945.       /* check list case */
  946.       if (prop.is_list) {
  947.         /* pointer to list */
  948.         if (type_size == sizeof (void *)) {
  949.           prop.offset = size;
  950.           size += sizeof (void *);    /* always use size of a pointer here */
  951.         }
  952.         /* count of number of list elements */
  953.         if (type_size == ply_type_size[prop.count_external]) {
  954.           prop.count_offset = size;
  955.           size += ply_type_size[prop.count_external];
  956.         }
  957.       }
  958.       /* not list */
  959.       else if (type_size == ply_type_size[prop.external_type]) {
  960.         prop.offset = size;
  961.         size += ply_type_size[prop.external_type];
  962.       }
  963.     }
  964.   }
  965.   /* save the size for the other_props structure */
  966.   elem->other_size = size;
  967. }
  968. /*****************************************************************
  969. Specify that we want the "other" properties of an element to be 
  970. tucked away within the user's structure.  
  971. The user needn't be concerned for how these properties are stored.
  972. Entry:
  973.   elem_name - name of element that we want to store other_props in
  974.   offset    - offset to where other_props will be stored inside user's structure
  975. Exit:
  976.   returns pointer to structure containing description of other_props
  977. ******************************************************************/
  978. PlyOtherProp *
  979. PlyFile::get_other_properties(char *elem_name,
  980.       int   offset)
  981. {
  982.   int i;
  983.   PlyElement *elem;
  984.   PlyOtherProp *other;
  985.   /* find information about the element */
  986.   elem = find_element (elem_name);
  987.   if (elem == NULL) {
  988.     fprintf (stderr, "ply_get_other_properties: Can't find element '%s'n",
  989.              elem_name);
  990.     return (NULL);
  991.   }
  992.   /* remember that this is the "current" element */
  993.   which_elem = elem;
  994.   /* save the offset to where to store the other_props */
  995.   elem->other_offset = offset;
  996.   /* place the appropriate pointers, etc. in the element's property list */
  997.   setup_other_props (this, elem);
  998.   /* create structure for describing other_props */
  999.   other = new PlyOtherProp;
  1000.   other->name = strdup (elem_name);
  1001.   other->size = elem->other_size;
  1002.   
  1003.   /* save descriptions of each "other" property */
  1004.   for (i = 0; i < elem->props.size(); i++) {
  1005.     if (elem->store_prop[i])
  1006.       continue;
  1007.     other->props.push_back(elem->props[i]);
  1008.   }
  1009.   // set other_offset pointer appropriately if there are 
  1010.   // NO other properties
  1011.   if (other->props.size() == 0) {
  1012.     elem->other_offset = NO_OTHER_PROPS;
  1013.   }
  1014.   
  1015.   /* return structure */
  1016.   return other;
  1017. }
  1018. /*************************/
  1019. /*  Other Element Stuff  */
  1020. /*************************/
  1021. /*****************************************************************
  1022. Grab all the data for an element that a user does not want to explicitly
  1023. read in.
  1024. Entry:
  1025.   elem_name  - name of element whose data is to be read in
  1026.   elem_count - number of instances of this element stored in the file
  1027. Exit:
  1028.   returns pointer to ALL the "other" element data for this PLY file
  1029. ******************************************************************/
  1030. PlyOtherElems *
  1031. PlyFile::get_other_element(char *elem_name,
  1032.    int   elem_count)
  1033. {
  1034.   int i;
  1035.   PlyElement *elem;
  1036.   PlyOtherElems *o_elems;
  1037.   OtherElem *other;
  1038.   /* look for appropriate element */
  1039.   elem = find_element (elem_name);
  1040.   if (elem == NULL) {
  1041.     fprintf (stderr,
  1042.              "ply_get_other_element: can't find element '%s'n", 
  1043.      elem_name);
  1044.     exit (-1);
  1045.   }
  1046.   /* create room for the new "other" element, initializing the */
  1047.   /* other data structure if necessary */
  1048.   if (other_elems == NULL) {
  1049.     other_elems = new PlyOtherElems;
  1050.   }
  1051.   o_elems = other_elems;
  1052.   o_elems->list.push_back(OtherElem());
  1053.   other = &(o_elems->list.back());
  1054.   /* save name of element */
  1055.   other->elem_name = strdup (elem_name);
  1056.   /* set up for getting elements */
  1057.   other->other_props = get_other_properties(elem_name,
  1058.     offsetof(OtherData,
  1059.      other_props));
  1060.   /* grab all these elements */
  1061.   for (i = 0; i < elem_count; i++) {
  1062.     /* grab and element from the file */
  1063.     other->other_data.push_back(new OtherData);
  1064.     get_element ((void *) other->other_data[i]);
  1065.   }
  1066.   /* return pointer to the other elements data */
  1067.   return o_elems;
  1068. }
  1069. /*****************************************************************
  1070. Write out the "other" elements specified for this PLY file.
  1071. Entry:
  1072. ******************************************************************/
  1073. void 
  1074. PlyFile::put_other_elements (void)
  1075. {
  1076.   int i,j;
  1077.   OtherElem *other;
  1078.   /* make sure we have other elements to write */
  1079.   if (other_elems == NULL)
  1080.     return;
  1081.   /* write out the data for each "other" element */
  1082.   for (i = 0; i < other_elems->list.size(); i++) {
  1083.     other = &(other_elems->list[i]);
  1084.     put_element_setup (other->elem_name);
  1085.     /* write out each instance of the current element */
  1086.     for (j = 0; j < other->other_data.size(); j++)
  1087.       put_element ((void *) other->other_data[j]);
  1088.   }
  1089. }
  1090. /*******************/
  1091. /*  Miscellaneous  */
  1092. /*******************/
  1093. /*****************************************************************
  1094. Close a PLY file.
  1095. Entry:
  1096. ******************************************************************/
  1097. void 
  1098. PlyFile::close(void)
  1099. {
  1100.   if (fp) {
  1101.     fclose (fp);
  1102.     fp = NULL;
  1103.     fb_s = fb_e = fbuf;
  1104.   }
  1105. #ifndef WIN32
  1106.   if (gzfp) {
  1107.     gzclose(gzfp);
  1108.     gzfp = NULL;
  1109.   }
  1110. #endif
  1111. }
  1112. /*****************************************************************
  1113. Compare two strings.  Returns 1 if they are the same, 0 if not.
  1114. ******************************************************************/
  1115. int 
  1116. equal_strings(char *s1, char *s2)
  1117. {
  1118.   while (*s1 && *s2)
  1119.     if (*s1++ != *s2++)
  1120.       return (0);
  1121.   if (*s1 != *s2)
  1122.     return (0);
  1123.   else
  1124.     return (1);
  1125. }
  1126. /*****************************************************************
  1127. Find an element from the element list
  1128. Entry:
  1129.   element - name of element we're looking for
  1130. Exit:
  1131.   returns the element, or NULL if not found
  1132. ******************************************************************/
  1133. PlyElement *
  1134. PlyFile::find_element(char *element)
  1135. {
  1136.   for (int i = 0; i < elems.size(); i++)
  1137.     if (equal_strings (element, elems[i].name))
  1138.       return &elems[i];
  1139.   return NULL;
  1140. }
  1141. /*****************************************************************
  1142. Find a property in the list of properties of a given element.
  1143. Entry:
  1144.   elem      - pointer to element in which we want to find the property
  1145.   prop_name - name of property to find
  1146. Exit:
  1147.   index - index to position in list
  1148.   returns a pointer to the property, or NULL if not found
  1149. ******************************************************************/
  1150. PlyProperty *
  1151. PlyFile::find_property(PlyElement *elem, 
  1152.        char       *prop_name, 
  1153.        int        *index)
  1154. {
  1155.   for (int i = 0; i < elem->props.size(); i++)
  1156.     if (equal_strings (prop_name, elem->props[i].name)) {
  1157.       *index = i;
  1158.       return &elem->props[i];
  1159.     }
  1160.   *index = -1;
  1161.   return NULL;
  1162. }
  1163. /*****************************************************************
  1164. Read an element from an ascii file.
  1165. Entry:
  1166.   elem_ptr - pointer to element
  1167. ******************************************************************/
  1168. void 
  1169. PlyFile::ascii_get_element(char *elem_ptr, 
  1170.    int use_provided_storage)
  1171. {
  1172.   int j,k;
  1173.   int which_word;
  1174.   char *elem_data,*item;
  1175.   int int_val;
  1176.   unsigned int uint_val;
  1177.   double double_val;
  1178.   int list_count;
  1179.   int store_it;
  1180.   char **store_array;
  1181.   char *orig_line;
  1182.   char *other_data;
  1183.   int other_flag;
  1184.   /* the kind of element we're reading currently */
  1185.   PlyElement *elem = which_elem;
  1186.   /* do we need to setup for other_props? */
  1187.   if (elem->other_offset != NO_OTHER_PROPS) {
  1188.     char **ptr;
  1189.     other_flag = 1;
  1190.     /* make room for other_props */
  1191.     other_data = new char[elem->other_size];
  1192.     /* store pointer in user's structure to the other_props */
  1193.     ptr = (char **) (elem_ptr + elem->other_offset);
  1194.     *ptr = other_data;
  1195.   }
  1196.   else
  1197.     other_flag = 0;
  1198.   /* read in the element */
  1199.   int nwords;
  1200.   char **words = get_words(&nwords, &orig_line);
  1201.   if (words == NULL) {
  1202.     fprintf (stderr, "ply_get_element: unexpected end of filen");
  1203.     exit (-1);
  1204.   }
  1205.   which_word = 0;
  1206.   for (j = 0; j < elem->props.size(); j++) {
  1207.     PlyProperty &prop = elem->props[j];
  1208.     store_it = (elem->store_prop[j] | other_flag);
  1209.     /* store either in the user's structure or in other_props */
  1210.     if (elem->store_prop[j])
  1211.       elem_data = elem_ptr;
  1212.     else
  1213.       elem_data = other_data;
  1214.     if (prop.is_list) {       /* a list */
  1215.       /* get and store the number of items in the list */
  1216.       get_ascii_item (words[which_word++], prop.count_external,
  1217.                       &int_val, &uint_val, &double_val);
  1218.       if (store_it) {
  1219.         item = elem_data + prop.count_offset;
  1220.         store_item(item, prop.count_internal, int_val, uint_val, 
  1221.    double_val);
  1222.       }
  1223.       /* allocate space for an array of items and store a ptr to the array */
  1224.       list_count = int_val;
  1225.       int item_size = ply_type_size[prop.internal_type];
  1226.       store_array = (char **) (elem_data + prop.offset);
  1227.       if (list_count == 0) {
  1228.         if (store_it)
  1229.           *store_array = NULL;
  1230.       }
  1231.       else {
  1232.         if (store_it) {
  1233.   if (use_provided_storage) {
  1234.     item = elem_data + prop.offset;
  1235.   } else {
  1236.     item = new char[item_size * list_count];
  1237.     *store_array = item;
  1238.   }
  1239.         }
  1240.         /* read items and store them into the array */
  1241.         for (k = 0; k < list_count; k++) {
  1242.           get_ascii_item (words[which_word++], prop.external_type,
  1243.                           &int_val, &uint_val, &double_val);
  1244.           if (store_it) {
  1245.             store_item (item, prop.internal_type,
  1246.                         int_val, uint_val, double_val);
  1247.             item += item_size;
  1248.           }
  1249.         }
  1250.       }
  1251.     }
  1252.     else {                     /* not a list */
  1253.       get_ascii_item (words[which_word++], prop.external_type,
  1254.                       &int_val, &uint_val, &double_val);
  1255.       if (store_it) {
  1256.         item = elem_data + prop.offset;
  1257.         store_item (item, prop.internal_type, int_val, uint_val, double_val);
  1258.       }
  1259.     }
  1260.   }
  1261.   delete[] words;
  1262. }
  1263. static void
  1264. inv_memcpy(char *to, const char *from, int size, int n)
  1265. {
  1266.   for (int i=0; i<n; i++) {
  1267.     int off_to   = size*i;
  1268.     int off_from = off_to + size - 1;
  1269.     for (int j=0; j<size; j++) {
  1270.       to[off_to+j] = from[off_from-j];
  1271.     }
  1272.   }
  1273. }
  1274. void
  1275. PlyFile::get_and_store_binary_item(int type_ext, int type_int, 
  1276.    char *item)
  1277. {
  1278.   if (type_ext == type_int) {
  1279.     // external type and internal type is the same, short
  1280.     // circuit
  1281.     fbuf_need(ply_type_size[type_ext]);
  1282.     if (m_file_type == NATIVE_ENDIANNES) {
  1283.       memcpy(item, fb_s, ply_type_size[type_ext]);
  1284.     } else {
  1285.       inv_memcpy(item, fb_s, ply_type_size[type_ext], 1);
  1286.     }
  1287.     fb_s += ply_type_size[type_ext];
  1288.   } else {
  1289.     // the general case
  1290.     int          int_val;
  1291.     unsigned int uint_val;
  1292.     double       double_val;
  1293.     if (m_file_type == NATIVE_ENDIANNES) {
  1294.       get_binary_item_BE(type_ext, 
  1295.  &int_val, &uint_val, &double_val);
  1296.     } else {
  1297.       get_binary_item_LE(type_ext, 
  1298.  &int_val, &uint_val, &double_val);
  1299.     }
  1300.     store_item(item, type_int, int_val, uint_val, double_val);
  1301.   }
  1302. }
  1303.   
  1304. void
  1305. PlyFile::get_and_store_binary_list(int type_ext, int type_int, 
  1306.    char *item, int n)
  1307. {
  1308.   if (type_ext == type_int) {
  1309.     // external type and internal type is the same, short
  1310.     // circuit
  1311.     int _n = n*ply_type_size[type_ext];
  1312.     fbuf_need(_n);
  1313.     if (m_file_type == NATIVE_ENDIANNES) {
  1314.       memcpy(item, fb_s, _n);
  1315.     } else {
  1316.       inv_memcpy(item, fb_s, ply_type_size[type_ext], n);
  1317.     }
  1318.     fb_s += _n;
  1319.   } else {
  1320.     // the general case
  1321.     int          int_val;
  1322.     unsigned int uint_val;
  1323.     double       double_val;
  1324.     int          step = ply_type_size[type_int];
  1325.     if (m_file_type == NATIVE_ENDIANNES) {
  1326.       for (int i=0; i<n; i++, item += step) {
  1327. get_binary_item_BE(type_ext, 
  1328.    &int_val, &uint_val, &double_val);
  1329. store_item(item, type_int, int_val, uint_val, double_val);
  1330.       }
  1331.     } else {
  1332.       for (int i=0; i<n; i++, item += step) {
  1333. get_binary_item_LE(type_ext, 
  1334.    &int_val, &uint_val, &double_val);
  1335. store_item(item, type_int, int_val, uint_val, double_val);
  1336.       }
  1337.     }
  1338.   }
  1339. }
  1340. /*****************************************************************
  1341. Read an element from a binary file.
  1342. Entry:
  1343.   elem_ptr - pointer to an element
  1344. ******************************************************************/
  1345. void 
  1346. PlyFile::binary_get_element(char *elem_ptr, 
  1347.     int use_provided_storage)
  1348. {
  1349.   int j,k;
  1350.   char *elem_data,*item;
  1351.   int int_val;
  1352.   unsigned int uint_val;
  1353.   double double_val;
  1354.   int list_count;
  1355.   char *other_data;
  1356.   int other_flag;
  1357.   // the kind of element we're reading currently
  1358.   PlyElement *elem = which_elem;
  1359.   // do we need to setup for other_props?
  1360.   if (elem->other_offset != NO_OTHER_PROPS) {
  1361.     other_flag = 1;
  1362.     // make room for other_props
  1363.     other_data = new char[elem->other_size];
  1364.     // store pointer in user's structure to the other_props
  1365.     char **ptr = (char **) (elem_ptr + elem->other_offset);
  1366.     *ptr = other_data;
  1367.   } else {
  1368.     other_flag = 0;
  1369.   }
  1370.   // read in a number of elements
  1371.   for (j = 0; j < elem->props.size(); j++) {
  1372.     PlyProperty &prop = elem->props[j];
  1373.     
  1374.     if (elem->store_prop[j] | other_flag) {
  1375.       // read and store data
  1376.       // store either in the user's structure or in other_props
  1377.       if (elem->store_prop[j])  elem_data = elem_ptr;
  1378.       else                      elem_data = other_data;
  1379.       if (prop.is_list) {       // a list
  1380. // get and store the number of items in the list
  1381. item = elem_data + prop.count_offset;
  1382. get_and_store_binary_item(prop.count_external,
  1383.   prop.count_internal,
  1384.   item);
  1385. list_count = to_int(item, prop.count_internal);
  1386. if (list_count) {
  1387.   // read items and store them into the array
  1388.   if (!use_provided_storage) {
  1389.     int item_size = ply_type_size[prop.internal_type];
  1390.     char **tmp = (char **) (elem_data + prop.offset);
  1391.     *tmp = item = new char[item_size * list_count];
  1392.   } else {
  1393.     item = elem_data + prop.offset;
  1394.   }
  1395.   get_and_store_binary_list(prop.external_type,
  1396.     prop.internal_type,
  1397.     item,
  1398.     list_count);
  1399. }
  1400.       } else {                     // not a list
  1401. get_and_store_binary_item(prop.external_type,
  1402.   prop.internal_type, 
  1403.   elem_data + prop.offset);
  1404.       }
  1405.     } else {
  1406.       // just read, don't store
  1407.       if (prop.is_list) {       // a list
  1408. // get the number of items in the list
  1409. get_binary_item_BE(prop.count_external,
  1410.    &list_count, &uint_val, &double_val);
  1411. if (list_count) {
  1412.   // read items and store them into the array
  1413.   for (k = 0; k < list_count; k++) {
  1414.     get_binary_item_BE(prop.external_type,
  1415.        &int_val, &uint_val, &double_val);
  1416.   }
  1417. }
  1418.       } else {                     // not a list
  1419. get_binary_item_BE(prop.external_type,
  1420.    &int_val, &uint_val, &double_val);
  1421.       }
  1422.     }
  1423.   }
  1424. }
  1425. /*****************************************************************
  1426. Write to a file the word that represents a PLY data type.
  1427. Entry:
  1428.   code - code for type
  1429. ******************************************************************/
  1430. void 
  1431. PlyFile::write_scalar_type (int code)
  1432. {
  1433.   /* make sure this is a valid code */
  1434.   if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
  1435.     fprintf (stderr, "write_scalar_type: bad data code = %dn", 
  1436.      code);
  1437.     exit (-1);
  1438.   }
  1439.   /* write the code to a file */
  1440.   fprintf (fp, "%s", type_names[code]);
  1441. }
  1442. /*****************************************************************
  1443. Get a text line from a file and break it up into words.
  1444. IMPORTANT: The calling routine call delete[] on the returned 
  1445. pointer once finished with it.
  1446. Entry:
  1447. Exit:
  1448.   nwords    - number of words returned
  1449.   orig_line - the original line of characters
  1450.   returns a list of words from the line, or NULL if end-of-file
  1451. ******************************************************************/
  1452. char **
  1453. PlyFile::get_words(int *nwords, char **orig_line)
  1454. {
  1455. #define BIG_STRING 4096
  1456.   static char str[BIG_STRING];
  1457.   static char str_copy[BIG_STRING];
  1458.   int max_words = 10;
  1459.   int num_words = 0;
  1460.   char *ptr,*ptr2;
  1461.   char *result;
  1462.   char **words = new char *[max_words];
  1463.   /* read in a line */
  1464. #ifdef WIN32
  1465.   result = fgets (str, BIG_STRING, fp);
  1466. #else
  1467.   result = gzgets (str, BIG_STRING, gzfp);
  1468. #endif
  1469.   if (result == NULL) {
  1470.     *nwords = 0;
  1471.     *orig_line = NULL;
  1472.     return NULL;
  1473.   }
  1474.   /* convert line-feed and tabs into spaces */
  1475.   /* (this guarentees that there will be a space before the */
  1476.   /*  null character at the end of the string) */
  1477.   str[BIG_STRING-2] = ' ';
  1478.   str[BIG_STRING-1] = '';
  1479.   for (ptr = str, ptr2 = str_copy; *ptr != ''; ptr++, ptr2++) {
  1480.     *ptr2 = *ptr;
  1481.     if (*ptr == 't') {
  1482.       *ptr = ' ';
  1483.       *ptr2 = ' ';
  1484.     }
  1485.   #ifdef _WIN32 // reading ascii file in binary mode: handle rn
  1486.     else if (*ptr == 'r') {
  1487.       *ptr = ' ';
  1488.       *ptr2 = '';
  1489.     }
  1490.   #endif
  1491.     else if (*ptr == 'n') {
  1492.       *ptr = ' ';
  1493.       *ptr2 = '';
  1494.       break;
  1495.     }
  1496.   }
  1497.   /* find the words in the line */
  1498.   ptr = str;
  1499.   while (*ptr != '') {
  1500.     /* jump over leading spaces */
  1501.     while (*ptr == ' ')
  1502.       ptr++;
  1503.     /* break if we reach the end */
  1504.     if (*ptr == '')
  1505.       break;
  1506.     /* save pointer to beginning of word */
  1507.     if (num_words >= max_words) {
  1508.       max_words += 10;
  1509.       delete[] words;
  1510.       words = new char *[max_words];
  1511.     }
  1512.     words[num_words++] = ptr;
  1513.     /* jump over non-spaces */
  1514.     while (*ptr != ' ')
  1515.       ptr++;
  1516.     /* place a null character here to mark the end of the word */
  1517.     *ptr++ = '';
  1518.   }
  1519.   /* return the list of words */
  1520.   *nwords = num_words;
  1521.   *orig_line = str_copy;
  1522.   return words;
  1523. }
  1524. /*****************************************************************
  1525. Return the value of an item, given a pointer to it and its type.
  1526. Entry:
  1527.   item - pointer to item
  1528.   type - data type that "item" points to
  1529. Exit:
  1530.   returns a double-precision float that contains the value of the item
  1531. ******************************************************************/
  1532. double 
  1533. PlyFile::get_item_value(char *item, int type)
  1534. {
  1535.   unsigned char *puchar;
  1536.   char *pchar;
  1537.   short int *pshort;
  1538.   unsigned short int *pushort;
  1539.   int *pint;
  1540.   unsigned int *puint;
  1541.   float *pfloat;
  1542.   double *pdouble;
  1543.   int int_value;
  1544.   unsigned int uint_value;
  1545.   double double_value;
  1546.   switch (type) {
  1547.     case PLY_CHAR:
  1548.       pchar = (char *) item;
  1549.       int_value = *pchar;
  1550.       return ((double) int_value);
  1551.     case PLY_UCHAR:
  1552.       puchar = (unsigned char *) item;
  1553.       int_value = *puchar;
  1554.       return ((double) int_value);
  1555.     case PLY_SHORT:
  1556.       pshort = (short int *) item;
  1557.       int_value = *pshort;
  1558.       return ((double) int_value);
  1559.     case PLY_USHORT:
  1560.       pushort = (unsigned short int *) item;
  1561.       int_value = *pushort;
  1562.       return ((double) int_value);
  1563.     case PLY_INT:
  1564.       pint = (int *) item;
  1565.       int_value = *pint;
  1566.       return ((double) int_value);
  1567.     case PLY_UINT:
  1568.       puint = (unsigned int *) item;
  1569.       uint_value = *puint;
  1570.       return ((double) uint_value);
  1571.     case PLY_FLOAT:
  1572.       pfloat = (float *) item;
  1573.       double_value = *pfloat;
  1574.       return (double_value);
  1575.     case PLY_DOUBLE:
  1576.       pdouble = (double *) item;
  1577.       double_value = *pdouble;
  1578.       return (double_value);
  1579.     default:
  1580.       fprintf (stderr, "get_item_value: bad type = %dn", type);
  1581.       exit (-1);
  1582.   }
  1583.   return 0.0; // remove warning (never gets here)
  1584. }
  1585. /*****************************************************************
  1586. Write out an item to a file as raw binary bytes.
  1587. Entry:
  1588.   int_val    - integer version of item
  1589.   uint_val   - unsigned integer version of item
  1590.   double_val - double-precision float version of item
  1591.   type       - data type to write out
  1592. ******************************************************************/
  1593. void 
  1594. PlyFile::write_binary_item_BE(int int_val,
  1595.       unsigned int uint_val,
  1596.       double double_val,
  1597.       int type)
  1598. {
  1599.   unsigned char uchar_val;
  1600.   char char_val;
  1601.   unsigned short ushort_val;
  1602.   short short_val;
  1603.   float float_val;
  1604.   switch (type) {
  1605.     case PLY_CHAR:
  1606.       char_val = int_val;
  1607.       fwrite (&char_val, 1, 1, fp);
  1608.       break;
  1609.     case PLY_SHORT:
  1610.       short_val = int_val;
  1611.       fwrite (&short_val, 2, 1, fp);
  1612.       break;
  1613.     case PLY_INT:
  1614.       fwrite (&int_val, 4, 1, fp);
  1615.       break;
  1616.     case PLY_UCHAR:
  1617.       uchar_val = uint_val;
  1618.       fwrite (&uchar_val, 1, 1, fp);
  1619.       break;
  1620.     case PLY_USHORT:
  1621.       ushort_val = uint_val;
  1622.       fwrite (&ushort_val, 2, 1, fp);
  1623.       break;
  1624.     case PLY_UINT:
  1625.       fwrite (&uint_val, 4, 1, fp);
  1626.       break;
  1627.     case PLY_FLOAT:
  1628.       float_val = double_val;
  1629.       fwrite (&float_val, 4, 1, fp);
  1630.       break;
  1631.     case PLY_DOUBLE:
  1632.       fwrite (&double_val, 8, 1, fp);
  1633.       break;
  1634.     default:
  1635.       cerr << "write_binary_item_BE: bad type = " 
  1636.    << type << endl;
  1637.       exit (-1);
  1638.   }
  1639. }
  1640. static void
  1641. swap(short i, char *c)
  1642. {
  1643.   char *p = (char *)&i;
  1644.   c[0] = p[1];
  1645.   c[1] = p[2];
  1646. }
  1647. static void
  1648. swap(unsigned short i, char *c)
  1649. {
  1650.   char *p = (char *)&i;
  1651.   c[0] = p[1];
  1652.   c[1] = p[2];
  1653. }
  1654. static void
  1655. swap(int i, char *c)
  1656. {
  1657.   char *p = (char *)&i;
  1658.   c[0] = p[3];
  1659.   c[1] = p[2];
  1660.   c[2] = p[1];
  1661.   c[3] = p[0];
  1662. }
  1663. static void
  1664. swap(unsigned int i, char *c)
  1665. {
  1666.   char *p = (char *)&i;
  1667.   c[0] = p[3];
  1668.   c[1] = p[2];
  1669.   c[2] = p[1];
  1670.   c[3] = p[0];
  1671. }
  1672. static void
  1673. swap(float i, char *c)
  1674. {
  1675.   char *p = (char *)&i;
  1676.   c[0] = p[3];
  1677.   c[1] = p[2];
  1678.   c[2] = p[1];
  1679.   c[3] = p[0];
  1680. }
  1681. static void
  1682. swap(double i, char *c)
  1683. {
  1684.   char *p = (char *)&i;
  1685.   c[0] = p[7];
  1686.   c[1] = p[6];
  1687.   c[2] = p[5];
  1688.   c[3] = p[4];
  1689.   c[4] = p[3];
  1690.   c[5] = p[2];
  1691.   c[6] = p[1];
  1692.   c[7] = p[0];
  1693. }
  1694. void 
  1695. PlyFile::write_binary_item_LE(int int_val,
  1696.       unsigned int uint_val,
  1697.       double double_val,
  1698.       int type)
  1699. {
  1700.   unsigned char uchar_val;
  1701.   char char_val;
  1702.   char c[8];
  1703.   switch (type) {
  1704.     case PLY_CHAR:
  1705.       char_val = int_val;
  1706.       fwrite (&char_val, 1, 1, fp);
  1707.       break;
  1708.     case PLY_SHORT:
  1709.       swap(short(int_val), c);
  1710.       fwrite (c, 1, 2, fp);
  1711.       break;
  1712.     case PLY_INT:
  1713.       swap(int_val, c);
  1714.       fwrite (c, 1, 4, fp);
  1715.       break;
  1716.     case PLY_UCHAR:
  1717.       uchar_val = uint_val;
  1718.       fwrite (&uchar_val, 1, 1, fp);
  1719.       break;
  1720.     case PLY_USHORT:
  1721.       swap((unsigned short)int_val, c);
  1722.       fwrite (c, 1, 2, fp);
  1723.       break;
  1724.     case PLY_UINT:
  1725.       swap(uint_val, c);
  1726.       fwrite (c, 1, 4, fp);
  1727.       break;
  1728.     case PLY_FLOAT:
  1729.       swap(float(double_val), c);
  1730.       fwrite (c, 1, 4, fp);
  1731.       break;
  1732.     case PLY_DOUBLE:
  1733.       swap(double_val, c);
  1734.       fwrite (c, 1, 8, fp);
  1735.       break;
  1736.     default:
  1737.       cerr << "write_binary_item_LE: bad type = " 
  1738.    << type << endl;
  1739.       exit (-1);
  1740.   }
  1741. }
  1742. /*****************************************************************
  1743. Write out an item to a file as ascii characters.
  1744. Entry:
  1745.   int_val    - integer version of item
  1746.   uint_val   - unsigned integer version of item
  1747.   double_val - double-precision float version of item
  1748.   type       - data type to write out
  1749. ******************************************************************/
  1750. void 
  1751. PlyFile::write_ascii_item(
  1752.   int int_val,
  1753.   unsigned int uint_val,
  1754.   double double_val,
  1755.   int type
  1756. )
  1757. {
  1758.   switch (type) {
  1759.     case PLY_CHAR:
  1760.     case PLY_SHORT:
  1761.     case PLY_INT:
  1762.       fprintf (fp, "%d ", int_val);
  1763.       break;
  1764.     case PLY_UCHAR:
  1765.     case PLY_USHORT:
  1766.     case PLY_UINT:
  1767.       fprintf (fp, "%u ", uint_val);
  1768.       break;
  1769.     case PLY_FLOAT:
  1770.     case PLY_DOUBLE:
  1771.       fprintf (fp, "%g ", double_val);
  1772.       break;
  1773.     default:
  1774.       fprintf (stderr, "write_ascii_item: bad type = %dn", type);
  1775.       exit (-1);
  1776.   }
  1777. }
  1778. /*****************************************************************
  1779. Get the value of an item that is in memory, and place the result
  1780. into an integer, an unsigned integer and a double.
  1781. Entry:
  1782.   ptr  - pointer to the item
  1783.   type - data type supposedly in the item
  1784. Exit:
  1785.   int_val    - integer value
  1786.   uint_val   - unsigned integer value
  1787.   double_val - double-precision floating point value
  1788. ******************************************************************/
  1789. void 
  1790. PlyFile::get_stored_item(void *ptr,
  1791.  int type,
  1792.  int *int_val,
  1793.  unsigned int *uint_val,
  1794.  double *double_val)
  1795. {
  1796.   switch (type) {
  1797.     case PLY_CHAR:
  1798.       *int_val = *((char *) ptr);
  1799.       *uint_val = *int_val;
  1800.       *double_val = *int_val;
  1801.       break;
  1802.     case PLY_UCHAR:
  1803.       *uint_val = *((unsigned char *) ptr);
  1804.       *int_val = *uint_val;
  1805.       *double_val = *uint_val;
  1806.       break;
  1807.     case PLY_SHORT:
  1808.       *int_val = *((short int *) ptr);
  1809.       *uint_val = *int_val;
  1810.       *double_val = *int_val;
  1811.       break;
  1812.     case PLY_USHORT:
  1813.       *uint_val = *((unsigned short int *) ptr);
  1814.       *int_val = *uint_val;
  1815.       *double_val = *uint_val;
  1816.       break;
  1817.     case PLY_INT:
  1818.       *int_val = *((int *) ptr);
  1819.       *uint_val = *int_val;
  1820.       *double_val = *int_val;
  1821.       break;
  1822.     case PLY_UINT:
  1823.       *uint_val = *((unsigned int *) ptr);
  1824.       *int_val = *uint_val;
  1825.       *double_val = *uint_val;
  1826.       break;
  1827.     case PLY_FLOAT:
  1828.       *double_val = *((float *) ptr);
  1829.       *int_val = *double_val;
  1830.       *uint_val = *double_val;
  1831.       break;
  1832.     case PLY_DOUBLE:
  1833.       *double_val = *((double *) ptr);
  1834.       *int_val = *double_val;
  1835.       *uint_val = *double_val;
  1836.       break;
  1837.     default:
  1838.       fprintf (stderr, "get_stored_item: bad type = %dn", type);
  1839.       exit (-1);
  1840.   }
  1841. }
  1842. /*****************************************************************
  1843. Get the value of an item from a binary file, and place the result
  1844. into an integer, an unsigned integer and a double.
  1845. Entry:
  1846.   type - data type supposedly in the word
  1847. Exit:
  1848.   int_val    - integer value
  1849.   uint_val   - unsigned integer value
  1850.   double_val - double-precision floating point value
  1851. ******************************************************************/
  1852. void 
  1853. PlyFile::get_binary_item_BE(int type,
  1854.     int *int_val,
  1855.     unsigned int *uint_val,
  1856.     double *double_val)
  1857. {
  1858.   switch (type) {
  1859.     case PLY_CHAR:
  1860.       *int_val = read_char();
  1861.       *double_val = *uint_val = *int_val;
  1862.       break;
  1863.     case PLY_UCHAR:
  1864.       *uint_val = read_uchar();
  1865.       *double_val = *int_val = *uint_val;
  1866.       break;
  1867.     case PLY_SHORT:
  1868.       *int_val = read_short_BE();
  1869.       *double_val = *uint_val = *int_val;
  1870.       break;
  1871.     case PLY_USHORT:
  1872.       *uint_val = read_ushort_BE();
  1873.       *double_val = *int_val = *uint_val;
  1874.       break;
  1875.     case PLY_INT:
  1876.       *int_val = read_int_BE();
  1877.       *double_val = *uint_val = *int_val;
  1878.       break;
  1879.     case PLY_UINT:
  1880.       *uint_val = read_uint_BE();
  1881.       *double_val = *int_val = *uint_val;
  1882.       break;
  1883.     case PLY_FLOAT:
  1884.       *double_val = read_float_BE();
  1885.       *uint_val = *int_val = *double_val;
  1886.       break;
  1887.     case PLY_DOUBLE:
  1888.       *double_val = read_double_BE();
  1889.       *uint_val = *int_val = *double_val;
  1890.       break;
  1891.     default:
  1892.       fprintf (stderr, "get_binary_item: bad type = %dn", type);
  1893.       exit (-1);
  1894.   }
  1895. }
  1896. void 
  1897. PlyFile::get_binary_item_LE(int type,
  1898.     int *int_val,
  1899.     unsigned int *uint_val,
  1900.     double *double_val)
  1901. {
  1902.   switch (type) {
  1903.     case PLY_CHAR:
  1904.       *int_val = read_char();
  1905.       *double_val = *uint_val = *int_val;
  1906.       break;
  1907.     case PLY_UCHAR:
  1908.       *uint_val = read_uchar();
  1909.       *double_val = *int_val = *uint_val;
  1910.       break;
  1911.     case PLY_SHORT:
  1912.       *int_val = read_short_LE();
  1913.       *double_val = *uint_val = *int_val;
  1914.       break;
  1915.     case PLY_USHORT:
  1916.       *uint_val = read_ushort_LE();
  1917.       *double_val = *int_val = *uint_val;
  1918.       break;
  1919.     case PLY_INT:
  1920.       *int_val = read_int_LE();
  1921.       *double_val = *uint_val = *int_val;
  1922.       break;
  1923.     case PLY_UINT:
  1924.       *uint_val = read_uint_LE();
  1925.       *double_val = *int_val = *uint_val;
  1926.       break;
  1927.     case PLY_FLOAT:
  1928.       *double_val = read_float_LE();
  1929.       *uint_val = *int_val = *double_val;
  1930.       break;
  1931.     case PLY_DOUBLE:
  1932.       *double_val = read_double_LE();
  1933.       *uint_val = *int_val = *double_val;
  1934.       break;
  1935.     default:
  1936.       fprintf (stderr, "get_binary_item: bad type = %dn", type);
  1937.       exit (-1);
  1938.   }
  1939. }
  1940. /*****************************************************************
  1941. Extract the value of an item from an ascii word, and place the result
  1942. into an integer, an unsigned integer and a double.
  1943. Entry:
  1944.   word - word to extract value from
  1945.   type - data type supposedly in the word
  1946. Exit:
  1947.   int_val    - integer value
  1948.   uint_val   - unsigned integer value
  1949.   double_val - double-precision floating point value
  1950. ******************************************************************/
  1951. void 
  1952. PlyFile::get_ascii_item(char *word,
  1953. int type,
  1954. int *int_val,
  1955. unsigned int *uint_val,
  1956. double *double_val)
  1957. {
  1958.   switch (type) {
  1959.     case PLY_CHAR:
  1960.     case PLY_UCHAR:
  1961.     case PLY_SHORT:
  1962.     case PLY_USHORT:
  1963.     case PLY_INT:
  1964.       *int_val = atoi (word);
  1965.       *uint_val = *int_val;
  1966.       *double_val = *int_val;
  1967.       break;
  1968.     case PLY_UINT:
  1969.       *uint_val = strtoul (word, (char **) NULL, 10);
  1970.       *int_val = *uint_val;
  1971.       *double_val = *uint_val;
  1972.       break;
  1973.     case PLY_FLOAT:
  1974.     case PLY_DOUBLE:
  1975.       *double_val = atof (word);
  1976.       *int_val = (int) *double_val;
  1977.       *uint_val = (unsigned int) *double_val;
  1978.       break;
  1979.     default:
  1980.       fprintf (stderr, "get_ascii_item: bad type = %dn", type);
  1981.       exit (-1);
  1982.   }
  1983. }
  1984. /*****************************************************************
  1985. Store a value into a place being pointed to, guided by a data type.
  1986. Entry:
  1987.   item       - place to store value
  1988.   type       - data type
  1989.   int_val    - integer version of value
  1990.   uint_val   - unsigned integer version of value
  1991.   double_val - double version of value
  1992. Exit:
  1993.   item - pointer to stored value
  1994. ******************************************************************/
  1995. void 
  1996. PlyFile::store_item(char *item,
  1997.     int type,
  1998.     int int_val,
  1999.     unsigned int uint_val,
  2000.     double double_val)
  2001. {
  2002.   unsigned char *puchar;
  2003.   short int *pshort;
  2004.   unsigned short int *pushort;
  2005.   int *pint;
  2006.   unsigned int *puint;
  2007.   float *pfloat;
  2008.   double *pdouble;
  2009.   switch (type) {
  2010.     case PLY_CHAR:
  2011.       *item = int_val;
  2012.       break;
  2013.     case PLY_UCHAR:
  2014.       puchar = (unsigned char *) item;
  2015.       *puchar = uint_val;
  2016.       break;
  2017.     case PLY_SHORT:
  2018.       pshort = (short *) item;
  2019.       *pshort = int_val;
  2020.       break;
  2021.     case PLY_USHORT:
  2022.       pushort = (unsigned short *) item;
  2023.       *pushort = uint_val;
  2024.       break;
  2025.     case PLY_INT:
  2026.       pint = (int *) item;
  2027.       *pint = int_val;
  2028.       break;
  2029.     case PLY_UINT:
  2030.       puint = (unsigned int *) item;
  2031.       *puint = uint_val;
  2032.       break;
  2033.     case PLY_FLOAT:
  2034.       pfloat = (float *) item;
  2035.       *pfloat = double_val;
  2036.       break;
  2037.     case PLY_DOUBLE:
  2038.       pdouble = (double *) item;
  2039.       *pdouble = double_val;
  2040.       break;
  2041.     default:
  2042.       fprintf (stderr, "store_item: bad type = %dn", type);
  2043.       exit (-1);
  2044.   }
  2045. }
  2046. /*****************************************************************
  2047. Add an element to a PLY file descriptor.
  2048. Entry:
  2049.   words   - list of words describing the element
  2050.   nwords  - number of words in the list
  2051. ******************************************************************/
  2052. void 
  2053. PlyFile::add_element (char **words, int nwords)
  2054. {
  2055.   /* create the new element */
  2056.   PlyElement elem(words[1]);
  2057.   elem.num = atoi (words[2]);
  2058.   /* add the new element to the object's list */
  2059.   elems.push_back(elem);
  2060. }
  2061. /*****************************************************************
  2062. Return the type of a property, given the name of the property.
  2063. Entry:
  2064.   name - name of property type
  2065. Exit:
  2066.   returns integer code for property, or 0 if not found
  2067. ******************************************************************/
  2068. int 
  2069. get_prop_type(char *type_name)
  2070. {
  2071.   int i;
  2072.   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
  2073.     if (equal_strings (type_name, type_names[i]))
  2074.       return i;
  2075.   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
  2076.     if (equal_strings (type_name, new_type_names[i]))
  2077.       return i;
  2078.   /* if we get here, we didn't find the type */
  2079.   return 0;
  2080. }
  2081. /*****************************************************************
  2082. Add a property to a PLY file descriptor.
  2083. Entry:
  2084.   words   - list of words describing the property
  2085.   nwords  - number of words in the list
  2086. ******************************************************************/
  2087. void 
  2088. PlyFile::add_property(char **words, int nwords)
  2089. {
  2090.   PlyProperty prop;
  2091.   if (equal_strings (words[1], "list")) {       /* is a list */
  2092.     prop.count_external = get_prop_type (words[2]);
  2093.     prop.external_type = get_prop_type (words[3]);
  2094.     prop.name = strdup (words[4]);
  2095.     prop.is_list = 1;
  2096.   }
  2097.   else {                                        /* not a list */
  2098.     prop.external_type = get_prop_type (words[1]);
  2099.     prop.name = strdup(words[2]);
  2100.     prop.is_list = 0;
  2101.   }
  2102.   // add this property to the list of properties of the 
  2103.   // current element
  2104.   elems.back().props.push_back(prop);
  2105. }
  2106. /*****************************************************************
  2107. Add a comment to a PLY file descriptor.
  2108. Entry:
  2109.   line    - line containing comment
  2110. ******************************************************************/
  2111. void 
  2112. PlyFile::add_comment(char *line)
  2113. {
  2114.   int i;
  2115.   /* skip over "comment" and leading spaces and tabs */
  2116.   i = 7;
  2117.   while (line[i] == ' ' || line[i] == 't')
  2118.     i++;
  2119.   put_comment (&line[i]);
  2120. }
  2121. /*****************************************************************
  2122. Add a some object information to a PLY file descriptor.
  2123. Entry:
  2124.   line    - line containing text info
  2125. ******************************************************************/
  2126. void 
  2127. PlyFile::add_obj_info(char *line)
  2128. {
  2129.   int i;
  2130.   /* skip over "obj_info" and leading spaces and tabs */
  2131.   i = 8;
  2132.   while (line[i] == ' ' || line[i] == 't')
  2133.     i++;
  2134.   put_obj_info (&line[i]);
  2135. }
  2136. /*****************************************************************
  2137. Determine whether a property currently exists for an element.
  2138. Entry:
  2139.   elem_name - name of element that information is being 
  2140.               specified about
  2141.   prop_name - name of property to find
  2142. ******************************************************************/
  2143. int 
  2144. PlyFile::is_valid_property(char *elem_name, 
  2145.    char *prop_name)
  2146. {
  2147.   // find information about the element
  2148.   PlyElement *elem = find_element (elem_name);
  2149.   which_elem = elem;
  2150.   int index;
  2151.   return (NULL != find_property(elem, prop_name, &index));
  2152. }
  2153. int 
  2154. isPlyFile(char *filename)
  2155. {
  2156.   int nelems;
  2157.   char **elist;
  2158.   PlyFile ply;
  2159.   return ply.open_for_reading(filename, &nelems, &elist);
  2160. }