polyhedron.c
Go to the documentation of this file.
1 #include "polyhedron.h"
2 
3 #include "htransform.h"
4 #include "error.h"
5 #include "algebra.h"
6 #include "geom.h"
7 #include "boolean.h"
8 
9 #include <stdio.h>
10 #include <math.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <xlocale.h>
14 #include <sys/stat.h>
15 
16 #if (_ASSIMP)
17  #include <assimp/cimport.h>
18  #include <assimp/scene.h>
19  #include <assimp/postprocess.h>
20 #endif
21 
40 boolean ReadGeneralMesh(char *fn,Tpolyhedron *p);
41 
53 void ReadSTL(char *fn,Tpolyhedron *p);
54 
65 void ReadOFF(FILE *f,Tpolyhedron *p);
66 
81 void GenerateCylinderOFF(unsigned int g,Tpolyhedron *p);
82 
93 void ReadLine(FILE *f,Tpolyhedron *p);
94 
105 void ReadSegments(FILE *f,Tpolyhedron *p);
106 
119 void ReadCylinder(FILE *f,unsigned int g,Tpolyhedron *p);
120 
135 void GenerateSphereOFF(unsigned int g,Tpolyhedron *p);
136 
149 void ReadSphere(FILE *f,unsigned int g,Tpolyhedron *p);
150 
151 #if (_ASSIMP)
152 
165 void ProcessSceneNode(unsigned int *oV,unsigned int *oF,
166  Tpolyhedron *p,const struct aiScene *sc,const struct aiNode *nd);
167 
168 void ProcessSceneNode(unsigned int *oV,unsigned int *oF,
169  Tpolyhedron *p,const struct aiScene *sc,const struct aiNode *nd)
170 {
171  unsigned int i,j,k;
172  THTransform tr;
173  const struct aiMesh *mesh;
174  unsigned int ndxV,ndxF;
175 
176  /* Get the transform for this node */
177  HTransformSetElement(0,0,nd->mTransformation.a1,&tr);
178  HTransformSetElement(0,1,nd->mTransformation.a2,&tr);
179  HTransformSetElement(0,2,nd->mTransformation.a3,&tr);
180  HTransformSetElement(0,3,nd->mTransformation.a4,&tr);
181 
182  HTransformSetElement(1,0,nd->mTransformation.b1,&tr);
183  HTransformSetElement(1,1,nd->mTransformation.b2,&tr);
184  HTransformSetElement(1,2,nd->mTransformation.b3,&tr);
185  HTransformSetElement(1,3,nd->mTransformation.b4,&tr);
186 
187  HTransformSetElement(2,0,nd->mTransformation.c1,&tr);
188  HTransformSetElement(2,1,nd->mTransformation.c2,&tr);
189  HTransformSetElement(2,2,nd->mTransformation.c3,&tr);
190  HTransformSetElement(2,3,nd->mTransformation.c4,&tr);
191 
192  HTransformSetElement(3,0,nd->mTransformation.d1,&tr);
193  HTransformSetElement(3,1,nd->mTransformation.d2,&tr);
194  HTransformSetElement(3,2,nd->mTransformation.d3,&tr);
195  HTransformSetElement(3,3,nd->mTransformation.d4,&tr);
196 
197  /* Add the meshes to the polyhedron structure */
198  for(k=0;k<nd->mNumMeshes;k++)
199  {
200  mesh=sc->mMeshes[nd->mMeshes[k]];
201 
202  for(i=0;i<mesh->mNumVertices;i++)
203  {
204  ndxV=(*oV)+i;
205  NEW(p->v[ndxV],3,double);
206  p->v[ndxV][0]=(double)mesh->mVertices[i].x;
207  p->v[ndxV][1]=(double)mesh->mVertices[i].y;
208  p->v[ndxV][2]=(double)mesh->mVertices[i].z;
209 
210  HTransformApply(p->v[ndxV],p->v[ndxV],&tr);
211  }
212 
213  for(i=0;i<mesh->mNumFaces;i++)
214  {
215  ndxF=(*oF)+i;
216  p->nvf[ndxF]=mesh->mFaces[i].mNumIndices;
217  NEW(p->fv[ndxF],p->nvf[i],unsigned int);
218  for(j=0;j<p->nvf[ndxF];j++)
219  p->fv[ndxF][j]=((*oV)+mesh->mFaces[i].mIndices[j]);
220  }
221  (*oV)+=mesh->mNumVertices;
222  (*oF)+=mesh->mNumFaces;
223  }
224 
225  /* Recursively process the child nodes */
226  for(i=0;i<nd->mNumChildren;i++)
227  ProcessSceneNode(oV,oF,p,sc,nd->mChildren[i]);
228 }
229 #endif
230 
231 boolean ReadGeneralMesh(char *fn,Tpolyhedron *p)
232 {
233  boolean ok=FALSE;
234 
235  #if (_ASSIMP)
236  const struct aiScene *sc;
237 
238  /* We triangulate (as required by some collision detection
239  engines). */
240  sc=aiImportFile(fn,aiProcess_Triangulate);
241 
242  if ((sc)&&(sc->mNumMeshes>0))
243  {
244  const struct aiMesh *mesh;
245  unsigned int k,oV,oF;
246 
247  p->type=OFF;
248 
249  ok=TRUE;
250 
251  /* Count the total number of vertices and faces
252  in the scene. */
253  p->nv=0;
254  p->nf=0;
255  for(k=0;k<sc->mNumMeshes;k++)
256  {
257  mesh=sc->mMeshes[k];
258 
259  p->nv+=mesh->mNumVertices;
260  p->nf+=mesh->mNumFaces;
261 
262  }
263  p->ne=0;/* Number of edges not used */
264 
265  /* allocate enough space for all the vertices */
266  NEW(p->v,p->nv,double*);
267  /* allocate space for all the faces */
268  NEW(p->nvf,p->nf,unsigned int);
269  NEW(p->fv,p->nf,unsigned int*);
270 
271  /* Recursively process all the nodes in the scene */
272  oV=0;
273  oF=0;
274  ProcessSceneNode(&oV,&oF,p,sc,sc->mRootNode);
275 
276  aiReleaseImport(sc);
277  }
278  else
279  Error("Error reading the geometry file");
280  #else
281  Error("The assimp library is missing");
282  #endif
283 
284  return(ok);
285 }
286 
287 void ReadSTL(char *fn,Tpolyhedron *p)
288 {
289  char header[75];
290  short int u;
291  float v[3];
292  double vd[3];
293  unsigned int nt,i,j,k;
294  boolean found;
295  FILE *f;
296 
297  f=fopen(fn,"rb");
298  if (!f)
299  Error("Can not open STL file");
300 
301  p->type=OFF;
302 
303  fread(header,sizeof(char),5,f);
304  header[5]=0;
305  if (strcasecmp(header,"SOLID")==0)
306  Error("Can not read ASCII STL files yet");
307  /* skip the rest of the header */
308  fread(header,sizeof(char),75,f);
309 
310  /* read the number of triangles */
311  fread(&nt,sizeof(int),1,f);
312 
313  p->nv=0; /* this will be increased as needed */
314  p->nf=nt;
315  p->ne=0; /* not used */
316 
317  /* allocate enough space for all the vertices */
318  NEW(p->v,nt,double*);
319 
320  /* and for all the faces */
321  NEW(p->nvf,nt,unsigned int);
322  NEW(p->fv,nt,unsigned int*);
323 
324  for(i=0;i<nt;i++)
325  {
326  /* skip the normal */
327  fread(v,sizeof(float),3,f);
328 
329  p->nvf[i]=3; /* all faces have 3 vertices */
330  NEW(p->fv[i],p->nvf[i],unsigned int);
331 
332  for(j=0;j<3;j++)
333  {
334  /* read the vertex and convert it to double */
335  fread(v,sizeof(float),3,f);
336  vd[0]=(double)v[0];
337  vd[1]=(double)v[1];
338  vd[2]=(double)v[2];
339 
340  /* Check if we already have this vertex (with 1e-3 accuracy) */
341  found=FALSE;
342  k=0;
343  while((!found)&&(k<p->nv))
344  {
345  found=(Distance(3,vd,p->v[k])<1e-3);
346  if (!found) k++;
347  }
348  if (!found)
349  {
350  /* k==p->nv */
351  NEW(p->v[k],3,double);
352  p->v[k][0]=vd[0];
353  p->v[k][1]=vd[1];
354  p->v[k][2]=vd[2];
355  p->nv++;
356  }
357  p->fv[i][j]=k;
358  }
359 
360  /* skip the tail (supposed to be 0 always) */
361  fread(&u,sizeof(short),1,f);
362  }
363  fclose(f);
364 }
365 
366 void ReadOFF(FILE *f,Tpolyhedron *p)
367 {
368  unsigned int i,j;
369  double av;
370 
371  p->type=OFF;
372 
373  fscanf(f,"%u",&(p->nv));
374  fscanf(f,"%u",&(p->nf));
375  fscanf(f,"%u",&(p->ne));
376  if ((p->nv==0)||(p->nf==0))
377  Error("Empty OFF");
378 
379  NEW(p->v,p->nv,double*);
380  for(i=0;i<p->nv;i++)
381  {
382  NEW(p->v[i],3,double);
383  fscanf(f,"%lf",&(p->v[i][0]));
384  fscanf(f,"%lf",&(p->v[i][1]));
385  fscanf(f,"%lf",&(p->v[i][2]));
386  }
387 
388  NEW(p->nvf,p->nf,unsigned int);
389  NEW(p->fv,p->nf,unsigned int*);
390  for(i=0;i<p->nf;i++)
391  {
392  fscanf(f,"%u",&(p->nvf[i]));
393  if (p->nvf[i]==0)
394  Error("Empty face in OFF");
395  NEW(p->fv[i],p->nvf[i],unsigned int);
396 
397  for(j=0;j<p->nvf[i];j++)
398  fscanf(f,"%u",&(p->fv[i][j]));
399  }
400 
401  /* Cancel the sphere information */
402  p->rad=0;
403  p->center[0]=p->center[1]=p->center[2]=0.0;
404 
405  /* and the cylinder information too */
406  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
407  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
408 
409  /* Compute the bounding box */
410  p->maxCoord=0;
411  for(i=0;i<p->nv;i++)
412  {
413  for(j=0;j<3;j++)
414  {
415  av=fabs(p->v[i][j]);
416  if (av>p->maxCoord)
417  p->maxCoord=av;
418  }
419  }
420 }
421 
422 void GenerateCylinderOFF(unsigned int g,Tpolyhedron *p)
423 {
424  unsigned int i,j,k,n;
425  THTransform m;
426  double a,av;
427 
428  if ((p->type!=CYLINDER)&&(p->type!=LINE))
429  Error("Using GenerateCylinderOFF in a non cylindric/line convex polyhedron");
430 
431  /*The points are defined on the reference cylinder (aligned along axis X
432  and with length 1 and radii 1) that is later on scaled and enlarged */
433  n=4+g;
434  p->nv=2*n;
435  NEW(p->v,p->nv,double*);
436  for(i=0;i<n;i++)
437  {
438  NEW(p->v[i],3,double);
439  NEW(p->v[n+i],3,double);
440 
441  p->v[i][0]=0;
442  p->v[n+i][0]=1;
443 
444  a=((double)i/(double)n)*M_2PI;
445  p->v[i][1]=p->v[n+i][1]=cos(a);
446  p->v[i][2]=p->v[n+i][2]=sin(a);
447  }
448 
449  /*Now rotate the points according to the cylinder orientation defined by p1,p2*/
450  HTransformX2Vect(p->rad,p->rad,p->p1,p->p2,&m);
451 
452  for(i=0;i<p->nv;i++)
453  HTransformApply(p->v[i],p->v[i],&m);
454 
455  HTransformDelete(&m);
456 
457  /* face information */
458  p->nf=n+2*(n-2);
459  p->ne=0; /* not used */
460 
461  NEW(p->nvf,p->nf,unsigned int);
462  NEW(p->fv,p->nf,unsigned int*);
463  /* lateral faces */
464  for(i=0;i<n;i++)
465  {
466  j=(i+1)%n;
467 
468  p->nvf[i]=4;
469  NEW(p->fv[i],4,unsigned int);
470  p->fv[i][0]=i;
471  p->fv[i][1]=i+n;
472  p->fv[i][2]=j+n;
473  p->fv[i][3]=j;
474  }
475  /* up faces */
476  for(i=2;i<n;i++)
477  {
478  k=n+i-2;
479  p->nvf[k]=3;
480  NEW(p->fv[k],3,unsigned int);
481  p->fv[k][0]=n+0;
482  p->fv[k][1]=n+i;
483  p->fv[k][2]=n+i-1;
484  }
485  for(i=2;i<n;i++)
486  {
487  k=n+(n-2)+i-2;
488  p->nvf[k]=3;
489  NEW(p->fv[k],3,unsigned int);
490  p->fv[k][0]=i-1;
491  p->fv[k][1]=i;
492  p->fv[k][2]=0;
493  }
494 
495  /* Compute the bounding box using the points that approximate the cylinder */
496  p->maxCoord=0;
497  for(i=0;i<p->nv;i++)
498  {
499  for(j=0;j<3;j++)
500  {
501  av=fabs(p->v[i][j]);
502  if (av>p->maxCoord)
503  p->maxCoord=av;
504  }
505  }
506 }
507 
508 void ReadLine(FILE *f,Tpolyhedron *p)
509 {
510  p->type=LINE;
511 
512  p->rad=0.01;
513 
514  fscanf(f,"%lf",&(p->p1[0]));
515  fscanf(f,"%lf",&(p->p1[1]));
516  fscanf(f,"%lf",&(p->p1[2]));
517 
518  fscanf(f,"%lf",&(p->p2[0]));
519  fscanf(f,"%lf",&(p->p2[1]));
520  fscanf(f,"%lf",&(p->p2[2]));
521 
522  /*Cancel sphere information*/
523  p->center[0]=p->center[1]=p->center[2]=0.0;
524 
525  /*Generate the OFF information*/
526  GenerateCylinderOFF(0,p);
527 }
528 
529 void ReadSegments(FILE *f,Tpolyhedron *p)
530 {
531  unsigned int i,j;
532  double av;
533 
534  p->type=SEGMENTS;
535 
536  fscanf(f,"%u",&(p->nv));
537 
538  NEW(p->v,p->nv,double*);
539  for(i=0;i<p->nv;i++)
540  {
541  NEW(p->v[i],3,double);
542  fscanf(f,"%lf",&(p->v[i][0]));
543  fscanf(f,"%lf",&(p->v[i][1]));
544  fscanf(f,"%lf",&(p->v[i][2]));
545  }
546  /* Compute the bounding box */
547  p->maxCoord=0;
548  for(i=0;i<p->nv;i++)
549  {
550  for(j=0;j<3;j++)
551  {
552  av=fabs(p->v[i][j]);
553  if (av>p->maxCoord)
554  p->maxCoord=av;
555  }
556  }
557 
558  /*Cancel sphere information*/
559  p->center[0]=p->center[1]=p->center[2]=0.0;
560 
561  /* Cancel cylinder/line info */
562  p->rad=0;
563  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
564  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
565 
566  /*Cancel OFF information*/
567  p->nf=0;
568  p->nvf=0;
569  p->ne=0;
570 }
571 
572 void ReadCylinder(FILE *f,unsigned int g,Tpolyhedron *p)
573 {
574  p->type=CYLINDER;
575 
576  fscanf(f,"%lf",&(p->rad));
577 
578  fscanf(f,"%lf",&(p->p1[0]));
579  fscanf(f,"%lf",&(p->p1[1]));
580  fscanf(f,"%lf",&(p->p1[2]));
581 
582  fscanf(f,"%lf",&(p->p2[0]));
583  fscanf(f,"%lf",&(p->p2[1]));
584  fscanf(f,"%lf",&(p->p2[2]));
585 
586  /*Cancel sphere information*/
587  p->center[0]=p->center[1]=p->center[2]=0.0;
588 
589  /*Generate the OFF information*/
590  GenerateCylinderOFF(g,p);
591 }
592 
593 void GenerateSphereOFF(unsigned int g,Tpolyhedron *p)
594 {
595  unsigned int i,j,k,in,r1,r2,n,m;
596  double **meridian;
597  THTransform tr,t;
598  double a,offset,av;
599 
600  if (p->type!=SPHERE)
601  Error("Using GenerateSphereOFF in a non spheric convex polyhedron");
602 
603  /*Vertex information for collision avoidance (in the future refined according to 'g')*/
604  n=3+g;
605  m=4+g;
606 
607  offset=M_PI/((double)n-1);
608  a=-M_PI_2;
609 
610  NEW(meridian,n,double*);
611  for(i=0;i<n;i++)
612  {
613  NEW(meridian[i],3,double);
614  meridian[i][0]=p->rad*cos(a);
615  meridian[i][1]=0.0;
616  meridian[i][2]=p->rad*sin(a);
617 
618  a+=offset;
619  }
620 
621  p->nv=n*m;
622  NEW(p->v,p->nv,double*);
623  for(i=0;i<p->nv;i++)
624  NEW(p->v[i],3,double);
625 
626  a=0.0;
627  offset=M_2PI/(double)m;
628 
629  HTransformTxyz(p->center[0],p->center[1],p->center[2],&t);
630  for(j=0;j<m;j++)
631  {
632  HTransformRz(a,&tr);
633  HTransformProduct(&t,&tr,&tr);
634  for(i=0;i<n;i++)
635  HTransformApply(meridian[i],p->v[j*n+i],&tr);
636 
637  a+=offset;
638 
639  HTransformDelete(&tr);
640  }
641  HTransformDelete(&t);
642 
643  for(i=0;i<n;i++)
644  free(meridian[i]);
645  free(meridian);
646 
647  /* face information */
648  p->nf=m*(n-2)+m;
649  p->ne=0; /* not used */
650 
651  NEW(p->nvf,p->nf,unsigned int);
652  NEW(p->fv,p->nf,unsigned int*);
653  k=0;
654  for(j=0;j<m;j++) /* for each meridian */
655  {
656  r1=j*n; //first point in this meridian
657  r2=((j+1)%m)*n; //first point in next meridian
658 
659  for(i=0;i<n-1;i++) /* for each point in the meridian */
660  {
661  in=i+1; // Next point in meridian. Never goes to 0 (i<n-1)
662 
663  // Define a face
664  if (i==0)
665  {
666  p->nvf[k]=3;
667  NEW(p->fv[k],3,unsigned int);
668  p->fv[k][0]=r1+i; // == r2+i
669  p->fv[k][1]=r2+in;
670  p->fv[k][2]=r1+in;
671  }
672  else
673  {
674  if (i==(n-2))
675  {
676  p->nvf[k]=3;
677  NEW(p->fv[k],3,unsigned int);
678  p->fv[k][0]=r1+i;
679  p->fv[k][1]=r2+i;
680  p->fv[k][2]=r1+in; // == r2+in
681  }
682  else
683  {
684  p->nvf[k]=4;
685  NEW(p->fv[k],4,unsigned int);
686  p->fv[k][0]=r1+i;
687  p->fv[k][1]=r2+i;
688  p->fv[k][2]=r2+in;
689  p->fv[k][3]=r1+in;
690  }
691  }
692  k++;
693  }
694  }
695 
696  /* Compute the bounding box using the points that approximate the sphere */
697  p->maxCoord=0;
698  for(i=0;i<p->nv;i++)
699  {
700  for(j=0;j<3;j++)
701  {
702  av=fabs(p->v[i][j]);
703  if (av>p->maxCoord)
704  p->maxCoord=av;
705  }
706  }
707 }
708 
709 void ReadSphere(FILE *f,unsigned int g,Tpolyhedron *p)
710 {
711  p->type=SPHERE;
712 
713  fscanf(f,"%lf",&(p->rad));
714 
715  fscanf(f,"%lf",&(p->center[0]));
716  fscanf(f,"%lf",&(p->center[1]));
717  fscanf(f,"%lf",&(p->center[2]));
718 
719  /*Cancel cylinder information*/
720  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
721  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
722 
723  /*Generate the OFF information*/
724  GenerateSphereOFF(g,p);
725 }
726 
728  unsigned int gr,unsigned int bs,Tpolyhedron *p)
729 {
730  char *ext;
731 
732  p->status=bs; /* normal, hidden, decoration*/
733 
734  if (bs==HIDDEN_SHAPE)
735  NewColor(1.0,1.0,1.0,c); /* for hidden shapes we use a default color */
736  else
737  CopyColor(&(p->color),c);
738 
739  p->obj3d=NO_UINT;
740 
741  ext=GetFileExtension(fname);
742  if ((ext==NULL)||(strcasecmp(ext,"OFF")==0))
743  {
744  /* Note that the CuikSuite uses and extended OFF
745  files which can also include the definition of
746  cylinders, spheres, lines, or sets of segments.
747  */
748  FILE *f;
749  char *stmp;
750  boolean off, cylinder,sphere,line,segments;
751 
752  NEW(stmp,20,char); /* 20 is enough to read OFF/SPHERE/CYLINDER */
753 
754  f=fopen(GetFileFullName(fname),"r");
755  if (!f)
756  Error("Could not open Polyhedron file");
757 
758  fscanf(f,"%s",stmp); /* OFF -> skip it */
759 
760  off=(strcasecmp(stmp,"OFF")==0);
761  cylinder=(strcasecmp(stmp,"CYLINDER")==0);
762  sphere=(strcasecmp(stmp,"SPHERE")==0);
763  line=(strcasecmp(stmp,"LINE")==0);
764  segments=(strcasecmp(stmp,"SEGMENTS")==0);
765 
766  if ((!off)&&(!cylinder)&&(!sphere)&&(!line)&&(!segments))
767  Error("Unknow type of shape");
768 
769  if (off)
770  ReadOFF(f,p);
771 
772  if (cylinder)
773  ReadCylinder(f,gr,p);
774 
775  if (line)
776  ReadLine(f,p);
777 
778  if (segments)
779  ReadSegments(f,p);
780 
781  if (sphere)
782  ReadSphere(f,gr,p);
783 
784  free(stmp);
785  fclose(f);
786  }
787  else
788  {
789  #if (_ASSIMP)
790  if (!ReadGeneralMesh(GetFileFullName(fname),p))
791  Error("Error reading geometry from file in InitPolyhedronFromFile");
792  #else
793  if (strcasecmp(ext,"STL")==0)
794  ReadSTL(GetFileFullName(fname),p);
795  else
796  Error("Unknown file type in InitPolyhedronFromFile. Try compiling with the Assimp library");
797  #endif
798  }
799 }
800 
801 void InitPolyhedronFromTriangles(unsigned int nv,double **v,
802  unsigned int nt,unsigned int **t,
803  Tcolor *c,unsigned int bs,Tpolyhedron *p)
804 {
805  unsigned int i,j;
806  double av;
807 
808  p->type=OFF;
809 
810  p->status=bs; /* normal, hidden, decoration*/
811  CopyColor(&(p->color),c);
812  p->obj3d=NO_UINT;
813 
814  p->nv=nv;
815  p->nf=nt;
816  p->ne=3*nt; /* not used */
817 
818  NEW(p->v,p->nv,double*);
819  for(i=0;i<p->nv;i++)
820  {
821  NEW(p->v[i],3,double);
822  for(j=0;j<3;j++)
823  p->v[i][j]=v[i][j];
824  }
825 
826  NEW(p->nvf,p->nf,unsigned int);
827  NEW(p->fv,p->nf,unsigned int*);
828  for(i=0;i<p->nf;i++)
829  {
830  p->nvf[i]=3; /* three vertices per face */
831  NEW(p->fv[i],p->nvf[i],unsigned int);
832  for(j=0;j<3;j++)
833  p->fv[i][j]=t[i][j];
834  }
835 
836  /* Cancel the sphere information */
837  p->rad=0;
838  p->center[0]=p->center[1]=p->center[2]=0.0;
839 
840  /* and the cylinder information too */
841  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
842  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
843 
844  /* Compute the bounding box */
845  p->maxCoord=0;
846  for(i=0;i<p->nv;i++)
847  {
848  for(j=0;j<3;j++)
849  {
850  av=fabs(p->v[i][j]);
851  if (av>p->maxCoord)
852  p->maxCoord=av;
853  }
854  }
855 }
857 {
858  return(p->type==EMPTY_BODY);
859 }
860 
861 void NewTriangularPrism(double *p1,double *p2,double *p3,
862  double h,
863  Tcolor *c,unsigned int bs,Tpolyhedron *p)
864 {
865  unsigned int i,j;
866  double av;
867  double n[3];
868  double pt1[3],pt2[3],pt3[3];
869 
870  p->type=OFF;
871 
872  p->status=bs; /* normal, hidden, decoration*/
873  CopyColor(&(p->color),c);
874  p->obj3d=NO_UINT;
875 
876  p->nv=6;
877  p->nf=5;
878  p->ne=9; /* not used */
879 
880  NEW(p->v,p->nv,double*);
881  for(i=0;i<p->nv;i++)
882  NEW(p->v[i],3,double);
883 
884  DifferenceVector(3,p2,p1,pt1);
885  DifferenceVector(3,p3,p1,pt2);
886  CrossProduct(pt1,pt2,n);
887  Normalize(3,n);
888  SumVectorScale(3,p1,h,n,pt1);
889  SumVectorScale(3,p2,h,n,pt2);
890  SumVectorScale(3,p3,h,n,pt3);
891 
892  for(i=0;i<3;i++)
893  {
894  p->v[0][i]=p1[i];
895  p->v[1][i]=p2[i];
896  p->v[2][i]=p3[i];
897  p->v[3][i]=pt1[i];
898  p->v[4][i]=pt2[i];
899  p->v[5][i]=pt3[i];
900  }
901 
902  NEW(p->nvf,p->nf,unsigned int);
903  NEW(p->fv,p->nf,unsigned int*);
904 
905  p->nvf[0]=3;
906  NEW(p->fv[0],p->nvf[0],unsigned int);
907  p->fv[0][0]=0; p->fv[0][1]=1; p->fv[0][2]=2;
908 
909  p->nvf[1]=3;
910  NEW(p->fv[1],p->nvf[1],unsigned int);
911  p->fv[1][0]=5; p->fv[1][1]=4; p->fv[1][2]=3;
912 
913  p->nvf[2]=4;
914  NEW(p->fv[2],p->nvf[2],unsigned int);
915  p->fv[2][0]=3; p->fv[2][1]=4; p->fv[2][2]=1; p->fv[2][3]=0;
916 
917  p->nvf[3]=4;
918  NEW(p->fv[3],p->nvf[3],unsigned int);
919  p->fv[3][0]=4; p->fv[3][1]=5; p->fv[3][2]=2; p->fv[3][3]=1;
920 
921  p->nvf[4]=4;
922  NEW(p->fv[4],p->nvf[4],unsigned int);
923  p->fv[4][0]=5; p->fv[4][1]=3; p->fv[4][2]=0; p->fv[4][3]=2;
924 
925  /* Cancel the sphere information */
926  p->rad=0;
927  p->center[0]=p->center[1]=p->center[2]=0.0;
928 
929  /* and the cylinder information too */
930  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
931  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
932 
933  /* Compute the bounding box */
934  p->maxCoord=0;
935  for(i=0;i<p->nv;i++)
936  {
937  for(j=0;j<3;j++)
938  {
939  av=fabs(p->v[i][j]);
940  if (av>p->maxCoord)
941  p->maxCoord=av;
942  }
943  }
944 }
945 
946 void NewBox(double xl,double yl,double zl,
947  double xu,double yu,double zu,
948  Tcolor *c,unsigned int bs,Tpolyhedron *p)
949 {
950  unsigned int i,j;
951  double av;
952 
953  if ((xu<xl)||(yu<yl)||(zu<zl))
954  Error("Incorrect ranges in the box definition");
955 
956  if ((xu==xl)&&(yu==yl)&&(zu==zl))
957  p->type=EMPTY_BODY;
958  else
959  {
960  p->type=OFF;
961 
962  p->status=bs; /* normal, hidden, decoration*/
963  CopyColor(&(p->color),c);
964  p->obj3d=NO_UINT;
965 
966  p->nv=8;
967  p->nf=6;
968  p->ne=12; /* not used */
969 
970  NEW(p->v,p->nv,double*);
971  for(i=0;i<p->nv;i++)
972  NEW(p->v[i],3,double);
973 
974  p->v[0][0]=xl; p->v[0][1]=yl; p->v[0][2]=zl;
975  p->v[1][0]=xl; p->v[1][1]=yu; p->v[1][2]=zl;
976  p->v[2][0]=xu; p->v[2][1]=yu; p->v[2][2]=zl;
977  p->v[3][0]=xu; p->v[3][1]=yl; p->v[3][2]=zl;
978  p->v[4][0]=xl; p->v[4][1]=yl; p->v[4][2]=zu;
979  p->v[5][0]=xl; p->v[5][1]=yu; p->v[5][2]=zu;
980  p->v[6][0]=xu; p->v[6][1]=yu; p->v[6][2]=zu;
981  p->v[7][0]=xu; p->v[7][1]=yl; p->v[7][2]=zu;
982 
983  NEW(p->nvf,p->nf,unsigned int);
984  NEW(p->fv,p->nf,unsigned int*);
985  for(i=0;i<p->nf;i++)
986  {
987  p->nvf[i]=4; /* four vertices per face */
988  NEW(p->fv[i],p->nvf[i],unsigned int);
989  }
990 
991  p->fv[0][0]=0; p->fv[0][1]=1; p->fv[0][2]=2; p->fv[0][3]=3;
992  p->fv[1][0]=6; p->fv[1][1]=5; p->fv[1][2]=4; p->fv[1][3]=7;
993  p->fv[2][0]=3; p->fv[2][1]=2; p->fv[2][2]=6; p->fv[2][3]=7;
994  p->fv[3][0]=2; p->fv[3][1]=1; p->fv[3][2]=5; p->fv[3][3]=6;
995  p->fv[4][0]=4; p->fv[4][1]=5; p->fv[4][2]=1; p->fv[4][3]=0;
996  p->fv[5][0]=3; p->fv[5][1]=0; p->fv[5][2]=4; p->fv[5][3]=7;
997 
998  /* Cancel the sphere information */
999  p->rad=0;
1000  p->center[0]=p->center[1]=p->center[2]=0.0;
1001 
1002  /* and the cylinder information too */
1003  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
1004  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
1005 
1006  /* Compute the bounding box */
1007  p->maxCoord=0;
1008  for(i=0;i<p->nv;i++)
1009  {
1010  for(j=0;j<3;j++)
1011  {
1012  av=fabs(p->v[i][j]);
1013  if (av>p->maxCoord)
1014  p->maxCoord=av;
1015  }
1016  }
1017  }
1018 }
1019 
1020 void NewSphere(double r,double *center,Tcolor *c,
1021  unsigned int gr,unsigned int bs,Tpolyhedron *p)
1022 {
1023  p->type=SPHERE;
1024  p->status=bs; /* normal, hidden, decoration*/
1025 
1026  CopyColor(&(p->color),c);
1027  p->obj3d=NO_UINT;
1028 
1029  /*Set the sphere information*/
1030  p->rad=r;
1031 
1032  p->center[0]=center[0];
1033  p->center[1]=center[1];
1034  p->center[2]=center[2];
1035 
1036  /*Cancel cylinder information*/
1037  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
1038  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
1039 
1040  /*Generate the OFF information*/
1041  GenerateSphereOFF(gr,p);
1042 }
1043 
1044 void NewCylinder(double r,double *p1,double *p2,Tcolor *c,
1045  unsigned int gr,unsigned int bs,Tpolyhedron *p)
1046 {
1047  p->type=CYLINDER;
1048  p->status=bs; /* normal, hidden, decoration*/
1049 
1050  CopyColor(&(p->color),c);
1051  p->obj3d=NO_UINT;
1052 
1053  /*Set the cylinder information*/
1054  p->rad=r;
1055 
1056  p->p1[0]=p1[0];
1057  p->p1[1]=p1[1];
1058  p->p1[2]=p1[2];
1059 
1060  p->p2[0]=p2[0];
1061  p->p2[1]=p2[1];
1062  p->p2[2]=p2[2];
1063 
1064  /*Cancel sphere information*/
1065  p->center[0]=p->center[1]=p->center[2]=0.0;
1066 
1067  /*Generate the OFF information*/
1068  GenerateCylinderOFF(gr,p);
1069 }
1070 
1071 void NewLine(double *p1,double *p2,Tcolor *c,
1072  unsigned int bs,Tpolyhedron *p)
1073 {
1074  p->type=LINE;
1075  p->status=bs; /* normal, hidden, decoration*/
1076 
1077  CopyColor(&(p->color),c);
1078  p->obj3d=NO_UINT;
1079 
1080  /*Set the line information*/
1081  p->rad=0.01; /* small radius for collision detection */
1082 
1083  p->p1[0]=p1[0];
1084  p->p1[1]=p1[1];
1085  p->p1[2]=p1[2];
1086 
1087  p->p2[0]=p2[0];
1088  p->p2[1]=p2[1];
1089  p->p2[2]=p2[2];
1090 
1091  /*Cancel sphere information*/
1092  p->center[0]=p->center[1]=p->center[2]=0.0;
1093 
1094  /*Generate the OFF information*/
1095  GenerateCylinderOFF(0,p);
1096 }
1097 
1098 void NewSegments(unsigned int n,double *x,double *y,double *z,Tcolor *c,
1099  Tpolyhedron *p)
1100 {
1101  unsigned int i,j;
1102  double av;
1103 
1104  p->type=SEGMENTS;
1105  p->status=DECOR_SHAPE; /* never included in collision detection */
1106 
1107  CopyColor(&(p->color),c);
1108  p->obj3d=NO_UINT;
1109 
1110  /*Set the segments information*/
1111  p->nv=n;
1112  NEW(p->v,n,double*);
1113  for(i=0;i<n;i++)
1114  {
1115  NEW(p->v[i],3,double);
1116  p->v[i][0]=x[i];
1117  p->v[i][1]=y[i];
1118  p->v[i][2]=z[i];
1119  }
1120 
1121  /* Compute the bounding box */
1122  p->maxCoord=0;
1123  for(i=0;i<p->nv;i++)
1124  {
1125  for(j=0;j<3;j++)
1126  {
1127  av=fabs(p->v[i][j]);
1128  if (av>p->maxCoord)
1129  p->maxCoord=av;
1130  }
1131  }
1132 
1133  /*Cancel sphere/cylinder information*/
1134  p->center[0]=p->center[1]=p->center[2]=0.0;
1135  p->rad=0;
1136  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
1137  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
1138 
1139  /*Cancel the OFF information*/
1140  p->nf=0;
1141  p->ne=0;
1142  p->nvf=0;
1143 }
1144 
1145 void NewSpring(double length,double start,double rad,unsigned int lps,
1146  Tcolor *c,Tpolyhedron *p)
1147 {
1148  double end,step;
1149  unsigned int loops,pointsXLoop;
1150  unsigned int i,j,n;
1151  double x,a,av;
1152 
1153  /* */
1154  p->type=SEGMENTS;
1155  p->status=DECOR_SHAPE; /* never included in collision detection */
1156 
1157  CopyColor(&(p->color),c);
1158  p->obj3d=NO_UINT;
1159 
1160  /* some hard-coded parameters of the spring */
1161  end=1.0-start; /* size of the last segment */
1162  loops=(unsigned int)((lps==0?80:lps)*length); /* number of loops in the central part */
1163  pointsXLoop=20; /* points to represent each loop */
1164 
1165  n=loops*pointsXLoop;
1166  step=(end-start)/(double)n;
1167 
1168  /* To reuse the SEGMENTS structure we define each
1169  segment with initialPoint-finalPoint*/
1170  p->nv=(3+n)*2;
1171  NEW(p->v,p->nv,double*);
1172 
1173  /* initial point */
1174  NEW(p->v[0],3,double);
1175  p->v[0][0]=0;
1176  p->v[0][1]=0;
1177  p->v[0][2]=0;
1178 
1179  /* firt point of the loops point */
1180  NEW(p->v[1],3,double);
1181  p->v[1][0]=start*length;
1182  p->v[1][1]=0;
1183  p->v[1][2]=0;
1184 
1185  x=start;
1186  for(i=0,j=2;i<n;i++,x+=step)
1187  {
1188  /* copy the previous point */
1189  NEW(p->v[j],3,double);
1190  p->v[j][0]=p->v[j-1][0];
1191  p->v[j][1]=p->v[j-1][1];
1192  p->v[j][2]=p->v[j-1][2];
1193  j++;
1194 
1195  /* define a new point */
1196  NEW(p->v[j],3,double);
1197  a=M_2PI*loops*(x-start)/(end-start);
1198  p->v[j][0]=x*length;
1199  p->v[j][1]=rad*sin(a);
1200  p->v[j][2]=rad*cos(a);
1201  j++;
1202  }
1203 
1204  /* copy the previous point */
1205  NEW(p->v[j],3,double);
1206  p->v[j][0]=p->v[j-1][0];
1207  p->v[j][1]=p->v[j-1][1];
1208  p->v[j][2]=p->v[j-1][2];
1209  j++;
1210 
1211  /* last point of the loops */
1212  NEW(p->v[j],3,double);
1213  p->v[j][0]=end*length;
1214  p->v[j][1]=0;
1215  p->v[j][2]=0;
1216  j++;
1217 
1218  /* copy the previous point */
1219  NEW(p->v[j],3,double);
1220  p->v[j][0]=p->v[j-1][0];
1221  p->v[j][1]=p->v[j-1][1];
1222  p->v[j][2]=p->v[j-1][2];
1223  j++;
1224 
1225  /* last point */
1226  NEW(p->v[j],3,double);
1227  p->v[j][0]=length;
1228  p->v[j][1]=0;
1229  p->v[j][2]=0;
1230  j++;
1231 
1232  if (j!=p->nv)
1233  Error("Wrong number or points in spring");
1234 
1235  /* Compute the bounding box */
1236  p->maxCoord=0;
1237  for(i=0;i<p->nv;i++)
1238  {
1239  for(j=0;j<3;j++)
1240  {
1241  av=fabs(p->v[i][j]);
1242  if (av>p->maxCoord)
1243  p->maxCoord=av;
1244  }
1245  }
1246 
1247  /*Cancel sphere/cylinder information*/
1248  p->center[0]=p->center[1]=p->center[2]=0.0;
1249  p->rad=0;
1250  p->p1[0]=p->p1[1]=p->p1[2]=0.0;
1251  p->p2[0]=p->p2[1]=p->p2[2]=0.0;
1252 
1253  /*Cancel the OFF information*/
1254  p->nf=0;
1255  p->ne=0;
1256  p->nvf=0;
1257 }
1258 
1260 {
1261  unsigned int i,j;
1262 
1263  p_dst->type=p_src->type;
1264  p_dst->status=p_src->status;
1265 
1266  /*plot3d information*/
1267  CopyColor(&(p_dst->color),&(p_src->color));
1268 
1269  p_dst->obj3d=p_src->obj3d;
1270 
1271  /* off information */
1272  p_dst->nv=p_src->nv;
1273  p_dst->nf=p_src->nf;
1274  p_dst->ne=p_src->ne;
1275 
1276  if (p_dst->nv>0)
1277  {
1278  NEW(p_dst->v,p_src->nv,double*);
1279  for(i=0;i<p_dst->nv;i++)
1280  {
1281  NEW(p_dst->v[i],3,double);
1282  p_dst->v[i][0]=p_src->v[i][0];
1283  p_dst->v[i][1]=p_src->v[i][1];
1284  p_dst->v[i][2]=p_src->v[i][2];
1285  }
1286  }
1287  else
1288  p_dst->v=NULL;
1289 
1290  if (p_dst->nf>0)
1291  {
1292  NEW(p_dst->nvf,p_dst->nf,unsigned int);
1293  NEW(p_dst->fv,p_dst->nf,unsigned int*);
1294  for(i=0;i<p_dst->nf;i++)
1295  {
1296  p_dst->nvf[i]=p_src->nvf[i];
1297  NEW(p_dst->fv[i],p_dst->nvf[i],unsigned int);
1298 
1299  for(j=0;j<p_dst->nvf[i];j++)
1300  p_dst->fv[i][j]=p_src->fv[i][j];
1301  }
1302  }
1303  else
1304  {
1305  p_dst->nvf=NULL;
1306  p_dst->fv=NULL;
1307  }
1308 
1309  /*Sphere - Cylinder - Line information (if any)*/
1310  p_dst->rad=p_src->rad;
1311  for(i=0;i<3;i++)
1312  {
1313  p_dst->center[i]=p_src->center[i];
1314  p_dst->p1[i]=p_src->p1[i];
1315  p_dst->p2[i]=p_src->p2[i];
1316  }
1317 
1318  p_dst->maxCoord=p_src->maxCoord;
1319 }
1320 
1322 {
1323  /* if the transform is the identity just do not apply it */
1324  if (!HTransformIsIdentity(t))
1325  {
1326  unsigned int i,j;
1327  double av;
1328 
1329  if (p->nv>0)
1330  {
1331  /*Off information*/
1332  p->maxCoord=0;
1333  for(i=0;i<p->nv;i++)
1334  {
1335  HTransformApply(p->v[i],p->v[i],t);
1336  for(j=0;j<3;j++)
1337  {
1338  av=fabs(p->v[i][j]);
1339  if (av>p->maxCoord)
1340  p->maxCoord=av;
1341  }
1342  }
1343  }
1344 
1345  /*Sphere - Cylinder - Line information*/
1346  /* recall that sphere,cylinder,line also have vertices */
1347  HTransformApply(p->center,p->center,t);
1348  HTransformApply(p->p1,p->p1,t);
1349  HTransformApply(p->p2,p->p2,t);
1350  }
1351 }
1352 
1354 {
1355  if (p->type!=SPHERE)
1356  Error("GetPolyhedronCenter is only defined for spheres");
1357 
1358  c[0]=p->center[0];
1359  c[1]=p->center[1];
1360  c[2]=p->center[2];
1361 }
1362 
1364 {
1365  return(p->type);
1366 }
1367 
1369 {
1370  CopyColor(&(p->color),c);
1371 }
1372 
1374 {
1375  CopyColor(c,&(p->color));
1376 }
1377 
1379 {
1380  return(p->status);
1381 }
1382 
1383 void GetOFFInfo(unsigned int *nv,double ***v,unsigned int *nf,
1384  unsigned int **nvf,unsigned int ***fv,Tpolyhedron *p)
1385 {
1386  *nv=p->nv;
1387  *v=p->v;
1388  *nf=p->nf;
1389  *nvf=p->nvf;
1390  *fv=p->fv;
1391 }
1392 
1394 {
1395  return(p->nv);
1396 }
1397 
1398 void GetPolyhedronDefiningPoint(unsigned int i,double *point,Tpolyhedron *p)
1399 {
1400  unsigned int j;
1401 
1402  switch(p->type)
1403  {
1404  case CYLINDER:
1405  case LINE:
1406  if (i>1)
1407  Error("Point counter out of range in GetPolyhedronDefiningPoint");
1408 
1409  if (i==0)
1410  {
1411  for(j=0;j<3;j++)
1412  point[j]=p->p1[j];
1413  }
1414  else
1415  {
1416  for(j=0;j<3;j++)
1417  point[j]=p->p2[j];
1418  }
1419  break;
1420 
1421  case SPHERE:
1422  if (i>0)
1423  Error("Point counter out of range in GetPolyhedronDefiningPoint");
1424 
1425  for(j=0;j<3;j++)
1426  point[j]=p->center[j];
1427  break;
1428 
1429  case OFF:
1430  case SEGMENTS:
1431  GetPolyhedronVertex(i,point,p);
1432  break;
1433 
1434  default:
1435  Error("Undefined Polyhedron type in GetPolyhedronDefiningPoint");
1436  break;
1437  }
1438 }
1439 
1441 {
1442  if ((p->type==OFF)||(p->type==LINE)||(p->type==SEGMENTS))
1443  Error("Radius is not defined for OFFs,LINEs, or SEGMENTS");
1444  return(p->rad);
1445 }
1446 
1447 void GetPolyhedronVertex(unsigned int i,double *point,Tpolyhedron *p)
1448 {
1449  unsigned int j;
1450 
1451  if (i>=p->nv)
1452  Error("Vertex counter out of range");
1453 
1454  for(j=0;j<3;j++)
1455  point[j]=p->v[i][j];
1456 }
1457 
1459 {
1460  return(p->maxCoord);
1461 }
1462 
1464 {
1465  if (p->status!=HIDDEN_SHAPE)
1466  {
1467  p->obj3d=StartNew3dObject(&(p->color),pt);
1468 
1469  switch(p->type)
1470  {
1471  case OFF:
1472  Plot3dObject(p->nv,p->nf,p->ne,p->v,p->nvf,p->fv,pt);
1473  break;
1474  case LINE:
1475  PlotLine(p->p1,p->p2,pt);
1476  break;
1477  case CYLINDER:
1478  //PlotCylinder(p->rad,p->p1,p->p2,pt);
1479  Plot3dObject(p->nv,p->nf,p->ne,p->v,p->nvf,p->fv,pt);
1480  break;
1481  case SPHERE:
1482  PlotSphere(p->rad,p->center[0],p->center[1],p->center[2],pt);
1483  break;
1484  case SEGMENTS:
1485  PlotSegments(p->nv,p->v,pt);
1486  break;
1487  }
1488 
1489  Close3dObject(pt);
1490  }
1491 }
1492 
1494 {
1495  if (p->type==SPHERE)
1496  {
1497  double v[3];
1498 
1499  HTransformApply(p->center,v,t);
1500 
1501  fprintf(f,"%.16f %.16f %.16f\n",v[0],v[1],v[2]);
1502  }
1503 }
1504 
1506 {
1507  if (p->type==SPHERE)
1508  {
1509  double v[3];
1510 
1511  HTransformApply(p->center,v,t);
1512 
1513  fprintf(f,"%.16f %.16f %.16f %.16f\n",v[0],v[1],v[2],p->rad);
1514  }
1515 }
1516 
1518 {
1519  if ((p->obj3d!=NO_UINT)&&(p->status!=HIDDEN_SHAPE))
1520  Move3dObject(p->obj3d,t,pt);
1521 }
1522 
1523 void SavePolyhedron(char *fileName,Tpolyhedron *p)
1524 {
1525  FILE *f;
1526  unsigned int i,j;
1527 
1528  f=fopen(fileName,"w");
1529  if (!f)
1530  Error("Could not open output file for a convex polyhedron");
1531 
1532  switch(p->type)
1533  {
1534  case OFF:
1535  fprintf(f,"OFF\n");
1536  fprintf(f,"%u %u 1\n",p->nv,p->nf);
1537  for(i=0;i<p->nv;i++)
1538  fprintf(f,"%f %f %f\n",p->v[i][0],p->v[i][1],p->v[i][2]);
1539  fprintf(f,"\n");
1540  for(i=0;i<p->nf;i++)
1541  {
1542  fprintf(f,"%u ",p->nvf[i]);
1543  for(j=0;j<p->nvf[i];j++)
1544  fprintf(f," %u",p->fv[i][j]);
1545  fprintf(f,"\n");
1546  }
1547  break;
1548  case LINE:
1549  fprintf(f,"LINE\n");
1550  fprintf(f,"%.16f %.16f %.16f\n",p->p1[0],p->p1[1],p->p1[2]);
1551  fprintf(f,"%.16f %.16f %.16f\n",p->p2[0],p->p2[1],p->p2[2]);
1552  break;
1553  case CYLINDER:
1554  fprintf(f,"CYLINDER\n");
1555  fprintf(f,"%.16f\n",p->rad);
1556  fprintf(f,"%.16f %.16f %.16f\n",p->p1[0],p->p1[1],p->p1[2]);
1557  fprintf(f,"%.16f %.16f %.16f\n",p->p2[0],p->p2[1],p->p2[2]);
1558  break;
1559  case SPHERE:
1560  fprintf(f,"SPHERE\n");
1561  fprintf(f,"%.16f\n",p->rad);
1562  fprintf(f,"%.16f %.16f %.16f\n",p->center[0],p->center[1],p->center[2]);
1563  break;
1564  case SEGMENTS:
1565  fprintf(f,"SEGMENTS\n");
1566  fprintf(f,"%u\n",p->nv);
1567  for(i=0;i<p->nv;i++)
1568  fprintf(f,"%f %f %f\n",p->v[i][0],p->v[i][1],p->v[i][2]);
1569  break;
1570  }
1571  fclose(f);
1572 }
1573 
1574 void PrintPolyhedron(FILE *f,char *path,char *label,unsigned int n,Tpolyhedron *p)
1575 {
1576  unsigned int i;
1577 
1578  if (n>0)
1579  fprintf(f," ");
1580 
1581  switch(p->type)
1582  {
1583  case OFF:
1584  {
1585  unsigned int l;
1586  char *pname;
1587  Tfilename fbody;
1588 
1589  /* ensure that folder "bodies" exists */
1590  CreateFileName(path,"bodies",NULL,NULL,&fbody);
1591  mkdir(GetFileFullName(&fbody),0777);
1592  DeleteFileName(&fbody);
1593 
1594  /* store the object in file */
1595  if (label!=NULL)
1596  {
1597  l=strlen(label);
1598  NEW(pname,l+30,char);
1599  sprintf(pname,"bodies/%s_%u",label,n);
1600  }
1601  else
1602  {
1603  NEW(pname,30,char);
1604  sprintf(pname,"bodies/_body_%u",n);
1605  }
1606 
1607  CreateFileName(path,pname,NULL,OFF_EXT,&fbody);
1608 
1609  SavePolyhedron(GetFileFullName(&fbody),p);
1610  fprintf(f,"body \"%s\"",GetFileFullName(&fbody));
1611 
1612  DeleteFileName(&fbody);
1613  free(pname);
1614  }
1615  break;
1616  case LINE:
1617  fprintf(f,"line (");
1618  Print3Reals(f,p->p1[0],p->p1[1],p->p1[2]);
1619  fprintf(f,") (");
1620  Print3Reals(f,p->p2[0],p->p2[1],p->p2[2]);
1621  fprintf(f,")");
1622  break;
1623  case CYLINDER:
1624  fprintf(f,"cylinder %g (",p->rad);
1625  Print3Reals(f,p->p1[0],p->p1[1],p->p1[2]);
1626  fprintf(f,") (");
1627  Print3Reals(f,p->p2[0],p->p2[1],p->p2[2]);
1628  fprintf(f,")");
1629  break;
1630  case SPHERE:
1631  fprintf(f,"sphere %g (",p->rad);
1632  Print3Reals(f,p->center[0],p->center[1],p->center[2]);
1633  fprintf(f,")");
1634  break;
1635  case SEGMENTS:
1636  {
1637  /* Print the segments in blocks to avoid memory overflow in the parser*/
1638  unsigned int s,e;
1639  boolean end;
1640 
1641  end=FALSE;
1642  s=0;
1643  while(!end)
1644  {
1645  e=s+1000; /* Adjust this if you have memory overflow in the parser */
1646  if (e>=p->nv)
1647  {
1648  e=p->nv;
1649  end=TRUE;
1650  }
1651  fprintf(f,"segments (");
1652  for(i=s;i<e;i++)
1653  {
1654  Print3Reals(f,p->v[i][0],p->v[i][1],p->v[i][2]);
1655  if (i<e-1)
1656  {
1657  fprintf(f,";");
1658  if (((i-s)%2)==1) fprintf(f,"\n ");
1659  }
1660  }
1661  fprintf(f,") color (%g,%g,%g)\n ",
1662  GetRed(&(p->color)),GetGreen(&(p->color)),GetBlue(&(p->color)));
1663  s=e;
1664  }
1665  }
1666  break;
1667  }
1668 
1669  if (p->type!=SEGMENTS)
1670  {
1671  if (p->status!=HIDDEN_SHAPE)
1672  fprintf(f," color (%g,%g,%g)",
1673  GetRed(&(p->color)),GetGreen(&(p->color)),GetBlue(&(p->color)));
1674 
1675  switch(p->status)
1676  {
1677  case NORMAL_SHAPE:
1678  break;
1679  case HIDDEN_SHAPE:
1680  fprintf(f," hidden");
1681  break;
1682  case DECOR_SHAPE:
1683  fprintf(f," decoration");
1684  break;
1685  default:
1686  Error("Unknown body disply status in PrintPolyhedron");
1687  }
1688  }
1689  fprintf(f,"\n");
1690 }
1691 
1693 {
1694  if (p->type!=EMPTY_BODY)
1695  {
1696  unsigned int i;
1697 
1698  if (p->nv>0)
1699  {
1700  for(i=0;i<p->nv;i++)
1701  free(p->v[i]);
1702  free(p->v);
1703  }
1704 
1705  if (p->nf>0)
1706  {
1707  for(i=0;i<p->nf;i++)
1708  free(p->fv[i]);
1709 
1710  free(p->fv);
1711  free(p->nvf);
1712  }
1713  }
1714 }
1715 
1716 
Definition of the boolean type.
void GetPolyhedronDefiningPoint(unsigned int i, double *point, Tpolyhedron *p)
Gets a point defining a a object.
Definition: polyhedron.c:1398
void NewTriangularPrism(double *p1, double *p2, double *p3, double h, Tcolor *c, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:861
unsigned int ** fv
Definition: polyhedron.h:150
double p1[3]
Definition: polyhedron.h:156
Definition of basic functions.
void PrintPolyhedron(FILE *f, char *path, char *label, unsigned int n, Tpolyhedron *p)
Stores the polyhedron information into a file.
Definition: polyhedron.c:1574
double maxCoord
Definition: polyhedron.h:159
#define FALSE
FALSE.
Definition: boolean.h:30
void GetOFFInfo(unsigned int *nv, double ***v, unsigned int *nf, unsigned int **nvf, unsigned int ***fv, Tpolyhedron *p)
Gets the OFF information.
Definition: polyhedron.c:1383
void HTransformApply(double *p_in, double *p_out, THTransform *t)
Multiply a homogeneous transform and a vector.
Definition: htransform.c:782
unsigned int obj3d
Definition: polyhedron.h:143
void HTransformTxyz(double tx, double ty, double tz, THTransform *t)
Constructor.
Definition: htransform.c:146
#define NEW(_var, _n, _type)
Allocates memory space.
Definition: defines.h:385
Data structure to hold the information about the name of a file.
Definition: filename.h:271
boolean EmptyPolyhedron(Tpolyhedron *p)
Used for objects that failed to initialize.
Definition: polyhedron.c:856
void PolyhedronPrintCenter(FILE *f, THTransform *t, Tpolyhedron *p)
Prints the center of a sphere to a file.
Definition: polyhedron.c:1493
void ReadSphere(FILE *f, unsigned int g, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:709
A homgeneous transform in R^3.
void GetPolyhedronColor(Tcolor *c, Tpolyhedron *p)
Gets the color of a polyhedron.
Definition: polyhedron.c:1373
void PlotSegments(unsigned int n, double **pt, Tplot3d *p)
Adds a collecion of segments to the current object.
Definition: plot3d.c:412
void PolyhedronPrintCenterAndRadius(FILE *f, THTransform *t, Tpolyhedron *p)
Prints the center and the radius of a sphere to a file.
Definition: polyhedron.c:1505
double p2[3]
Definition: polyhedron.h:157
double GetGreen(Tcolor *c)
Gets the green component of a color.
Definition: color.c:128
#define EMPTY_BODY
One of the possible type of polyhedrons.
Definition: polyhedron.h:110
#define OFF_EXT
File extension for geomview OFF files.
Definition: filename.h:102
void NewSpring(double length, double start, double rad, unsigned int lps, Tcolor *c, Tpolyhedron *p)
Defines a spring.
Definition: polyhedron.c:1145
double center[3]
Definition: polyhedron.h:154
#define NORMAL_SHAPE
One of the possible type of shapes.
Definition: polyhedron.h:28
void GetPolyhedronCenter(double *c, Tpolyhedron *p)
Gets the center of the spheres.
Definition: polyhedron.c:1353
double GetPolyhedronRadius(Tpolyhedron *p)
Returns the radius used in the definition of the object.
Definition: polyhedron.c:1440
#define TRUE
TRUE.
Definition: boolean.h:21
CBLAS_INLINE void Normalize(unsigned int s, double *v)
Normalizes a vector.
#define CYLINDER
One of the possible type of polyhedrons.
Definition: polyhedron.h:80
void Error(const char *s)
General error function.
Definition: error.c:80
void CopyColor(Tcolor *c_dst, Tcolor *c_src)
Copy constructor.
Definition: color.c:57
A color.
Definition: color.h:86
void PlotLine(double x0, double y0, double x1, double y1, Tplot *p)
Plots a segment.
Definition: plot.c:215
#define OFF
One of the possible type of polyhedrons.
Definition: polyhedron.h:59
void PlotSphere(double r, double x, double y, double z, Tplot3d *p)
Adds a sphere to the current object.
Definition: plot3d.c:369
#define SEGMENTS
One of the possible type of polyhedrons.
Definition: polyhedron.h:100
void CopyPolyhedron(Tpolyhedron *p_dst, Tpolyhedron *p_src)
Copy constructor.
Definition: polyhedron.c:1259
CBLAS_INLINE void HTransformProduct(THTransform *t1, THTransform *t2, THTransform *t3)
Product of two homogeneous transforms.
Definition: htransform.c:410
unsigned int GetPolyhedronNVertex(Tpolyhedron *p)
Gets the number of vertexes of a polyhedron.
Definition: polyhedron.c:1393
void ReadLine(FILE *f, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:508
#define LINE
One of the possible type of polyhedrons.
Definition: polyhedron.h:90
void HTransformX2Vect(double sy, double sz, double *p1, double *p2, THTransform *t)
Transform a unitary vector along the X axis to a generic vector.
Definition: htransform.c:574
void Move3dObject(unsigned int nobj, THTransform *t, Tplot3d *p)
Moves a 3d object.
Definition: plot3d.c:217
A polyhedron.
Definition: polyhedron.h:134
Error and warning functions.
void DeleteFileName(Tfilename *fn)
Destructor.
Definition: filename.c:205
void ReadSTL(char *fn, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:287
A 3D plot.
Definition: plot3d.h:54
void ReadCylinder(FILE *f, unsigned int g, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:572
void PlotPolyhedron(Tplot3d *pt, Tpolyhedron *p)
Adds the polyhedron to a 3D geometry.
Definition: polyhedron.c:1463
double Distance(unsigned int s, double *v1, double *v2)
Computes the distance of two points.
unsigned int GetPolyhedronStatus(Tpolyhedron *p)
Gets the status of a polyhedron (NORMAL, HIDDEN, DECOR).
Definition: polyhedron.c:1378
boolean ReadGeneralMesh(char *fn, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:231
void HTransformRz(double rz, THTransform *t)
Constructor.
Definition: htransform.c:195
double ** v
Definition: polyhedron.h:148
unsigned int status
Definition: polyhedron.h:137
void NewSphere(double r, double *center, Tcolor *c, unsigned int gr, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:1020
#define M_PI_2
Pi/2.
Definition: defines.h:92
void ReadOFF(FILE *f, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:366
void DifferenceVector(unsigned int s, double *v1, double *v2, double *v)
Substracts two vectors.
void NewCylinder(double r, double *p1, double *p2, Tcolor *c, unsigned int gr, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:1044
double rad
Definition: polyhedron.h:152
void GenerateCylinderOFF(unsigned int g, Tpolyhedron *p)
Generates an OFF that approximates a cylinder.
Definition: polyhedron.c:422
void MovePolyhedron(Tplot3d *pt, THTransform *t, Tpolyhedron *p)
Moves an object previously added to a 3D scene.
Definition: polyhedron.c:1517
void SavePolyhedron(char *fileName, Tpolyhedron *p)
Stores the geometic information of a polyhedron into a file.
Definition: polyhedron.c:1523
void CreateFileName(char *path, char *name, char *suffix, char *ext, Tfilename *fn)
Constructor.
Definition: filename.c:22
Definition of the THTransform type and the associated functions.
unsigned int * nvf
Definition: polyhedron.h:149
char * GetFileFullName(Tfilename *fn)
Gets the file full name (paht+name+extension).
Definition: filename.c:151
#define M_2PI
2*Pi.
Definition: defines.h:100
#define M_PI
Pi.
Definition: defines.h:83
#define SPHERE
One of the possible type of polyhedrons.
Definition: polyhedron.h:70
Tcolor color
Definition: polyhedron.h:141
double GetRed(Tcolor *c)
Gets the red component of a color.
Definition: color.c:123
Definition of the Tpolyhedron type and the associated functions.
#define NO_UINT
Used to denote an identifier that has not been initialized.
Definition: defines.h:435
CBLAS_INLINE void SumVectorScale(unsigned int s, double *v1, double w, double *v2, double *v)
Adds two vectors with a scale.
Definition: basic_algebra.c:86
double GetPolyhedronMaxCoordinate(Tpolyhedron *p)
Returns the maximum coordinate value used in a polyhedron.
Definition: polyhedron.c:1458
void InitPolyhedronFromFile(Tfilename *fname, Tcolor *c, unsigned int gr, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:727
unsigned int nf
Definition: polyhedron.h:146
void HTransformDelete(THTransform *t)
Destructor.
Definition: htransform.c:887
void GetPolyhedronVertex(unsigned int i, double *point, Tpolyhedron *p)
Gets a vertex of a polyhedron.
Definition: polyhedron.c:1447
void HTransformSetElement(unsigned int i, unsigned int j, double v, THTransform *t)
Sets an element in a homogeneous transform.
Definition: htransform.c:312
void DeletePolyhedron(Tpolyhedron *p)
Destructor.
Definition: polyhedron.c:1692
unsigned int GetPolyhedronType(Tpolyhedron *p)
Retrives the type of a polyhedron.
Definition: polyhedron.c:1363
unsigned int ne
Definition: polyhedron.h:147
void NewSegments(unsigned int n, double *x, double *y, double *z, Tcolor *c, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:1098
void NewColor(double r, double g, double b, Tcolor *c)
Constructor.
Definition: color.c:14
unsigned int nv
Definition: polyhedron.h:145
void Plot3dObject(unsigned int nv, unsigned int nf, unsigned int ne, double **v, unsigned int *nvf, unsigned int **fv, Tplot3d *p)
Adds a polytope to the current object.
Definition: plot3d.c:276
void NewLine(double *p1, double *p2, Tcolor *c, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:1071
char * GetFileExtension(Tfilename *fn)
Gets the file extension.
Definition: filename.c:171
void GenerateSphereOFF(unsigned int g, Tpolyhedron *p)
Generates an OFF that approximates a sphere.
Definition: polyhedron.c:593
void SetPolyhedronColor(Tcolor *c, Tpolyhedron *p)
Changes the color of a polyhedron.
Definition: polyhedron.c:1368
void NewBox(double xl, double yl, double zl, double xu, double yu, double zu, Tcolor *c, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:946
double GetBlue(Tcolor *c)
Gets the blue component of a color.
Definition: color.c:133
void CrossProduct(double *v1, double *v2, double *v3)
Computes the cross product of two 3d vectors.
Definition: geom.c:639
unsigned int StartNew3dObject(Tcolor *c, Tplot3d *p)
Start a composed object.
Definition: plot3d.c:157
void Close3dObject(Tplot3d *p)
Closes a composed object.
Definition: plot3d.c:171
void InitPolyhedronFromTriangles(unsigned int nv, double **v, unsigned int nt, unsigned int **t, Tcolor *c, unsigned int bs, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:801
void Print3Reals(FILE *f, double r1, double r2, double r3)
Pretty print three real number.
Definition: geom.c:763
void ReadSegments(FILE *f, Tpolyhedron *p)
Constructor.
Definition: polyhedron.c:529
#define DECOR_SHAPE
One of the possible type of shapes.
Definition: polyhedron.h:46
void TransformPolyhedron(THTransform *t, Tpolyhedron *p)
Applies a homogenoeus transform to a polyhedron.
Definition: polyhedron.c:1321
unsigned int type
Definition: polyhedron.h:135
boolean HTransformIsIdentity(THTransform *t)
Identify the identity matrix.
Definition: htransform.c:91
#define HIDDEN_SHAPE
One of the possible type of shapes.
Definition: polyhedron.h:37