|
Closest Point
Find the Closest Point on a mesh
|
00001 /* 00002 00003 The interface routines for reading and writing PLY polygon files. 00004 00005 Greg Turk 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) 1998 Georgia Institute of Technology. All rights reserved. 00022 00023 Permission to use, copy, modify and distribute this software and its 00024 documentation for any purpose is hereby granted without fee, provided 00025 that the above copyright notice and this permission notice appear in 00026 all copies of this software and that you do not sell the software. 00027 00028 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, 00029 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 00030 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 00031 00032 */ 00033 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <math.h> 00037 #include <string.h> 00038 #include "../include/ply.h" 00039 00040 char *type_names[] = { /* names of scalar types */ 00041 "invalid", 00042 "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64", 00043 }; 00044 00045 char *old_type_names[] = { /* old names of types for backward compatability */ 00046 "invalid", 00047 "char", "short", "int", "uchar", "ushort", "uint", "float", "double", 00048 }; 00049 00050 int ply_type_size[] = { 00051 0, 1, 2, 4, 1, 2, 4, 4, 8 00052 }; 00053 00054 #define NO_OTHER_PROPS -1 00055 00056 #define DONT_STORE_PROP 0 00057 #define STORE_PROP 1 00058 00059 #define OTHER_PROP 0 00060 #define NAMED_PROP 1 00061 00062 /* returns 1 if strings are equal, 0 if not */ 00063 int equal_strings(char *, char *); 00064 00065 /* find an element in a plyfile's list */ 00066 PlyElement *find_element(PlyFile *, char *); 00067 00068 /* find a property in an element's list */ 00069 PlyProperty *find_property(PlyElement *, char *, int *); 00070 00071 /* write to a file the word describing a PLY file data type */ 00072 void write_scalar_type (FILE *, int); 00073 00074 /* read a line from a file and break it up into separate words */ 00075 char **get_words(FILE *, int *, char **); 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 00081 /* add information to a PLY file descriptor */ 00082 void add_element(PlyFile *, char **, int); 00083 void add_property(PlyFile *, char **, int); 00084 void add_comment(PlyFile *, char *); 00085 void add_obj_info(PlyFile *, char *); 00086 00087 /* copy a property */ 00088 void copy_property(PlyProperty *, PlyProperty *); 00089 00090 /* store a value into where a pointer and a type specify */ 00091 void store_item(char *, int, int, unsigned int, double); 00092 00093 /* return the value of a stored item */ 00094 void get_stored_item( void *, int, int *, unsigned int *, double *); 00095 00096 /* return the value stored in an item, given ptr to it and its type */ 00097 double get_item_value(char *, int); 00098 00099 /* get binary or ascii item and store it according to ptr and type */ 00100 void get_ascii_item(char *, int, int *, unsigned int *, double *); 00101 void get_binary_item(FILE *, int, int *, unsigned int *, double *); 00102 00103 /* get a bunch of elements from a file */ 00104 void ascii_get_element(PlyFile *, char *); 00105 void binary_get_element(PlyFile *, char *); 00106 00107 /* memory allocation */ 00108 static char *my_alloc(int, int, char *); 00109 00110 00111 /*************/ 00112 /* Writing */ 00113 /*************/ 00114 00115 00116 /****************************************************************************** 00117 Given a file pointer, get ready to write PLY data to the file. 00118 00119 Entry: 00120 fp - the given file pointer 00121 nelems - number of elements in object 00122 elem_names - list of element names 00123 file_type - file type, either ascii or binary 00124 00125 Exit: 00126 returns a pointer to a PlyFile, used to refer to this file, or NULL if error 00127 ******************************************************************************/ 00128 00129 PlyFile *ply_write( 00130 FILE *fp, 00131 int nelems, 00132 char **elem_names, 00133 int file_type 00134 ) 00135 { 00136 int i; 00137 PlyFile *plyfile; 00138 PlyElement *elem; 00139 00140 /* check for NULL file pointer */ 00141 if (fp == NULL) 00142 return (NULL); 00143 00144 /* create a record for this object */ 00145 00146 plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); 00147 plyfile->file_type = file_type; 00148 plyfile->num_comments = 0; 00149 plyfile->num_obj_info = 0; 00150 plyfile->num_elem_types = nelems; 00151 plyfile->version = 1.0; 00152 plyfile->fp = fp; 00153 plyfile->other_elems = NULL; 00154 00155 /* tuck aside the names of the elements */ 00156 00157 plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems); 00158 for (i = 0; i < nelems; i++) { 00159 elem = (PlyElement *) myalloc (sizeof (PlyElement)); 00160 plyfile->elems[i] = elem; 00161 elem->name = strdup (elem_names[i]); 00162 elem->num = 0; 00163 elem->nprops = 0; 00164 } 00165 00166 /* return pointer to the file descriptor */ 00167 return (plyfile); 00168 } 00169 00170 00171 /****************************************************************************** 00172 Open a polygon file for writing. 00173 00174 Entry: 00175 filename - name of file to read from 00176 nelems - number of elements in object 00177 elem_names - list of element names 00178 file_type - file type, either ascii or binary 00179 00180 Exit: 00181 returns a file identifier, used to refer to this file, or NULL if error 00182 ******************************************************************************/ 00183 00184 PlyFile *open_for_writing_ply( 00185 char *filename, 00186 int nelems, 00187 char **elem_names, 00188 int file_type 00189 ) 00190 { 00191 int i; 00192 PlyFile *plyfile; 00193 PlyElement *elem; 00194 char *name; 00195 FILE *fp; 00196 00197 /* tack on the extension .ply, if necessary */ 00198 00199 name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5)); 00200 strcpy (name, filename); 00201 if (strlen (name) < 4 || 00202 strcmp (name + strlen (name) - 4, ".ply") != 0) 00203 strcat (name, ".ply"); 00204 00205 /* open the file for writing */ 00206 00207 fp = fopen (name, "w"); 00208 if (fp == NULL) { 00209 return (NULL); 00210 } 00211 00212 /* create the actual PlyFile structure */ 00213 00214 plyfile = ply_write (fp, nelems, elem_names, file_type); 00215 if (plyfile == NULL) 00216 return (NULL); 00217 00218 /* return pointer to the file descriptor */ 00219 return (plyfile); 00220 } 00221 00222 00223 /****************************************************************************** 00224 Describe an element, including its properties and how many will be written 00225 to the file. 00226 00227 Entry: 00228 plyfile - file identifier 00229 elem_name - name of element that information is being specified about 00230 nelems - number of elements of this type to be written 00231 nprops - number of properties contained in the element 00232 prop_list - list of properties 00233 ******************************************************************************/ 00234 00235 void element_layout_ply( 00236 PlyFile *plyfile, 00237 char *elem_name, 00238 int nelems, 00239 int nprops, 00240 PlyProperty *prop_list 00241 ) 00242 { 00243 int i; 00244 PlyElement *elem; 00245 PlyProperty *prop; 00246 00247 /* look for appropriate element */ 00248 elem = find_element (plyfile, elem_name); 00249 if (elem == NULL) { 00250 fprintf(stderr,"element_layout_ply: can't find element '%s'\n",elem_name); 00251 exit (-1); 00252 } 00253 00254 elem->num = nelems; 00255 00256 /* copy the list of properties */ 00257 00258 elem->nprops = nprops; 00259 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops); 00260 elem->store_prop = (char *) myalloc (sizeof (char) * nprops); 00261 00262 for (i = 0; i < nprops; i++) { 00263 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 00264 elem->props[i] = prop; 00265 elem->store_prop[i] = NAMED_PROP; 00266 copy_property (prop, &prop_list[i]); 00267 } 00268 } 00269 00270 00271 /****************************************************************************** 00272 Describe a property of an element. 00273 00274 Entry: 00275 plyfile - file identifier 00276 elem_name - name of element that information is being specified about 00277 prop - the new property 00278 ******************************************************************************/ 00279 00280 void ply_describe_property( 00281 PlyFile *plyfile, 00282 char *elem_name, 00283 PlyProperty *prop 00284 ) 00285 { 00286 PlyElement *elem; 00287 PlyProperty *elem_prop; 00288 00289 /* look for appropriate element */ 00290 elem = find_element (plyfile, elem_name); 00291 if (elem == NULL) { 00292 fprintf(stderr, "ply_describe_property: can't find element '%s'\n", 00293 elem_name); 00294 return; 00295 } 00296 00297 /* create room for new property */ 00298 00299 if (elem->nprops == 0) { 00300 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); 00301 elem->store_prop = (char *) myalloc (sizeof (char)); 00302 elem->nprops = 1; 00303 } 00304 else { 00305 elem->nprops++; 00306 elem->props = (PlyProperty **) 00307 realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); 00308 elem->store_prop = (char *) 00309 realloc (elem->store_prop, sizeof (char) * elem->nprops); 00310 } 00311 00312 /* copy the new property */ 00313 00314 elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 00315 elem->props[elem->nprops - 1] = elem_prop; 00316 elem->store_prop[elem->nprops - 1] = NAMED_PROP; 00317 copy_property (elem_prop, prop); 00318 } 00319 00320 00321 /****************************************************************************** 00322 State how many of a given element will be written. 00323 00324 Entry: 00325 plyfile - file identifier 00326 elem_name - name of element that information is being specified about 00327 nelems - number of elements of this type to be written 00328 ******************************************************************************/ 00329 00330 void element_count_ply( 00331 PlyFile *plyfile, 00332 char *elem_name, 00333 int nelems 00334 ) 00335 { 00336 int i; 00337 PlyElement *elem; 00338 PlyProperty *prop; 00339 00340 /* look for appropriate element */ 00341 elem = find_element (plyfile, elem_name); 00342 if (elem == NULL) { 00343 fprintf(stderr,"element_count_ply: can't find element '%s'\n",elem_name); 00344 exit (-1); 00345 } 00346 00347 elem->num = nelems; 00348 } 00349 00350 00351 /****************************************************************************** 00352 Signal that we've described everything a PLY file's header and that the 00353 header should be written to the file. 00354 00355 Entry: 00356 plyfile - file identifier 00357 ******************************************************************************/ 00358 00359 void header_complete_ply(PlyFile *plyfile) 00360 { 00361 int i,j; 00362 FILE *fp = plyfile->fp; 00363 PlyElement *elem; 00364 PlyProperty *prop; 00365 00366 fprintf (fp, "ply\n"); 00367 00368 switch (plyfile->file_type) { 00369 case PLY_ASCII: 00370 fprintf (fp, "format ascii 1.0\n"); 00371 break; 00372 case PLY_BINARY_BE: 00373 fprintf (fp, "format binary_big_endian 1.0\n"); 00374 break; 00375 case PLY_BINARY_LE: 00376 fprintf (fp, "format binary_little_endian 1.0\n"); 00377 break; 00378 default: 00379 fprintf (stderr, "ply_header_complete: bad file type = %d\n", 00380 plyfile->file_type); 00381 exit (-1); 00382 } 00383 00384 /* write out the comments */ 00385 00386 for (i = 0; i < plyfile->num_comments; i++) 00387 fprintf (fp, "comment %s\n", plyfile->comments[i]); 00388 00389 /* write out object information */ 00390 00391 for (i = 0; i < plyfile->num_obj_info; i++) 00392 fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]); 00393 00394 /* write out information about each element */ 00395 00396 for (i = 0; i < plyfile->num_elem_types; i++) { 00397 00398 elem = plyfile->elems[i]; 00399 fprintf (fp, "element %s %d\n", elem->name, elem->num); 00400 00401 /* write out each property */ 00402 for (j = 0; j < elem->nprops; j++) { 00403 prop = elem->props[j]; 00404 if (prop->is_list == PLY_LIST) { 00405 fprintf (fp, "property list "); 00406 write_scalar_type (fp, prop->count_external); 00407 fprintf (fp, " "); 00408 write_scalar_type (fp, prop->external_type); 00409 fprintf (fp, " %s\n", prop->name); 00410 } 00411 else if (prop->is_list == PLY_STRING) { 00412 fprintf (fp, "property string"); 00413 fprintf (fp, " %s\n", prop->name); 00414 } 00415 else { 00416 fprintf (fp, "property "); 00417 write_scalar_type (fp, prop->external_type); 00418 fprintf (fp, " %s\n", prop->name); 00419 } 00420 } 00421 } 00422 00423 fprintf (fp, "end_header\n"); 00424 } 00425 00426 00427 /****************************************************************************** 00428 Specify which elements are going to be written. This should be called 00429 before a call to the routine ply_put_element(). 00430 00431 Entry: 00432 plyfile - file identifier 00433 elem_name - name of element we're talking about 00434 ******************************************************************************/ 00435 00436 void put_element_setup_ply(PlyFile *plyfile, char *elem_name) 00437 { 00438 PlyElement *elem; 00439 00440 elem = find_element (plyfile, elem_name); 00441 if (elem == NULL) { 00442 fprintf(stderr, "put_element_setup_ply: can't find element '%s'\n", elem_name); 00443 exit (-1); 00444 } 00445 00446 plyfile->which_elem = elem; 00447 } 00448 00449 00450 /****************************************************************************** 00451 Write an element to the file. This routine assumes that we're 00452 writing the type of element specified in the last call to the routine 00453 put_element_setup_ply(). 00454 00455 Entry: 00456 plyfile - file identifier 00457 elem_ptr - pointer to the element 00458 ******************************************************************************/ 00459 00460 void put_element_ply(PlyFile *plyfile, void *elem_ptr) 00461 { 00462 int i,j,k; 00463 FILE *fp = plyfile->fp; 00464 PlyElement *elem; 00465 PlyProperty *prop; 00466 char *item; 00467 char *elem_data; 00468 char **item_ptr; 00469 int list_count; 00470 int item_size; 00471 int int_val; 00472 unsigned int uint_val; 00473 double double_val; 00474 char **other_ptr; 00475 00476 elem = plyfile->which_elem; 00477 elem_data = (char *) elem_ptr; 00478 other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset); 00479 00480 /* write out either to an ascii or binary file */ 00481 00482 if (plyfile->file_type == PLY_ASCII) { 00483 00484 /* write an ascii file */ 00485 00486 /* write out each property of the element */ 00487 for (j = 0; j < elem->nprops; j++) { 00488 00489 prop = elem->props[j]; 00490 00491 if (elem->store_prop[j] == OTHER_PROP) 00492 elem_data = *other_ptr; 00493 else 00494 elem_data = (char *) elem_ptr; 00495 00496 if (prop->is_list == PLY_LIST) { /* list */ 00497 item = elem_data + prop->count_offset; 00498 get_stored_item ((void *) item, prop->count_internal, 00499 &int_val, &uint_val, &double_val); 00500 write_ascii_item (fp, int_val, uint_val, double_val, 00501 prop->count_external); 00502 list_count = uint_val; 00503 item_ptr = (char **) (elem_data + prop->offset); 00504 item = item_ptr[0]; 00505 item_size = ply_type_size[prop->internal_type]; 00506 for (k = 0; k < list_count; k++) { 00507 get_stored_item ((void *) item, prop->internal_type, 00508 &int_val, &uint_val, &double_val); 00509 write_ascii_item (fp, int_val, uint_val, double_val, 00510 prop->external_type); 00511 item += item_size; 00512 } 00513 } 00514 else if (prop->is_list == PLY_STRING) { /* string */ 00515 char **str; 00516 item = elem_data + prop->offset; 00517 str = (char **) item; 00518 fprintf (fp, "\"%s\"", *str); 00519 } 00520 else { /* scalar */ 00521 item = elem_data + prop->offset; 00522 get_stored_item ((void *) item, prop->internal_type, 00523 &int_val, &uint_val, &double_val); 00524 write_ascii_item (fp, int_val, uint_val, double_val, 00525 prop->external_type); 00526 } 00527 } 00528 00529 fprintf (fp, "\n"); 00530 } 00531 else { 00532 00533 /* write a binary file */ 00534 00535 /* write out each property of the element */ 00536 for (j = 0; j < elem->nprops; j++) { 00537 prop = elem->props[j]; 00538 if (elem->store_prop[j] == OTHER_PROP) 00539 elem_data = *other_ptr; 00540 else 00541 elem_data = (char *) elem_ptr; 00542 if (prop->is_list == PLY_LIST) { /* list */ 00543 item = elem_data + prop->count_offset; 00544 item_size = ply_type_size[prop->count_internal]; 00545 get_stored_item ((void *) item, prop->count_internal, 00546 &int_val, &uint_val, &double_val); 00547 write_binary_item (fp, int_val, uint_val, double_val, 00548 prop->count_external); 00549 list_count = uint_val; 00550 item_ptr = (char **) (elem_data + prop->offset); 00551 item = item_ptr[0]; 00552 item_size = ply_type_size[prop->internal_type]; 00553 for (k = 0; k < list_count; k++) { 00554 get_stored_item ((void *) item, prop->internal_type, 00555 &int_val, &uint_val, &double_val); 00556 write_binary_item (fp, int_val, uint_val, double_val, 00557 prop->external_type); 00558 item += item_size; 00559 } 00560 } 00561 else if (prop->is_list == PLY_STRING) { /* string */ 00562 int len; 00563 char **str; 00564 item = elem_data + prop->offset; 00565 str = (char **) item; 00566 00567 /* write the length */ 00568 len = strlen(*str) + 1; 00569 fwrite (&len, sizeof(int), 1, fp); 00570 00571 /* write the string, including the null character */ 00572 fwrite (*str, len, 1, fp); 00573 } 00574 else { /* scalar */ 00575 item = elem_data + prop->offset; 00576 item_size = ply_type_size[prop->internal_type]; 00577 get_stored_item ((void *) item, prop->internal_type, 00578 &int_val, &uint_val, &double_val); 00579 write_binary_item (fp, int_val, uint_val, double_val, 00580 prop->external_type); 00581 } 00582 } 00583 00584 } 00585 } 00586 00587 00588 00589 00590 00591 00592 /*************/ 00593 /* Reading */ 00594 /*************/ 00595 00596 00597 00598 /****************************************************************************** 00599 Given a file pointer, get ready to read PLY data from the file. 00600 00601 Entry: 00602 fp - the given file pointer 00603 00604 Exit: 00605 nelems - number of elements in object 00606 elem_names - list of element names 00607 returns a pointer to a PlyFile, used to refer to this file, or NULL if error 00608 ******************************************************************************/ 00609 00610 PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names) 00611 { 00612 int i,j; 00613 PlyFile *plyfile; 00614 int nwords; 00615 char **words; 00616 int found_format = 0; 00617 char **elist; 00618 PlyElement *elem; 00619 char *orig_line; 00620 00621 /* check for NULL file pointer */ 00622 if (fp == NULL) 00623 return (NULL); 00624 00625 /* create record for this object */ 00626 00627 plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); 00628 plyfile->num_elem_types = 0; 00629 plyfile->comments = NULL; 00630 plyfile->num_comments = 0; 00631 plyfile->obj_info = NULL; 00632 plyfile->num_obj_info = 0; 00633 plyfile->fp = fp; 00634 plyfile->other_elems = NULL; 00635 plyfile->rule_list = NULL; 00636 00637 /* read and parse the file's header */ 00638 00639 words = get_words (plyfile->fp, &nwords, &orig_line); 00640 if (!words || !equal_strings (words[0], "ply")) 00641 return (NULL); 00642 00643 while (words) { 00644 00645 /* parse words */ 00646 00647 if (equal_strings (words[0], "format")) { 00648 if (nwords != 3) 00649 return (NULL); 00650 if (equal_strings (words[1], "ascii")) 00651 plyfile->file_type = PLY_ASCII; 00652 else if (equal_strings (words[1], "binary_big_endian")) 00653 plyfile->file_type = PLY_BINARY_BE; 00654 else if (equal_strings (words[1], "binary_little_endian")) 00655 plyfile->file_type = PLY_BINARY_LE; 00656 else 00657 return (NULL); 00658 plyfile->version = atof (words[2]); 00659 found_format = 1; 00660 } 00661 else if (equal_strings (words[0], "element")) 00662 add_element (plyfile, words, nwords); 00663 else if (equal_strings (words[0], "property")) 00664 add_property (plyfile, words, nwords); 00665 else if (equal_strings (words[0], "comment")) 00666 add_comment (plyfile, orig_line); 00667 else if (equal_strings (words[0], "obj_info")) 00668 add_obj_info (plyfile, orig_line); 00669 else if (equal_strings (words[0], "end_header")) 00670 break; 00671 00672 /* free up words space */ 00673 free (words); 00674 00675 words = get_words (plyfile->fp, &nwords, &orig_line); 00676 } 00677 00678 /* create tags for each property of each element, to be used */ 00679 /* later to say whether or not to store each property for the user */ 00680 00681 for (i = 0; i < plyfile->num_elem_types; i++) { 00682 elem = plyfile->elems[i]; 00683 elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); 00684 for (j = 0; j < elem->nprops; j++) 00685 elem->store_prop[j] = DONT_STORE_PROP; 00686 elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ 00687 } 00688 00689 /* set return values about the elements */ 00690 00691 elist = (char **) myalloc (sizeof (char *) * plyfile->num_elem_types); 00692 for (i = 0; i < plyfile->num_elem_types; i++) 00693 elist[i] = strdup (plyfile->elems[i]->name); 00694 00695 *elem_names = elist; 00696 *nelems = plyfile->num_elem_types; 00697 00698 /* return a pointer to the file's information */ 00699 00700 return (plyfile); 00701 } 00702 00703 00704 /****************************************************************************** 00705 Open a polygon file for reading. 00706 00707 Entry: 00708 filename - name of file to read from 00709 00710 Exit: 00711 nelems - number of elements in object 00712 elem_names - list of element names 00713 file_type - file type, either ascii or binary 00714 version - version number of PLY file 00715 returns a file identifier, used to refer to this file, or NULL if error 00716 ******************************************************************************/ 00717 00718 PlyFile *ply_open_for_reading( 00719 char *filename, 00720 int *nelems, 00721 char ***elem_names, 00722 int *file_type, 00723 float *version 00724 ) 00725 { 00726 FILE *fp; 00727 PlyFile *plyfile; 00728 char *name; 00729 00730 /* tack on the extension .ply, if necessary */ 00731 00732 name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5)); 00733 strcpy (name, filename); 00734 if (strlen (name) < 4 || 00735 strcmp (name + strlen (name) - 4, ".ply") != 0) 00736 strcat (name, ".ply"); 00737 00738 /* open the file for reading */ 00739 /*kc*/ 00740 fp = fopen (name, "rb"); 00741 if (fp == NULL) 00742 return (NULL); 00743 00744 /* create the PlyFile data structure */ 00745 00746 plyfile = ply_read (fp, nelems, elem_names); 00747 00748 /* determine the file type and version */ 00749 00750 *file_type = plyfile->file_type; 00751 *version = plyfile->version; 00752 00753 /* return a pointer to the file's information */ 00754 00755 return (plyfile); 00756 } 00757 00758 00759 /****************************************************************************** 00760 Get information about a particular element. 00761 00762 Entry: 00763 plyfile - file identifier 00764 elem_name - name of element to get information about 00765 00766 Exit: 00767 nelems - number of elements of this type in the file 00768 nprops - number of properties 00769 returns a list of properties, or NULL if the file doesn't contain that elem 00770 ******************************************************************************/ 00771 00772 PlyProperty **get_element_description_ply( 00773 PlyFile *plyfile, 00774 char *elem_name, 00775 int *nelems, 00776 int *nprops 00777 ) 00778 { 00779 int i; 00780 PlyElement *elem; 00781 PlyProperty *prop; 00782 PlyProperty **prop_list; 00783 00784 /* find information about the element */ 00785 elem = find_element (plyfile, elem_name); 00786 if (elem == NULL) 00787 return (NULL); 00788 00789 *nelems = elem->num; 00790 *nprops = elem->nprops; 00791 00792 /* make a copy of the element's property list */ 00793 prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops); 00794 for (i = 0; i < elem->nprops; i++) { 00795 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 00796 copy_property (prop, elem->props[i]); 00797 prop_list[i] = prop; 00798 } 00799 00800 /* return this duplicate property list */ 00801 return (prop_list); 00802 } 00803 00804 00805 /****************************************************************************** 00806 Specify which properties of an element are to be returned. This should be 00807 called before a call to the routine get_element_ply(). 00808 00809 Entry: 00810 plyfile - file identifier 00811 elem_name - which element we're talking about 00812 nprops - number of properties 00813 prop_list - list of properties 00814 ******************************************************************************/ 00815 00816 void get_element_setup_ply( 00817 PlyFile *plyfile, 00818 char *elem_name, 00819 int nprops, 00820 PlyProperty *prop_list 00821 ) 00822 { 00823 int i; 00824 PlyElement *elem; 00825 PlyProperty *prop; 00826 int index; 00827 00828 /* find information about the element */ 00829 elem = find_element (plyfile, elem_name); 00830 plyfile->which_elem = elem; 00831 00832 /* deposit the property information into the element's description */ 00833 for (i = 0; i < nprops; i++) { 00834 00835 /* look for actual property */ 00836 prop = find_property (elem, prop_list[i].name, &index); 00837 if (prop == NULL) { 00838 fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", 00839 prop_list[i].name, elem_name); 00840 continue; 00841 } 00842 00843 /* store its description */ 00844 prop->internal_type = prop_list[i].internal_type; 00845 prop->offset = prop_list[i].offset; 00846 prop->count_internal = prop_list[i].count_internal; 00847 prop->count_offset = prop_list[i].count_offset; 00848 00849 /* specify that the user wants this property */ 00850 elem->store_prop[index] = STORE_PROP; 00851 } 00852 } 00853 00854 00855 /****************************************************************************** 00856 Specify a property of an element that is to be returned. This should be 00857 called (usually multiple times) before a call to the routine ply_get_element(). 00858 This routine should be used in preference to the less flexible old routine 00859 called ply_get_element_setup(). 00860 00861 Entry: 00862 plyfile - file identifier 00863 elem_name - which element we're talking about 00864 prop - property to add to those that will be returned 00865 ******************************************************************************/ 00866 00867 void ply_get_property( 00868 PlyFile *plyfile, 00869 char *elem_name, 00870 PlyProperty *prop 00871 ) 00872 { 00873 PlyElement *elem; 00874 PlyProperty *prop_ptr; 00875 int index; 00876 00877 /* find information about the element */ 00878 elem = find_element (plyfile, elem_name); 00879 plyfile->which_elem = elem; 00880 00881 /* deposit the property information into the element's description */ 00882 00883 prop_ptr = find_property (elem, prop->name, &index); 00884 if (prop_ptr == NULL) { 00885 fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", 00886 prop->name, elem_name); 00887 return; 00888 } 00889 prop_ptr->internal_type = prop->internal_type; 00890 prop_ptr->offset = prop->offset; 00891 prop_ptr->count_internal = prop->count_internal; 00892 prop_ptr->count_offset = prop->count_offset; 00893 00894 /* specify that the user wants this property */ 00895 elem->store_prop[index] = STORE_PROP; 00896 } 00897 00898 00899 /****************************************************************************** 00900 Read one element from the file. This routine assumes that we're reading 00901 the type of element specified in the last call to the routine 00902 ply_get_element_setup(). 00903 00904 Entry: 00905 plyfile - file identifier 00906 elem_ptr - pointer to location where the element information should be put 00907 ******************************************************************************/ 00908 00909 void ply_get_element(PlyFile *plyfile, void *elem_ptr) 00910 { 00911 if (plyfile->file_type == PLY_ASCII) 00912 ascii_get_element (plyfile, (char *) elem_ptr); 00913 else 00914 binary_get_element (plyfile, (char *) elem_ptr); 00915 } 00916 00917 00918 /****************************************************************************** 00919 Extract the comments from the header information of a PLY file. 00920 00921 Entry: 00922 plyfile - file identifier 00923 00924 Exit: 00925 num_comments - number of comments returned 00926 returns a pointer to a list of comments 00927 ******************************************************************************/ 00928 00929 char **get_comments_ply(PlyFile *plyfile, int *num_comments) 00930 { 00931 *num_comments = plyfile->num_comments; 00932 return (plyfile->comments); 00933 } 00934 00935 00936 /****************************************************************************** 00937 Extract the object information (arbitrary text) from the header information 00938 of a PLY file. 00939 00940 Entry: 00941 plyfile - file identifier 00942 00943 Exit: 00944 num_obj_info - number of lines of text information returned 00945 returns a pointer to a list of object info lines 00946 ******************************************************************************/ 00947 00948 char **get_obj_info_ply(PlyFile *plyfile, int *num_obj_info) 00949 { 00950 *num_obj_info = plyfile->num_obj_info; 00951 return (plyfile->obj_info); 00952 } 00953 00954 00955 /****************************************************************************** 00956 Make ready for "other" properties of an element-- those properties that 00957 the user has not explicitly asked for, but that are to be stashed away 00958 in a special structure to be carried along with the element's other 00959 information. 00960 00961 Entry: 00962 plyfile - file identifier 00963 elem - element for which we want to save away other properties 00964 ******************************************************************************/ 00965 00966 void setup_other_props(PlyFile *plyfile, PlyElement *elem) 00967 { 00968 int i; 00969 PlyProperty *prop; 00970 int size = 0; 00971 int type_size; 00972 00973 /* Examine each property in decreasing order of size. */ 00974 /* We do this so that all data types will be aligned by */ 00975 /* word, half-word, or whatever within the structure. */ 00976 00977 for (type_size = 8; type_size > 0; type_size /= 2) { 00978 00979 /* add up the space taken by each property, and save this information */ 00980 /* away in the property descriptor */ 00981 00982 for (i = 0; i < elem->nprops; i++) { 00983 00984 /* don't bother with properties we've been asked to store explicitly */ 00985 if (elem->store_prop[i]) 00986 continue; 00987 00988 prop = elem->props[i]; 00989 00990 /* internal types will be same as external */ 00991 prop->internal_type = prop->external_type; 00992 prop->count_internal = prop->count_external; 00993 00994 /* list case */ 00995 if (prop->is_list == PLY_LIST) { 00996 00997 /* pointer to list */ 00998 if (type_size == sizeof (void *)) { 00999 prop->offset = size; 01000 size += sizeof (void *); /* always use size of a pointer here */ 01001 } 01002 01003 /* count of number of list elements */ 01004 if (type_size == ply_type_size[prop->count_external]) { 01005 prop->count_offset = size; 01006 size += ply_type_size[prop->count_external]; 01007 } 01008 } 01009 /* string */ 01010 else if (prop->is_list == PLY_STRING) { 01011 /* pointer to string */ 01012 if (type_size == sizeof (char *)) { 01013 prop->offset = size; 01014 size += sizeof (char *); 01015 } 01016 } 01017 /* scalar */ 01018 else if (type_size == ply_type_size[prop->external_type]) { 01019 prop->offset = size; 01020 size += ply_type_size[prop->external_type]; 01021 } 01022 } 01023 01024 } 01025 01026 /* save the size for the other_props structure */ 01027 elem->other_size = size; 01028 } 01029 01030 01031 /****************************************************************************** 01032 Specify that we want the "other" properties of an element to be tucked 01033 away within the user's structure. 01034 01035 Entry: 01036 plyfile - file identifier 01037 elem - the element that we want to store other_props in 01038 offset - offset to where other_props will be stored inside user's structure 01039 01040 Exit: 01041 returns pointer to structure containing description of other_props 01042 ******************************************************************************/ 01043 01044 static PlyOtherProp *get_other_properties( 01045 PlyFile *plyfile, 01046 PlyElement *elem, 01047 int offset 01048 ) 01049 { 01050 int i; 01051 PlyOtherProp *other; 01052 PlyProperty *prop; 01053 int nprops; 01054 01055 /* remember that this is the "current" element */ 01056 plyfile->which_elem = elem; 01057 01058 /* save the offset to where to store the other_props */ 01059 elem->other_offset = offset; 01060 01061 /* place the appropriate pointers, etc. in the element's property list */ 01062 setup_other_props (plyfile, elem); 01063 01064 /* create structure for describing other_props */ 01065 other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); 01066 other->name = strdup (elem->name); 01067 #if 0 01068 if (elem->other_offset == NO_OTHER_PROPS) { 01069 other->size = 0; 01070 other->props = NULL; 01071 other->nprops = 0; 01072 return (other); 01073 } 01074 #endif 01075 other->size = elem->other_size; 01076 other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); 01077 01078 /* save descriptions of each "other" property */ 01079 nprops = 0; 01080 for (i = 0; i < elem->nprops; i++) { 01081 if (elem->store_prop[i]) 01082 continue; 01083 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 01084 copy_property (prop, elem->props[i]); 01085 other->props[nprops] = prop; 01086 nprops++; 01087 } 01088 other->nprops = nprops; 01089 01090 /* set other_offset pointer appropriately if there are NO other properties */ 01091 if (other->nprops == 0) { 01092 elem->other_offset = NO_OTHER_PROPS; 01093 } 01094 01095 /* return structure */ 01096 return (other); 01097 } 01098 01099 01100 /****************************************************************************** 01101 Specify that we want the "other" properties of an element to be tucked 01102 away within the user's structure. The user needn't be concerned for how 01103 these properties are stored. 01104 01105 Entry: 01106 plyfile - file identifier 01107 elem_name - name of element that we want to store other_props in 01108 offset - offset to where other_props will be stored inside user's structure 01109 01110 Exit: 01111 returns pointer to structure containing description of other_props 01112 ******************************************************************************/ 01113 01114 PlyOtherProp *ply_get_other_properties( 01115 PlyFile *plyfile, 01116 char *elem_name, 01117 int offset 01118 ) 01119 { 01120 PlyElement *elem; 01121 PlyOtherProp *other; 01122 01123 /* find information about the element */ 01124 elem = find_element (plyfile, elem_name); 01125 if (elem == NULL) { 01126 fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n", 01127 elem_name); 01128 return (NULL); 01129 } 01130 01131 other = get_other_properties (plyfile, elem, offset); 01132 return (other); 01133 } 01134 01135 01136 01137 01138 /*************************/ 01139 /* Other Element Stuff */ 01140 /*************************/ 01141 01142 01143 01144 01145 01146 /****************************************************************************** 01147 Grab all the data for the current element that a user does not want to 01148 explicitly read in. Stores this in the PLY object's data structure. 01149 01150 Entry: 01151 plyfile - pointer to file 01152 01153 Exit: 01154 returns pointer to ALL the "other" element data for this PLY file 01155 ******************************************************************************/ 01156 01157 PlyOtherElems *get_other_element_ply (PlyFile *plyfile) 01158 { 01159 int i; 01160 PlyElement *elem; 01161 char *elem_name; 01162 int elem_count; 01163 PlyOtherElems *other_elems; 01164 OtherElem *other; 01165 01166 elem = plyfile->which_elem; 01167 elem_name = elem->name; 01168 elem_count = elem->num; 01169 01170 /* create room for the new "other" element, initializing the */ 01171 /* other data structure if necessary */ 01172 01173 if (plyfile->other_elems == NULL) { 01174 plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); 01175 other_elems = plyfile->other_elems; 01176 other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem)); 01177 other = &(other_elems->other_list[0]); 01178 other_elems->num_elems = 1; 01179 } 01180 else { 01181 other_elems = plyfile->other_elems; 01182 other_elems->other_list = (OtherElem *) realloc (other_elems->other_list, 01183 sizeof (OtherElem) * other_elems->num_elems + 1); 01184 other = &(other_elems->other_list[other_elems->num_elems]); 01185 other_elems->num_elems++; 01186 } 01187 01188 /* count of element instances in file */ 01189 other->elem_count = elem_count; 01190 01191 /* save name of element */ 01192 other->elem_name = strdup (elem_name); 01193 01194 /* create a list to hold all the current elements */ 01195 other->other_data = (OtherData **) 01196 malloc (sizeof (OtherData *) * other->elem_count); 01197 01198 /* set up for getting elements */ 01199 other->other_props = ply_get_other_properties (plyfile, elem_name, 01200 offsetof(OtherData,other_props)); 01201 01202 /* grab all these elements */ 01203 for (i = 0; i < other->elem_count; i++) { 01204 /* grab and element from the file */ 01205 other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); 01206 ply_get_element (plyfile, (void *) other->other_data[i]); 01207 } 01208 01209 /* return pointer to the other elements data */ 01210 return (other_elems); 01211 } 01212 01213 01214 /****************************************************************************** 01215 Write out the "other" elements specified for this PLY file. 01216 01217 Entry: 01218 plyfile - pointer to PLY file to write out other elements for 01219 ******************************************************************************/ 01220 01221 void put_other_elements_ply (PlyFile *plyfile) 01222 { 01223 int i,j; 01224 OtherElem *other; 01225 01226 /* make sure we have other elements to write */ 01227 if (plyfile->other_elems == NULL) 01228 return; 01229 01230 /* write out the data for each "other" element */ 01231 01232 for (i = 0; i < plyfile->other_elems->num_elems; i++) { 01233 01234 other = &(plyfile->other_elems->other_list[i]); 01235 put_element_setup_ply (plyfile, other->elem_name); 01236 01237 /* write out each instance of the current element */ 01238 for (j = 0; j < other->elem_count; j++) 01239 put_element_ply (plyfile, (void *) other->other_data[j]); 01240 } 01241 } 01242 01243 01244 /****************************************************************************** 01245 Free up storage used by an "other" elements data structure. 01246 01247 Entry: 01248 other_elems - data structure to free up 01249 ******************************************************************************/ 01250 01251 void free_other_elements_ply (PlyOtherElems *other_elems) 01252 { 01253 01254 } 01255 01256 01257 01258 /*******************/ 01259 /* Miscellaneous */ 01260 /*******************/ 01261 01262 01263 01264 /****************************************************************************** 01265 Close a PLY file. 01266 01267 Entry: 01268 plyfile - identifier of file to close 01269 ******************************************************************************/ 01270 01271 void ply_close(PlyFile *plyfile) 01272 { 01273 fclose (plyfile->fp); 01274 01275 /* free up memory associated with the PLY file */ 01276 free (plyfile); 01277 } 01278 01279 01280 /****************************************************************************** 01281 Get version number and file type of a PlyFile. 01282 01283 Entry: 01284 ply - pointer to PLY file 01285 01286 Exit: 01287 version - version of the file 01288 file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE 01289 ******************************************************************************/ 01290 01291 void get_info_ply(PlyFile *ply, float *version, int *file_type) 01292 { 01293 if (ply == NULL) 01294 return; 01295 01296 *version = ply->version; 01297 *file_type = ply->file_type; 01298 } 01299 01300 01301 /****************************************************************************** 01302 Compare two strings. Returns 1 if they are the same, 0 if not. 01303 ******************************************************************************/ 01304 01305 int equal_strings(char *s1, char *s2) 01306 { 01307 int i; 01308 01309 while (*s1 && *s2) 01310 if (*s1++ != *s2++) 01311 return (0); 01312 01313 if (*s1 != *s2) 01314 return (0); 01315 else 01316 return (1); 01317 } 01318 01319 01320 /****************************************************************************** 01321 Re-create the command line that was used to invoke this program. 01322 01323 Entry: 01324 argc - number of words in argv 01325 argv - array of words in command line 01326 ******************************************************************************/ 01327 01328 char *recreate_command_line (int argc, char *argv[]) 01329 { 01330 int i; 01331 char *line; 01332 int len = 0; 01333 01334 /* count total number of characters needed, including separating spaces */ 01335 for (i = 0; i < argc; i++) 01336 len += strlen(argv[i]) + 1; 01337 01338 /* create empty line */ 01339 line = (char *) malloc (sizeof(char) * len); 01340 line[0] = '\0'; 01341 01342 /* repeatedly append argv */ 01343 for (i = 0; i < argc; i++) { 01344 strcat (line, argv[i]); 01345 if (i != argc - 1) 01346 strcat (line, " "); 01347 } 01348 01349 return (line); 01350 } 01351 01352 01353 /****************************************************************************** 01354 Find an element from the element list of a given PLY object. 01355 01356 Entry: 01357 plyfile - file id for PLY file 01358 element - name of element we're looking for 01359 01360 Exit: 01361 returns the element, or NULL if not found 01362 ******************************************************************************/ 01363 01364 PlyElement *find_element(PlyFile *plyfile, char *element) 01365 { 01366 int i; 01367 01368 for (i = 0; i < plyfile->num_elem_types; i++) 01369 if (equal_strings (element, plyfile->elems[i]->name)) 01370 return (plyfile->elems[i]); 01371 01372 return (NULL); 01373 } 01374 01375 01376 /****************************************************************************** 01377 Find a property in the list of properties of a given element. 01378 01379 Entry: 01380 elem - pointer to element in which we want to find the property 01381 prop_name - name of property to find 01382 01383 Exit: 01384 index - index to position in list 01385 returns a pointer to the property, or NULL if not found 01386 ******************************************************************************/ 01387 01388 PlyProperty *find_property(PlyElement *elem, char *prop_name, int *index) 01389 { 01390 int i; 01391 01392 for (i = 0; i < elem->nprops; i++) 01393 if (equal_strings (prop_name, elem->props[i]->name)) { 01394 *index = i; 01395 return (elem->props[i]); 01396 } 01397 01398 *index = -1; 01399 return (NULL); 01400 } 01401 01402 01403 /****************************************************************************** 01404 Read an element from an ascii file. 01405 01406 Entry: 01407 plyfile - file identifier 01408 elem_ptr - pointer to element 01409 ******************************************************************************/ 01410 01411 void ascii_get_element(PlyFile *plyfile, char *elem_ptr) 01412 { 01413 int i,j,k; 01414 PlyElement *elem; 01415 PlyProperty *prop; 01416 char **words; 01417 int nwords; 01418 int which_word; 01419 FILE *fp = plyfile->fp; 01420 char *elem_data,*item; 01421 char *item_ptr; 01422 int item_size; 01423 int int_val; 01424 unsigned int uint_val; 01425 double double_val; 01426 int list_count; 01427 int store_it; 01428 char **store_array; 01429 char *orig_line; 01430 char *other_data; 01431 int other_flag; 01432 01433 /* the kind of element we're reading currently */ 01434 elem = plyfile->which_elem; 01435 01436 /* do we need to setup for other_props? */ 01437 01438 if (elem->other_offset != NO_OTHER_PROPS) { 01439 char **ptr; 01440 other_flag = 1; 01441 /* make room for other_props */ 01442 other_data = (char *) myalloc (elem->other_size); 01443 /* store pointer in user's structure to the other_props */ 01444 ptr = (char **) (elem_ptr + elem->other_offset); 01445 *ptr = other_data; 01446 } 01447 else 01448 other_flag = 0; 01449 01450 /* read in the element */ 01451 01452 words = get_words (plyfile->fp, &nwords, &orig_line); 01453 if (words == NULL) { 01454 fprintf (stderr, "ply_get_element: unexpected end of file\n"); 01455 exit (-1); 01456 } 01457 01458 which_word = 0; 01459 01460 for (j = 0; j < elem->nprops; j++) { 01461 01462 prop = elem->props[j]; 01463 store_it = (elem->store_prop[j] | other_flag); 01464 01465 /* store either in the user's structure or in other_props */ 01466 if (elem->store_prop[j]) 01467 elem_data = elem_ptr; 01468 else 01469 elem_data = other_data; 01470 01471 if (prop->is_list == PLY_LIST) { /* a list */ 01472 01473 /* get and store the number of items in the list */ 01474 get_ascii_item (words[which_word++], prop->count_external, 01475 &int_val, &uint_val, &double_val); 01476 if (store_it) { 01477 item = elem_data + prop->count_offset; 01478 store_item(item, prop->count_internal, int_val, uint_val, double_val); 01479 } 01480 01481 /* allocate space for an array of items and store a ptr to the array */ 01482 list_count = int_val; 01483 item_size = ply_type_size[prop->internal_type]; 01484 store_array = (char **) (elem_data + prop->offset); 01485 01486 if (list_count == 0) { 01487 if (store_it) 01488 *store_array = NULL; 01489 } 01490 else { 01491 if (store_it) { 01492 item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); 01493 item = item_ptr; 01494 *store_array = item_ptr; 01495 } 01496 01497 /* read items and store them into the array */ 01498 for (k = 0; k < list_count; k++) { 01499 get_ascii_item (words[which_word++], prop->external_type, 01500 &int_val, &uint_val, &double_val); 01501 if (store_it) { 01502 store_item (item, prop->internal_type, 01503 int_val, uint_val, double_val); 01504 item += item_size; 01505 } 01506 } 01507 } 01508 01509 } 01510 else if (prop->is_list == PLY_STRING) { /* a string */ 01511 if (store_it) { 01512 char *str; 01513 char **str_ptr; 01514 str = strdup (words[which_word++]); 01515 item = elem_data + prop->offset; 01516 str_ptr = (char **) item; 01517 *str_ptr = str; 01518 } 01519 else { 01520 which_word++; 01521 } 01522 } 01523 else { /* a scalar */ 01524 get_ascii_item (words[which_word++], prop->external_type, 01525 &int_val, &uint_val, &double_val); 01526 if (store_it) { 01527 item = elem_data + prop->offset; 01528 store_item (item, prop->internal_type, int_val, uint_val, double_val); 01529 } 01530 } 01531 01532 } 01533 01534 free (words); 01535 } 01536 01537 01538 /****************************************************************************** 01539 Read an element from a binary file. 01540 01541 Entry: 01542 plyfile - file identifier 01543 elem_ptr - pointer to an element 01544 ******************************************************************************/ 01545 01546 void binary_get_element(PlyFile *plyfile, char *elem_ptr) 01547 { 01548 int i,j,k; 01549 PlyElement *elem; 01550 PlyProperty *prop; 01551 FILE *fp = plyfile->fp; 01552 char *elem_data; 01553 char *item; 01554 char *item_ptr; 01555 int item_size; 01556 int int_val; 01557 unsigned int uint_val; 01558 double double_val; 01559 int list_count; 01560 int store_it; 01561 char **store_array; 01562 char *other_data; 01563 int other_flag; 01564 01565 /* the kind of element we're reading currently */ 01566 elem = plyfile->which_elem; 01567 01568 /* do we need to setup for other_props? */ 01569 01570 if (elem->other_offset != NO_OTHER_PROPS) { 01571 char **ptr; 01572 other_flag = 1; 01573 /* make room for other_props */ 01574 other_data = (char *) myalloc (elem->other_size); 01575 /* store pointer in user's structure to the other_props */ 01576 ptr = (char **) (elem_ptr + elem->other_offset); 01577 *ptr = other_data; 01578 } 01579 else 01580 other_flag = 0; 01581 01582 /* read in a number of elements */ 01583 01584 for (j = 0; j < elem->nprops; j++) { 01585 01586 prop = elem->props[j]; 01587 store_it = (elem->store_prop[j] | other_flag); 01588 01589 /* store either in the user's structure or in other_props */ 01590 if (elem->store_prop[j]) 01591 elem_data = elem_ptr; 01592 else 01593 elem_data = other_data; 01594 01595 if (prop->is_list == PLY_LIST) { /* list */ 01596 01597 /* get and store the number of items in the list */ 01598 get_binary_item (fp, prop->count_external, 01599 &int_val, &uint_val, &double_val); 01600 if (store_it) { 01601 item = elem_data + prop->count_offset; 01602 store_item(item, prop->count_internal, int_val, uint_val, double_val); 01603 } 01604 01605 /* allocate space for an array of items and store a ptr to the array */ 01606 list_count = int_val; 01607 item_size = ply_type_size[prop->internal_type]; 01608 store_array = (char **) (elem_data + prop->offset); 01609 if (list_count == 0) { 01610 if (store_it) 01611 *store_array = NULL; 01612 } 01613 else { 01614 if (store_it) { 01615 item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); 01616 item = item_ptr; 01617 *store_array = item_ptr; 01618 } 01619 01620 /* read items and store them into the array */ 01621 for (k = 0; k < list_count; k++) { 01622 get_binary_item (fp, prop->external_type, 01623 &int_val, &uint_val, &double_val); 01624 if (store_it) { 01625 store_item (item, prop->internal_type, 01626 int_val, uint_val, double_val); 01627 item += item_size; 01628 } 01629 } 01630 } 01631 01632 } 01633 else if (prop->is_list == PLY_STRING) { /* string */ 01634 int len; 01635 char *str; 01636 fread (&len, sizeof(int), 1, fp); 01637 str = (char *) myalloc (len); 01638 fread (str, len, 1, fp); 01639 if (store_it) { 01640 char **str_ptr; 01641 item = elem_data + prop->offset; 01642 str_ptr = (char **) item; 01643 *str_ptr = str; 01644 } 01645 } 01646 else { /* scalar */ 01647 get_binary_item (fp, prop->external_type, 01648 &int_val, &uint_val, &double_val); 01649 if (store_it) { 01650 item = elem_data + prop->offset; 01651 store_item (item, prop->internal_type, int_val, uint_val, double_val); 01652 } 01653 } 01654 01655 } 01656 } 01657 01658 01659 /****************************************************************************** 01660 Write to a file the word that represents a PLY data type. 01661 01662 Entry: 01663 fp - file pointer 01664 code - code for type 01665 ******************************************************************************/ 01666 01667 void write_scalar_type (FILE *fp, int code) 01668 { 01669 /* make sure this is a valid code */ 01670 01671 if (code <= StartType || code >= EndType) { 01672 fprintf (stderr, "write_scalar_type: bad data code = %d\n", code); 01673 exit (-1); 01674 } 01675 01676 /* write the code to a file */ 01677 01678 fprintf (fp, "%s", type_names[code]); 01679 } 01680 01681 01682 /****************************************************************************** 01683 Get a text line from a file and break it up into words. 01684 01685 IMPORTANT: The calling routine should call "free" on the returned pointer once 01686 finished with it. 01687 01688 Entry: 01689 fp - file to read from 01690 01691 Exit: 01692 nwords - number of words returned 01693 orig_line - the original line of characters 01694 returns a list of words from the line, or NULL if end-of-file 01695 ******************************************************************************/ 01696 01697 char **get_words(FILE *fp, int *nwords, char **orig_line) 01698 { 01699 #define BIG_STRING 4096 01700 int i,j; 01701 static char str[BIG_STRING]; 01702 static char str_copy[BIG_STRING]; 01703 char **words; 01704 int max_words = 10; 01705 int num_words = 0; 01706 char *ptr,*ptr2; 01707 char *result; 01708 01709 words = (char **) myalloc (sizeof (char *) * max_words); 01710 01711 /* read in a line */ 01712 result = fgets (str, BIG_STRING, fp); 01713 if (result == NULL) { 01714 *nwords = 0; 01715 *orig_line = NULL; 01716 return (NULL); 01717 } 01718 01719 /* convert line-feed and tabs into spaces */ 01720 /* (this guarentees that there will be a space before the */ 01721 /* null character at the end of the string) */ 01722 01723 str[BIG_STRING-2] = ' '; 01724 str[BIG_STRING-1] = '\0'; 01725 01726 for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { 01727 *ptr2 = *ptr; 01728 if (*ptr == '\t') { 01729 *ptr = ' '; 01730 *ptr2 = ' '; 01731 } 01732 else if (*ptr == '\n') { 01733 *ptr = ' '; 01734 *ptr2 = '\0'; 01735 break; 01736 } 01737 } 01738 01739 /* find the words in the line */ 01740 01741 ptr = str; 01742 while (*ptr != '\0') { 01743 01744 /* jump over leading spaces */ 01745 while (*ptr == ' ') 01746 ptr++; 01747 01748 /* break if we reach the end */ 01749 if (*ptr == '\0') 01750 break; 01751 01752 /* allocate more room for words if necessary */ 01753 if (num_words >= max_words) { 01754 max_words += 10; 01755 words = (char **) realloc (words, sizeof (char *) * max_words); 01756 } 01757 01758 if (*ptr == '\"') { /* a quote indidicates that we have a string */ 01759 01760 /* skip over leading quote */ 01761 ptr++; 01762 01763 /* save pointer to beginning of word */ 01764 words[num_words++] = ptr; 01765 01766 /* find trailing quote or end of line */ 01767 while (*ptr != '\"' && *ptr != '\0') 01768 ptr++; 01769 01770 /* replace quote with a null character to mark the end of the word */ 01771 /* if we are not already at the end of the line */ 01772 if (*ptr != '\0') 01773 *ptr++ = '\0'; 01774 } 01775 else { /* non-string */ 01776 01777 /* save pointer to beginning of word */ 01778 words[num_words++] = ptr; 01779 01780 /* jump over non-spaces */ 01781 while (*ptr != ' ') 01782 ptr++; 01783 01784 /* place a null character here to mark the end of the word */ 01785 *ptr++ = '\0'; 01786 } 01787 } 01788 01789 /* return the list of words */ 01790 *nwords = num_words; 01791 *orig_line = str_copy; 01792 return (words); 01793 } 01794 01795 01796 /****************************************************************************** 01797 Return the value of an item, given a pointer to it and its type. 01798 01799 Entry: 01800 item - pointer to item 01801 type - data type that "item" points to 01802 01803 Exit: 01804 returns a double-precision float that contains the value of the item 01805 ******************************************************************************/ 01806 01807 double get_item_value(char *item, int type) 01808 { 01809 unsigned char *puchar; 01810 char *pchar; 01811 short int *pshort; 01812 unsigned short int *pushort; 01813 int *pint; 01814 unsigned int *puint; 01815 float *pfloat; 01816 double *pdouble; 01817 int int_value; 01818 unsigned int uint_value; 01819 double double_value; 01820 01821 switch (type) { 01822 case Int8: 01823 pchar = (char *) item; 01824 int_value = *pchar; 01825 return ((double) int_value); 01826 case Uint8: 01827 puchar = (unsigned char *) item; 01828 int_value = *puchar; 01829 return ((double) int_value); 01830 case Int16: 01831 pshort = (short int *) item; 01832 int_value = *pshort; 01833 return ((double) int_value); 01834 case Uint16: 01835 pushort = (unsigned short int *) item; 01836 int_value = *pushort; 01837 return ((double) int_value); 01838 case Int32: 01839 pint = (int *) item; 01840 int_value = *pint; 01841 return ((double) int_value); 01842 case Uint32: 01843 puint = (unsigned int *) item; 01844 uint_value = *puint; 01845 return ((double) uint_value); 01846 case Float32: 01847 pfloat = (float *) item; 01848 double_value = *pfloat; 01849 return (double_value); 01850 case Float64: 01851 pdouble = (double *) item; 01852 double_value = *pdouble; 01853 return (double_value); 01854 default: 01855 fprintf (stderr, "get_item_value: bad type = %d\n", type); 01856 exit (-1); 01857 } 01858 01859 return (0.0); /* never actually gets here */ 01860 } 01861 01862 01863 /****************************************************************************** 01864 Write out an item to a file as raw binary bytes. 01865 01866 Entry: 01867 fp - file to write to 01868 int_val - integer version of item 01869 uint_val - unsigned integer version of item 01870 double_val - double-precision float version of item 01871 type - data type to write out 01872 ******************************************************************************/ 01873 01874 void write_binary_item( 01875 FILE *fp, 01876 int int_val, 01877 unsigned int uint_val, 01878 double double_val, 01879 int type 01880 ) 01881 { 01882 unsigned char uchar_val; 01883 char char_val; 01884 unsigned short ushort_val; 01885 short short_val; 01886 float float_val; 01887 01888 switch (type) { 01889 case Int8: 01890 char_val = int_val; 01891 fwrite (&char_val, 1, 1, fp); 01892 break; 01893 case Int16: 01894 short_val = int_val; 01895 fwrite (&short_val, 2, 1, fp); 01896 break; 01897 case Int32: 01898 fwrite (&int_val, 4, 1, fp); 01899 break; 01900 case Uint8: 01901 uchar_val = uint_val; 01902 fwrite (&uchar_val, 1, 1, fp); 01903 break; 01904 case Uint16: 01905 ushort_val = uint_val; 01906 fwrite (&ushort_val, 2, 1, fp); 01907 break; 01908 case Uint32: 01909 fwrite (&uint_val, 4, 1, fp); 01910 break; 01911 case Float32: 01912 float_val = double_val; 01913 fwrite (&float_val, 4, 1, fp); 01914 break; 01915 case Float64: 01916 fwrite (&double_val, 8, 1, fp); 01917 break; 01918 default: 01919 fprintf (stderr, "write_binary_item: bad type = %d\n", type); 01920 exit (-1); 01921 } 01922 } 01923 01924 01925 /****************************************************************************** 01926 Write out an item to a file as ascii characters. 01927 01928 Entry: 01929 fp - file to write to 01930 int_val - integer version of item 01931 uint_val - unsigned integer version of item 01932 double_val - double-precision float version of item 01933 type - data type to write out 01934 ******************************************************************************/ 01935 01936 void write_ascii_item( 01937 FILE *fp, 01938 int int_val, 01939 unsigned int uint_val, 01940 double double_val, 01941 int type 01942 ) 01943 { 01944 switch (type) { 01945 case Int8: 01946 case Int16: 01947 case Int32: 01948 fprintf (fp, "%d ", int_val); 01949 break; 01950 case Uint8: 01951 case Uint16: 01952 case Uint32: 01953 fprintf (fp, "%u ", uint_val); 01954 break; 01955 case Float32: 01956 case Float64: 01957 fprintf (fp, "%g ", double_val); 01958 break; 01959 default: 01960 fprintf (stderr, "write_ascii_item: bad type = %d\n", type); 01961 exit (-1); 01962 } 01963 } 01964 01965 01966 /****************************************************************************** 01967 Get the value of an item that is in memory, and place the result 01968 into an integer, an unsigned integer and a double. 01969 01970 Entry: 01971 ptr - pointer to the item 01972 type - data type supposedly in the item 01973 01974 Exit: 01975 int_val - integer value 01976 uint_val - unsigned integer value 01977 double_val - double-precision floating point value 01978 ******************************************************************************/ 01979 01980 void get_stored_item( 01981 void *ptr, 01982 int type, 01983 int *int_val, 01984 unsigned int *uint_val, 01985 double *double_val 01986 ) 01987 { 01988 switch (type) { 01989 case Int8: 01990 *int_val = *((char *) ptr); 01991 *uint_val = *int_val; 01992 *double_val = *int_val; 01993 break; 01994 case Uint8: 01995 *uint_val = *((unsigned char *) ptr); 01996 *int_val = *uint_val; 01997 *double_val = *uint_val; 01998 break; 01999 case Int16: 02000 *int_val = *((short int *) ptr); 02001 *uint_val = *int_val; 02002 *double_val = *int_val; 02003 break; 02004 case Uint16: 02005 *uint_val = *((unsigned short int *) ptr); 02006 *int_val = *uint_val; 02007 *double_val = *uint_val; 02008 break; 02009 case Int32: 02010 *int_val = *((int *) ptr); 02011 *uint_val = *int_val; 02012 *double_val = *int_val; 02013 break; 02014 case Uint32: 02015 *uint_val = *((unsigned int *) ptr); 02016 *int_val = *uint_val; 02017 *double_val = *uint_val; 02018 break; 02019 case Float32: 02020 *double_val = *((float *) ptr); 02021 *int_val = *double_val; 02022 *uint_val = *double_val; 02023 break; 02024 case Float64: 02025 *double_val = *((double *) ptr); 02026 *int_val = *double_val; 02027 *uint_val = *double_val; 02028 break; 02029 default: 02030 fprintf (stderr, "get_stored_item: bad type = %d\n", type); 02031 exit (-1); 02032 } 02033 } 02034 02035 02036 /****************************************************************************** 02037 Get the value of an item from a binary file, and place the result 02038 into an integer, an unsigned integer and a double. 02039 02040 Entry: 02041 fp - file to get item from 02042 type - data type supposedly in the word 02043 02044 Exit: 02045 int_val - integer value 02046 uint_val - unsigned integer value 02047 double_val - double-precision floating point value 02048 ******************************************************************************/ 02049 02050 void get_binary_item( 02051 FILE *fp, 02052 int type, 02053 int *int_val, 02054 unsigned int *uint_val, 02055 double *double_val 02056 ) 02057 { 02058 char c[8]; 02059 void *ptr; 02060 02061 ptr = (void *) c; 02062 02063 switch (type) { 02064 case Int8: 02065 fread (ptr, 1, 1, fp); 02066 *int_val = *((char *) ptr); 02067 *uint_val = *int_val; 02068 *double_val = *int_val; 02069 break; 02070 case Uint8: 02071 fread (ptr, 1, 1, fp); 02072 *uint_val = *((unsigned char *) ptr); 02073 *int_val = *uint_val; 02074 *double_val = *uint_val; 02075 break; 02076 case Int16: 02077 fread (ptr, 2, 1, fp); 02078 *int_val = *((short int *) ptr); 02079 *uint_val = *int_val; 02080 *double_val = *int_val; 02081 break; 02082 case Uint16: 02083 fread (ptr, 2, 1, fp); 02084 *uint_val = *((unsigned short int *) ptr); 02085 *int_val = *uint_val; 02086 *double_val = *uint_val; 02087 break; 02088 case Int32: 02089 fread (ptr, 4, 1, fp); 02090 *int_val = *((int *) ptr); 02091 *uint_val = *int_val; 02092 *double_val = *int_val; 02093 break; 02094 case Uint32: 02095 fread (ptr, 4, 1, fp); 02096 *uint_val = *((unsigned int *) ptr); 02097 *int_val = *uint_val; 02098 *double_val = *uint_val; 02099 break; 02100 case Float32: 02101 fread (ptr, 4, 1, fp); 02102 *double_val = *((float *) ptr); 02103 *int_val = *double_val; 02104 *uint_val = *double_val; 02105 break; 02106 case Float64: 02107 fread (ptr, 8, 1, fp); 02108 *double_val = *((double *) ptr); 02109 *int_val = *double_val; 02110 *uint_val = *double_val; 02111 break; 02112 default: 02113 fprintf (stderr, "get_binary_item: bad type = %d\n", type); 02114 exit (-1); 02115 } 02116 } 02117 02118 02119 /****************************************************************************** 02120 Extract the value of an item from an ascii word, and place the result 02121 into an integer, an unsigned integer and a double. 02122 02123 Entry: 02124 word - word to extract value from 02125 type - data type supposedly in the word 02126 02127 Exit: 02128 int_val - integer value 02129 uint_val - unsigned integer value 02130 double_val - double-precision floating point value 02131 ******************************************************************************/ 02132 02133 void get_ascii_item( 02134 char *word, 02135 int type, 02136 int *int_val, 02137 unsigned int *uint_val, 02138 double *double_val 02139 ) 02140 { 02141 switch (type) { 02142 case Int8: 02143 case Uint8: 02144 case Int16: 02145 case Uint16: 02146 case Int32: 02147 *int_val = atoi (word); 02148 *uint_val = *int_val; 02149 *double_val = *int_val; 02150 break; 02151 02152 case Uint32: 02153 *uint_val = strtoul (word, (char **) NULL, 10); 02154 *int_val = *uint_val; 02155 *double_val = *uint_val; 02156 break; 02157 02158 case Float32: 02159 case Float64: 02160 *double_val = atof (word); 02161 *int_val = (int) *double_val; 02162 *uint_val = (unsigned int) *double_val; 02163 break; 02164 02165 default: 02166 fprintf (stderr, "get_ascii_item: bad type = %d\n", type); 02167 exit (-1); 02168 } 02169 } 02170 02171 02172 /****************************************************************************** 02173 Store a value into a place being pointed to, guided by a data type. 02174 02175 Entry: 02176 item - place to store value 02177 type - data type 02178 int_val - integer version of value 02179 uint_val - unsigned integer version of value 02180 double_val - double version of value 02181 02182 Exit: 02183 item - pointer to stored value 02184 ******************************************************************************/ 02185 02186 void store_item ( 02187 char *item, 02188 int type, 02189 int int_val, 02190 unsigned int uint_val, 02191 double double_val 02192 ) 02193 { 02194 unsigned char *puchar; 02195 short int *pshort; 02196 unsigned short int *pushort; 02197 int *pint; 02198 unsigned int *puint; 02199 float *pfloat; 02200 double *pdouble; 02201 02202 switch (type) { 02203 case Int8: 02204 *item = int_val; 02205 break; 02206 case Uint8: 02207 puchar = (unsigned char *) item; 02208 *puchar = uint_val; 02209 break; 02210 case Int16: 02211 pshort = (short *) item; 02212 *pshort = int_val; 02213 break; 02214 case Uint16: 02215 pushort = (unsigned short *) item; 02216 *pushort = uint_val; 02217 break; 02218 case Int32: 02219 pint = (int *) item; 02220 *pint = int_val; 02221 break; 02222 case Uint32: 02223 puint = (unsigned int *) item; 02224 *puint = uint_val; 02225 break; 02226 case Float32: 02227 pfloat = (float *) item; 02228 *pfloat = double_val; 02229 break; 02230 case Float64: 02231 pdouble = (double *) item; 02232 *pdouble = double_val; 02233 break; 02234 default: 02235 fprintf (stderr, "store_item: bad type = %d\n", type); 02236 exit (-1); 02237 } 02238 } 02239 02240 02241 /****************************************************************************** 02242 Add an element to a PLY file descriptor. 02243 02244 Entry: 02245 plyfile - PLY file descriptor 02246 words - list of words describing the element 02247 nwords - number of words in the list 02248 ******************************************************************************/ 02249 02250 void add_element (PlyFile *plyfile, char **words, int nwords) 02251 { 02252 PlyElement *elem; 02253 02254 /* create the new element */ 02255 elem = (PlyElement *) myalloc (sizeof (PlyElement)); 02256 elem->name = strdup (words[1]); 02257 elem->num = atoi (words[2]); 02258 elem->nprops = 0; 02259 02260 /* make room for new element in the object's list of elements */ 02261 if (plyfile->num_elem_types == 0) 02262 plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); 02263 else 02264 plyfile->elems = (PlyElement **) realloc (plyfile->elems, 02265 sizeof (PlyElement *) * (plyfile->num_elem_types + 1)); 02266 02267 /* add the new element to the object's list */ 02268 plyfile->elems[plyfile->num_elem_types] = elem; 02269 plyfile->num_elem_types++; 02270 } 02271 02272 02273 /****************************************************************************** 02274 Return the type of a property, given the name of the property. 02275 02276 Entry: 02277 name - name of property type 02278 02279 Exit: 02280 returns integer code for property, or 0 if not found 02281 ******************************************************************************/ 02282 02283 int get_prop_type(char *type_name) 02284 { 02285 int i; 02286 02287 /* try to match the type name */ 02288 for (i = StartType + 1; i < EndType; i++) 02289 if (equal_strings (type_name, type_names[i])) 02290 return (i); 02291 02292 /* see if we can match an old type name */ 02293 for (i = StartType + 1; i < EndType; i++) 02294 if (equal_strings (type_name, old_type_names[i])) 02295 return (i); 02296 02297 /* if we get here, we didn't find the type */ 02298 return (0); 02299 } 02300 02301 02302 /****************************************************************************** 02303 Add a property to a PLY file descriptor. 02304 02305 Entry: 02306 plyfile - PLY file descriptor 02307 words - list of words describing the property 02308 nwords - number of words in the list 02309 ******************************************************************************/ 02310 02311 void add_property (PlyFile *plyfile, char **words, int nwords) 02312 { 02313 int prop_type; 02314 int count_type; 02315 PlyProperty *prop; 02316 PlyElement *elem; 02317 02318 /* create the new property */ 02319 02320 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 02321 02322 if (equal_strings (words[1], "list")) { /* list */ 02323 prop->count_external = get_prop_type (words[2]); 02324 prop->external_type = get_prop_type (words[3]); 02325 prop->name = strdup (words[4]); 02326 prop->is_list = PLY_LIST; 02327 } 02328 else if (equal_strings (words[1], "string")) { /* string */ 02329 prop->count_external = Int8; 02330 prop->external_type = Int8; 02331 prop->name = strdup (words[2]); 02332 prop->is_list = PLY_STRING; 02333 } 02334 else { /* scalar */ 02335 prop->external_type = get_prop_type (words[1]); 02336 prop->name = strdup (words[2]); 02337 prop->is_list = PLY_SCALAR; 02338 } 02339 02340 /* add this property to the list of properties of the current element */ 02341 02342 elem = plyfile->elems[plyfile->num_elem_types - 1]; 02343 02344 if (elem->nprops == 0) 02345 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); 02346 else 02347 elem->props = (PlyProperty **) realloc (elem->props, 02348 sizeof (PlyProperty *) * (elem->nprops + 1)); 02349 02350 elem->props[elem->nprops] = prop; 02351 elem->nprops++; 02352 } 02353 02354 02355 /****************************************************************************** 02356 Add a comment to a PLY file descriptor. 02357 02358 Entry: 02359 plyfile - PLY file descriptor 02360 line - line containing comment 02361 ******************************************************************************/ 02362 02363 void add_comment (PlyFile *plyfile, char *line) 02364 { 02365 int i; 02366 02367 /* skip over "comment" and leading spaces and tabs */ 02368 i = 7; 02369 while (line[i] == ' ' || line[i] == '\t') 02370 i++; 02371 02372 append_comment_ply (plyfile, &line[i]); 02373 } 02374 02375 02376 /****************************************************************************** 02377 Add a some object information to a PLY file descriptor. 02378 02379 Entry: 02380 plyfile - PLY file descriptor 02381 line - line containing text info 02382 ******************************************************************************/ 02383 02384 void add_obj_info (PlyFile *plyfile, char *line) 02385 { 02386 int i; 02387 02388 /* skip over "obj_info" and leading spaces and tabs */ 02389 i = 8; 02390 while (line[i] == ' ' || line[i] == '\t') 02391 i++; 02392 02393 append_obj_info_ply (plyfile, &line[i]); 02394 } 02395 02396 02397 /****************************************************************************** 02398 Copy a property. 02399 ******************************************************************************/ 02400 02401 void copy_property(PlyProperty *dest, PlyProperty *src) 02402 { 02403 dest->name = strdup (src->name); 02404 dest->external_type = src->external_type; 02405 dest->internal_type = src->internal_type; 02406 dest->offset = src->offset; 02407 02408 dest->is_list = src->is_list; 02409 dest->count_external = src->count_external; 02410 dest->count_internal = src->count_internal; 02411 dest->count_offset = src->count_offset; 02412 } 02413 02414 02415 /****************************************************************************** 02416 Allocate some memory. 02417 02418 Entry: 02419 size - amount of memory requested (in bytes) 02420 lnum - line number from which memory was requested 02421 fname - file name from which memory was requested 02422 ******************************************************************************/ 02423 02424 static char *my_alloc(int size, int lnum, char *fname) 02425 { 02426 char *ptr; 02427 02428 ptr = (char *) malloc (size); 02429 02430 if (ptr == 0) { 02431 fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname); 02432 } 02433 02434 return (ptr); 02435 } 02436 02437 02438 /**** NEW STUFF ****/ 02439 /**** NEW STUFF ****/ 02440 /**** NEW STUFF ****/ 02441 /**** NEW STUFF ****/ 02442 02443 02444 02445 /****************************************************************************** 02446 Given a file pointer, get ready to read PLY data from the file. 02447 02448 Entry: 02449 fp - the given file pointer 02450 02451 Exit: 02452 nelems - number of elements in object 02453 elem_names - list of element names 02454 returns a pointer to a PlyFile, used to refer to this file, or NULL if error 02455 ******************************************************************************/ 02456 02457 PlyFile *read_ply(FILE *fp) 02458 { 02459 PlyFile *ply; 02460 int num_elems; 02461 char **elem_names; 02462 02463 ply = ply_read (fp, &num_elems, &elem_names); 02464 02465 return (ply); 02466 } 02467 02468 02469 /****************************************************************************** 02470 Given a file pointer, get ready to write PLY data to the file. 02471 02472 Entry: 02473 fp - the given file pointer 02474 nelems - number of elements in object 02475 elem_names - list of element names 02476 file_type - file type, either ascii or binary 02477 02478 Exit: 02479 returns a pointer to a PlyFile, used to refer to this file, or NULL if error 02480 ******************************************************************************/ 02481 02482 PlyFile *write_ply( 02483 FILE *fp, 02484 int nelems, 02485 char **elem_names, 02486 int file_type 02487 ) 02488 { 02489 PlyFile *ply; 02490 02491 ply = ply_write (fp, nelems, elem_names, file_type); 02492 02493 return (ply); 02494 } 02495 02496 02497 /****************************************************************************** 02498 Return a list of the names of the elements in a particular PLY file. 02499 02500 Entry: 02501 ply - PLY file whose element name list we want 02502 02503 Exit: 02504 num_elems - the number of element names in the list 02505 returns the list of names 02506 ******************************************************************************/ 02507 02508 char **get_element_list_ply(PlyFile *ply, int *num_elems) 02509 { 02510 int i; 02511 char **elist; 02512 02513 /* create the list of element names */ 02514 02515 elist = (char **) myalloc (sizeof (char *) * ply->num_elem_types); 02516 for (i = 0; i < ply->num_elem_types; i++) 02517 elist[i] = strdup (ply->elems[i]->name); 02518 02519 /* return the number of elements and the list of element names */ 02520 *num_elems = ply->num_elem_types; 02521 return (elist); 02522 } 02523 02524 02525 /****************************************************************************** 02526 Append a comment to a PLY file. 02527 02528 Entry: 02529 ply - file to append comment to 02530 comment - the comment to append 02531 ******************************************************************************/ 02532 02533 void append_comment_ply(PlyFile *ply, char *comment) 02534 { 02535 /* (re)allocate space for new comment */ 02536 if (ply->num_comments == 0) 02537 ply->comments = (char **) myalloc (sizeof (char *)); 02538 else 02539 ply->comments = (char **) realloc (ply->comments, 02540 sizeof (char *) * (ply->num_comments + 1)); 02541 02542 /* add comment to list */ 02543 ply->comments[ply->num_comments] = strdup (comment); 02544 ply->num_comments++; 02545 } 02546 02547 02548 /****************************************************************************** 02549 Copy the comments from one PLY file to another. 02550 02551 Entry: 02552 out_ply - destination file to copy comments to 02553 in_ply - the source of the comments 02554 ******************************************************************************/ 02555 02556 void copy_comments_ply(PlyFile *out_ply, PlyFile *in_ply) 02557 { 02558 int i; 02559 02560 for (i = 0; i < in_ply->num_comments; i++) 02561 append_comment_ply (out_ply, in_ply->comments[i]); 02562 } 02563 02564 02565 /****************************************************************************** 02566 Append object information (arbitrary text) to a PLY file. 02567 02568 Entry: 02569 ply - file to append object info to 02570 obj_info - the object info to append 02571 ******************************************************************************/ 02572 02573 void append_obj_info_ply(PlyFile *ply, char *obj_info) 02574 { 02575 /* (re)allocate space for new info */ 02576 if (ply->num_obj_info == 0) 02577 ply->obj_info = (char **) myalloc (sizeof (char *)); 02578 else 02579 ply->obj_info = (char **) realloc (ply->obj_info, 02580 sizeof (char *) * (ply->num_obj_info + 1)); 02581 02582 /* add info to list */ 02583 ply->obj_info[ply->num_obj_info] = strdup (obj_info); 02584 ply->num_obj_info++; 02585 } 02586 02587 02588 /****************************************************************************** 02589 Copy the object information from one PLY file to another. 02590 02591 Entry: 02592 out_ply - destination file to copy object information to 02593 in_ply - the source of the object information 02594 ******************************************************************************/ 02595 02596 void copy_obj_info_ply(PlyFile *out_ply, PlyFile *in_ply) 02597 { 02598 int i; 02599 02600 for (i = 0; i < in_ply->num_obj_info; i++) 02601 append_obj_info_ply (out_ply, in_ply->obj_info[i]); 02602 } 02603 02604 02605 /****************************************************************************** 02606 Close a PLY file. 02607 02608 Entry: 02609 plyfile - identifier of file to close 02610 ******************************************************************************/ 02611 02612 void close_ply(PlyFile *plyfile) 02613 { 02614 fclose (plyfile->fp); 02615 } 02616 02617 02618 /****************************************************************************** 02619 Free the memory used by a PLY file. 02620 02621 Entry: 02622 plyfile - identifier of file 02623 ******************************************************************************/ 02624 02625 void free_ply(PlyFile *plyfile) 02626 { 02627 /* free up memory associated with the PLY file */ 02628 free (plyfile); 02629 } 02630 02631 02632 /****************************************************************************** 02633 Specify the index of the next element to be read in from a PLY file. 02634 02635 Entry: 02636 ply - file to read from 02637 index - index of the element to be read 02638 02639 Exit: 02640 elem_count - the number of elements in the file 02641 returns pointer to the name of this next element 02642 ******************************************************************************/ 02643 02644 char *setup_element_read_ply (PlyFile *ply, int index, int *elem_count) 02645 { 02646 PlyElement *elem; 02647 02648 if (index < 0 || index > ply->num_elem_types) { 02649 fprintf (stderr, "Warning: No element with index %d\n", index); 02650 return (0); 02651 } 02652 02653 elem = ply->elems[index]; 02654 02655 /* set this to be the current element */ 02656 ply->which_elem = elem; 02657 02658 /* return the number of such elements in the file and the element's name */ 02659 *elem_count = elem->num; 02660 return (elem->name); 02661 } 02662 02663 02664 /****************************************************************************** 02665 Read one element from the file. This routine assumes that we're reading 02666 the type of element specified in the last call to the routine 02667 setup_element_read_ply(). 02668 02669 Entry: 02670 plyfile - file identifier 02671 elem_ptr - pointer to location where the element information should be put 02672 ******************************************************************************/ 02673 02674 void get_element_ply (PlyFile *plyfile, void *elem_ptr) 02675 { 02676 if (plyfile->file_type == PLY_ASCII) 02677 ascii_get_element (plyfile, (char *) elem_ptr); 02678 else 02679 binary_get_element (plyfile, (char *) elem_ptr); 02680 } 02681 02682 02683 /****************************************************************************** 02684 Specify one of several properties of the current element that is to be 02685 read from a file. This should be called (usually multiple times) before a 02686 call to the routine get_element_ply(). 02687 02688 Entry: 02689 plyfile - file identifier 02690 prop - property to add to those that will be returned 02691 ******************************************************************************/ 02692 02693 void setup_property_ply( 02694 PlyFile *plyfile, 02695 PlyProperty *prop 02696 ) 02697 { 02698 PlyElement *elem; 02699 PlyProperty *prop_ptr; 02700 int index; 02701 02702 elem = plyfile->which_elem; 02703 02704 /* deposit the property information into the element's description */ 02705 02706 prop_ptr = find_property (elem, prop->name, &index); 02707 if (prop_ptr == NULL) { 02708 fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", 02709 prop->name, elem->name); 02710 return; 02711 } 02712 prop_ptr->internal_type = prop->internal_type; 02713 prop_ptr->offset = prop->offset; 02714 prop_ptr->count_internal = prop->count_internal; 02715 prop_ptr->count_offset = prop->count_offset; 02716 02717 /* specify that the user wants this property */ 02718 elem->store_prop[index] = STORE_PROP; 02719 } 02720 02721 02722 /****************************************************************************** 02723 Specify that we want the "other" properties of the current element to be tucked 02724 away within the user's structure. 02725 02726 Entry: 02727 plyfile - file identifier 02728 offset - offset to where other_props will be stored inside user's structure 02729 02730 Exit: 02731 returns pointer to structure containing description of other_props 02732 ******************************************************************************/ 02733 02734 PlyOtherProp *get_other_properties_ply( 02735 PlyFile *plyfile, 02736 int offset 02737 ) 02738 { 02739 PlyOtherProp *other; 02740 02741 other = get_other_properties (plyfile, plyfile->which_elem, offset); 02742 return (other); 02743 } 02744 02745 02746 /****************************************************************************** 02747 Describe which element is to be written next and state how many of them will 02748 be written. 02749 02750 Entry: 02751 plyfile - file identifier 02752 elem_name - name of element that information is being described 02753 nelems - number of elements of this type to be written 02754 ******************************************************************************/ 02755 02756 void describe_element_ply( 02757 PlyFile *plyfile, 02758 char *elem_name, 02759 int nelems 02760 ) 02761 { 02762 int i; 02763 PlyElement *elem; 02764 PlyProperty *prop; 02765 02766 /* look for appropriate element */ 02767 elem = find_element (plyfile, elem_name); 02768 if (elem == NULL) { 02769 fprintf(stderr,"describe_element_ply: can't find element '%s'\n",elem_name); 02770 exit (-1); 02771 } 02772 02773 elem->num = nelems; 02774 02775 /* now this element is the current element */ 02776 plyfile->which_elem = elem; 02777 } 02778 02779 02780 /****************************************************************************** 02781 Describe a property of an element. 02782 02783 Entry: 02784 plyfile - file identifier 02785 prop - the new property 02786 ******************************************************************************/ 02787 02788 void describe_property_ply( 02789 PlyFile *plyfile, 02790 PlyProperty *prop 02791 ) 02792 { 02793 PlyElement *elem; 02794 PlyProperty *elem_prop; 02795 02796 elem = plyfile->which_elem; 02797 02798 /* create room for new property */ 02799 02800 if (elem->nprops == 0) { 02801 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); 02802 elem->store_prop = (char *) myalloc (sizeof (char)); 02803 elem->nprops = 1; 02804 } 02805 else { 02806 elem->nprops++; 02807 elem->props = (PlyProperty **) 02808 realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); 02809 elem->store_prop = (char *) 02810 realloc (elem->store_prop, sizeof (char) * elem->nprops); 02811 } 02812 02813 /* copy the new property */ 02814 02815 elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 02816 elem->props[elem->nprops - 1] = elem_prop; 02817 elem->store_prop[elem->nprops - 1] = NAMED_PROP; 02818 copy_property (elem_prop, prop); 02819 } 02820 02821 02822 /****************************************************************************** 02823 Describe what the "other" properties are that are to be stored, and where 02824 they are in an element. 02825 ******************************************************************************/ 02826 02827 void describe_other_properties_ply( 02828 PlyFile *plyfile, 02829 PlyOtherProp *other, 02830 int offset 02831 ) 02832 { 02833 int i; 02834 PlyElement *elem; 02835 PlyProperty *prop; 02836 02837 /* look for appropriate element */ 02838 elem = find_element (plyfile, other->name); 02839 if (elem == NULL) { 02840 fprintf(stderr, "describe_other_properties_ply: can't find element '%s'\n", 02841 other->name); 02842 return; 02843 } 02844 02845 /* create room for other properties */ 02846 02847 if (elem->nprops == 0) { 02848 elem->props = (PlyProperty **) 02849 myalloc (sizeof (PlyProperty *) * other->nprops); 02850 elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops); 02851 elem->nprops = 0; 02852 } 02853 else { 02854 int newsize; 02855 newsize = elem->nprops + other->nprops; 02856 elem->props = (PlyProperty **) 02857 realloc (elem->props, sizeof (PlyProperty *) * newsize); 02858 elem->store_prop = (char *) 02859 realloc (elem->store_prop, sizeof (char) * newsize); 02860 } 02861 02862 /* copy the other properties */ 02863 02864 for (i = 0; i < other->nprops; i++) { 02865 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 02866 copy_property (prop, other->props[i]); 02867 elem->props[elem->nprops] = prop; 02868 elem->store_prop[elem->nprops] = OTHER_PROP; 02869 elem->nprops++; 02870 } 02871 02872 /* save other info about other properties */ 02873 elem->other_size = other->size; 02874 elem->other_offset = offset; 02875 } 02876 02877 02878 /****************************************************************************** 02879 Pass along a pointer to "other" elements that we want to save in a given 02880 PLY file. These other elements were presumably read from another PLY file. 02881 02882 Entry: 02883 plyfile - file pointer in which to store this other element info 02884 other_elems - info about other elements that we want to store 02885 ******************************************************************************/ 02886 02887 void describe_other_elements_ply ( 02888 PlyFile *plyfile, 02889 PlyOtherElems *other_elems 02890 ) 02891 { 02892 int i; 02893 OtherElem *other; 02894 02895 /* ignore this call if there is no other element */ 02896 if (other_elems == NULL) 02897 return; 02898 02899 /* save pointer to this information */ 02900 plyfile->other_elems = other_elems; 02901 02902 /* describe the other properties of this element */ 02903 02904 for (i = 0; i < other_elems->num_elems; i++) { 02905 other = &(other_elems->other_list[i]); 02906 element_count_ply (plyfile, other->elem_name, other->elem_count); 02907 describe_other_properties_ply (plyfile, other->other_props, 02908 offsetof(OtherData,other_props)); 02909 } 02910 } 02911 02912 02913 02914 /**** Property Propagation Rules ****/ 02915 02916 02917 typedef struct RuleName { 02918 int code; 02919 char *name; 02920 } RuleName; 02921 02922 RuleName rule_name_list[] = { 02923 AVERAGE_RULE, "avg", 02924 RANDOM_RULE, "rnd", 02925 MINIMUM_RULE, "max", 02926 MAXIMUM_RULE, "min", 02927 MAJORITY_RULE, "major", 02928 SAME_RULE, "same", 02929 -1, "end_marker", 02930 }; 02931 02932 02933 02934 /****************************************************************************** 02935 Initialize the property propagation rules for an element. Default is to 02936 use averaging (AVERAGE_RULE) for creating all new properties. 02937 02938 Entry: 02939 ply - PLY object that this is for 02940 elem_name - name of the element that we're making the rules for 02941 02942 Exit: 02943 returns pointer to the default rules 02944 ******************************************************************************/ 02945 02946 PlyPropRules *init_rule_ply (PlyFile *ply, char *elem_name) 02947 { 02948 int i,j; 02949 PlyElement *elem; 02950 PlyPropRules *rules; 02951 PlyRuleList *list; 02952 int found_prop; 02953 02954 elem = find_element (ply, elem_name); 02955 if (elem == NULL) { 02956 fprintf (stderr, "init_rule_ply: Can't find element '%s'\n", elem_name); 02957 exit (-1); 02958 } 02959 02960 rules = (PlyPropRules *) myalloc (sizeof (PlyPropRules)); 02961 rules->elem = elem; 02962 rules->rule_list = (int *) myalloc (sizeof(int) * elem->nprops); 02963 rules->max_props = 0; 02964 rules->nprops = 0; 02965 02966 /* default is to use averaging rule */ 02967 for (i = 0; i < elem->nprops; i++) 02968 rules->rule_list[i] = AVERAGE_RULE; 02969 02970 /* see if there are other rules we should use */ 02971 02972 if (ply->rule_list == NULL) 02973 return (rules); 02974 02975 /* try to match the element, property and rule name */ 02976 02977 for (list = ply->rule_list; list != NULL; list = list->next) { 02978 02979 if (!equal_strings (list->element, elem->name)) 02980 continue; 02981 02982 found_prop = 0; 02983 02984 for (i = 0; i < elem->nprops; i++) 02985 if (equal_strings (list->property, elem->props[i]->name)) { 02986 02987 found_prop = 1; 02988 02989 /* look for matching rule name */ 02990 for (j = 0; rule_name_list[j].code != -1; j++) 02991 if (equal_strings (list->name, rule_name_list[j].name)) { 02992 rules->rule_list[i] = rule_name_list[j].code; 02993 break; 02994 } 02995 } 02996 02997 if (!found_prop) { 02998 fprintf (stderr, "Can't find property '%s' for rule '%s'\n", 02999 list->property, list->name); 03000 continue; 03001 } 03002 } 03003 03004 return (rules); 03005 } 03006 03007 03008 /****************************************************************************** 03009 Modify a property propagation rule. 03010 03011 Entry: 03012 rules - rules for the element 03013 prop_name - name of the property whose rule we're modifying 03014 rule_type - type of rule (MAXIMUM_RULE, MINIMUM_RULE, MAJORITY_RULE, etc.) 03015 ******************************************************************************/ 03016 03017 void modify_rule_ply (PlyPropRules *rules, char *prop_name, int rule_type) 03018 { 03019 int i; 03020 PlyElement *elem = rules->elem; 03021 03022 /* find the property and modify its rule type */ 03023 03024 for (i = 0; i < elem->nprops; i++) 03025 if (equal_strings (elem->props[i]->name, prop_name)) { 03026 rules->rule_list[i] = rule_type; 03027 return; 03028 } 03029 03030 /* we didn't find the property if we get here */ 03031 fprintf (stderr, "modify_rule_ply: Can't find property '%s'\n", prop_name); 03032 exit (-1); 03033 } 03034 03035 03036 /****************************************************************************** 03037 Begin to create a set of properties from a set of propagation rules. 03038 03039 Entry: 03040 ply - PLY object whose rules we're preparing to use 03041 rules - rules for the element 03042 ******************************************************************************/ 03043 03044 void start_props_ply (PlyFile *ply, PlyPropRules *rules) 03045 { 03046 int i; 03047 int count; 03048 PlyElement *elem = rules->elem; 03049 03050 /* save pointer to the rules in the PLY object */ 03051 ply->current_rules = rules; 03052 03053 /* get ready for new sets of properties to combine */ 03054 rules->nprops = 0; 03055 } 03056 03057 03058 /****************************************************************************** 03059 Remember a set of properties and their weights for creating a new set of 03060 properties. 03061 03062 Entry: 03063 weight - weights for this set of properties 03064 other_props - the properties to use 03065 ******************************************************************************/ 03066 03067 void weight_props_ply (PlyFile *ply, float weight, void *other_props) 03068 { 03069 PlyPropRules *rules = ply->current_rules; 03070 03071 /* allocate space for properties and weights, if necessary */ 03072 if (rules->max_props == 0) { 03073 rules->max_props = 6; 03074 rules->props = (void **) myalloc (sizeof (void *) * rules->max_props); 03075 rules->weights = (float *) myalloc (sizeof (float) * rules->max_props); 03076 } 03077 if (rules->nprops == rules->max_props) { 03078 rules->max_props *= 2; 03079 rules->props = (void **) realloc (rules->props, 03080 sizeof (void *) * rules->max_props); 03081 rules->weights = (float *) realloc (rules->weights, 03082 sizeof (float) * rules->max_props); 03083 } 03084 03085 /* remember these new properties and their weights */ 03086 03087 rules->props[rules->nprops] = other_props; 03088 rules->weights[rules->nprops] = weight; 03089 rules->nprops++; 03090 } 03091 03092 03093 /****************************************************************************** 03094 Return a pointer to a new set of properties that have been created using 03095 a specified set of property combination rules and a given collection of 03096 "other" properties. 03097 03098 Exit: 03099 returns a pointer to the new properties 03100 ******************************************************************************/ 03101 03102 void *get_new_props_ply(PlyFile *ply) 03103 { 03104 int i,j; 03105 static double *vals; 03106 static int max_vals = 0; 03107 PlyPropRules *rules = ply->current_rules; 03108 PlyElement *elem = rules->elem; 03109 PlyProperty *prop; 03110 char *data; 03111 char *new_data; 03112 void *ptr; 03113 int offset; 03114 int type; 03115 double double_val; 03116 int int_val; 03117 unsigned int uint_val; 03118 int random_pick; 03119 03120 /* return NULL if we've got no "other" properties */ 03121 if (elem->other_size == 0) { 03122 return (NULL); 03123 } 03124 03125 /* create room for combined other properties */ 03126 new_data = (char *) myalloc (sizeof (char) * elem->other_size); 03127 03128 /* make sure there is enough room to store values we're to combine */ 03129 03130 if (max_vals == 0) { 03131 max_vals = rules->nprops; 03132 vals = (double *) myalloc (sizeof (double) * rules->nprops); 03133 } 03134 if (rules->nprops >= max_vals) { 03135 max_vals = rules->nprops; 03136 vals = (double *) realloc (vals, sizeof (double) * rules->nprops); 03137 } 03138 03139 /* in case we need a random choice */ 03140 random_pick = (int) floor (rules->nprops * 0.5); 03141 03142 /* calculate the combination for each "other" property of the element */ 03143 03144 for (i = 0; i < elem->nprops; i++) { 03145 03146 /* don't bother with properties we've been asked to store explicitly */ 03147 if (elem->store_prop[i]) 03148 continue; 03149 03150 prop = elem->props[i]; 03151 offset = prop->offset; 03152 type = prop->external_type; 03153 03154 /* collect together all the values we're to combine */ 03155 03156 for (j = 0; j < rules->nprops; j++) { 03157 data = (char *) rules->props[j]; 03158 ptr = (void *) (data + offset); 03159 get_stored_item ((void *) ptr, type, &int_val, &uint_val, &double_val); 03160 vals[j] = double_val; 03161 } 03162 03163 /* calculate the combined value */ 03164 03165 switch (rules->rule_list[i]) { 03166 case AVERAGE_RULE: { 03167 double sum = 0; 03168 double weight_sum = 0; 03169 for (j = 0; j < rules->nprops; j++) { 03170 sum += vals[j] * rules->weights[j]; 03171 weight_sum += rules->weights[j]; 03172 } 03173 double_val = sum / weight_sum; 03174 break; 03175 } 03176 case MINIMUM_RULE: { 03177 double_val = vals[0]; 03178 for (j = 1; j < rules->nprops; j++) 03179 if (double_val > vals[j]) 03180 double_val = vals[j]; 03181 break; 03182 } 03183 case MAXIMUM_RULE: { 03184 double_val = vals[0]; 03185 for (j = 1; j < rules->nprops; j++) 03186 if (double_val < vals[j]) 03187 double_val = vals[j]; 03188 break; 03189 } 03190 case RANDOM_RULE: { 03191 double_val = vals[random_pick]; 03192 break; 03193 } 03194 case SAME_RULE: { 03195 double_val = vals[0]; 03196 for (j = 1; j < rules->nprops; j++) 03197 if (double_val != vals[j]) { 03198 fprintf (stderr, 03199 "get_new_props_ply: Error combining properties that should be the same.\n"); 03200 exit (-1); 03201 } 03202 break; 03203 } 03204 default: 03205 fprintf (stderr, "get_new_props_ply: Bad rule = %d\n", 03206 rules->rule_list[i]); 03207 exit (-1); 03208 } 03209 03210 /* store the combined value */ 03211 03212 int_val = (int) double_val; 03213 uint_val = (unsigned int) double_val; 03214 ptr = (void *) (new_data + offset); 03215 store_item ((char *) ptr, type, int_val, uint_val, double_val); 03216 } 03217 03218 return ((void *) new_data); 03219 } 03220 03221 03222 /****************************************************************************** 03223 Set the list of user-specified property combination rules. 03224 ******************************************************************************/ 03225 03226 void set_prop_rules_ply (PlyFile *ply, PlyRuleList *prop_rules) 03227 { 03228 ply->rule_list = prop_rules; 03229 } 03230 03231 03232 /****************************************************************************** 03233 Append a property rule to a growing list of user-specified rules. 03234 03235 Entry: 03236 rule_list - current rule list 03237 name - name of property combination rule 03238 property - "element.property" says which property the rule affects 03239 03240 Exit: 03241 returns pointer to the new rule list 03242 ******************************************************************************/ 03243 03244 PlyRuleList *append_prop_rule ( 03245 PlyRuleList *rule_list, 03246 char *name, 03247 char *property 03248 ) 03249 { 03250 PlyRuleList *rule; 03251 PlyRuleList *rule_ptr; 03252 char *str,*str2; 03253 char *ptr; 03254 03255 /* find . */ 03256 str = strdup (property); 03257 for (ptr = str; *ptr != '\0' && *ptr != '.'; ptr++) ; 03258 03259 /* split string at . */ 03260 if (*ptr == '.') { 03261 *ptr = '\0'; 03262 str2 = ptr + 1; 03263 } 03264 else { 03265 fprintf (stderr, "Can't find property '%s' for rule '%s'\n", 03266 property, name); 03267 return (rule_list); 03268 } 03269 03270 rule = (PlyRuleList *) malloc (sizeof (PlyRuleList)); 03271 rule->name = name; 03272 rule->element = str; 03273 rule->property = str2; 03274 rule->next = NULL; 03275 03276 /* either start rule list or append to it */ 03277 03278 if (rule_list == NULL) 03279 rule_list = rule; 03280 else { /* append new rule to current list */ 03281 rule_ptr = rule_list; 03282 while (rule_ptr->next != NULL) 03283 rule_ptr = rule_ptr->next; 03284 rule_ptr->next = rule; 03285 } 03286 03287 /* return pointer to list */ 03288 03289 return (rule_list); 03290 } 03291 03292 03293 /****************************************************************************** 03294 See if a name matches the name of any property combination rules. 03295 03296 Entry: 03297 name - name of rule we're trying to match 03298 03299 Exit: 03300 returns 1 if we find a match, 0 if not 03301 ******************************************************************************/ 03302 03303 int matches_rule_name (char *name) 03304 { 03305 int i; 03306 03307 for (i = 0; rule_name_list[i].code != -1; i++) 03308 if (equal_strings (rule_name_list[i].name, name)) 03309 return (1); 03310 03311 return (0); 03312 } 03313
1.7.6.1