source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/vrippack-0.31/src/plytools/plycomps.c @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 20.3 KB
Line 
1/*
2
3Determine the connected components of a PLY object, and maybe write out
4only selected components of the object.
5
6Greg Turk, August 1994
7
8*/
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <malloc.h>
14#include <string.h>
15#include <ply.h>
16#include <unistd.h>
17#include <sys/types.h>
18#include <sys/times.h>
19#include <limits.h>
20#include <time.h>
21
22
23/* user's vertex and face definitions for a polygonal object */
24
25typedef struct Vertex {
26  float x,y,z;                  /* coordinate of vertex */
27  int index;                    /* index of vertex in vertex list */
28  int nfaces;                   /* number of faces in face list */
29  int max_faces;                /* maximum number of faces in list */
30  struct Face **faces;          /* face list */
31  struct Comp *comp;            /* pointer to component description */
32  struct Vertex *next;          /* pointer for vertex queue */
33  void *other_props;            /* other properties */
34} Vertex;
35
36typedef struct Face {
37  unsigned char nverts;         /* number of vertex indices in list */
38  Vertex **verts;               /* vertex index list */
39  struct Comp *comp;            /* pointer to component description */
40  void *other_props;            /* other properties */
41} Face;
42
43char *elem_names[] = { /* list of the kinds of elements in the user's object */
44  "vertex", "face"
45};
46
47PlyProperty vert_props[] = { /* list of property information for a vertex */
48  {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
49  {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0},
50  {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0},
51};
52
53PlyProperty face_props[] = { /* list of property information for a vertex */
54  {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
55   1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
56};
57
58
59/*** the PLY object ***/
60
61int nverts,nfaces;
62Vertex **vlist;
63Face **flist;
64PlyOtherElems *other_elements = NULL;
65PlyOtherProp *vert_other,*face_other;
66int nelems;
67char **elist;
68int num_comments;
69char **comments;
70int num_obj_info;
71char **obj_info;
72int file_type;
73
74#define UNTOUCHED -1
75#define ON_QUEUE  -2
76
77
78/* queue used to assign components */
79static Vertex *queue_start = NULL;
80static Vertex *queue_end = NULL;
81
82/* the connected components */
83
84typedef struct Comp {
85  int comp_num;         /* component number stored at vertices */
86  int vcount;           /* how many vertices in this component */
87  int fcount;           /* how many faces in this component */
88} Comp;
89
90static int num_comps;           /* number of components */
91static Comp **comp_list;        /* list of components */
92static int comp_max = 100;      /* maximum number in list */
93
94static int not_silent = 1;      /* print out info about components? */
95static int top_n = 10;          /* don't print or write out
96                                   more components than this */
97static int wanted_top_n = 0;    /* Did the user want to limit the number
98                                   of copmonents printed? */
99
100void usage(char *progname);
101void write_file();
102void read_file();
103void find_components();
104int compare_components(Comp **c1, Comp **c2);
105void process_queue(int num_comps);
106void on_queue(Vertex *vert);
107void index_verts();
108void ints_to_ptrs();
109void write_more(char *filename, int more);
110void write_less(char *filename, int less);
111
112
113/******************************************************************************
114Transform a PLY file.
115******************************************************************************/
116
117int
118main(int argc, char *argv[])
119{
120  int i,j;
121  char *s;
122  char *progname;
123  int less = -1;
124  int more = -1;
125  char *filename;
126  struct tms buffer;
127  clock_t tm;
128  FILE *inFile = stdin;
129
130  times(&buffer);
131  tm = buffer.tms_utime;
132
133  progname = argv[0];
134
135  /* Parse all -flags */
136  while (--argc > 0 && (*++argv)[0]=='-') {
137    for (s = argv[0]+1; *s; s++)
138      switch (*s) {
139        case 't':
140          top_n = atoi (*++argv);
141          wanted_top_n = 1;
142          argc -= 1;
143          break;
144        case 's':
145          not_silent = 1 - not_silent;
146          break;
147        case 'm':
148          more = atoi (*++argv);
149          filename = strdup (*++argv);
150          argc -= 2;
151          break;
152        case 'l':
153          less = atoi (*++argv);
154          filename = strdup (*++argv);
155          argc -= 2;
156          break;
157        default:
158          usage (progname);
159          exit (-1);
160          break;
161      }
162  }
163
164   /* optional input file (if not, read stdin ) */
165   if (argc > 0 && *argv[0] != '-') {
166       inFile = fopen(argv[0], "r");
167       if (inFile == NULL) {
168           fprintf(stderr, "Error: Couldn't open input file %s\n", argv[0]);
169           usage(progname);
170           exit(-1);
171       }
172       argc --;
173       argv ++;
174   } 
175
176   /* Check no extra args */
177   if (argc > 0) {
178     fprintf(stderr, "Error: Unhandled arg: %s\n", argv[0]);
179     usage(progname);
180     exit(-1);
181   }
182
183
184
185  read_file(inFile);
186  index_verts();
187  ints_to_ptrs();
188  find_components();
189
190  /* maybe write all components that have at least this number of vertices */
191  if (more > -1)
192    write_more (filename, more);
193
194  /* maybe write all components that have at most this number of vertices */
195  if (less > -1)
196    write_less (filename, less);
197
198  times(&buffer);
199  tm = buffer.tms_utime - tm;
200
201  fprintf(stdout, "%f seconds\n", tm/(double)CLOCKS_PER_SEC);
202
203  exit(0);
204
205}
206
207
208/******************************************************************************
209Print out usage information about this program.
210******************************************************************************/
211
212void
213usage(char *progname)
214{
215  fprintf (stdout, "usage: %s [flags] [in.ply]\n", progname);
216  fprintf (stdout, "usage: %s [flags] < in.ply\n", progname);
217  fprintf (stdout, "       -s (silent mode)\n");
218  fprintf (stdout, "       -m num filename\n");
219  fprintf (stdout, "          (writes out all components with >= num verts)\n");
220  fprintf (stdout, "       -l num filename\n");
221  fprintf (stdout, "          (writes out all components with <= num verts)\n");
222  fprintf (stdout, "       -t num (max num of components printed to screen and written to file)\n");
223  exit(-1);
224}
225
226
227/******************************************************************************
228Find the connected components of a collection of polygons.
229******************************************************************************/
230
231void
232find_components()
233{
234  int i,j,k;
235  Face *face;
236  Vertex *vert,*vert2;
237  int compare_components();
238
239  /* create pointers from the vertices to the faces */
240
241  for (i = 0; i < nfaces; i++) {
242
243    face = flist[i];
244
245    /* make pointers from the vertices to this face */
246
247    for (j = 0; j < face->nverts; j++) {
248      vert = face->verts[j];
249      /* make sure there is enough room for the new face pointer */
250      if (vert->nfaces >= vert->max_faces) {
251        vert->max_faces += 3;
252        vert->faces = (Face **) 
253                      realloc (vert->faces, sizeof (Face *) * vert->max_faces);
254      }
255      /* add the face to this vertice's list of faces */
256      vert->faces[vert->nfaces] = face;
257      vert->nfaces++;
258    }
259  }
260
261  /* label all vertices as initially untouched */
262
263  for (i = 0; i < nverts; i++)
264    vlist[i]->comp = (Comp *) UNTOUCHED;
265
266  /* initialize the component count list */
267  comp_list = (Comp **) malloc (sizeof (Comp *) * comp_max);
268
269  /* examine each vertex to see what component it belongs to */
270
271  num_comps = 0;
272
273  for (i = 0; i < nverts; i++) {
274
275    vert = vlist[i];
276
277    /* don't touch it if we've already assigned it a component number */
278    if (vert->comp != (Comp *) UNTOUCHED)
279      continue;
280
281    /* initialize the info for this component */
282    comp_list[num_comps] = (Comp *) malloc (sizeof (Comp));
283    comp_list[num_comps]->comp_num = num_comps;
284    comp_list[num_comps]->vcount = 0;
285    comp_list[num_comps]->fcount = 0;
286
287    /* place this vertex on the queue */
288    on_queue (vert);
289
290    /* process the queue until it is empty */
291    while (queue_start)
292      process_queue (num_comps);
293
294    /* if we get here we've got a new component */
295    num_comps++;
296    if (num_comps >= comp_max) {
297      comp_max *= 2;
298      comp_list = (Comp **) realloc (comp_list, sizeof (Comp *) * comp_max);
299    }
300  }
301
302  /* count the faces in each component */
303
304  for (i = 0; i < nfaces; i++) {
305    flist[i]->comp = flist[i]->verts[0]->comp;
306    flist[i]->comp->fcount++;
307  }
308
309  /* sort the list of components by number of vertices */
310
311  qsort (comp_list, num_comps, sizeof (Comp *), 
312         (int (*)(const void *, const void *))compare_components);
313
314  /* print out info about components */
315
316  if (not_silent) {
317    fprintf (stdout, "\n");
318
319    for (i = 0; i < num_comps; i++) {
320      /*
321      fprintf (stdout, "comp %d : %d verts, %d faces\n",
322              comp_list[i]->comp_num,
323              comp_list[i]->vcount,
324              comp_list[i]->fcount);
325      */
326      fprintf (stdout, "%d verts, %d faces\n",
327               comp_list[i]->vcount, comp_list[i]->fcount);
328      if (i+1 >= top_n)
329        break;
330    }
331    if (num_comps > top_n)
332      fprintf (stdout, "...\n");
333
334    fprintf (stdout, "(%d components)\n", num_comps);
335    fprintf (stdout, "\n");
336  }
337}
338
339
340/******************************************************************************
341Compare two component entries for quicksort.
342******************************************************************************/
343
344int
345compare_components(Comp **c1, Comp **c2)
346{
347  if ((*c1)->vcount < (*c2)->vcount)
348    return (1);
349  else if ((*c1)->vcount > (*c2)->vcount)
350    return (-1);
351  else
352    return (0);
353}
354
355
356/******************************************************************************
357Process one vertex on the queue.
358******************************************************************************/
359
360void
361process_queue(int num_comps)
362{
363  int i,j;
364  Vertex *vert,*vert2;
365  Face *face;
366
367  /* pop one vertex off the queue */
368
369  vert = queue_start;
370  queue_start = vert->next;
371
372  /* store the vertex's component number */
373  vert->comp = comp_list[num_comps];
374
375  /* count this new component */
376  comp_list[num_comps]->vcount++;
377
378  /* place this vertex's neighbors on the queue */
379
380  for (i = 0; i < vert->nfaces; i++) {
381    face = vert->faces[i];
382    for (j = 0; j < face->nverts; j++) {
383      vert2 = face->verts[j];
384      if (vert2->comp == (Comp *) UNTOUCHED)
385        on_queue (vert2);
386    }
387  }
388}
389
390
391/******************************************************************************
392Place a vertex on the queue.
393******************************************************************************/
394
395void
396on_queue(Vertex *vert)
397{
398  vert->comp = (Comp *) ON_QUEUE;
399  vert->next = NULL;
400
401  if (queue_start == NULL) {
402    queue_start = vert;
403    queue_end = vert;
404  }
405  else {
406    queue_end->next = vert;
407    queue_end = vert;
408  }
409}
410
411
412/******************************************************************************
413Index the vertices.
414******************************************************************************/
415
416void
417index_verts()
418{
419  int i;
420  Vertex *vert;
421
422  for (i = 0; i < nverts; i++) {
423    vert = vlist[i];
424    vert->index = i;
425    vert->nfaces = 0;
426    vert->max_faces = 3;
427    vert->faces = (Face **) malloc (sizeof (Face *) * vert->max_faces);
428  }
429}
430
431
432/******************************************************************************
433Change the vertex indices from integers to pointers.
434******************************************************************************/
435
436void
437ints_to_ptrs()
438{
439  int i,j;
440  Vertex **verts;
441
442  for (i = 0; i < nfaces; i++) {
443    verts = flist[i]->verts;
444    for (j = 0; j < flist[i]->nverts; j++)
445      verts[j] = vlist[(int) verts[j]];
446  }
447}
448
449
450/******************************************************************************
451Read in the PLY file from standard in.
452******************************************************************************/
453
454void
455read_file(FILE *inFile)
456{
457  int i,j,k;
458  PlyFile *ply;
459  int nprops;
460  int num_elems;
461  PlyProperty **plist;
462  char *elem_name;
463  float version;
464
465
466  /*** Read in the original PLY object ***/
467
468
469  ply  = ply_read (inFile, &nelems, &elist);
470  ply_get_info (ply, &version, &file_type);
471
472  for (i = 0; i < nelems; i++) {
473
474    /* get the description of the first element */
475    elem_name = elist[i];
476    plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
477
478    if (equal_strings ("vertex", elem_name)) {
479
480      /* create a vertex list to hold all the vertices */
481      vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems);
482      nverts = num_elems;
483
484      /* set up for getting vertex elements */
485
486      ply_get_property (ply, elem_name, &vert_props[0]);
487      ply_get_property (ply, elem_name, &vert_props[1]);
488      ply_get_property (ply, elem_name, &vert_props[2]);
489      vert_other = ply_get_other_properties (ply, elem_name,
490                     offsetof(Vertex,other_props));
491
492      /* grab all the vertex elements */
493      for (j = 0; j < num_elems; j++) {
494        vlist[j] = (Vertex *) malloc (sizeof (Vertex));
495        ply_get_element (ply, (void *) vlist[j]);
496      }
497    }
498    else if (equal_strings ("face", elem_name)) {
499
500      /* create a list to hold all the face elements */
501      flist = (Face **) malloc (sizeof (Face *) * num_elems);
502      nfaces = num_elems;
503
504      /* set up for getting face elements */
505
506      ply_get_property (ply, elem_name, &face_props[0]);
507      face_other = ply_get_other_properties (ply, elem_name,
508                     offsetof(Face,other_props));
509
510      /* grab all the face elements */
511      for (j = 0; j < num_elems; j++) {
512        flist[j] = (Face *) malloc (sizeof (Face));
513        ply_get_element (ply, (void *) flist[j]);
514      }
515    }
516    else
517      other_elements = ply_get_other_element (ply, elem_name, num_elems);
518  }
519
520  comments = ply_get_comments (ply, &num_comments);
521  obj_info = ply_get_obj_info (ply, &num_obj_info);
522
523  ply_close (ply);
524}
525
526
527/******************************************************************************
528Write out those components that contain at least a given number of vertices.
529
530Entry:
531  filename - name of file to write to
532  more     - minimum number of vertices to have component be written
533******************************************************************************/
534
535void
536write_more(char *filename, int more)
537{
538  int i,j,k;
539  PlyFile *ply;
540  int num_elems;
541  char *elem_name;
542  int vsum,fsum;
543  float version;
544  Vertex **verts;
545  int vcount;
546  int comp_count;
547  int new_more;
548
549  ply = ply_open_for_writing(filename, nelems, elist, file_type, &version);
550
551
552  if (wanted_top_n) {
553      comp_count = top_n < num_comps ? top_n : num_comps;
554      new_more = comp_list[comp_count-1]->vcount;
555  }
556  else {
557      comp_count = num_comps;
558      new_more = more;
559  }
560
561  /* count vertices and faces that will be written */
562  vsum = 0;
563  fsum = 0;
564  for (i = 0; i < comp_count; i++) {
565    if (comp_list[i]->vcount >= new_more) {
566      vsum += comp_list[i]->vcount;
567      fsum += comp_list[i]->fcount;
568    }
569  }
570
571  /* describe what properties go into the vertex and face elements */
572
573  ply_element_count (ply, "vertex", vsum);
574  ply_describe_property (ply, "vertex", &vert_props[0]);
575  ply_describe_property (ply, "vertex", &vert_props[1]);
576  ply_describe_property (ply, "vertex", &vert_props[2]);
577  ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props));
578
579  ply_element_count (ply, "face", fsum);
580  ply_describe_property (ply, "face", &face_props[0]);
581  ply_describe_other_properties (ply, face_other, offsetof(Face,other_props));
582
583  ply_describe_other_elements (ply, other_elements);
584
585  for (i = 0; i < num_comments; i++)
586    ply_put_comment (ply, comments[i]);
587
588  for (i = 0; i < num_obj_info; i++)
589    ply_put_obj_info (ply, obj_info[i]);
590
591  ply_header_complete (ply);
592
593  /* change the vertex indices from pointers to indices */
594
595  vcount = 0;
596  for (i = 0; i < nverts; i++)
597    if (vlist[i]->comp->vcount >= new_more)
598      vlist[i]->index = vcount++;
599
600  for (i = 0; i < nfaces; i++) {
601    verts = flist[i]->verts;
602    for (j = 0; j < flist[i]->nverts; j++)
603      verts[j] = (Vertex *) verts[j]->index;
604  }
605
606  /* set up and write the vertex elements */
607  ply_put_element_setup (ply, "vertex");
608  for (i = 0; i < nverts; i++)
609    if (vlist[i]->comp->vcount >= new_more)
610      ply_put_element (ply, (void *) vlist[i]);
611
612  /* set up and write the face elements */
613  ply_put_element_setup (ply, "face");
614  for (i = 0; i < nfaces; i++)
615    if (flist[i]->comp->vcount >= new_more)
616      ply_put_element (ply, (void *) flist[i]);
617
618  ply_put_other_elements (ply);
619
620  /* close the PLY file */
621  ply_close (ply);
622}
623
624
625/******************************************************************************
626Write out those components that contain at most a given number of vertices.
627
628Entry:
629  filename - name of file to write to
630  less     - maximum number of vertices to have component be written
631******************************************************************************/
632
633void
634write_less(char *filename, int less)
635{
636  int i,j,k;
637  PlyFile *ply;
638  int num_elems;
639  char *elem_name;
640  int vsum,fsum;
641  float version;
642  Vertex **verts;
643  int vcount;
644  int new_less, comp_count;
645
646  ply = ply_open_for_writing(filename, nelems, elem_names, file_type, &version);
647
648  if (wanted_top_n) {
649      comp_count = top_n < num_comps ? top_n : num_comps;
650      new_less = comp_list[comp_count-1]->vcount;
651  }
652  else {
653      comp_count = num_comps;
654      new_less = less;
655  }
656
657  /* count vertices and faces that will be written */
658  vsum = 0;
659  fsum = 0;
660  for (i = 0; i < num_comps; i++) {
661    if (comp_list[i]->vcount <= new_less) {
662      vsum += comp_list[i]->vcount;
663      fsum += comp_list[i]->fcount;
664    }
665  }
666
667  /* describe what properties go into the vertex and face elements */
668
669  ply_element_count (ply, "vertex", vsum);
670  ply_describe_property (ply, "vertex", &vert_props[0]);
671  ply_describe_property (ply, "vertex", &vert_props[1]);
672  ply_describe_property (ply, "vertex", &vert_props[2]);
673  ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props));
674
675  ply_element_count (ply, "face", fsum);
676  ply_describe_property (ply, "face", &face_props[0]);
677  ply_describe_other_properties (ply, face_other, offsetof(Face,other_props));
678
679  ply_describe_other_elements (ply, other_elements);
680
681  for (i = 0; i < num_comments; i++)
682    ply_put_comment (ply, comments[i]);
683
684  for (i = 0; i < num_obj_info; i++)
685    ply_put_obj_info (ply, obj_info[i]);
686
687  ply_header_complete (ply);
688
689  /* change the vertex indices from pointers to indices */
690
691  vcount = 0;
692  for (i = 0; i < nverts; i++)
693    if (vlist[i]->comp->vcount <= new_less)
694      vlist[i]->index = vcount++;
695
696  for (i = 0; i < nfaces; i++) {
697    verts = flist[i]->verts;
698    for (j = 0; j < flist[i]->nverts; j++)
699      verts[j] = (Vertex *) verts[j]->index;
700  }
701
702  /* set up and write the vertex elements */
703  ply_put_element_setup (ply, "vertex");
704  for (i = 0; i < nverts; i++)
705    if (vlist[i]->comp->vcount <= new_less)
706      ply_put_element (ply, (void *) vlist[i]);
707
708  /* set up and write the face elements */
709  ply_put_element_setup (ply, "face");
710  for (i = 0; i < nfaces; i++)
711    if (flist[i]->comp->vcount <= new_less)
712      ply_put_element (ply, (void *) flist[i]);
713
714  ply_put_other_elements (ply);
715
716  /* close the PLY file */
717  ply_close (ply);
718}
719
720
721/******************************************************************************
722Write out the PLY file to standard out.
723******************************************************************************/
724
725void
726write_file()
727{
728  int i,j,k;
729  PlyFile *ply;
730  int num_elems;
731
732  /*** Write out the transformed PLY object ***/
733
734
735  ply = ply_write (stdout, nelems, elem_names, file_type);
736
737
738  /* describe what properties go into the vertex and face elements */
739
740  ply_element_count (ply, "vertex", nverts);
741  ply_describe_property (ply, "vertex", &vert_props[0]);
742  ply_describe_property (ply, "vertex", &vert_props[1]);
743  ply_describe_property (ply, "vertex", &vert_props[2]);
744  ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props));
745
746  ply_element_count (ply, "face", nfaces);
747  ply_describe_property (ply, "face", &face_props[0]);
748  ply_describe_other_properties (ply, face_other, offsetof(Face,other_props));
749
750  ply_describe_other_elements (ply, other_elements);
751
752  for (i = 0; i < num_comments; i++)
753    ply_put_comment (ply, comments[i]);
754
755  for (i = 0; i < num_obj_info; i++)
756    ply_put_obj_info (ply, obj_info[i]);
757
758  ply_header_complete (ply);
759
760  /* set up and write the vertex elements */
761  ply_put_element_setup (ply, "vertex");
762  for (i = 0; i < nverts; i++)
763    ply_put_element (ply, (void *) vlist[i]);
764
765  /* set up and write the face elements */
766  ply_put_element_setup (ply, "face");
767  for (i = 0; i < nfaces; i++)
768    ply_put_element (ply, (void *) flist[i]);
769
770  ply_put_other_elements (ply);
771
772  /* close the PLY file */
773  ply_close (ply);
774}
775
Note: See TracBrowser for help on using the repository browser.