Institut de Robòtica i Informàtica Industrial
KRD Group

The CuikSuite Project

cpolyhedron.c

Go to the documentation of this file.
00001 #include "cpolyhedron.h"
00002 
00003 #include "htransform.h"
00004 #include "error.h"
00005 
00006 #include <string.h>
00007 #include <math.h>
00008 
00009 
00028 void ReadOFF(FILE *f,Tcpolyhedron *p);
00029 
00044 void GenerateCylinderOFF(unsigned int g,Tcpolyhedron *p);
00045 
00058 void ReadCylinder(FILE *f,unsigned int g,Tcpolyhedron *p);
00059 
00074 void GenerateSphereOFF(unsigned int g,Tcpolyhedron *p);
00075 
00088 void ReadSphere(FILE *f,unsigned int g,Tcpolyhedron *p);
00089 
00090 void ReadOFF(FILE *f,Tcpolyhedron *p)
00091 {
00092   unsigned int i,j;
00093   double av;
00094 
00095   p->type=OFF;
00096 
00097   fscanf(f,"%u",&(p->nv));
00098   fscanf(f,"%u",&(p->nf));
00099   fscanf(f,"%u",&(p->ne));
00100   if ((p->nv==0)||(p->nf==0))
00101     Error("Empty OFF");
00102 
00103   NEW(p->v,p->nv,double*);
00104   for(i=0;i<p->nv;i++)
00105     {
00106       NEW(p->v[i],3,double);
00107       fscanf(f,"%lf",&(p->v[i][0]));
00108       fscanf(f,"%lf",&(p->v[i][1]));
00109       fscanf(f,"%lf",&(p->v[i][2]));
00110     }
00111   
00112   NEW(p->nvf,p->nf,unsigned int);
00113   NEW(p->fv,p->nf,unsigned int*);
00114   for(i=0;i<p->nf;i++)
00115     {
00116       fscanf(f,"%u",&(p->nvf[i]));
00117       if (p->nvf[i]==0)
00118         Error("Empty face in OFF");
00119       NEW(p->fv[i],p->nvf[i],unsigned int);
00120 
00121       for(j=0;j<p->nvf[i];j++)
00122         fscanf(f,"%u",&(p->fv[i][j]));
00123     }
00124 
00125   /* Cancel the sphere information */
00126   p->rad=0;
00127   p->center[0]=p->center[1]=p->center[2]=0.0;
00128 
00129   /* and the cylinder information too */
00130   p->p1[0]=p->p1[1]=p->p1[2]=0.0;
00131   p->p2[0]=p->p2[1]=p->p2[2]=0.0;
00132 
00133   /* Compute the bounding box */
00134   p->maxCoord=0;
00135   for(i=0;i<p->nv;i++)
00136     {
00137       for(j=0;j<3;j++)
00138         {
00139           av=fabs(p->v[i][j]);
00140           if (av>p->maxCoord)
00141             p->maxCoord=av;
00142         }
00143     }
00144 }
00145 
00146 void GenerateCylinderOFF(unsigned int g,Tcpolyhedron *p)
00147 {
00148   unsigned int i,j,n;
00149   THTransform m;
00150   double a,av;
00151 
00152   if (p->type!=CYLINDER)
00153     Error("Using GenerateCylinderOFF in a non cylindric convex polyhedron");
00154 
00155   /*The points are defined on the reference cylinder (aligned along axis X
00156     and with length 1 and radii 1) that is later on scaled and enlarged */
00157   n=4+g;
00158   p->nv=2*n;
00159   NEW(p->v,p->nv,double*);
00160   for(i=0;i<n;i++)
00161     {
00162       NEW(p->v[i],3,double);
00163       NEW(p->v[n+i],3,double);
00164 
00165       p->v[i][0]=0;
00166       p->v[n+i][0]=1;
00167 
00168       a=(double)i/(double)n*M_2PI;
00169       p->v[i][1]=p->v[n+i][1]=cos(a);
00170       p->v[i][2]=p->v[n+i][2]=sin(a);
00171     }
00172 
00173   /*Now rotate the points according to the cylinder orientation defined by p1,p2*/
00174   HTransformX2Vect(p->rad,p->rad,p->p1,p->p2,&m);
00175 
00176   for(i=0;i<p->nv;i++)
00177     HTransformApply(p->v[i],p->v[i],&m);
00178 
00179   /*no face information*/
00180   p->nf=0;
00181   p->fv=NULL;
00182   p->nvf=NULL;
00183 
00184   HTransformDelete(&m);
00185 
00186   /* Compute the bounding box using the points that approximate the cylinder */
00187   p->maxCoord=0;
00188   for(i=0;i<p->nv;i++)
00189     {
00190       for(j=0;j<3;j++)
00191         {
00192           av=fabs(p->v[i][j]);
00193           if (av>p->maxCoord)
00194             p->maxCoord=av;
00195         }
00196     }
00197 }
00198 
00199 void ReadCylinder(FILE *f,unsigned int g,Tcpolyhedron *p)
00200 {
00201   p->type=CYLINDER;
00202 
00203   fscanf(f,"%lf",&(p->rad));
00204 
00205   fscanf(f,"%lf",&(p->p1[0]));
00206   fscanf(f,"%lf",&(p->p1[1]));
00207   fscanf(f,"%lf",&(p->p1[2]));
00208 
00209   fscanf(f,"%lf",&(p->p2[0]));
00210   fscanf(f,"%lf",&(p->p2[1]));
00211   fscanf(f,"%lf",&(p->p2[2]));
00212 
00213   /*Cancel sphere information*/
00214   p->center[0]=p->center[1]=p->center[2]=0.0;
00215 
00216   /*Generate the OFF information*/
00217   GenerateCylinderOFF(g,p);
00218 }
00219 
00220 void GenerateSphereOFF(unsigned int g,Tcpolyhedron *p)
00221 {
00222   unsigned int i,j,n,m;
00223   double **meridian;
00224   THTransform rz,tr;
00225   double a,offset,av;
00226 
00227   if (p->type!=SPHERE)
00228     Error("Using GenerateCylinderOFF in a non spheric convex polyhedron");
00229 
00230   /*Vertex information for collision avoidance (in the future refined according to 'g')*/
00231   n=1+g;
00232   m=4+g;
00233 
00234   offset=M_PI_2/((double)(n+1));
00235   a=0.0;
00236 
00237   NEW(meridian,2*n,double*);
00238   for(i=0;i<n;i++)
00239     {
00240       a+=offset;
00241       NEW(meridian[i],3,double);
00242       meridian[i][0]=p->rad*cos(a);
00243       meridian[i][1]=0.0;
00244       meridian[i][2]=p->rad*sin(a);
00245 
00246       NEW(meridian[n+i],3,double); 
00247       meridian[n+i][0]=meridian[i][0];
00248       meridian[n+i][1]=0.0;
00249       meridian[n+i][2]=-meridian[i][2];
00250     }
00251 
00252   p->nv=2*n*m;
00253   NEW(p->v,p->nv,double*);
00254   for(i=0;i<p->nv;i++)
00255     NEW(p->v[i],3,double);
00256 
00257   a=0.0;
00258   offset=M_2PI/(double)m;
00259 
00260   for(j=0;j<m;j++)
00261     {
00262       HTransformTxyz(p->center[0],p->center[1],p->center[2],&tr);
00263       HTransformRz(a,&rz);
00264       HTransformProduct(&tr,&rz,&tr);
00265       for(i=0;i<2*n;i++)
00266         HTransformApply(meridian[i],p->v[j*(2*n)+i],&tr);
00267 
00268       a+=offset;
00269       
00270       HTransformDelete(&tr);
00271       HTransformDelete(&rz);
00272     }
00273   
00274   for(i=0;i<2*n;i++)
00275     free(meridian[i]);
00276   free(meridian);
00277 
00278   /*no face information*/
00279   p->nf=0;
00280   p->fv=NULL;
00281   p->nvf=NULL;
00282 
00283   /* Compute the bounding box using the points that approximate the sphere */
00284   p->maxCoord=0;
00285   for(i=0;i<p->nv;i++)
00286     {
00287       for(j=0;j<3;j++)
00288         {
00289           av=fabs(p->v[i][j]);
00290           if (av>p->maxCoord)
00291             p->maxCoord=av;
00292         }
00293     }
00294 }
00295 
00296 void ReadSphere(FILE *f,unsigned int g,Tcpolyhedron *p)
00297 {
00298   p->type=SPHERE;
00299 
00300   fscanf(f,"%lf",&(p->rad));
00301 
00302   fscanf(f,"%lf",&(p->center[0]));
00303   fscanf(f,"%lf",&(p->center[1]));
00304   fscanf(f,"%lf",&(p->center[2]));
00305 
00306   /*Cancel cylinder information*/
00307   p->p1[0]=p->p1[1]=p->p1[2]=0.0;
00308   p->p2[0]=p->p2[1]=p->p2[2]=0.0;
00309 
00310   /*Generate the OFF information*/
00311   GenerateSphereOFF(g,p);
00312 }
00313 
00314 void InitCPolyhedronFromFile(char *fname,Tcolor *c,
00315                              unsigned int gr,Tcpolyhedron *p)
00316 {
00317   FILE *f;
00318   char *stmp; 
00319   boolean off, cylinder,sphere;
00320 
00321   CopyColor(&(p->color),c);
00322   
00323   p->obj3d=NO_UINT;
00324 
00325   NEW(stmp,20,char); /* 20 is enough to read OFF/SPHERE/CYLINDER */
00326 
00327   f=fopen(fname,"r");
00328   if (!f)
00329     Error("Could not open CPolyhedron file");
00330 
00331   fscanf(f,"%s",stmp); /* OFF -> skip it */
00332 
00333   off=(strcmp(stmp,"OFF")==0);
00334   cylinder=(strcmp(stmp,"CYLINDER")==0);
00335   sphere=(strcmp(stmp,"SPHERE")==0);
00336 
00337   if ((!off)&&(!cylinder)&&(!sphere))
00338     Error("Unknow type of shape");
00339 
00340   if (off)
00341     ReadOFF(f,p);
00342   
00343   if (cylinder)
00344     ReadCylinder(f,gr,p);
00345 
00346   if (sphere)
00347     ReadSphere(f,gr,p);
00348 
00349   free(stmp);
00350   fclose(f);
00351 }
00352 
00353 void NewSphere(double r,double *center,Tcolor *c,
00354                unsigned int gr,Tcpolyhedron *p)
00355 {
00356   p->type=SPHERE;
00357 
00358   CopyColor(&(p->color),c);
00359   p->obj3d=NO_UINT;
00360 
00361   /*Set the sphere information*/
00362   p->rad=r;
00363 
00364   p->center[0]=center[0];
00365   p->center[1]=center[1];
00366   p->center[2]=center[2];
00367 
00368   /*Cancel cylinder information*/
00369   p->p1[0]=p->p1[1]=p->p1[2]=0.0;
00370   p->p2[0]=p->p2[1]=p->p2[2]=0.0;
00371 
00372   /*Generate the OFF information*/
00373   GenerateSphereOFF(gr,p);
00374 }
00375 
00376 void NewCylinder(double r,double *p1,double *p2,Tcolor *c,
00377                  unsigned int gr,Tcpolyhedron *p)
00378 {
00379   p->type=CYLINDER;
00380 
00381   CopyColor(&(p->color),c);
00382   p->obj3d=NO_UINT;
00383 
00384   /*Set the cylinder information*/
00385   p->rad=r;
00386 
00387   p->p1[0]=p1[0];
00388   p->p1[1]=p1[1];
00389   p->p1[2]=p1[2];
00390 
00391   p->p2[0]=p2[0];
00392   p->p2[1]=p2[1];
00393   p->p2[2]=p2[2];
00394 
00395   /*Cancel sphere information*/
00396   p->center[0]=p->center[1]=p->center[2]=0.0;
00397 
00398   /*Generate the OFF information*/
00399   GenerateCylinderOFF(gr,p);
00400 }
00401 
00402 
00403 void CopyCPolyhedron(Tcpolyhedron *p_dst,Tcpolyhedron *p_src)
00404 {
00405   unsigned int i,j;
00406 
00407   p_dst->type=p_src->type;
00408 
00409   /*plot3d information*/
00410   CopyColor(&(p_dst->color),&(p_src->color));
00411  
00412   p_dst->obj3d=p_src->obj3d;
00413 
00414   /* off information */
00415   p_dst->nv=p_src->nv;
00416   p_dst->nf=p_src->nf;
00417   p_dst->ne=p_src->ne;
00418 
00419   NEW(p_dst->v,p_src->nv,double*);
00420   for(i=0;i<p_dst->nv;i++)
00421     {
00422       NEW(p_dst->v[i],3,double);
00423       p_dst->v[i][0]=p_src->v[i][0];
00424       p_dst->v[i][1]=p_src->v[i][1];
00425       p_dst->v[i][2]=p_src->v[i][2];
00426     }
00427 
00428   NEW(p_dst->nvf,p_dst->nf,unsigned int);
00429   NEW(p_dst->fv,p_dst->nf,unsigned int*);
00430   for(i=0;i<p_dst->nf;i++)
00431     {
00432       p_dst->nvf[i]=p_src->nvf[i];
00433       NEW(p_dst->fv[i],p_dst->nvf[i],unsigned int);
00434 
00435       for(j=0;j<p_dst->nvf[i];j++)
00436         p_dst->fv[i][j]=p_src->fv[i][j];
00437     }
00438 
00439   /*Sphere - Cylinder information*/
00440   p_dst->rad=p_src->rad;
00441   for(i=0;i<3;i++)
00442     {
00443       p_dst->center[i]=p_src->center[i];
00444       p_dst->p1[i]=p_src->p1[i];
00445       p_dst->p2[i]=p_src->p2[i];
00446     }
00447 
00448   p_dst->maxCoord=p_src->maxCoord;
00449 }
00450 
00451 void TransformCPolyhedron(THTransform *t,Tcpolyhedron *p)
00452 {
00453   unsigned int i,j;
00454   double av;
00455 
00456   /*Off information*/
00457   p->maxCoord=0;
00458   for(i=0;i<p->nv;i++)
00459     {
00460       HTransformApply(p->v[i],p->v[i],t);
00461       for(j=0;j<3;j++)
00462         {
00463           av=fabs(p->v[i][j]);
00464           if (av>p->maxCoord)
00465             p->maxCoord=av;
00466         }
00467     }
00468 
00469   /*Sphere - Cylinder information*/
00470   HTransformApply(p->center,p->center,t);
00471   HTransformApply(p->p1,p->p1,t);
00472   HTransformApply(p->p2,p->p2,t);
00473 }
00474 
00475 unsigned int GetCPolyhedronType(Tcpolyhedron *p)
00476 {
00477   return(p->type);
00478 }
00479 
00480 void SetCPolyhedronColor(Tcolor *c,Tcpolyhedron *p)
00481 {
00482   CopyColor(&(p->color),c);
00483 }
00484 
00485 void GetCPolyhedronColor(Tcolor *c,Tcpolyhedron *p)
00486 {
00487   CopyColor(c,&(p->color));
00488 }
00489 
00490 unsigned int GetCPolyhedronNVertex(Tcpolyhedron *p)
00491 {
00492   return(p->nv);
00493 }
00494 
00495 void GetCPolyhedronDefiningPoint(unsigned int i,double *point,Tcpolyhedron *p)
00496 {
00497   unsigned int j;
00498 
00499   switch(p->type)
00500     {
00501     case CYLINDER:
00502       if (i>1)
00503         Error("Vertex counter out of range in GetCPolyhedronInterestPoint");
00504       
00505       if (i==0)
00506         {
00507           for(j=0;j<3;j++)
00508             point[j]=p->p1[j];
00509         }
00510       else
00511         {
00512           for(j=0;j<3;j++)
00513             point[j]=p->p2[j];
00514         }
00515       break;
00516 
00517     case SPHERE:
00518       if (i>0)
00519         Error("Vertex counter out of range in GetCPolyhedronInterestPoint");
00520       
00521       for(j=0;j<3;j++)
00522         point[j]=p->center[j];
00523       break;
00524 
00525     case OFF:
00526       GetCPolyhedronVertex(i,point,p);
00527       break;
00528 
00529     default:
00530       Error("Undefined CPolyhedron type in GetCPolyhedronInterestPoint");
00531       break;
00532     }
00533 }
00534 
00535 double GetCpolyhedronRadius(Tcpolyhedron *p)
00536 {
00537   if (p->type==OFF)
00538     Error("Radius is not defined for OFFs");
00539   return(p->rad);
00540 }
00541 
00542 void GetCPolyhedronVertex(unsigned int i,double *point,Tcpolyhedron *p)
00543 {
00544   unsigned int j;
00545 
00546   if (i>=p->nv)
00547     Error("Vertex counter out of range");
00548 
00549   for(j=0;j<3;j++)
00550     point[j]=p->v[i][j];
00551 }
00552 
00553 double GetCPolyhedronMaxCoordinate(Tcpolyhedron *p)
00554 {
00555   return(p->maxCoord);
00556 }
00557 
00558 void PlotCPolyhedron(Tplot3d *pt,Tcpolyhedron *p)
00559 {
00560   p->obj3d=StartNew3dObject(&(p->color),pt);
00561 
00562   switch(p->type)
00563     {
00564     case OFF:
00565       Plot3dObject(p->nv,p->nf,p->ne,p->v,p->nvf,p->fv,pt);                                     
00566       break;
00567     case CYLINDER:
00568       PlotCylinder(p->rad,p->p1,p->p2,pt);
00569       /*
00570         {
00571         unsigned int i;
00572 
00573         for(i=0;i<p->nv;i++)
00574         PlotSphere(0.015,p->v[i][0],p->v[i][1],p->v[i][2],pt);
00575         }
00576       */
00577       break;
00578     case SPHERE:
00579       PlotSphere(p->rad,p->center[0],p->center[1],p->center[2],pt);
00580       /*
00581         {
00582         unsigned int i;
00583 
00584         for(i=0;i<p->nv;i++)
00585         PlotSphere(0.015,p->v[i][0],p->v[i][1],p->v[i][2],pt);
00586         }
00587       */
00588       break;
00589     }
00590   
00591   Close3dObject(pt);
00592 }
00593 
00594 void MoveCPolyhedron(Tplot3d *pt,THTransform *t,Tcpolyhedron *p)
00595 {
00596   if (p->obj3d!=NO_UINT)
00597     Move3dObject(p->obj3d,t,pt);
00598 }
00599 
00600 void SaveCPolyhedron(char *fileName,Tcpolyhedron *p)
00601 {
00602   FILE *f;
00603   unsigned int i,j;
00604   
00605   f=fopen(fileName,"w");
00606   if (!f)
00607     Error("Could not open output file for a convex polyhedron");
00608 
00609   switch(p->type)
00610     {
00611     case OFF:
00612       fprintf(f,"OFF\n");
00613       fprintf(f,"%u %u 1\n\n",p->nv,p->nf);
00614       for(i=0;i<p->nv;i++)
00615         fprintf(f,"%f %f %f\n",p->v[i][0],p->v[i][1],p->v[i][2]);
00616       fprintf(f,"\n");
00617       for(i=0;i<p->nf;i++)
00618         {
00619           fprintf(f,"%u ",p->nvf[i]);
00620           for(j=0;j<p->nvf[i];j++)
00621             fprintf(f," %u",p->fv[i][j]);
00622           fprintf(f,"\n");
00623         }
00624       break;
00625     case CYLINDER:
00626       fprintf(f,"CYLINDER\n");
00627       fprintf(f,"%f\n",p->rad);
00628       fprintf(f,"%f %f %f\n",p->p1[0],p->p1[1],p->p1[2]);
00629       fprintf(f,"%f %f %f\n",p->p2[0],p->p2[1],p->p2[2]);
00630       break;
00631     case SPHERE:
00632       fprintf(f,"SPHERE\n");
00633       fprintf(f,"%f\n",p->rad);
00634       fprintf(f,"%f %f %f\n",p->center[0],p->center[1],p->center[2]);
00635       break;
00636     }
00637 
00638   fclose(f);
00639 }
00640 
00641 void DeleteCPolyhedron(Tcpolyhedron *p)
00642 {
00643   unsigned int i;
00644 
00645   for(i=0;i<p->nv;i++)
00646     free(p->v[i]);
00647   free(p->v);
00648 
00649   if (p->nf>0)
00650     {
00651       for(i=0;i<p->nf;i++)
00652         free(p->fv[i]);
00653       
00654       free(p->fv);
00655       free(p->nvf);
00656     }
00657 }
00658 
00659