Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

plyfile.c

Go to the documentation of this file.
00001 /*
00002  
00003 The interface routines for reading and writing PLY polygon files.
00004 
00005 Greg Turk, February 1994
00006 
00007 ---------------------------------------------------------------
00008 
00009 A PLY file contains a single polygonal _object_.
00010 
00011 An object is composed of lists of _elements_.  Typical elements are
00012 vertices, faces, edges and materials.
00013 
00014 Each type of element for a given object has one or more _properties_
00015 associated with the element type.  For instance, a vertex element may
00016 have as properties the floating-point values x,y,z and the three unsigned
00017 chars representing red, green and blue.
00018 
00019 ---------------------------------------------------------------
00020 
00021 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
00022 Junior University.  All rights reserved.   
00023   
00024 Permission to use, copy, modify and distribute this software and its   
00025 documentation for any purpose is hereby granted without fee, provided   
00026 that the above copyright notice and this permission notice appear in   
00027 all copies of this software and that you do not sell the software.   
00028   
00029 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,   
00030 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY   
00031 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   
00032 
00033 */
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <math.h>
00038 #include <string.h>
00039 #include <ply.h>
00040 
00041 char *type_names[] = {
00042 "invalid",
00043 "char", "short", "int",
00044 "uchar", "ushort", "uint",
00045 "float", "double",
00046 };
00047 
00048 int ply_type_size[] = {
00049   0, 1, 2, 4, 1, 2, 4, 4, 8
00050 };
00051 
00052 #define NO_OTHER_PROPS  -1
00053 
00054 #define DONT_STORE_PROP  0
00055 #define STORE_PROP       1
00056 
00057 #define OTHER_PROP       0
00058 #define NAMED_PROP       1
00059 
00060 
00061 /* returns 1 if strings are equal, 0 if not */
00062 int equal_strings(char *, char *);
00063 
00064 /* find an element in a plyfile's list */
00065 PlyElement *find_element(PlyFile *, char *);
00066 
00067 /* find a property in an element's list */
00068 PlyProperty *find_property(PlyElement *, char *, int *);
00069 
00070 /* write to a file the word describing a PLY file data type */
00071 void write_scalar_type (FILE *, int);
00072 
00073 /* read a line from a file and break it up into separate words */
00074 char **get_words(FILE *, int *, char **);
00075 char **old_get_words(FILE *, int *);
00076 
00077 /* write an item to a file */
00078 void write_binary_item(FILE *, int, unsigned int, double, int);
00079 void write_ascii_item(FILE *, int, unsigned int, double, int);
00080 double old_write_ascii_item(FILE *, char *, int);
00081 
00082 /* add information to a PLY file descriptor */
00083 void add_element(PlyFile *, char **, int);
00084 void add_property(PlyFile *, char **, int);
00085 void add_comment(PlyFile *, char *);
00086 void add_obj_info(PlyFile *, char *);
00087 
00088 /* copy a property */
00089 void copy_property(PlyProperty *, PlyProperty *);
00090 
00091 /* store a value into where a pointer and a type specify */
00092 void store_item(char *, int, int, unsigned int, double);
00093 
00094 /* return the value of a stored item */
00095 void get_stored_item( void *, int, int *, unsigned int *, double *);
00096 
00097 /* return the value stored in an item, given ptr to it and its type */
00098 double get_item_value(char *, int);
00099 
00100 /* get binary or ascii item and store it according to ptr and type */
00101 void get_ascii_item(char *, int, int *, unsigned int *, double *);
00102 void get_binary_item(FILE *, int, int *, unsigned int *, double *);
00103 
00104 /* get a bunch of elements from a file */
00105 void ascii_get_element(PlyFile *, char *);
00106 void binary_get_element(PlyFile *, char *);
00107 
00108 /* memory allocation */
00109 static char *my_alloc(int, int, char *);
00110 
00111 
00112 /*************/
00113 /*  Writing  */
00114 /*************/
00115 
00116 
00117 /******************************************************************************
00118 Given a file pointer, get ready to write PLY data to the file.
00119 
00120 Entry:
00121   fp         - the given file pointer
00122   nelems     - number of elements in object
00123   elem_names - list of element names
00124   file_type  - file type, either ascii or binary
00125 
00126 Exit:
00127   returns a pointer to a PlyFile, used to refer to this file, or NULL if error
00128 ******************************************************************************/
00129 
00130 PlyFile *ply_write(
00131   FILE *fp,
00132   int nelems,
00133   char **elem_names,
00134   int file_type
00135 )
00136 {
00137   int i;
00138   PlyFile *plyfile;
00139   PlyElement *elem;
00140 
00141   /* check for NULL file pointer */
00142   if (fp == NULL)
00143     return (NULL);
00144 
00145   /* create a record for this object */
00146 
00147   plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
00148   plyfile->file_type = file_type;
00149   plyfile->num_comments = 0;
00150   plyfile->num_obj_info = 0;
00151   plyfile->nelems = nelems;
00152   plyfile->version = 1.0;
00153   plyfile->fp = fp;
00154   plyfile->other_elems = NULL;
00155 
00156   /* tuck aside the names of the elements */
00157 
00158   plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
00159   for (i = 0; i < nelems; i++) {
00160     elem = (PlyElement *) myalloc (sizeof (PlyElement));
00161     plyfile->elems[i] = elem;
00162     elem->name = strdup (elem_names[i]);
00163     elem->num = 0;
00164     elem->nprops = 0;
00165   }
00166 
00167   /* return pointer to the file descriptor */
00168   return (plyfile);
00169 }
00170 
00171 
00172 /******************************************************************************
00173 Open a polygon file for writing.
00174 
00175 Entry:
00176   filename   - name of file to read from
00177   nelems     - number of elements in object
00178   elem_names - list of element names
00179   file_type  - file type, either ascii or binary
00180 
00181 Exit:
00182   version - version number of PLY file
00183   returns a file identifier, used to refer to this file, or NULL if error
00184 ******************************************************************************/
00185 
00186 PlyFile *ply_open_for_writing(
00187   char *filename,
00188   int nelems,
00189   char **elem_names,
00190   int file_type,
00191   float *version
00192 )
00193 {
00194   int i;
00195   PlyFile *plyfile;
00196   PlyElement *elem;
00197   char *name;
00198   FILE *fp;
00199 
00200   /* tack on the extension .ply, if necessary */
00201 
00202   name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
00203   strcpy (name, filename);
00204   if (strlen (name) < 4 ||
00205       strcmp (name + strlen (name) - 4, ".ply") != 0)
00206       strcat (name, ".ply");
00207 
00208   /* open the file for writing */
00209 
00210   fp = fopen (name, "w");
00211   if (fp == NULL) {
00212     return (NULL);
00213   }
00214 
00215   /* create the actual PlyFile structure */
00216 
00217   plyfile = ply_write (fp, nelems, elem_names, file_type);
00218   if (plyfile == NULL)
00219     return (NULL);
00220 
00221   /* say what PLY file version number we're writing */
00222   *version = plyfile->version;
00223 
00224   /* return pointer to the file descriptor */
00225   return (plyfile);
00226 }
00227 
00228 
00229 /******************************************************************************
00230 Describe an element, including its properties and how many will be written
00231 to the file.
00232 
00233 Entry:
00234   plyfile   - file identifier
00235   elem_name - name of element that information is being specified about
00236   nelems    - number of elements of this type to be written
00237   nprops    - number of properties contained in the element
00238   prop_list - list of properties
00239 ******************************************************************************/
00240 
00241 void ply_describe_element(
00242   PlyFile *plyfile,
00243   char *elem_name,
00244   int nelems,
00245   int nprops,
00246   PlyProperty *prop_list
00247 )
00248 {
00249   int i;
00250   PlyElement *elem;
00251   PlyProperty *prop;
00252 
00253   /* look for appropriate element */
00254   elem = find_element (plyfile, elem_name);
00255   if (elem == NULL) {
00256     fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
00257     exit (-1);
00258   }
00259 
00260   elem->num = nelems;
00261 
00262   /* copy the list of properties */
00263 
00264   elem->nprops = nprops;
00265   elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
00266   elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
00267 
00268   for (i = 0; i < nprops; i++) {
00269     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00270     elem->props[i] = prop;
00271     elem->store_prop[i] = NAMED_PROP;
00272     copy_property (prop, &prop_list[i]);
00273   }
00274 }
00275 
00276 
00277 /******************************************************************************
00278 Describe a property of an element.
00279 
00280 Entry:
00281   plyfile   - file identifier
00282   elem_name - name of element that information is being specified about
00283   prop      - the new property
00284 ******************************************************************************/
00285 
00286 void ply_describe_property(
00287   PlyFile *plyfile,
00288   char *elem_name,
00289   PlyProperty *prop
00290 )
00291 {
00292   PlyElement *elem;
00293   PlyProperty *elem_prop;
00294 
00295   /* look for appropriate element */
00296   elem = find_element (plyfile, elem_name);
00297   if (elem == NULL) {
00298     fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
00299             elem_name);
00300     return;
00301   }
00302 
00303   /* create room for new property */
00304 
00305   if (elem->nprops == 0) {
00306     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
00307     elem->store_prop = (char *) myalloc (sizeof (char));
00308     elem->nprops = 1;
00309   }
00310   else {
00311     elem->nprops++;
00312     elem->props = (PlyProperty **)
00313                   realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
00314     elem->store_prop = (char *)
00315                   realloc (elem->store_prop, sizeof (char) * elem->nprops);
00316   }
00317 
00318   /* copy the new property */
00319 
00320   elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00321   elem->props[elem->nprops - 1] = elem_prop;
00322   elem->store_prop[elem->nprops - 1] = NAMED_PROP;
00323   copy_property (elem_prop, prop);
00324 }
00325 
00326 
00327 /******************************************************************************
00328 Describe what the "other" properties are that are to be stored, and where
00329 they are in an element.
00330 ******************************************************************************/
00331 
00332 void ply_describe_other_properties(
00333   PlyFile *plyfile,
00334   PlyOtherProp *other,
00335   int offset
00336 )
00337 {
00338   int i;
00339   PlyElement *elem;
00340   PlyProperty *prop;
00341 
00342   /* look for appropriate element */
00343   elem = find_element (plyfile, other->name);
00344   if (elem == NULL) {
00345     fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
00346             other->name);
00347     return;
00348   }
00349 
00350   /* create room for other properties */
00351 
00352   if (elem->nprops == 0) {
00353     elem->props = (PlyProperty **)
00354                   myalloc (sizeof (PlyProperty *) * other->nprops);
00355     elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
00356     elem->nprops = 0;
00357   }
00358   else {
00359     int newsize;
00360     newsize = elem->nprops + other->nprops;
00361     elem->props = (PlyProperty **)
00362                   realloc (elem->props, sizeof (PlyProperty *) * newsize);
00363     elem->store_prop = (char *)
00364                   realloc (elem->store_prop, sizeof (char) * newsize);
00365   }
00366 
00367   /* copy the other properties */
00368 
00369   for (i = 0; i < other->nprops; i++) {
00370     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00371     copy_property (prop, other->props[i]);
00372     elem->props[elem->nprops] = prop;
00373     elem->store_prop[elem->nprops] = OTHER_PROP;
00374     elem->nprops++;
00375   }
00376 
00377   /* save other info about other properties */
00378   elem->other_size = other->size;
00379   elem->other_offset = offset;
00380 }
00381 
00382 
00383 /******************************************************************************
00384 State how many of a given element will be written.
00385 
00386 Entry:
00387   plyfile   - file identifier
00388   elem_name - name of element that information is being specified about
00389   nelems    - number of elements of this type to be written
00390 ******************************************************************************/
00391 
00392 void ply_element_count(
00393   PlyFile *plyfile,
00394   char *elem_name,
00395   int nelems
00396 )
00397 {
00398   int i;
00399   PlyElement *elem;
00400   PlyProperty *prop;
00401 
00402   /* look for appropriate element */
00403   elem = find_element (plyfile, elem_name);
00404   if (elem == NULL) {
00405     fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
00406     exit (-1);
00407   }
00408 
00409   elem->num = nelems;
00410 }
00411 
00412 
00413 /******************************************************************************
00414 Signal that we've described everything a PLY file's header and that the
00415 header should be written to the file.
00416 
00417 Entry:
00418   plyfile - file identifier
00419 ******************************************************************************/
00420 
00421 void ply_header_complete(PlyFile *plyfile)
00422 {
00423   int i,j;
00424   FILE *fp = plyfile->fp;
00425   PlyElement *elem;
00426   PlyProperty *prop;
00427 
00428   fprintf (fp, "ply\n");
00429 
00430   switch (plyfile->file_type) {
00431     case PLY_ASCII:
00432       fprintf (fp, "format ascii 1.0\n");
00433       break;
00434     case PLY_BINARY_BE:
00435       fprintf (fp, "format binary_big_endian 1.0\n");
00436       break;
00437     case PLY_BINARY_LE:
00438       fprintf (fp, "format binary_little_endian 1.0\n");
00439       break;
00440     default:
00441       fprintf (stderr, "ply_header_complete: bad file type = %d\n",
00442                plyfile->file_type);
00443       exit (-1);
00444   }
00445 
00446   /* write out the comments */
00447 
00448   for (i = 0; i < plyfile->num_comments; i++)
00449     fprintf (fp, "comment %s\n", plyfile->comments[i]);
00450 
00451   /* write out object information */
00452 
00453   for (i = 0; i < plyfile->num_obj_info; i++)
00454     fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
00455 
00456   /* write out information about each element */
00457 
00458   for (i = 0; i < plyfile->nelems; i++) {
00459 
00460     elem = plyfile->elems[i];
00461     fprintf (fp, "element %s %d\n", elem->name, elem->num);
00462 
00463     /* write out each property */
00464     for (j = 0; j < elem->nprops; j++) {
00465       prop = elem->props[j];
00466       if (prop->is_list) {
00467         fprintf (fp, "property list ");
00468         write_scalar_type (fp, prop->count_external);
00469         fprintf (fp, " ");
00470         write_scalar_type (fp, prop->external_type);
00471         fprintf (fp, " %s\n", prop->name);
00472       }
00473       else {
00474         fprintf (fp, "property ");
00475         write_scalar_type (fp, prop->external_type);
00476         fprintf (fp, " %s\n", prop->name);
00477       }
00478     }
00479   }
00480 
00481   fprintf (fp, "end_header\n");
00482 }
00483 
00484 
00485 /******************************************************************************
00486 Specify which elements are going to be written.  This should be called
00487 before a call to the routine ply_put_element().
00488 
00489 Entry:
00490   plyfile   - file identifier
00491   elem_name - name of element we're talking about
00492 ******************************************************************************/
00493 
00494 void ply_put_element_setup(PlyFile *plyfile, char *elem_name)
00495 {
00496   PlyElement *elem;
00497 
00498   elem = find_element (plyfile, elem_name);
00499   if (elem == NULL) {
00500     fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
00501     exit (-1);
00502   }
00503 
00504   plyfile->which_elem = elem;
00505 }
00506 
00507 
00508 /******************************************************************************
00509 Write an element to the file.  This routine assumes that we're
00510 writing the type of element specified in the last call to the routine
00511 ply_put_element_setup().
00512 
00513 Entry:
00514   plyfile  - file identifier
00515   elem_ptr - pointer to the element
00516 ******************************************************************************/
00517 
00518 void ply_put_element(PlyFile *plyfile, void *elem_ptr)
00519 {
00520   int i,j,k;
00521   FILE *fp = plyfile->fp;
00522   PlyElement *elem;
00523   PlyProperty *prop;
00524   char *elem_data,*item;
00525   char **item_ptr;
00526   int list_count;
00527   int item_size;
00528   int int_val;
00529   unsigned int uint_val;
00530   double double_val;
00531   char **other_ptr;
00532 
00533   elem = plyfile->which_elem;
00534   elem_data = elem_ptr;
00535   other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
00536 
00537   /* write out either to an ascii or binary file */
00538 
00539   if (plyfile->file_type == PLY_ASCII) {
00540 
00541     /* write an ascii file */
00542 
00543     /* write out each property of the element */
00544     for (j = 0; j < elem->nprops; j++) {
00545       prop = elem->props[j];
00546       if (elem->store_prop[j] == OTHER_PROP)
00547         elem_data = *other_ptr;
00548       else
00549         elem_data = elem_ptr;
00550       if (prop->is_list) {
00551         item = elem_data + prop->count_offset;
00552         get_stored_item ((void *) item, prop->count_internal,
00553                          &int_val, &uint_val, &double_val);
00554         write_ascii_item (fp, int_val, uint_val, double_val,
00555                           prop->count_external);
00556         list_count = uint_val;
00557         item_ptr = (char **) (elem_data + prop->offset);
00558         item = item_ptr[0];
00559        item_size = ply_type_size[prop->internal_type];
00560         for (k = 0; k < list_count; k++) {
00561           get_stored_item ((void *) item, prop->internal_type,
00562                            &int_val, &uint_val, &double_val);
00563           write_ascii_item (fp, int_val, uint_val, double_val,
00564                             prop->external_type);
00565           item += item_size;
00566         }
00567       }
00568       else {
00569         item = elem_data + prop->offset;
00570         get_stored_item ((void *) item, prop->internal_type,
00571                          &int_val, &uint_val, &double_val);
00572         write_ascii_item (fp, int_val, uint_val, double_val,
00573                           prop->external_type);
00574       }
00575     }
00576 
00577     fprintf (fp, "\n");
00578   }
00579   else {
00580 
00581     /* write a binary file */
00582 
00583     /* write out each property of the element */
00584     for (j = 0; j < elem->nprops; j++) {
00585       prop = elem->props[j];
00586       if (elem->store_prop[j] == OTHER_PROP)
00587         elem_data = *other_ptr;
00588       else
00589         elem_data = elem_ptr;
00590       if (prop->is_list) {
00591         item = elem_data + prop->count_offset;
00592         item_size = ply_type_size[prop->count_internal];
00593         get_stored_item ((void *) item, prop->count_internal,
00594                          &int_val, &uint_val, &double_val);
00595         write_binary_item (fp, int_val, uint_val, double_val,
00596                            prop->count_external);
00597         list_count = uint_val;
00598         item_ptr = (char **) (elem_data + prop->offset);
00599         item = item_ptr[0];
00600         item_size = ply_type_size[prop->internal_type];
00601         for (k = 0; k < list_count; k++) {
00602           get_stored_item ((void *) item, prop->internal_type,
00603                            &int_val, &uint_val, &double_val);
00604           write_binary_item (fp, int_val, uint_val, double_val,
00605                              prop->external_type);
00606           item += item_size;
00607         }
00608       }
00609       else {
00610         item = elem_data + prop->offset;
00611         item_size = ply_type_size[prop->internal_type];
00612         get_stored_item ((void *) item, prop->internal_type,
00613                          &int_val, &uint_val, &double_val);
00614         write_binary_item (fp, int_val, uint_val, double_val,
00615                            prop->external_type);
00616       }
00617     }
00618 
00619   }
00620 }
00621 
00622 
00623 /******************************************************************************
00624 Specify a comment that will be written in the header.
00625 
00626 Entry:
00627   plyfile - file identifier
00628   comment - the comment to be written
00629 ******************************************************************************/
00630 
00631 void ply_put_comment(PlyFile *plyfile, char *comment)
00632 {
00633   /* (re)allocate space for new comment */
00634   if (plyfile->num_comments == 0)
00635     plyfile->comments = (char **) myalloc (sizeof (char *));
00636   else
00637     plyfile->comments = (char **) realloc (plyfile->comments,
00638                          sizeof (char *) * (plyfile->num_comments + 1));
00639 
00640   /* add comment to list */
00641   plyfile->comments[plyfile->num_comments] = strdup (comment);
00642   plyfile->num_comments++;
00643 }
00644 
00645 
00646 /******************************************************************************
00647 Specify a piece of object information (arbitrary text) that will be written
00648 in the header.
00649 
00650 Entry:
00651   plyfile  - file identifier
00652   obj_info - the text information to be written
00653 ******************************************************************************/
00654 
00655 void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
00656 {
00657   /* (re)allocate space for new info */
00658   if (plyfile->num_obj_info == 0)
00659     plyfile->obj_info = (char **) myalloc (sizeof (char *));
00660   else
00661     plyfile->obj_info = (char **) realloc (plyfile->obj_info,
00662                          sizeof (char *) * (plyfile->num_obj_info + 1));
00663 
00664   /* add info to list */
00665   plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info);
00666   plyfile->num_obj_info++;
00667 }
00668 
00669 
00670 
00671 
00672 
00673 
00674 
00675 /*************/
00676 /*  Reading  */
00677 /*************/
00678 
00679 
00680 
00681 /******************************************************************************
00682 Given a file pointer, get ready to read PLY data from the file.
00683 
00684 Entry:
00685   fp - the given file pointer
00686 
00687 Exit:
00688   nelems     - number of elements in object
00689   elem_names - list of element names
00690   returns a pointer to a PlyFile, used to refer to this file, or NULL if error
00691 ******************************************************************************/
00692 
00693 PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
00694 {
00695   int i,j;
00696   PlyFile *plyfile;
00697   int nwords;
00698   char **words;
00699   int found_format = 0;
00700   char **elist;
00701   PlyElement *elem;
00702   char *orig_line;
00703 
00704   /* check for NULL file pointer */
00705   if (fp == NULL)
00706     return (NULL);
00707 
00708   /* create record for this object */
00709 
00710   plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
00711   plyfile->nelems = 0;
00712   plyfile->comments = NULL;
00713   plyfile->num_comments = 0;
00714   plyfile->obj_info = NULL;
00715   plyfile->num_obj_info = 0;
00716   plyfile->fp = fp;
00717   plyfile->other_elems = NULL;
00718 
00719   /* read and parse the file's header */
00720 
00721   words = get_words (plyfile->fp, &nwords, &orig_line);
00722   if (!words || !equal_strings (words[0], "ply"))
00723     return (NULL);
00724 
00725   while (words) {
00726 
00727     /* parse words */
00728 
00729     if (equal_strings (words[0], "format")) {
00730       if (nwords != 3)
00731         return (NULL);
00732       if (equal_strings (words[1], "ascii"))
00733         plyfile->file_type = PLY_ASCII;
00734       else if (equal_strings (words[1], "binary_big_endian"))
00735         plyfile->file_type = PLY_BINARY_BE;
00736       else if (equal_strings (words[1], "binary_little_endian"))
00737         plyfile->file_type = PLY_BINARY_LE;
00738       else
00739         return (NULL);
00740       plyfile->version = atof (words[2]);
00741       found_format = 1;
00742     }
00743     else if (equal_strings (words[0], "element"))
00744       add_element (plyfile, words, nwords);
00745     else if (equal_strings (words[0], "property"))
00746       add_property (plyfile, words, nwords);
00747     else if (equal_strings (words[0], "comment"))
00748       add_comment (plyfile, orig_line);
00749     else if (equal_strings (words[0], "obj_info"))
00750       add_obj_info (plyfile, orig_line);
00751     else if (equal_strings (words[0], "end_header"))
00752       break;
00753 
00754     /* free up words space */
00755     free (words);
00756 
00757     words = get_words (plyfile->fp, &nwords, &orig_line);
00758   }
00759 
00760   /* create tags for each property of each element, to be used */
00761   /* later to say whether or not to store each property for the user */
00762 
00763   for (i = 0; i < plyfile->nelems; i++) {
00764     elem = plyfile->elems[i];
00765     elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
00766     for (j = 0; j < elem->nprops; j++)
00767       elem->store_prop[j] = DONT_STORE_PROP;
00768     elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
00769   }
00770 
00771   /* set return values about the elements */
00772 
00773   elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
00774   for (i = 0; i < plyfile->nelems; i++)
00775     elist[i] = strdup (plyfile->elems[i]->name);
00776 
00777   *elem_names = elist;
00778   *nelems = plyfile->nelems;
00779 
00780   /* return a pointer to the file's information */
00781 
00782   return (plyfile);
00783 }
00784 
00785 
00786 /******************************************************************************
00787 Open a polygon file for reading.
00788 
00789 Entry:
00790   filename - name of file to read from
00791 
00792 Exit:
00793   nelems     - number of elements in object
00794   elem_names - list of element names
00795   file_type  - file type, either ascii or binary
00796   version    - version number of PLY file
00797   returns a file identifier, used to refer to this file, or NULL if error
00798 ******************************************************************************/
00799 
00800 PlyFile *ply_open_for_reading(
00801   char *filename,
00802   int *nelems,
00803   char ***elem_names,
00804   int *file_type,
00805   float *version
00806 )
00807 {
00808   FILE *fp;
00809   PlyFile *plyfile;
00810   char *name;
00811 
00812   /* tack on the extension .ply, if necessary */
00813 
00814   name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
00815   strcpy (name, filename);
00816   if (strlen (name) < 4 ||
00817       strcmp (name + strlen (name) - 4, ".ply") != 0)
00818       strcat (name, ".ply");
00819 
00820   /* open the file for reading */
00821 
00822   fp = fopen (name, "r");
00823   if (fp == NULL)
00824     return (NULL);
00825 
00826   /* create the PlyFile data structure */
00827 
00828   plyfile = ply_read (fp, nelems, elem_names);
00829 
00830   /* determine the file type and version */
00831 
00832   *file_type = plyfile->file_type;
00833   *version = plyfile->version;
00834 
00835   /* return a pointer to the file's information */
00836 
00837   return (plyfile);
00838 }
00839 
00840 
00841 /******************************************************************************
00842 Get information about a particular element.
00843 
00844 Entry:
00845   plyfile   - file identifier
00846   elem_name - name of element to get information about
00847 
00848 Exit:
00849   nelems   - number of elements of this type in the file
00850   nprops   - number of properties
00851   returns a list of properties, or NULL if the file doesn't contain that elem
00852 ******************************************************************************/
00853 
00854 PlyProperty **ply_get_element_description(
00855   PlyFile *plyfile,
00856   char *elem_name,
00857   int *nelems,
00858   int *nprops
00859 )
00860 {
00861   int i;
00862   PlyElement *elem;
00863   PlyProperty *prop;
00864   PlyProperty **prop_list;
00865 
00866   /* find information about the element */
00867   elem = find_element (plyfile, elem_name);
00868   if (elem == NULL)
00869     return (NULL);
00870 
00871   *nelems = elem->num;
00872   *nprops = elem->nprops;
00873 
00874   /* make a copy of the element's property list */
00875   prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
00876   for (i = 0; i < elem->nprops; i++) {
00877     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00878     copy_property (prop, elem->props[i]);
00879     prop_list[i] = prop;
00880   }
00881 
00882   /* return this duplicate property list */
00883   return (prop_list);
00884 }
00885 
00886 
00887 /******************************************************************************
00888 Specify which properties of an element are to be returned.  This should be
00889 called before a call to the routine ply_get_element().
00890 
00891 Entry:
00892   plyfile   - file identifier
00893   elem_name - which element we're talking about
00894   nprops    - number of properties
00895   prop_list - list of properties
00896 ******************************************************************************/
00897 
00898 void ply_get_element_setup(
00899   PlyFile *plyfile,
00900   char *elem_name,
00901   int nprops,
00902   PlyProperty *prop_list
00903 )
00904 {
00905   int i;
00906   PlyElement *elem;
00907   PlyProperty *prop;
00908   int index;
00909 
00910   /* find information about the element */
00911   elem = find_element (plyfile, elem_name);
00912   plyfile->which_elem = elem;
00913 
00914   /* deposit the property information into the element's description */
00915   for (i = 0; i < nprops; i++) {
00916 
00917     /* look for actual property */
00918     prop = find_property (elem, prop_list[i].name, &index);
00919     if (prop == NULL) {
00920       fprintf (stderr, "Warning:  Can't find property '%s' in element '%s'\n",
00921                prop_list[i].name, elem_name);
00922       continue;
00923     }
00924 
00925     /* store its description */
00926     prop->internal_type = prop_list[i].internal_type;
00927     prop->offset = prop_list[i].offset;
00928     prop->count_internal = prop_list[i].count_internal;
00929     prop->count_offset = prop_list[i].count_offset;
00930 
00931     /* specify that the user wants this property */
00932     elem->store_prop[index] = STORE_PROP;
00933   }
00934 }
00935 
00936 
00937 /******************************************************************************
00938 Specify a property of an element that is to be returned.  This should be
00939 called (usually multiple times) before a call to the routine ply_get_element().
00940 This routine should be used in preference to the less flexible old routine
00941 called ply_get_element_setup().
00942 
00943 Entry:
00944   plyfile   - file identifier
00945   elem_name - which element we're talking about
00946   prop      - property to add to those that will be returned
00947 ******************************************************************************/
00948 
00949 void ply_get_property(
00950   PlyFile *plyfile,
00951   char *elem_name,
00952   PlyProperty *prop
00953 )
00954 {
00955   PlyElement *elem;
00956   PlyProperty *prop_ptr;
00957   int index;
00958 
00959   /* find information about the element */
00960   elem = find_element (plyfile, elem_name);
00961   plyfile->which_elem = elem;
00962 
00963   /* deposit the property information into the element's description */
00964 
00965   prop_ptr = find_property (elem, prop->name, &index);
00966   if (prop_ptr == NULL) {
00967     fprintf (stderr, "Warning:  Can't find property '%s' in element '%s'\n",
00968              prop->name, elem_name);
00969     return;
00970   }
00971   prop_ptr->internal_type  = prop->internal_type;
00972   prop_ptr->offset         = prop->offset;
00973   prop_ptr->count_internal = prop->count_internal;
00974   prop_ptr->count_offset   = prop->count_offset;
00975 
00976   /* specify that the user wants this property */
00977   elem->store_prop[index] = STORE_PROP;
00978 }
00979 
00980 
00981 /******************************************************************************
00982 Read one element from the file.  This routine assumes that we're reading
00983 the type of element specified in the last call to the routine
00984 ply_get_element_setup().
00985 
00986 Entry:
00987   plyfile  - file identifier
00988   elem_ptr - pointer to location where the element information should be put
00989 ******************************************************************************/
00990 
00991 void ply_get_element(PlyFile *plyfile, void *elem_ptr)
00992 {
00993   if (plyfile->file_type == PLY_ASCII)
00994     ascii_get_element (plyfile, (char *) elem_ptr);
00995   else
00996     binary_get_element (plyfile, (char *) elem_ptr);
00997 }
00998 
00999 
01000 /******************************************************************************
01001 Extract the comments from the header information of a PLY file.
01002 
01003 Entry:
01004   plyfile - file identifier
01005 
01006 Exit:
01007   num_comments - number of comments returned
01008   returns a pointer to a list of comments
01009 ******************************************************************************/
01010 
01011 char **ply_get_comments(PlyFile *plyfile, int *num_comments)
01012 {
01013   *num_comments = plyfile->num_comments;
01014   return (plyfile->comments);
01015 }
01016 
01017 
01018 /******************************************************************************
01019 Extract the object information (arbitrary text) from the header information
01020 of a PLY file.
01021 
01022 Entry:
01023   plyfile - file identifier
01024 
01025 Exit:
01026   num_obj_info - number of lines of text information returned
01027   returns a pointer to a list of object info lines
01028 ******************************************************************************/
01029 
01030 char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
01031 {
01032   *num_obj_info = plyfile->num_obj_info;
01033   return (plyfile->obj_info);
01034 }
01035 
01036 
01037 /******************************************************************************
01038 Make ready for "other" properties of an element-- those properties that
01039 the user has not explicitly asked for, but that are to be stashed away
01040 in a special structure to be carried along with the element's other
01041 information.
01042 
01043 Entry:
01044   plyfile - file identifier
01045   elem    - element for which we want to save away other properties
01046 ******************************************************************************/
01047 
01048 void setup_other_props(PlyFile *plyfile, PlyElement *elem)
01049 {
01050   int i;
01051   PlyProperty *prop;
01052   int size = 0;
01053   int type_size;
01054 
01055   /* Examine each property in decreasing order of size. */
01056   /* We do this so that all data types will be aligned by */
01057   /* word, half-word, or whatever within the structure. */
01058 
01059   for (type_size = 8; type_size > 0; type_size /= 2) {
01060 
01061     /* add up the space taken by each property, and save this information */
01062     /* away in the property descriptor */
01063 
01064     for (i = 0; i < elem->nprops; i++) {
01065 
01066       /* don't bother with properties we've been asked to store explicitly */
01067       if (elem->store_prop[i])
01068         continue;
01069 
01070       prop = elem->props[i];
01071 
01072       /* internal types will be same as external */
01073       prop->internal_type = prop->external_type;
01074       prop->count_internal = prop->count_external;
01075 
01076       /* check list case */
01077       if (prop->is_list) {
01078 
01079         /* pointer to list */
01080         if (type_size == sizeof (void *)) {
01081           prop->offset = size;
01082           size += sizeof (void *);    /* always use size of a pointer here */
01083         }
01084 
01085         /* count of number of list elements */
01086         if (type_size == ply_type_size[prop->count_external]) {
01087           prop->count_offset = size;
01088           size += ply_type_size[prop->count_external];
01089         }
01090       }
01091       /* not list */
01092       else if (type_size == ply_type_size[prop->external_type]) {
01093         prop->offset = size;
01094         size += ply_type_size[prop->external_type];
01095       }
01096     }
01097 
01098   }
01099 
01100   /* save the size for the other_props structure */
01101   elem->other_size = size;
01102 }
01103 
01104 
01105 /******************************************************************************
01106 Specify that we want the "other" properties of an element to be tucked
01107 away within the user's structure.  The user needn't be concerned for how
01108 these properties are stored.
01109 
01110 Entry:
01111   plyfile   - file identifier
01112   elem_name - name of element that we want to store other_props in
01113   offset    - offset to where other_props will be stored inside user's structure
01114 
01115 Exit:
01116   returns pointer to structure containing description of other_props
01117 ******************************************************************************/
01118 
01119 PlyOtherProp *ply_get_other_properties(
01120   PlyFile *plyfile,
01121   char *elem_name,
01122   int offset
01123 )
01124 {
01125   int i;
01126   PlyElement *elem;
01127   PlyOtherProp *other;
01128   PlyProperty *prop;
01129   int nprops;
01130 
01131   /* find information about the element */
01132   elem = find_element (plyfile, elem_name);
01133   if (elem == NULL) {
01134     fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
01135              elem_name);
01136     return (NULL);
01137   }
01138 
01139   /* remember that this is the "current" element */
01140   plyfile->which_elem = elem;
01141 
01142   /* save the offset to where to store the other_props */
01143   elem->other_offset = offset;
01144 
01145   /* place the appropriate pointers, etc. in the element's property list */
01146   setup_other_props (plyfile, elem);
01147 
01148   /* create structure for describing other_props */
01149   other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
01150   other->name = strdup (elem_name);
01151 #if 0
01152   if (elem->other_offset == NO_OTHER_PROPS) {
01153     other->size = 0;
01154     other->props = NULL;
01155     other->nprops = 0;
01156     return (other);
01157   }
01158 #endif
01159   other->size = elem->other_size;
01160   other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
01161   
01162   /* save descriptions of each "other" property */
01163   nprops = 0;
01164   for (i = 0; i < elem->nprops; i++) {
01165     if (elem->store_prop[i])
01166       continue;
01167     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
01168     copy_property (prop, elem->props[i]);
01169     other->props[nprops] = prop;
01170     nprops++;
01171   }
01172   other->nprops = nprops;
01173 
01174 #if 1
01175   /* set other_offset pointer appropriately if there are NO other properties */
01176   if (other->nprops == 0) {
01177     elem->other_offset = NO_OTHER_PROPS;
01178   }
01179 #endif
01180   
01181   /* return structure */
01182   return (other);
01183 }
01184 
01185 
01186 
01187 
01188 /*************************/
01189 /*  Other Element Stuff  */
01190 /*************************/
01191 
01192 
01193 
01194 
01195 /******************************************************************************
01196 Grab all the data for an element that a user does not want to explicitly
01197 read in.
01198 
01199 Entry:
01200   plyfile    - pointer to file
01201   elem_name  - name of element whose data is to be read in
01202   elem_count - number of instances of this element stored in the file
01203 
01204 Exit:
01205   returns pointer to ALL the "other" element data for this PLY file
01206 ******************************************************************************/
01207 
01208 PlyOtherElems *ply_get_other_element (
01209   PlyFile *plyfile,
01210   char *elem_name,
01211   int elem_count
01212 )
01213 {
01214   int i;
01215   PlyElement *elem;
01216   PlyOtherElems *other_elems;
01217   OtherElem *other;
01218   int num_elems;
01219 
01220   /* look for appropriate element */
01221   elem = find_element (plyfile, elem_name);
01222   if (elem == NULL) {
01223     fprintf (stderr,
01224              "ply_get_other_element: can't find element '%s'\n", elem_name);
01225     exit (-1);
01226   }
01227 
01228   /* create room for the new "other" element, initializing the */
01229   /* other data structure if necessary */
01230 
01231   if (plyfile->other_elems == NULL) {
01232     plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
01233     other_elems = plyfile->other_elems;
01234     other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
01235     other = &(other_elems->other_list[0]);
01236     other_elems->num_elems = 1;
01237   }
01238   else {
01239     other_elems = plyfile->other_elems;
01240     other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
01241                               sizeof (OtherElem) * other_elems->num_elems + 1);
01242     other = &(other_elems->other_list[other_elems->num_elems]);
01243     other_elems->num_elems++;
01244   }
01245 
01246   /* count of element instances in file */
01247   other->elem_count = elem_count;
01248 
01249   /* save name of element */
01250   other->elem_name = strdup (elem_name);
01251 
01252   /* create a list to hold all the current elements */
01253   other->other_data = (OtherData **)
01254                   malloc (sizeof (OtherData *) * other->elem_count);
01255 
01256   /* set up for getting elements */
01257   other->other_props = ply_get_other_properties (plyfile, elem_name,
01258                          offsetof(OtherData,other_props));
01259 
01260   /* grab all these elements */
01261   for (i = 0; i < other->elem_count; i++) {
01262     /* grab and element from the file */
01263     other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
01264     ply_get_element (plyfile, (void *) other->other_data[i]);
01265   }
01266 
01267   /* return pointer to the other elements data */
01268   return (other_elems);
01269 }
01270 
01271 
01272 /******************************************************************************
01273 Pass along a pointer to "other" elements that we want to save in a given
01274 PLY file.  These other elements were presumably read from another PLY file.
01275 
01276 Entry:
01277   plyfile     - file pointer in which to store this other element info
01278   other_elems - info about other elements that we want to store
01279 ******************************************************************************/
01280 
01281 void ply_describe_other_elements (
01282   PlyFile *plyfile,
01283   PlyOtherElems *other_elems
01284 )
01285 {
01286   int i;
01287   OtherElem *other;
01288 
01289   /* ignore this call if there is no other element */
01290   if (other_elems == NULL)
01291     return;
01292 
01293   /* save pointer to this information */
01294   plyfile->other_elems = other_elems;
01295 
01296   /* describe the other properties of this element */
01297 
01298   for (i = 0; i < other_elems->num_elems; i++) {
01299     other = &(other_elems->other_list[i]);
01300     ply_element_count (plyfile, other->elem_name, other->elem_count);
01301     ply_describe_other_properties (plyfile, other->other_props,
01302                                    offsetof(OtherData,other_props));
01303   }
01304 }
01305 
01306 
01307 /******************************************************************************
01308 Write out the "other" elements specified for this PLY file.
01309 
01310 Entry:
01311   plyfile - pointer to PLY file to write out other elements for
01312 ******************************************************************************/
01313 
01314 void ply_put_other_elements (PlyFile *plyfile)
01315 {
01316   int i,j;
01317   OtherElem *other;
01318 
01319   /* make sure we have other elements to write */
01320   if (plyfile->other_elems == NULL)
01321     return;
01322 
01323   /* write out the data for each "other" element */
01324 
01325   for (i = 0; i < plyfile->other_elems->num_elems; i++) {
01326 
01327     other = &(plyfile->other_elems->other_list[i]);
01328     ply_put_element_setup (plyfile, other->elem_name);
01329 
01330     /* write out each instance of the current element */
01331     for (j = 0; j < other->elem_count; j++)
01332       ply_put_element (plyfile, (void *) other->other_data[j]);
01333   }
01334 }
01335 
01336 
01337 /******************************************************************************
01338 Free up storage used by an "other" elements data structure.
01339 
01340 Entry:
01341   other_elems - data structure to free up
01342 ******************************************************************************/
01343 
01344 void ply_free_other_elements (PlyOtherElems *other_elems)
01345 {
01346 
01347 }
01348 
01349 
01350 
01351 /*******************/
01352 /*  Miscellaneous  */
01353 /*******************/
01354 
01355 
01356 
01357 /******************************************************************************
01358 Close a PLY file.
01359 
01360 Entry:
01361   plyfile - identifier of file to close
01362 ******************************************************************************/
01363 
01364 void ply_close(PlyFile *plyfile)
01365 {
01366   fclose (plyfile->fp);
01367 
01368   /* free up memory associated with the PLY file */
01369   free (plyfile);
01370 }
01371 
01372 
01373 /******************************************************************************
01374 Get version number and file type of a PlyFile.
01375 
01376 Entry:
01377   ply - pointer to PLY file
01378 
01379 Exit:
01380   version - version of the file
01381   file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
01382 ******************************************************************************/
01383 
01384 void ply_get_info(PlyFile *ply, float *version, int *file_type)
01385 {
01386   if (ply == NULL)
01387     return;
01388 
01389   *version = ply->version;
01390   *file_type = ply->file_type;
01391 }
01392 
01393 
01394 /******************************************************************************
01395 Compare two strings.  Returns 1 if they are the same, 0 if not.
01396 ******************************************************************************/
01397 
01398 int equal_strings(char *s1, char *s2)
01399 {
01400   int i;
01401 
01402   while (*s1 && *s2)
01403     if (*s1++ != *s2++)
01404       return (0);
01405 
01406   if (*s1 != *s2)
01407     return (0);
01408   else
01409     return (1);
01410 }
01411 
01412 
01413 /******************************************************************************
01414 Find an element from the element list of a given PLY object.
01415 
01416 Entry:
01417   plyfile - file id for PLY file
01418   element - name of element we're looking for
01419 
01420 Exit:
01421   returns the element, or NULL if not found
01422 ******************************************************************************/
01423 
01424 PlyElement *find_element(PlyFile *plyfile, char *element)
01425 {
01426   int i;
01427 
01428   for (i = 0; i < plyfile->nelems; i++)
01429     if (equal_strings (element, plyfile->elems[i]->name))
01430       return (plyfile->elems[i]);
01431 
01432   return (NULL);
01433 }
01434 
01435 
01436 /******************************************************************************
01437 Find a property in the list of properties of a given element.
01438 
01439 Entry:
01440   elem      - pointer to element in which we want to find the property
01441   prop_name - name of property to find
01442 
01443 Exit:
01444   index - index to position in list
01445   returns a pointer to the property, or NULL if not found
01446 ******************************************************************************/
01447 
01448 PlyProperty *find_property(PlyElement *elem, char *prop_name, int *index)
01449 {
01450   int i;
01451 
01452   for (i = 0; i < elem->nprops; i++)
01453     if (equal_strings (prop_name, elem->props[i]->name)) {
01454       *index = i;
01455       return (elem->props[i]);
01456     }
01457 
01458   *index = -1;
01459   return (NULL);
01460 }
01461 
01462 
01463 /******************************************************************************
01464 Read an element from an ascii file.
01465 
01466 Entry:
01467   plyfile  - file identifier
01468   elem_ptr - pointer to element
01469 ******************************************************************************/
01470 
01471 void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
01472 {
01473   int i,j,k;
01474   PlyElement *elem;
01475   PlyProperty *prop;
01476   char **words;
01477   int nwords;
01478   int which_word;
01479   FILE *fp = plyfile->fp;
01480   char *elem_data,*item;
01481   char *item_ptr;
01482   int item_size;
01483   int int_val;
01484   unsigned int uint_val;
01485   double double_val;
01486   int list_count;
01487   int store_it;
01488   char **store_array;
01489   char *orig_line;
01490   char *other_data;
01491   int other_flag;
01492 
01493   /* the kind of element we're reading currently */
01494   elem = plyfile->which_elem;
01495 
01496   /* do we need to setup for other_props? */
01497 
01498   if (elem->other_offset != NO_OTHER_PROPS) {
01499     char **ptr;
01500     other_flag = 1;
01501     /* make room for other_props */
01502     other_data = (char *) myalloc (elem->other_size);
01503     /* store pointer in user's structure to the other_props */
01504     ptr = (char **) (elem_ptr + elem->other_offset);
01505     *ptr = other_data;
01506   }
01507   else
01508     other_flag = 0;
01509 
01510   /* read in the element */
01511 
01512   words = get_words (plyfile->fp, &nwords, &orig_line);
01513   if (words == NULL) {
01514     fprintf (stderr, "ply_get_element: unexpected end of file\n");
01515     exit (-1);
01516   }
01517 
01518   which_word = 0;
01519 
01520   for (j = 0; j < elem->nprops; j++) {
01521 
01522     prop = elem->props[j];
01523     store_it = (elem->store_prop[j] | other_flag);
01524 
01525     /* store either in the user's structure or in other_props */
01526     if (elem->store_prop[j])
01527       elem_data = elem_ptr;
01528     else
01529       elem_data = other_data;
01530 
01531     if (prop->is_list) {       /* a list */
01532 
01533       /* get and store the number of items in the list */
01534       get_ascii_item (words[which_word++], prop->count_external,
01535                       &int_val, &uint_val, &double_val);
01536       if (store_it) {
01537         item = elem_data + prop->count_offset;
01538         store_item(item, prop->count_internal, int_val, uint_val, double_val);
01539       }
01540 
01541       /* allocate space for an array of items and store a ptr to the array */
01542       list_count = int_val;
01543       item_size = ply_type_size[prop->internal_type];
01544       store_array = (char **) (elem_data + prop->offset);
01545 
01546       if (list_count == 0) {
01547         if (store_it)
01548           *store_array = NULL;
01549       }
01550       else {
01551         if (store_it) {
01552           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
01553           item = item_ptr;
01554           *store_array = item_ptr;
01555         }
01556 
01557         /* read items and store them into the array */
01558         for (k = 0; k < list_count; k++) {
01559           get_ascii_item (words[which_word++], prop->external_type,
01560                           &int_val, &uint_val, &double_val);
01561           if (store_it) {
01562             store_item (item, prop->internal_type,
01563                         int_val, uint_val, double_val);
01564             item += item_size;
01565           }
01566         }
01567       }
01568 
01569     }
01570     else {                     /* not a list */
01571       get_ascii_item (words[which_word++], prop->external_type,
01572                       &int_val, &uint_val, &double_val);
01573       if (store_it) {
01574         item = elem_data + prop->offset;
01575         store_item (item, prop->internal_type, int_val, uint_val, double_val);
01576       }
01577     }
01578 
01579   }
01580 
01581   free (words);
01582 }
01583 
01584 
01585 /******************************************************************************
01586 Read an element from a binary file.
01587 
01588 Entry:
01589   plyfile  - file identifier
01590   elem_ptr - pointer to an element
01591 ******************************************************************************/
01592 
01593 void binary_get_element(PlyFile *plyfile, char *elem_ptr)
01594 {
01595   int i,j,k;
01596   PlyElement *elem;
01597   PlyProperty *prop;
01598   FILE *fp = plyfile->fp;
01599   char *elem_data,*item;
01600   char *item_ptr;
01601   int item_size;
01602   int int_val;
01603   unsigned int uint_val;
01604   double double_val;
01605   int list_count;
01606   int store_it;
01607   char **store_array;
01608   char *other_data;
01609   int other_flag;
01610 
01611   /* the kind of element we're reading currently */
01612   elem = plyfile->which_elem;
01613 
01614   /* do we need to setup for other_props? */
01615 
01616   if (elem->other_offset != NO_OTHER_PROPS) {
01617     char **ptr;
01618     other_flag = 1;
01619     /* make room for other_props */
01620     other_data = (char *) myalloc (elem->other_size);
01621     /* store pointer in user's structure to the other_props */
01622     ptr = (char **) (elem_ptr + elem->other_offset);
01623     *ptr = other_data;
01624   }
01625   else
01626     other_flag = 0;
01627 
01628   /* read in a number of elements */
01629 
01630   for (j = 0; j < elem->nprops; j++) {
01631 
01632     prop = elem->props[j];
01633     store_it = (elem->store_prop[j] | other_flag);
01634 
01635     /* store either in the user's structure or in other_props */
01636     if (elem->store_prop[j])
01637       elem_data = elem_ptr;
01638     else
01639       elem_data = other_data;
01640 
01641     if (prop->is_list) {       /* a list */
01642 
01643       /* get and store the number of items in the list */
01644       get_binary_item (fp, prop->count_external,
01645                       &int_val, &uint_val, &double_val);
01646       if (store_it) {
01647         item = elem_data + prop->count_offset;
01648         store_item(item, prop->count_internal, int_val, uint_val, double_val);
01649       }
01650 
01651       /* allocate space for an array of items and store a ptr to the array */
01652       list_count = int_val;
01653       /* The "if" was added by Afra Zomorodian 8/22/95
01654        * so that zipper won't crash reading plies that have additional
01655        * properties.
01656        */ 
01657       if (store_it) {
01658         item_size = ply_type_size[prop->internal_type];
01659       }
01660       store_array = (char **) (elem_data + prop->offset);
01661       if (list_count == 0) {
01662         if (store_it)
01663           *store_array = NULL;
01664       }
01665       else {
01666         if (store_it) {
01667           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
01668           item = item_ptr;
01669           *store_array = item_ptr;
01670         }
01671 
01672         /* read items and store them into the array */
01673         for (k = 0; k < list_count; k++) {
01674           get_binary_item (fp, prop->external_type,
01675                           &int_val, &uint_val, &double_val);
01676           if (store_it) {
01677             store_item (item, prop->internal_type,
01678                         int_val, uint_val, double_val);
01679             item += item_size;
01680           }
01681         }
01682       }
01683 
01684     }
01685     else {                     /* not a list */
01686       get_binary_item (fp, prop->external_type,
01687                       &int_val, &uint_val, &double_val);
01688       if (store_it) {
01689         item = elem_data + prop->offset;
01690         store_item (item, prop->internal_type, int_val, uint_val, double_val);
01691       }
01692     }
01693 
01694   }
01695 }
01696 
01697 
01698 /******************************************************************************
01699 Write to a file the word that represents a PLY data type.
01700 
01701 Entry:
01702   fp   - file pointer
01703   code - code for type
01704 ******************************************************************************/
01705 
01706 void write_scalar_type (FILE *fp, int code)
01707 {
01708   /* make sure this is a valid code */
01709 
01710   if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
01711     fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
01712     exit (-1);
01713   }
01714 
01715   /* write the code to a file */
01716 
01717   fprintf (fp, "%s", type_names[code]);
01718 }
01719 
01720 
01721 /******************************************************************************
01722 Get a text line from a file and break it up into words.
01723 
01724 IMPORTANT: The calling routine call "free" on the returned pointer once
01725 finished with it.
01726 
01727 Entry:
01728   fp - file to read from
01729 
01730 Exit:
01731   nwords    - number of words returned
01732   orig_line - the original line of characters
01733   returns a list of words from the line, or NULL if end-of-file
01734 ******************************************************************************/
01735 
01736 char **get_words(FILE *fp, int *nwords, char **orig_line)
01737 {
01738 #define BIG_STRING 4096
01739   int i,j;
01740   static char str[BIG_STRING];
01741   static char str_copy[BIG_STRING];
01742   char **words;
01743   int max_words = 10;
01744   int num_words = 0;
01745   char *ptr,*ptr2;
01746   char *result;
01747 
01748   words = (char **) myalloc (sizeof (char *) * max_words);
01749 
01750   /* read in a line */
01751   result = fgets (str, BIG_STRING, fp);
01752   if (result == NULL) {
01753     *nwords = 0;
01754     *orig_line = NULL;
01755     return (NULL);
01756   }
01757 
01758   /* convert line-feed and tabs into spaces */
01759   /* (this guarentees that there will be a space before the */
01760   /*  null character at the end of the string) */
01761 
01762   str[BIG_STRING-2] = ' ';
01763   str[BIG_STRING-1] = '\0';
01764 
01765   for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
01766     *ptr2 = *ptr;
01767     if (*ptr == '\t') {
01768       *ptr = ' ';
01769       *ptr2 = ' ';
01770     }
01771     else if (*ptr == '\n') {
01772       *ptr = ' ';
01773       *ptr2 = '\0';
01774       break;
01775     }
01776   }
01777 
01778   /* find the words in the line */
01779 
01780   ptr = str;
01781   while (*ptr != '\0') {
01782 
01783     /* jump over leading spaces */
01784     while (*ptr == ' ')
01785       ptr++;
01786 
01787     /* break if we reach the end */
01788     if (*ptr == '\0')
01789       break;
01790 
01791     /* save pointer to beginning of word */
01792     if (num_words >= max_words) {
01793       max_words += 10;
01794       words = (char **) realloc (words, sizeof (char *) * max_words);
01795     }
01796     words[num_words++] = ptr;
01797 
01798     /* jump over non-spaces */
01799     while (*ptr != ' ')
01800       ptr++;
01801 
01802     /* place a null character here to mark the end of the word */
01803     *ptr++ = '\0';
01804   }
01805 
01806   /* return the list of words */
01807   *nwords = num_words;
01808   *orig_line = str_copy;
01809   return (words);
01810 }
01811 
01812 
01813 /******************************************************************************
01814 Return the value of an item, given a pointer to it and its type.
01815 
01816 Entry:
01817   item - pointer to item
01818   type - data type that "item" points to
01819 
01820 Exit:
01821   returns a double-precision float that contains the value of the item
01822 ******************************************************************************/
01823 
01824 double get_item_value(char *item, int type)
01825 {
01826   unsigned char *puchar;
01827   char *pchar;
01828   short int *pshort;
01829   unsigned short int *pushort;
01830   int *pint;
01831   unsigned int *puint;
01832   float *pfloat;
01833   double *pdouble;
01834   int int_value;
01835   unsigned int uint_value;
01836   double double_value;
01837 
01838   switch (type) {
01839     case PLY_CHAR:
01840       pchar = (char *) item;
01841       int_value = *pchar;
01842       return ((double) int_value);
01843     case PLY_UCHAR:
01844       puchar = (unsigned char *) item;
01845       int_value = *puchar;
01846       return ((double) int_value);
01847     case PLY_SHORT:
01848       pshort = (short int *) item;
01849       int_value = *pshort;
01850       return ((double) int_value);
01851     case PLY_USHORT:
01852       pushort = (unsigned short int *) item;
01853       int_value = *pushort;
01854       return ((double) int_value);
01855     case PLY_INT:
01856       pint = (int *) item;
01857       int_value = *pint;
01858       return ((double) int_value);
01859     case PLY_UINT:
01860       puint = (unsigned int *) item;
01861       uint_value = *puint;
01862       return ((double) uint_value);
01863     case PLY_FLOAT:
01864       pfloat = (float *) item;
01865       double_value = *pfloat;
01866       return (double_value);
01867     case PLY_DOUBLE:
01868       pdouble = (double *) item;
01869       double_value = *pdouble;
01870       return (double_value);
01871     default:
01872       fprintf (stderr, "get_item_value: bad type = %d\n", type);
01873       exit (-1);
01874   }
01875 }
01876 
01877 
01878 /******************************************************************************
01879 Write out an item to a file as raw binary bytes.
01880 
01881 Entry:
01882   fp         - file to write to
01883   int_val    - integer version of item
01884   uint_val   - unsigned integer version of item
01885   double_val - double-precision float version of item
01886   type       - data type to write out
01887 ******************************************************************************/
01888 
01889 void write_binary_item(
01890   FILE *fp,
01891   int int_val,
01892   unsigned int uint_val,
01893   double double_val,
01894   int type
01895 )
01896 {
01897   unsigned char uchar_val;
01898   char char_val;
01899   unsigned short ushort_val;
01900   short short_val;
01901   float float_val;
01902 
01903   switch (type) {
01904     case PLY_CHAR:
01905       char_val = int_val;
01906       fwrite (&char_val, 1, 1, fp);
01907       break;
01908     case PLY_SHORT:
01909       short_val = int_val;
01910       fwrite (&short_val, 2, 1, fp);
01911       break;
01912     case PLY_INT:
01913       fwrite (&int_val, 4, 1, fp);
01914       break;
01915     case PLY_UCHAR:
01916       uchar_val = uint_val;
01917       fwrite (&uchar_val, 1, 1, fp);
01918       break;
01919     case PLY_USHORT:
01920       ushort_val = uint_val;
01921       fwrite (&ushort_val, 2, 1, fp);
01922       break;
01923     case PLY_UINT:
01924       fwrite (&uint_val, 4, 1, fp);
01925       break;
01926     case PLY_FLOAT:
01927       float_val = double_val;
01928       fwrite (&float_val, 4, 1, fp);
01929       break;
01930     case PLY_DOUBLE:
01931       fwrite (&double_val, 8, 1, fp);
01932       break;
01933     default:
01934       fprintf (stderr, "write_binary_item: bad type = %d\n", type);
01935       exit (-1);
01936   }
01937 }
01938 
01939 
01940 /******************************************************************************
01941 Write out an item to a file as ascii characters.
01942 
01943 Entry:
01944   fp         - file to write to
01945   int_val    - integer version of item
01946   uint_val   - unsigned integer version of item
01947   double_val - double-precision float version of item
01948   type       - data type to write out
01949 ******************************************************************************/
01950 
01951 void write_ascii_item(
01952   FILE *fp,
01953   int int_val,
01954   unsigned int uint_val,
01955   double double_val,
01956   int type
01957 )
01958 {
01959   switch (type) {
01960     case PLY_CHAR:
01961     case PLY_SHORT:
01962     case PLY_INT:
01963       fprintf (fp, "%d ", int_val);
01964       break;
01965     case PLY_UCHAR:
01966     case PLY_USHORT:
01967     case PLY_UINT:
01968       fprintf (fp, "%u ", uint_val);
01969       break;
01970     case PLY_FLOAT:
01971     case PLY_DOUBLE:
01972       fprintf (fp, "%g ", double_val);
01973       break;
01974     default:
01975       fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
01976       exit (-1);
01977   }
01978 }
01979 
01980 
01981 /******************************************************************************
01982 Write out an item to a file as ascii characters.
01983 
01984 Entry:
01985   fp   - file to write to
01986   item - pointer to item to write
01987   type - data type that "item" points to
01988 
01989 Exit:
01990   returns a double-precision float that contains the value of the written item
01991 ******************************************************************************/
01992 
01993 double old_write_ascii_item(FILE *fp, char *item, int type)
01994 {
01995   unsigned char *puchar;
01996   char *pchar;
01997   short int *pshort;
01998   unsigned short int *pushort;
01999   int *pint;
02000   unsigned int *puint;
02001   float *pfloat;
02002   double *pdouble;
02003   int int_value;
02004   unsigned int uint_value;
02005   double double_value;
02006 
02007   switch (type) {
02008     case PLY_CHAR:
02009       pchar = (char *) item;
02010       int_value = *pchar;
02011       fprintf (fp, "%d ", int_value);
02012       return ((double) int_value);
02013     case PLY_UCHAR:
02014       puchar = (unsigned char *) item;
02015       int_value = *puchar;
02016       fprintf (fp, "%d ", int_value);
02017       return ((double) int_value);
02018     case PLY_SHORT:
02019       pshort = (short int *) item;
02020       int_value = *pshort;
02021       fprintf (fp, "%d ", int_value);
02022       return ((double) int_value);
02023     case PLY_USHORT:
02024       pushort = (unsigned short int *) item;
02025       int_value = *pushort;
02026       fprintf (fp, "%d ", int_value);
02027       return ((double) int_value);
02028     case PLY_INT:
02029       pint = (int *) item;
02030       int_value = *pint;
02031       fprintf (fp, "%d ", int_value);
02032       return ((double) int_value);
02033     case PLY_UINT:
02034       puint = (unsigned int *) item;
02035       uint_value = *puint;
02036       fprintf (fp, "%u ", uint_value);
02037       return ((double) uint_value);
02038     case PLY_FLOAT:
02039       pfloat = (float *) item;
02040       double_value = *pfloat;
02041       fprintf (fp, "%g ", double_value);
02042       return (double_value);
02043     case PLY_DOUBLE:
02044       pdouble = (double *) item;
02045       double_value = *pdouble;
02046       fprintf (fp, "%g ", double_value);
02047       return (double_value);
02048     default:
02049       fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type);
02050       exit (-1);
02051   }
02052 }
02053 
02054 
02055 /******************************************************************************
02056 Get the value of an item that is in memory, and place the result
02057 into an integer, an unsigned integer and a double.
02058 
02059 Entry:
02060   ptr  - pointer to the item
02061   type - data type supposedly in the item
02062 
02063 Exit:
02064   int_val    - integer value
02065   uint_val   - unsigned integer value
02066   double_val - double-precision floating point value
02067 ******************************************************************************/
02068 
02069 void get_stored_item(
02070   void *ptr,
02071   int type,
02072   int *int_val,
02073   unsigned int *uint_val,
02074   double *double_val
02075 )
02076 {
02077   switch (type) {
02078     case PLY_CHAR:
02079       *int_val = *((char *) ptr);
02080       *uint_val = *int_val;
02081       *double_val = *int_val;
02082       break;
02083     case PLY_UCHAR:
02084       *uint_val = *((unsigned char *) ptr);
02085       *int_val = *uint_val;
02086       *double_val = *uint_val;
02087       break;
02088     case PLY_SHORT:
02089       *int_val = *((short int *) ptr);
02090       *uint_val = *int_val;
02091       *double_val = *int_val;
02092       break;
02093     case PLY_USHORT:
02094       *uint_val = *((unsigned short int *) ptr);
02095       *int_val = *uint_val;
02096       *double_val = *uint_val;
02097       break;
02098     case PLY_INT:
02099       *int_val = *((int *) ptr);
02100       *uint_val = *int_val;
02101       *double_val = *int_val;
02102       break;
02103     case PLY_UINT:
02104       *uint_val = *((unsigned int *) ptr);
02105       *int_val = *uint_val;
02106       *double_val = *uint_val;
02107       break;
02108     case PLY_FLOAT:
02109       *double_val = *((float *) ptr);
02110       *int_val = *double_val;
02111       *uint_val = *double_val;
02112       break;
02113     case PLY_DOUBLE:
02114       *double_val = *((double *) ptr);
02115       *int_val = *double_val;
02116       *uint_val = *double_val;
02117       break;
02118     default:
02119       fprintf (stderr, "get_stored_item: bad type = %d\n", type);
02120       exit (-1);
02121   }
02122 }
02123 
02124 
02125 /******************************************************************************
02126 Get the value of an item from a binary file, and place the result
02127 into an integer, an unsigned integer and a double.
02128 
02129 Entry:
02130   fp   - file to get item from
02131   type - data type supposedly in the word
02132 
02133 Exit:
02134   int_val    - integer value
02135   uint_val   - unsigned integer value
02136   double_val - double-precision floating point value
02137 ******************************************************************************/
02138 
02139 void get_binary_item(
02140   FILE *fp,
02141   int type,
02142   int *int_val,
02143   unsigned int *uint_val,
02144   double *double_val
02145 )
02146 {
02147   char c[8];
02148   void *ptr;
02149 
02150   ptr = (void *) c;
02151 
02152   switch (type) {
02153     case PLY_CHAR:
02154       fread (ptr, 1, 1, fp);
02155       *int_val = *((char *) ptr);
02156       *uint_val = *int_val;
02157       *double_val = *int_val;
02158       break;
02159     case PLY_UCHAR:
02160       fread (ptr, 1, 1, fp);
02161       *uint_val = *((unsigned char *) ptr);
02162       *int_val = *uint_val;
02163       *double_val = *uint_val;
02164       break;
02165     case PLY_SHORT:
02166       fread (ptr, 2, 1, fp);
02167       *int_val = *((short int *) ptr);
02168       *uint_val = *int_val;
02169       *double_val = *int_val;
02170       break;
02171     case PLY_USHORT:
02172       fread (ptr, 2, 1, fp);
02173       *uint_val = *((unsigned short int *) ptr);
02174       *int_val = *uint_val;
02175       *double_val = *uint_val;
02176       break;
02177     case PLY_INT:
02178       fread (ptr, 4, 1, fp);
02179       *int_val = *((int *) ptr);
02180       *uint_val = *int_val;
02181       *double_val = *int_val;
02182       break;
02183     case PLY_UINT:
02184       fread (ptr, 4, 1, fp);
02185       *uint_val = *((unsigned int *) ptr);
02186       *int_val = *uint_val;
02187       *double_val = *uint_val;
02188       break;
02189     case PLY_FLOAT:
02190       fread (ptr, 4, 1, fp);
02191       *double_val = *((float *) ptr);
02192       *int_val = *double_val;
02193       *uint_val = *double_val;
02194       break;
02195     case PLY_DOUBLE:
02196       fread (ptr, 8, 1, fp);
02197       *double_val = *((double *) ptr);
02198       *int_val = *double_val;
02199       *uint_val = *double_val;
02200       break;
02201     default:
02202       fprintf (stderr, "get_binary_item: bad type = %d\n", type);
02203       exit (-1);
02204   }
02205 }
02206 
02207 
02208 /******************************************************************************
02209 Extract the value of an item from an ascii word, and place the result
02210 into an integer, an unsigned integer and a double.
02211 
02212 Entry:
02213   word - word to extract value from
02214   type - data type supposedly in the word
02215 
02216 Exit:
02217   int_val    - integer value
02218   uint_val   - unsigned integer value
02219   double_val - double-precision floating point value
02220 ******************************************************************************/
02221 
02222 void get_ascii_item(
02223   char *word,
02224   int type,
02225   int *int_val,
02226   unsigned int *uint_val,
02227   double *double_val
02228 )
02229 {
02230   switch (type) {
02231     case PLY_CHAR:
02232     case PLY_UCHAR:
02233     case PLY_SHORT:
02234     case PLY_USHORT:
02235     case PLY_INT:
02236       *int_val = atoi (word);
02237       *uint_val = *int_val;
02238       *double_val = *int_val;
02239       break;
02240 
02241     case PLY_UINT:
02242       *uint_val = strtoul (word, (char **) NULL, 10);
02243       *int_val = *uint_val;
02244       *double_val = *uint_val;
02245       break;
02246 
02247     case PLY_FLOAT:
02248     case PLY_DOUBLE:
02249       *double_val = atof (word);
02250       *int_val = (int) *double_val;
02251       *uint_val = (unsigned int) *double_val;
02252       break;
02253 
02254     default:
02255       fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
02256       exit (-1);
02257   }
02258 }
02259 
02260 
02261 /******************************************************************************
02262 Store a value into a place being pointed to, guided by a data type.
02263 
02264 Entry:
02265   item       - place to store value
02266   type       - data type
02267   int_val    - integer version of value
02268   uint_val   - unsigned integer version of value
02269   double_val - double version of value
02270 
02271 Exit:
02272   item - pointer to stored value
02273 ******************************************************************************/
02274 
02275 void store_item (
02276   char *item,
02277   int type,
02278   int int_val,
02279   unsigned int uint_val,
02280   double double_val
02281 )
02282 {
02283   unsigned char *puchar;
02284   short int *pshort;
02285   unsigned short int *pushort;
02286   int *pint;
02287   unsigned int *puint;
02288   float *pfloat;
02289   double *pdouble;
02290 
02291   switch (type) {
02292     case PLY_CHAR:
02293       *item = int_val;
02294       break;
02295     case PLY_UCHAR:
02296       puchar = (unsigned char *) item;
02297       *puchar = uint_val;
02298       break;
02299     case PLY_SHORT:
02300       pshort = (short *) item;
02301       *pshort = int_val;
02302       break;
02303     case PLY_USHORT:
02304       pushort = (unsigned short *) item;
02305       *pushort = uint_val;
02306       break;
02307     case PLY_INT:
02308       pint = (int *) item;
02309       *pint = int_val;
02310       break;
02311     case PLY_UINT:
02312       puint = (unsigned int *) item;
02313       *puint = uint_val;
02314       break;
02315     case PLY_FLOAT:
02316       pfloat = (float *) item;
02317       *pfloat = double_val;
02318       break;
02319     case PLY_DOUBLE:
02320       pdouble = (double *) item;
02321       *pdouble = double_val;
02322       break;
02323     default:
02324       fprintf (stderr, "store_item: bad type = %d\n", type);
02325       exit (-1);
02326   }
02327 }
02328 
02329 
02330 /******************************************************************************
02331 Add an element to a PLY file descriptor.
02332 
02333 Entry:
02334   plyfile - PLY file descriptor
02335   words   - list of words describing the element
02336   nwords  - number of words in the list
02337 ******************************************************************************/
02338 
02339 void add_element (PlyFile *plyfile, char **words, int nwords)
02340 {
02341   PlyElement *elem;
02342 
02343   /* create the new element */
02344   elem = (PlyElement *) myalloc (sizeof (PlyElement));
02345   elem->name = strdup (words[1]);
02346   elem->num = atoi (words[2]);
02347   elem->nprops = 0;
02348 
02349   /* make room for new element in the object's list of elements */
02350   if (plyfile->nelems == 0)
02351     plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
02352   else
02353     plyfile->elems = (PlyElement **) realloc (plyfile->elems,
02354                      sizeof (PlyElement *) * (plyfile->nelems + 1));
02355 
02356   /* add the new element to the object's list */
02357   plyfile->elems[plyfile->nelems] = elem;
02358   plyfile->nelems++;
02359 }
02360 
02361 
02362 /******************************************************************************
02363 Return the type of a property, given the name of the property.
02364 
02365 Entry:
02366   name - name of property type
02367 
02368 Exit:
02369   returns integer code for property, or 0 if not found
02370 ******************************************************************************/
02371 
02372 int get_prop_type(char *type_name)
02373 {
02374   int i;
02375 
02376   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
02377     if (equal_strings (type_name, type_names[i]))
02378       return (i);
02379 
02380   /* if we get here, we didn't find the type */
02381   return (0);
02382 }
02383 
02384 
02385 /******************************************************************************
02386 Add a property to a PLY file descriptor.
02387 
02388 Entry:
02389   plyfile - PLY file descriptor
02390   words   - list of words describing the property
02391   nwords  - number of words in the list
02392 ******************************************************************************/
02393 
02394 void add_property (PlyFile *plyfile, char **words, int nwords)
02395 {
02396   int prop_type;
02397   int count_type;
02398   PlyProperty *prop;
02399   PlyElement *elem;
02400 
02401   /* create the new property */
02402 
02403   prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
02404 
02405   if (equal_strings (words[1], "list")) {       /* is a list */
02406     prop->count_external = get_prop_type (words[2]);
02407     prop->external_type = get_prop_type (words[3]);
02408     prop->name = strdup (words[4]);
02409     prop->is_list = 1;
02410   }
02411   else {                                        /* not a list */
02412     prop->external_type = get_prop_type (words[1]);
02413     prop->name = strdup (words[2]);
02414     prop->is_list = 0;
02415   }
02416 
02417   /* add this property to the list of properties of the current element */
02418 
02419   elem = plyfile->elems[plyfile->nelems - 1];
02420 
02421   if (elem->nprops == 0)
02422     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
02423   else
02424     elem->props = (PlyProperty **) realloc (elem->props,
02425                   sizeof (PlyProperty *) * (elem->nprops + 1));
02426 
02427   elem->props[elem->nprops] = prop;
02428   elem->nprops++;
02429 }
02430 
02431 
02432 /******************************************************************************
02433 Add a comment to a PLY file descriptor.
02434 
02435 Entry:
02436   plyfile - PLY file descriptor
02437   line    - line containing comment
02438 ******************************************************************************/
02439 
02440 void add_comment (PlyFile *plyfile, char *line)
02441 {
02442   int i;
02443 
02444   /* skip over "comment" and leading spaces and tabs */
02445   i = 7;
02446   while (line[i] == ' ' || line[i] == '\t')
02447     i++;
02448 
02449   ply_put_comment (plyfile, &line[i]);
02450 }
02451 
02452 
02453 /******************************************************************************
02454 Add a some object information to a PLY file descriptor.
02455 
02456 Entry:
02457   plyfile - PLY file descriptor
02458   line    - line containing text info
02459 ******************************************************************************/
02460 
02461 void add_obj_info (PlyFile *plyfile, char *line)
02462 {
02463   int i;
02464 
02465   /* skip over "obj_info" and leading spaces and tabs */
02466   i = 8;
02467   while (line[i] == ' ' || line[i] == '\t')
02468     i++;
02469 
02470   ply_put_obj_info (plyfile, &line[i]);
02471 }
02472 
02473 
02474 /******************************************************************************
02475 Copy a property.
02476 ******************************************************************************/
02477 
02478 void copy_property(PlyProperty *dest, PlyProperty *src)
02479 {
02480   dest->name = strdup (src->name);
02481   dest->external_type = src->external_type;
02482   dest->internal_type = src->internal_type;
02483   dest->offset = src->offset;
02484 
02485   dest->is_list = src->is_list;
02486   dest->count_external = src->count_external;
02487   dest->count_internal = src->count_internal;
02488   dest->count_offset = src->count_offset;
02489 }
02490 
02491 
02492 /******************************************************************************
02493 Allocate some memory.
02494 
02495 Entry:
02496   size  - amount of memory requested (in bytes)
02497   lnum  - line number from which memory was requested
02498   fname - file name from which memory was requested
02499 ******************************************************************************/
02500 
02501 static char *my_alloc(int size, int lnum, char *fname)
02502 {
02503   char *ptr;
02504 
02505   ptr = (char *) malloc (size);
02506 
02507   if (ptr == 0) {
02508     fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname);
02509   }
02510 
02511   return (ptr);
02512 }
02513 
 

Powered by Plone

This site conforms to the following standards: