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

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

Added original make3d

File size: 8.4 KB
Line 
1/*
2
3Compute the volume of a mesh
4
5Sean Anderson, February 1999
6
7*/
8
9#include <assert.h>
10#include <stdio.h>
11#include <ply.h>
12#include <stdlib.h>
13#include <strings.h>
14#include <iostream>
15#include <limits.h>
16
17#include <Linear.h>
18
19#include <vector.h>
20
21//#include "plyio.h"
22
23
24typedef Vec3f PlyVertex;
25
26
27struct PlyFace
28{
29   uchar nverts;
30   int * verts;
31};
32
33struct PlyTriStrip
34{
35   int nverts;
36   int * verts;
37};
38
39#define MAX_VERT_PROPS 3
40
41static PlyProperty vert_prop_x = 
42{"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
43static PlyProperty vert_prop_y = 
44{"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
45static PlyProperty vert_prop_z = 
46{"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
47
48
49static PlyProperty vert_props[MAX_VERT_PROPS];
50
51
52static PlyProperty face_props[] = 
53{ 
54   {"vertex_indices", PLY_INT, PLY_INT, 0, 1, PLY_UCHAR, PLY_UCHAR, 0},
55};
56
57static PlyProperty tristrip_props[] = 
58{
59   {"vertex_indices", PLY_INT, PLY_INT, 0, 1, PLY_INT, PLY_INT},
60};
61
62#define voffset(field) ((int) &(((PlyVertex *) 0)->field))
63#define foffset(field) ((int) &(((PlyFace *) 0)->field))
64
65
66
67class Plane
68{
69public:
70   Plane()
71   {
72      n = Vec3f(0, 0, 1);
73      d = 0;
74   }
75   Vec3f n;
76   float d;
77};
78
79inline void
80computeFaceContribution(const vector<PlyVertex> & verts, 
81                        const PlyFace & plyFace, 
82                        const Plane & plane, 
83                        double * subvolume, 
84                        double * subarea)
85{
86   const int * v = plyFace.verts;
87   const int k = plyFace.nverts;
88   Vec3f area;     
89   float vol;
90   Vec3f avePt;
91   
92   if (k == 3) // Make the common case fast:  triangle
93   {
94      area = 0.5 * 
95         (verts[v[1]] - verts[v[0]]).cross(verts[v[2]] - verts[v[0]]);
96      avePt = (1. / 3) * (verts[v[0]] + verts[v[1]] + verts[v[2]]);     
97      vol = (plane.n.dot(avePt) - plane.d) * plane.n.dot(area);
98   }
99   else
100   {
101      area.clear();
102      vol = 0;
103      const Vec3f v0 = verts[v[0]];
104      for (int i = 0; i < k - 1; i++)
105      {
106         Vec3f a = (verts[v[i]] - v0).cross(verts[v[i + 1]] - v0);
107         area += a;
108         avePt = (1. / 3) * (v0 + verts[v[i]] + verts[v[i + 1]]);     
109         vol += (plane.n.dot(avePt) - plane.d) * plane.n.dot(a);
110      }
111      vol *= 0.5;
112      area *= 0.5;
113   }
114
115   if (subvolume)
116   {
117      *subvolume += vol;
118   }
119   if (subarea)
120   {
121      *subarea += area.length();
122   } 
123}
124           
125
126//
127// Read in data from the ply file and compute the volume and area of faces
128// with plane.  The volume and area contributions are ADDED to what was
129// passed in.
130//
131
132bool
133computeSignedVolume(FILE * fp, const Plane & plane, 
134                    double * volume, double * area)
135{
136   int     j;
137   int     nelems;
138   char ** elist;
139   int     file_type;
140   float   version;
141   char *  elem_name;
142   int     num_vert_props;
143   int     num_elems;
144   
145   vector<PlyVertex> verts;
146   
147   face_props[0].offset = foffset(verts);
148   face_props[0].count_offset = foffset(nverts);  /* count offset */
149   
150   PlyFile * ply = 
151      ply_read(fp, &nelems, &elist);
152
153   
154   if (!ply)
155   {
156      return true;
157   }
158
159   int nvp = 0;
160   
161   if (ply_is_valid_property(ply, "vertex", vert_prop_x.name)) 
162   {
163      vert_props[nvp] = vert_prop_x;
164      vert_props[nvp].offset = voffset(x); 
165      nvp++;
166   }
167   
168   if (ply_is_valid_property(ply, "vertex", vert_prop_y.name)) 
169   {
170      vert_props[nvp] = vert_prop_y;
171      vert_props[nvp].offset = voffset(y); 
172      nvp++;
173   }
174   
175   if (ply_is_valid_property(ply, "vertex", vert_prop_z.name)) 
176   {
177      vert_props[nvp] = vert_prop_z;
178      vert_props[nvp].offset = voffset(z); 
179      nvp++;
180   }
181   
182
183   num_vert_props = nvp;
184
185   PlyVertex plyVert;
186   PlyFace plyFace;
187   int faceIndicesMem[256];
188   plyFace.verts = faceIndicesMem;
189
190   for (int i = 0; i < nelems; i++) 
191   {
192      /* get the description of the first element */
193      elem_name = elist[i];
194      int nprops;
195      ply_get_element_description(ply, elem_name, &num_elems, &nprops);
196     
197      /* if we're on vertex elements, read them in */
198      if (equal_strings("vertex", elem_name)) 
199      {
200         /* set up for getting vertex elements */
201         ply_get_element_setup(ply, elem_name, num_vert_props, vert_props);
202         
203         cerr << "Reading vertices . . .\n";
204
205         int percent = -1;
206         
207         /* grab all the vertex elements */
208         for (j = 0; j < num_elems; j++) 
209         {
210            int newpercent = 100 * j / num_elems;
211            if (newpercent != percent)
212            {
213               cerr << "\r" << (percent = newpercent) << "% complete" ;
214               cerr.flush();
215            }
216           
217            ply_get_element_noalloc(ply, (void *) &plyVert);
218           
219            verts.push_back(plyVert);
220         }
221         
222         cerr << "\rDone.        \n";
223      } 
224      else if (equal_strings("face", elem_name)) 
225      {     
226         ply_get_element_setup(ply, elem_name, 1, face_props);
227         
228         if (num_elems == 0)
229         {
230            continue;
231         }
232
233         cerr << "Reading faces . . .\n";
234         
235         if (verts.size() == 0)
236         {
237            cerr << "No vertices read yet; can't read faces\n";
238            continue;
239         }
240         
241         int percent = -1;
242         
243         for (j = 0; j < num_elems; j++) 
244         {             
245            int newpercent = 100 * j / num_elems;
246            if (newpercent != percent)
247            {
248               cerr << "\r" << (percent = newpercent) << "% complete";
249               cerr.flush();
250            }
251           
252            ply_get_element_noalloc(ply, (void *) &plyFace);
253            assert(plyFace.verts == faceIndicesMem);
254           
255            computeFaceContribution(verts, plyFace, plane, volume, area);
256             
257            //faces->push_back(plyFace);
258         }
259         
260         cerr << "\rDone.        \n";
261      }
262      else if (equal_strings("tristrips", elem_name)) 
263      {     
264         ply_get_element_setup(ply, elem_name, 1, tristrip_props);
265         
266         if (num_elems == 0)
267         {
268            continue;
269         }
270                 
271         cerr << "Reading tristrips . . .\n";
272         
273         if (verts.size() == 0)
274         {
275            cerr << "No vertices read yet; can't read tristrip\n";
276            continue;
277         }
278         
279         PlyTriStrip plyTriStrip;
280         
281         for (j = 0; j < num_elems; j++) 
282         {
283            ply_get_element(ply, (void *) &plyTriStrip);
284           
285            int percent = -1;
286         
287            bool clockwise = false;
288            for (int k = 2; k < plyTriStrip.nverts; )
289            {
290               int newpercent = 100 * j / num_elems;
291               if (newpercent != percent)
292               {
293                  cerr << "\r" << (percent = newpercent) << "% complete";
294                  cerr.flush();
295               }
296           
297               plyFace.nverts = 3;
298               //plyFace.verts = new int[3];
299               plyFace.verts[0]             = plyTriStrip.verts[k - 2];
300               plyFace.verts[1 + clockwise] = plyTriStrip.verts[k - 1];
301               plyFace.verts[2 - clockwise] = plyTriStrip.verts[k - 0];
302
303               computeFaceContribution(verts, plyFace, plane, 
304                                       volume, area);
305               
306               //faces->push_back(plyFace);           
307               
308               clockwise = !clockwise;
309
310               k++;
311
312               if (k < plyTriStrip.nverts && plyTriStrip.verts[k] == -1)
313               {
314                  k += 3;
315                  clockwise = false;
316               }
317            }
318           
319            free(plyTriStrip.verts);
320         }
321         
322         cerr << "\rDone.        \n";
323      }
324   }
325
326   ply_close(ply);
327
328   return false;
329}
330
331void
332printUsage(const char * name)
333{
334   cerr << "Usage:\n"
335        << "  " << name
336        << " -h | [-p nx ny nz d] (- | file1.ply [file2.ply [...]])\n"
337        << "where:\n"
338        << "  -h         Displays this help\n"
339        << "  -p         Specifies a plane to use as the base; \n"
340           "             the plane has normal (nx, ny, nz) and is distance \n"
341           "             d from the origin in the normal's direction\n"
342        << "  -          Reads one ply file from standard input\n"
343        << "  file.ply   Is a ply file whose volume is added to the total.\n";
344}
345
346int 
347main(int argc, char * argv[])
348{
349   double volume = 0, area = 0;
350   Plane plane;
351   
352   for (int c = 1; c < argc; c++)
353   {
354      if (!strcmp("-h", argv[c]))
355      {
356         printUsage(argv[0]);
357         return 1;
358      }
359      else if (!strcmp("-p", argv[c]))
360      {
361         if (c + 4 >= argc)
362         {
363            cerr << "Insufficient parameters for plane description\n";
364            return 1;
365         }
366         else
367         {
368            plane.n.x = atof(argv[c + 1]);
369            plane.n.y = atof(argv[c + 2]);
370            plane.n.z = atof(argv[c + 3]);
371            plane.= atof(argv[c + 4]);
372            c += 4;
373         }
374      }
375      else if (!strcmp("-", argv[c]))
376      {
377         cerr << "stdin:\n";
378         if (computeSignedVolume(stdin, plane, &volume, &area))
379         {
380            cerr << "Couldn't read ply file from stdin\n";
381         }
382      }
383      else
384      {
385         cerr << argv[c] << ":\n";
386         FILE * fp = fopen(argv[c], "r");
387         if (!fp)
388         {
389            cerr << "Couldn't open file '" << argv[c] << "'\n";
390         }
391         else
392         {
393            if (computeSignedVolume(fp, plane, &volume, &area))
394            {
395               cerr << "Couldn't read ply file '" << argv[c] << "'\n";
396            }
397            fclose(fp);
398         }
399      }
400   }
401   
402   //cout.flags(ios::fixed);
403   cout.precision(10);
404   cout << "Volume:  " << volume << endl
405        << "Area:  " << area << endl;
406   
407   return 0;
408}
Note: See TracBrowser for help on using the repository browser.