Show
Ignore:
Timestamp:
08/26/10 14:42:43 (21 months ago)
Author:
farhi
Message:

interoff-lib.c: update documentation, OFF display, remove 'define' functions

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/lib/share/interoff-lib.c

    r2416 r2913  
    1515* Version: McStas X.Y 
    1616* 
    17 * Object File Format intersection library for McStas. 
     17* Object File Format intersection library for McStas. Requires the qsort function. 
     18* 
     19* Such files may be obtained with e.g. 
     20*   qhull < points.xyz Qx Qv Tv o > points.off 
     21* where points.xyz has format (it supports comments): 
     22*   3 
     23*   <nb_points> 
     24*   <x> <y> <z> 
     25*   ... 
     26* The resulting file should have its first line being changed from '3' into 'OFF'. 
     27* It can then be displayed with geomview. 
     28* A similar, but somewhat older solution is to use 'powercrust' with e.g. 
     29*   powercrust -i points.xyz 
     30* which will generate a 'pc.off' file to be renamed as suited. 
    1831* 
    1932*******************************************************************************/ 
     
    2336#endif 
    2437 
     38double off_F(double x, double y,double z,double A,double B,double C,double D) { 
     39  return ( A*x + B*y + C*z + D ); 
     40} 
     41 
     42char off_sign(double a) {  
     43  if (a<0)       return(-1); 
     44  else if (a==0) return(0); 
     45  else           return(1); 
     46} 
     47 
     48// off_normal ****************************************************************** 
    2549//gives the normal vector of p 
    2650void off_normal(Coords* n, polygon p) 
    2751{ 
    28         //using Newell method   
    29   int i,j; 
     52  //using Newell method   
     53  int i=0,j=0; 
    3054  n->x=0;n->y=0;n->z=0; 
    31   for(i = 0, j = p.npol-1; i < p.npol; j = i++) 
     55  for (i = 0, j = p.npol-1; i < p.npol; j = i++) 
    3256  { 
    3357    MCNUM x1=p.p[3*i], 
    34            y1=p.p[3*i+1],  
    35            z1=p.p[3*i+2]; 
     58          y1=p.p[3*i+1],  
     59          z1=p.p[3*i+2]; 
    3660    MCNUM x2=p.p[3*j], 
    37            y2=p.p[3*j+1],  
    38            z2=p.p[3*j+2]; 
     61          y2=p.p[3*j+1],  
     62          z2=p.p[3*j+2]; 
    3963    // n is the cross product of v1*v2 
    4064    n->x += (y1 - y2) * (z1 + z2); 
    41           n->y += (z1 - z2) * (x1 + x2); 
    42           n->z += (x1 - x2) * (y1 + y2); 
    43   } 
    44 } 
    45  
    46  
     65    n->y += (z1 - z2) * (x1 + x2); 
     66    n->z += (x1 - x2) * (y1 + y2); 
     67  } 
     68} /* off_normal */ 
     69 
     70// off_pnpoly ****************************************************************** 
    4771//based on http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html 
    4872//return 0 if the vertex is out 
     
    5175int off_pnpoly(polygon p, Coords v) 
    5276{ 
    53       int i, j, c = 0; 
    54       MCNUM minx=FLT_MAX,maxx=-FLT_MAX,miny=FLT_MAX,maxy=-FLT_MAX,minz=FLT_MAX,maxz=-FLT_MAX; 
    55       MCNUM rangex,rangey,rangez; 
    56  
    57       int pol2dx,pol2dy;          //2d restriction of the poly 
    58       MCNUM x=v.x,y=v.y; 
    59  
    60  
    61       //take the most relevant 2D projection (prevent from instability) 
    62       for(i=0;i<p.npol;++i) 
    63       { 
    64         if(p.p[3*i]<minx)minx=p.p[3*i]; 
    65         if(p.p[3*i]>maxx)maxx=p.p[3*i]; 
    66         if(p.p[3*i+1]<miny)miny=p.p[3*i+1]; 
    67         if(p.p[3*i+1]>maxy)maxy=p.p[3*i+1]; 
    68         if(p.p[3*i+2]<minz)minz=p.p[3*i+2]; 
    69         if(p.p[3*i+2]>maxz)maxz=p.p[3*i+2];   
    70       } 
    71       rangex=maxx-minx; 
    72       rangey=maxy-miny; 
    73       rangez=maxz-minz; 
    74  
    75       pol2dx=0; 
    76       pol2dy=1; 
    77       if(rangex<rangez) 
    78       { 
    79         if(rangex<rangey) { 
    80           pol2dx=2;     
    81           x=v.z; 
    82         } else { 
    83           pol2dy=2; 
    84           y=v.z; 
    85         } 
    86       } 
    87       else if(rangey<rangez) { 
    88         pol2dy=2; 
    89         y=v.z;     
    90       } 
    91   
    92       //trace rays and test number of intersection 
    93       for (i = 0, j = p.npol-1; i < p.npol; j = i++) { 
    94         if (((((p.p[3*i+pol2dy])<=y) && (y<(p.p[3*j+pol2dy]))) || 
    95              (((p.p[3*j+pol2dy])<=y) && (y<(p.p[3*i+pol2dy])))) && 
    96             (x < ( (p.p[3*j+pol2dx] - p.p[3*i+pol2dx]) * (y - p.p[3*i+pol2dy])  
    97                  / (p.p[3*j+pol2dy] - p.p[3*i+pol2dy]) + p.p[3*i+pol2dx]) ))   
    98           c = !c; 
    99  
    100         if (((fabs(p.p[3*i+pol2dy]-y)<=EPSILON) || ((fabs(p.p[3*j+pol2dy]-y)<=EPSILON))) && 
    101             fabs(x -((p.p[3*j+pol2dx] - p.p[3*i+pol2dx]) * (y - p.p[3*i+pol2dy])  
    102               / (p.p[3*j+pol2dy] - p.p[3*i+pol2dy]) + p.p[3*i+pol2dx])) < EPSILON) 
    103         { 
    104           //the point lies on the edge 
    105           c=-1; 
    106           break; 
    107         } 
    108       } 
    109       //free(polx); 
    110       //free(poly); 
    111  
    112       return c; 
    113 } 
    114  
     77  int i=0, c = 0; 
     78  MCNUM minx=FLT_MAX,maxx=-FLT_MAX,miny=FLT_MAX,maxy=-FLT_MAX,minz=FLT_MAX,maxz=-FLT_MAX; 
     79  MCNUM rangex=0,rangey=0,rangez=0; 
     80 
     81  int pol2dx=0,pol2dy=1;          //2d restriction of the poly 
     82  MCNUM x=v.x,y=v.y; 
     83 
     84 
     85  //take the most relevant 2D projection (prevent from instability) 
     86  for (i=0; i<p.npol; ++i) 
     87  { 
     88    if (p.p[3*i]<minx)   minx=p.p[3*i]; 
     89    if (p.p[3*i]>maxx)   maxx=p.p[3*i]; 
     90    if (p.p[3*i+1]<miny) miny=p.p[3*i+1]; 
     91    if (p.p[3*i+1]>maxy) maxy=p.p[3*i+1]; 
     92    if (p.p[3*i+2]<minz) minz=p.p[3*i+2]; 
     93    if (p.p[3*i+2]>maxz) maxz=p.p[3*i+2];   
     94  } 
     95  rangex=maxx-minx; 
     96  rangey=maxy-miny; 
     97  rangez=maxz-minz; 
     98 
     99  if (rangex<rangez) 
     100  { 
     101    if (rangex<rangey) { 
     102      pol2dx=2;     
     103      x=v.z; 
     104    } else { 
     105      pol2dy=2; 
     106      y=v.z; 
     107    } 
     108  } 
     109  else if (rangey<rangez) { 
     110    pol2dy=2; 
     111    y=v.z;     
     112  } 
     113 
     114  //trace rays and test number of intersection 
     115  int j; 
     116  for (i = 0, j = p.npol-1; i < p.npol; j = i++) { 
     117    if (((((p.p[3*i+pol2dy])<=y) && (y<(p.p[3*j+pol2dy]))) || 
     118         (((p.p[3*j+pol2dy])<=y) && (y<(p.p[3*i+pol2dy])))) && 
     119        (x < ( (p.p[3*j+pol2dx] - p.p[3*i+pol2dx]) * (y - p.p[3*i+pol2dy])  
     120             / (p.p[3*j+pol2dy] - p.p[3*i+pol2dy]) + p.p[3*i+pol2dx]) ))   
     121      c = !c; 
     122 
     123    if (((fabs(p.p[3*i+pol2dy]-y)<=EPSILON) || ((fabs(p.p[3*j+pol2dy]-y)<=EPSILON))) && 
     124        fabs(x -((p.p[3*j+pol2dx] - p.p[3*i+pol2dx]) * (y - p.p[3*i+pol2dy])  
     125          / (p.p[3*j+pol2dy] - p.p[3*i+pol2dy]) + p.p[3*i+pol2dx])) < EPSILON) 
     126    { 
     127      //the point lies on the edge 
     128      c=-1; 
     129      break; 
     130    } 
     131  } 
     132 
     133  return c; 
     134} /* off_pnpoly */ 
     135 
     136// off_intersectPoly *********************************************************** 
    115137//gives the intersection vertex between ray [a,b) and polygon p and its parametric value on (a b) 
    116138//based on http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm 
     
    118140{ 
    119141  //direction vector of [a,b] 
    120   Coords dir; 
    121   dir.x = (b.x-a.x); 
    122   dir.y = (b.y-a.y); 
    123   dir.z = (b.z-a.z); 
     142  Coords dir = {b.x-a.x, b.y-a.y, b.z-a.z}; 
    124143   
    125144  //the normal vector to the polygon 
    126145  Coords normale=p.normal; 
    127   //off_normal(&normale, p);        
     146  //off_normal(&normale, p); done at the init stage 
    128147   
    129148  //direction vector from a to a vertex of the polygon 
    130   Coords w0; 
    131   w0.x = (a.x-p.p[0]); 
    132   w0.y = (a.y-p.p[1]); 
    133   w0.z = (a.z-p.p[2]); 
     149  Coords w0 = {a.x-p.p[0], a.y-p.p[1], a.z-p.p[2]}; 
    134150 
    135151  //scalar product 
    136   MCNUM nw0 = -scalar_prod(normale.x,normale.y,normale.z,w0.x,w0.y,w0.z); 
     152  MCNUM nw0  =-scalar_prod(normale.x,normale.y,normale.z,w0.x,w0.y,w0.z); 
    137153  MCNUM ndir = scalar_prod(normale.x,normale.y,normale.z,dir.x,dir.y,dir.z); 
    138   if (fabs(ndir) < EPSILON)          // ray is parallel to polygon plane 
     154  inter->time = inter->edge = inter->in_out=0; 
     155  inter->v = inter->normal = coords_set(0,0,1); 
     156 
     157  if (fabs(ndir) < EPSILON)    // ray is parallel to polygon plane 
    139158  {      
    140     if (nw0 == 0)                // ray lies in polygon plane (infinite number of solution) 
    141         return 0; 
     159    if (nw0 == 0)              // ray lies in polygon plane (infinite number of solution) 
     160      return 0; 
    142161    else return 0;             // ray disjoint from plane (no solution) 
    143162  } 
     
    146165  inter->time = nw0 / ndir;            //parametric value the point on line (a,b) 
    147166 
    148   //printf("----------t=%f",*t); 
    149   inter->v.x = a.x + inter->time * dir.x;// intersect point of ray and plane 
    150   inter->v.y = a.y + inter->time * dir.y;// 
    151   inter->v.z = a.z + inter->time * dir.z;// 
     167  inter->v = coords_set(a.x + inter->time * dir.x,// intersect point of ray and plane 
     168    a.y + inter->time * dir.y, 
     169    a.z + inter->time * dir.z); 
    152170         
    153171  int res=off_pnpoly(p,inter->v); 
    154172   
    155173  inter->edge=(res==-1); 
    156   if(ndir<0) 
    157     inter->in_out=1;    //the negative dot product means we enter the surface 
     174  if (ndir<0) 
     175    inter->in_out=1;  //the negative dot product means we enter the surface 
    158176  else 
    159177    inter->in_out=-1; 
     
    161179  inter->normal=p.normal; 
    162180 
    163   return res;  //true if the intersection point lies inside the poly 
    164 } 
    165  
    166  
    167  
     181  return res;         //true if the intersection point lies inside the poly 
     182} /* off_intersectPoly */ 
     183 
     184 
     185// off_getBlocksIndex ********************************************************** 
    168186/*reads the indexes at the beginning of the off file as this : 
    169187line 1  OFF 
     
    172190long off_getBlocksIndex(char* filename, long* vtxIndex, long* vtxSize, long* faceIndex, long* polySize ) 
    173191{ 
    174   if (!filename)  return(0); 
     192  if (!filename)             return(0); 
    175193  if (strlen(filename) == 0) return (0); 
    176194  if (!strcmp(filename,"NULL") || !strcmp(filename,"0"))  return(0); 
    177195  FILE* f = fopen(filename,"r"); 
    178   if(!f) { 
    179     char mc_rt_path[256]; 
    180     char mc_rt_dir[256]; 
     196  if (!f) { 
     197    char mc_rt_path[CHAR_BUF_LENGTH]; 
     198    char mc_rt_dir[CHAR_BUF_LENGTH]; 
    181199 
    182200    if (!f) 
     
    192210      f = fopen(mc_rt_path, "r"); 
    193211    } 
    194     if(!f) 
     212    if (!f) 
    195213    { 
    196214      fprintf(stderr, "Error: Could not open input file '%s' (interoff/off_getBlocksIndex)\n", filename); 
     
    199217  } 
    200218   
    201   printf("Loading file: %s\n",filename); 
    202   char line[buf]; 
    203   char *ret; 
    204    *vtxIndex=0; 
    205   *vtxSize=0; 
    206   *faceIndex=0; 
    207   ret=fgets(line,buf , f);// line 1 = "OFF" 
    208   if(ret == NULL) 
    209     { 
    210       fprintf(stderr, "Error: Can not read 1st line in file %s (interoff/off_getBlocksIndex)\n", filename); 
    211       exit(1); 
    212     } 
    213  
    214   if(strncmp(line,"OFF",3)) 
    215   { 
    216     fprintf(stderr, "Error: %s is probably not an OFF or NOFF file (interoff/off_getBlocksIndex)\n",filename); 
     219  printf("Loading geometry file: %s\n", filename); 
     220  char line[CHAR_BUF_LENGTH]; 
     221  char *ret=0; 
     222  *vtxIndex = *vtxSize  = *faceIndex=0; 
     223  ret=fgets(line,CHAR_BUF_LENGTH , f);// line 1 = "OFF" 
     224  if (ret == NULL) 
     225  { 
     226    fprintf(stderr, "Error: Can not read 1st line in file %s (interoff/off_getBlocksIndex)\n", filename); 
     227    exit(1); 
     228  } 
     229 
     230  if (strncmp(line,"OFF",3) && strncmp(line,"3",1)) 
     231  { 
     232    fprintf(stderr, "Error: %s is probably not an OFF or NOFF file (interoff/off_getBlocksIndex).\n" 
     233                    "       Requires first line to be 'OFF' or '3'.\n",filename); 
     234    fclose(f); 
    217235    return(0); 
    218236  } 
     
    220238  *vtxIndex+= strlen(line); 
    221239         
    222   do  /* skip comments */ 
    223   { 
    224     ret=fgets(line,buf , f); 
    225     if(ret == NULL) 
     240  do  /* skip # comments which may be there */ 
     241  { 
     242    ret=fgets(line,CHAR_BUF_LENGTH , f); 
     243    if (ret == NULL) 
    226244    { 
    227245      fprintf(stderr, "Error: Can not read line in file %s (interoff/off_getBlocksIndex)\n", filename); 
     
    229247    } 
    230248    *vtxIndex+= strlen(line); 
    231   } 
    232   while(line[0]=='#'); 
     249  } while (line[0]=='#'); 
    233250   
    234251  //line = nblines of vertex,faces and edges arrays 
     
    236253 
    237254  *faceIndex=*vtxIndex; 
    238   int i; 
    239   for(i=0;i<*vtxSize;) 
     255  int i=0; 
     256  for (i=0; i<*vtxSize; ) 
    240257  {                               
    241     ret=fgets(line,buf,f); 
    242     if(ret == NULL) 
     258    ret=fgets(line,CHAR_BUF_LENGTH,f); 
     259    if (ret == NULL) 
    243260    { 
    244261      fprintf(stderr, "Error: Can not read vertex %i in file %s (interoff/off_getBlocksIndex)\n", i, filename); 
     
    246263    } 
    247264    *faceIndex+=strlen(line);  
    248     if(line[0]!='#')i++;                
     265    if (line[0]!='#') i++;                
    249266  } 
    250267  
    251268  fclose(f); 
    252269  return(*vtxIndex); 
    253 } 
    254  
    255  
     270} /* off_getBlocksIndex */ 
     271 
     272// off_init_planes ************************************************************* 
    256273//gives the equations of 2 perpandicular planes of [ab] 
    257274void off_init_planes(Coords a, Coords b,  
     
    262279   
    263280  //the plane parallel to the 'y' is computed with the normal vector of the projection of [ab] on plane 'xz'   
    264   *A1=dir.z; 
     281  *A1= dir.z; 
    265282  *C1=-dir.x; 
    266283  if(*A1!=0 || *C1!=0) 
    267     *D1=-(a.x)**A1-(a.z)**C1; 
     284    *D1=-(a.x)*(*A1)-(a.z)*(*C1); 
    268285  else 
    269286  { 
    270     //the plane do not suppoindPolyrt the vector, take the one parallel to 'z'' 
     287    //the plane does not support the vector, take the one parallel to 'z'' 
    271288    *A1=1; 
    272289    //B1=dir.x=0 
     
    274291  } 
    275292  //the plane parallel to the 'x' is computed with the normal vector of the projection of [ab] on plane 'yz'   
    276   *B2=dir.z; 
     293  *B2= dir.z; 
    277294  *C2=-dir.y; 
    278   *A2=0; 
    279   if(*B2==0 && *C2==0) 
    280   { 
    281     //the plane do not support the vector, take the one parallel to 'z' 
     295  *A2= 0; 
     296  if (*B2==0 && *C2==0) 
     297  { 
     298    //the plane does not support the vector, take the one parallel to 'z' 
    282299    *B2=1; 
    283300    //B1=dir.x=0 
     
    285302  } 
    286303  else { 
    287     if(dir.z==0) 
     304    if (dir.z==0) 
    288305    { 
    289306      //the planes are the same, take the one parallel to 'z' 
    290       *A2=dir.y; 
     307      *A2= dir.y; 
    291308      *B2=-dir.x; 
    292       *D2=-(a.x)**A2-(a.y)**B2;  
     309      *D2=-(a.x)*(*A2)-(a.y)*(*B2);  
    293310    } 
    294311    else 
    295312      *D2=-(a.y)**B2-(a.z)**C2; 
    296313  } 
    297   //printf("F1=%f\n",F(b,*A1,0,*C1,*D1)); 
    298   //printf("F2=%f\n",F(b,*A2,*B2,*C2,*D2)); 
    299 } 
    300  
    301  
     314} /* off_init_planes */ 
     315 
     316// off_clip_3D_mod ************************************************************* 
    302317int off_clip_3D_mod(intersection* t, Coords a, Coords b,  
    303318  Coords* vtxArray, unsigned long vtxSize, unsigned long* faceArray,  
    304319  unsigned long faceSize, Coords* normalArray) 
    305320{ 
    306   MCNUM A1, C1, D1, A2, B2, C2, D2;      //perpendicular plane equations to [a,b] 
    307   off_init_planes(a, b, &A1, &C1, &D1, &A2, &B2, &C2, &D2);  //   
     321  MCNUM A1=0, C1=0, D1=0, A2=0, B2=0, C2=0, D2=0;      //perpendicular plane equations to [a,b] 
     322  off_init_planes(a, b, &A1, &C1, &D1, &A2, &B2, &C2, &D2); 
    308323   
    309324  int t_size=0; 
    310325  //unsigned long vtxSize=vtxTable.rows, faceSize=faceTable.columns;  //Size of the corresponding tables 
    311326  char sg[vtxSize];  //array telling if vertex is left or right of the plane 
    312   MCNUM popol[3*MAX_POL_SIZE]; 
    313   unsigned long i,indPoly; 
    314   for(i=0; i < vtxSize;++i) 
    315   { 
    316     sg[i]=sign(F(vtxArray[i].x,vtxArray[i].y,vtxArray[i].z,A1,0,C1,D1)); 
     327  MCNUM popol[3*CHAR_BUF_LENGTH]; 
     328  unsigned long i=0,indPoly=0; 
     329  for (i=0; i < vtxSize; ++i) 
     330  { 
     331    sg[i]=off_sign(off_F(vtxArray[i].x,vtxArray[i].y,vtxArray[i].z,A1,0,C1,D1)); 
    317332  } 
    318333   
    319334  //exploring the polygons : 
    320   i=0;indPoly=0; 
    321   while(i<faceSize) 
    322   {   
     335  i=indPoly=0; 
     336  while (i<faceSize) 
     337  { 
    323338    polygon pol; 
    324     pol.npol=faceArray[i];          //nb vertex of polygon 
    325          
    326     pol.p=popol; 
    327     unsigned long indVertP1=faceArray[++i];      //polygon's first vertex index in vtxTable 
     339    pol.npol  = faceArray[i];                //nb vertex of polygon 
     340    pol.p     = popol; 
     341    pol.normal= coords_set(0,0,1); 
     342    unsigned long indVertP1=faceArray[++i];  //polygon's first vertex index in vtxTable 
    328343    int j=1; 
    329     while(j<pol.npol) 
    330     { 
    331                   //polygon's j-th vertex index in vtxTable 
    332       if(sg[indVertP1]!=sg[faceArray[i+j]])    //if the plane intersect the polygon 
     344    while (j<pol.npol) 
     345    { 
     346      //polygon's j-th vertex index in vtxTable 
     347      if (sg[indVertP1]!=sg[faceArray[i+j]]) //if the plane intersect the polygon 
    333348        break;   
    334349 
     
    336351    } 
    337352     
    338     if((j<pol.npol))          //ok, let's test with the second plane 
    339     {   
    340       char sg1=sign(F(vtxArray[indVertP1].x,vtxArray[indVertP1].y,vtxArray[indVertP1].z,A2,B2,C2,D2));//tells if vertex is left or right of the plane   
     353    if (j<pol.npol)          //ok, let's test with the second plane 
     354    { 
     355      char sg1=off_sign(off_F(vtxArray[indVertP1].x,vtxArray[indVertP1].y,vtxArray[indVertP1].z,A2,B2,C2,D2));//tells if vertex is left or right of the plane   
    341356       
    342       j=1;     
    343       while(j<pol.npol) 
     357      j=1; 
     358      while (j<pol.npol) 
    344359      { 
    345360        //unsigned long indVertPi=faceArray[i+j];  //polyg's j-th vertex index in vtxTable     
    346361        Coords vertPi=vtxArray[faceArray[i+j]]; 
    347         if(sg1!=sign(F(vertPi.x,vertPi.y,vertPi.z,A2,B2,C2,D2)))//if the plane intersect the polygon 
     362        if (sg1!=off_sign(off_F(vertPi.x,vertPi.y,vertPi.z,A2,B2,C2,D2)))//if the plane intersect the polygon 
    348363          break; 
    349364        ++j; 
    350365      } 
    351       if(j<pol.npol) 
    352       {   
    353         if(t_size>MAX_INTERSECTION_SIZE) 
     366      if (j<pol.npol) 
     367      { 
     368        if (t_size>CHAR_BUF_LENGTH) 
    354369        { 
    355           fprintf(stderr, "Error: number of intersection exceeded (%d)\n", MAX_INTERSECTION_SIZE); 
    356                 return (0); 
     370          fprintf(stderr, "Warning: number of intersection exceeded (%d) (interoff-lib/off_clip_3D_mod)\n", CHAR_BUF_LENGTH); 
     371            return (t_size); 
    357372        } 
    358373        //both planes intersect the polygon, let's find the intersection point 
    359374        //our polygon : 
    360375        int k; 
    361         for(k=0;k<pol.npol;++k) 
     376        for (k=0; k<pol.npol; ++k) 
    362377        {   
    363378          Coords vertPk=vtxArray[faceArray[i+k]]; 
    364           pol.p[3*k]=vertPk.x; 
     379          pol.p[3*k]  =vertPk.x; 
    365380          pol.p[3*k+1]=vertPk.y; 
    366381          pol.p[3*k+2]=vertPk.z; 
    367382        } 
    368         pol.normal=normalArray[indPoly];   
     383        pol.normal=normalArray[indPoly]; 
    369384        intersection x; 
    370         if(off_intersectPoly(&x, a, b, pol)) 
     385        if (off_intersectPoly(&x, a, b, pol)) 
    371386        {             
    372387          t[t_size++]=x; 
    373388        }           
    374       }   
    375     } 
    376     i+=pol.npol; 
     389      } /* if (j<pol.npol) */ 
     390    } /* if (j<pol.npol) */ 
     391    i += pol.npol; 
    377392    indPoly++; 
    378   } 
     393  } /* while i<faceSize */ 
    379394  return t_size; 
    380 } 
    381  
    382  
    383  
     395} /* off_clip_3D_mod */ 
     396 
     397 
     398// off_compare ***************************************************************** 
    384399int off_compare (void const *a, void const *b) 
    385400{ 
     
    387402   intersection const *pb = b; 
    388403 
    389    return sign(pa->time - pb->time); 
    390 } 
    391  
     404   return off_sign(pa->time - pb->time); 
     405} /* off_compare */ 
     406 
     407// off_cleanDouble ************************************************************* 
    392408//given an array of intesction throw those which appear several times 
    393409//returns 1 if there is a possibility of error 
     
    395411{ 
    396412  int i=1; 
    397   intersection prev; 
    398   prev=t[0]; 
    399   while(i<*t_size)   
     413  intersection prev=t[0]; 
     414  while (i<*t_size)   
    400415  { 
    401416    int j=i; 
    402417    //for each intersection with the same time 
    403     while(j<*t_size && fabs(prev.time-t[j].time)<EPSILON) 
     418    while (j<*t_size && fabs(prev.time-t[j].time)<EPSILON) 
    404419    { 
    405420      //if the intersection is the exact same erase it 
    406       if(prev.in_out==t[j].in_out) 
     421      if (prev.in_out==t[j].in_out) 
    407422      { 
    408423        int k;       
    409         for(k=j+1;k<*t_size;++k) 
     424        for (k=j+1; k<*t_size; ++k) 
    410425        { 
    411426          t[k-1]=t[k]; 
     
    421436  } 
    422437  return 1; 
    423 } 
    424  
    425  
    426 //given an array of intesction throw those which enter and exit in the same time 
     438} /* off_cleanDouble */ 
     439 
     440// off_cleanInOut ************************************************************** 
     441//given an array of intesections throw those which enter and exit in the same time 
    427442//Meaning the ray passes very close to the volume 
    428443//returns 1 if there is a possibility of error 
     
    430445{ 
    431446  int i=1; 
    432   intersection prev; 
    433   prev=t[0]; 
    434   while(i<*t_size)   
     447  intersection prev=t[0]; 
     448  while (i<*t_size)   
    435449  { 
    436450    //if two intersection have the same time but one enters and the other exits erase both 
    437451    //(such intersections must be adjacent in the array : run off_cleanDouble before) 
    438     if(fabs(prev.time-t[i].time)<EPSILON && prev.in_out!=t[i].in_out) 
    439     { 
    440       int j;     
    441       for(j=i+1;j<*t_size;++j) 
     452    if (fabs(prev.time-t[i].time)<EPSILON && prev.in_out!=t[i].in_out) 
     453    { 
     454      int j=0;     
     455      for (j=i+1; j<*t_size; ++j) 
    442456      { 
    443457        t[j-2]=t[j]; 
     
    452466    }     
    453467  } 
    454   return 1; 
    455 } 
     468  return (*t_size); 
     469} /* off_cleanInOut */ 
    456470 
    457471/* PUBLIC functions ******************************************************** */ 
    458472 
    459 long off_init(  char *offfile, double xwidth, double yheight, double zdepth, off_struct* datas) 
    460 { 
    461   //datas to be initialized 
    462   long faceSize; 
    463   long vtxSize; 
    464   long polySize;    
    465   Coords* vtxArray; 
    466   Coords* normalArray; 
    467   unsigned long* faceArray; 
    468  
     473/******************************************************************************* 
     474* long off_init(  char *offfile, double xwidth, double yheight, double zdepth, off_struct* data) 
     475* ACTION: read an OFF file, optionally center object and rescale, initialize OFF data structure 
     476* INPUT: 'offfile' OFF file to read 
     477*        'xwidth,yheight,zdepth' if given as non-zero, apply bounding box.  
     478*           Specifying only one of these will also use the same ratio on all axes 
     479*        'center' center the object to the (0,0,0) position in local frame when set to non-zero 
     480* RETURN: number of polyhedra and 'data' OFF structure  
     481*******************************************************************************/ 
     482long off_init(  char *offfile, double xwidth, double yheight, double zdepth,  
     483                int center, off_struct* data) 
     484{ 
     485  //data to be initialized 
     486  long faceSize=0, vtxSize =0, polySize=0, vtxIndex=0, faceIndex=0;   
     487  Coords* vtxArray        =NULL; 
     488  Coords* normalArray     =NULL; 
     489  unsigned long* faceArray=NULL; 
    469490  t_Table vtxTable, faceTable; 
    470   long vtxIndex, faceIndex; 
    471491 
    472492  double minx=FLT_MAX,maxx=-FLT_MAX,miny=FLT_MAX,maxy=-FLT_MAX,minz=FLT_MAX,maxz=-FLT_MAX; 
    473493 
    474494  // get the indexes 
    475   if (off_getBlocksIndex(offfile,&vtxIndex,&vtxSize,&faceIndex, &polySize) <=0)  
     495  if (!data || off_getBlocksIndex(offfile,&vtxIndex,&vtxSize,&faceIndex, &polySize) <=0)  
    476496    return(0); 
    477   printf("  Number of polygons: %ld\n",polySize); 
    478497  
    479498  //read vertex table = [x y z | x y z | ...] 
     
    484503 
    485504  //initialize Arrays 
    486   faceSize=faceTable.columns; 
    487   vtxArray=malloc(vtxSize*sizeof(Coords)); 
    488   normalArray=malloc(polySize*sizeof(Coords)); 
    489  
    490   long i,j; 
    491   for(i=0;i<vtxSize;++i) 
     505  faceSize   = faceTable.columns; 
     506   
     507  printf("  Number of polygons: %ld\n", polySize); 
     508  printf("  Number of vertices: %ld\n", vtxSize); 
     509   
     510  vtxArray   = malloc(vtxSize*sizeof(Coords)); 
     511  normalArray= malloc(polySize*sizeof(Coords)); 
     512  if (!vtxArray || !normalArray) return(0); 
     513 
     514  long i=0,j=0; 
     515  for(i=0; i<vtxSize; ++i) 
    492516  { 
    493517    vtxArray[i].x=Table_Index(vtxTable, i,0); 
     
    496520   
    497521    //bounding box 
    498     if(vtxArray[i].x<minx)minx=vtxArray[i].x; 
    499     if(vtxArray[i].x>maxx)maxx=vtxArray[i].x; 
    500     if(vtxArray[i].y<miny)miny=vtxArray[i].y; 
    501     if(vtxArray[i].y>maxy)maxy=vtxArray[i].y; 
    502     if(vtxArray[i].z<minz)minz=vtxArray[i].z; 
    503     if(vtxArray[i].z>maxz)maxz=vtxArray[i].z; 
    504   } 
    505  
    506         //resizing and repositioning params 
    507   double centrex=(minx+maxx)*0.5, 
    508   centrey=(miny+maxy)*0.5, 
    509   centrez=(minz+maxz)*0.5; 
     522    if (vtxArray[i].x<minx) minx=vtxArray[i].x; 
     523    if (vtxArray[i].x>maxx) maxx=vtxArray[i].x; 
     524    if (vtxArray[i].y<miny) miny=vtxArray[i].y; 
     525    if (vtxArray[i].y>maxy) maxy=vtxArray[i].y; 
     526    if (vtxArray[i].z<minz) minz=vtxArray[i].z; 
     527    if (vtxArray[i].z>maxz) maxz=vtxArray[i].z; 
     528  } 
     529 
     530  //resizing and repositioning params 
     531  double centerx=0, centery=0, centerz=0; 
     532  if (center) { 
     533    centerx=(minx+maxx)*0.5; 
     534    centery=(miny+maxy)*0.5; 
     535    centerz=(minz+maxz)*0.5; 
     536  } 
    510537   
    511538  double rangex=-minx+maxx, 
    512   rangey=-miny+maxy, 
    513   rangez=-minz+maxz; 
     539         rangey=-miny+maxy, 
     540         rangez=-minz+maxz; 
    514541 
    515542  double ratiox=1,ratioy=1,ratioz=1; 
    516543 
    517   if(xwidth) 
     544  if (xwidth && rangex) 
    518545  { 
    519546    ratiox=xwidth/rangex; 
     
    522549  } 
    523550 
    524   if(yheight) 
     551  if (yheight && rangey) 
    525552  { 
    526553    ratioy=yheight/rangey; 
     
    529556  } 
    530557 
    531   if(zdepth) 
     558  if (zdepth && rangez) 
    532559  { 
    533560    ratioz=zdepth/rangez; 
     
    536563  } 
    537564   
    538     
    539  
    540   //center  and resize the object  
    541   for(i=0;i<vtxSize;++i) 
    542   { 
    543     vtxArray[i].x=(vtxArray[i].x-centrex)*ratiox; 
    544     vtxArray[i].y=(vtxArray[i].y-centrey)*ratioy; 
    545     vtxArray[i].z=(vtxArray[i].z-centrez)*ratioz;         
     565  rangex *= ratiox; 
     566  rangey *= ratioy; 
     567  rangez *= ratioz; 
     568   
     569  //center and resize the object  
     570  for (i=0; i<vtxSize; ++i) 
     571  { 
     572    vtxArray[i].x=(vtxArray[i].x-centerx)*ratiox+(center ? 0 : centerx); 
     573    vtxArray[i].y=(vtxArray[i].y-centery)*ratioy+(center ? 0 : centery); 
     574    vtxArray[i].z=(vtxArray[i].z-centerz)*ratioz+(center ? 0 : centerz);         
    546575  } 
    547576 
    548577 
    549578  //table_read create a table on one line if the number of columns is not constant, so there are 2 cases : 
    550   if(faceTable.rows==1) 
     579  if (faceTable.rows==1) 
    551580  { 
    552581    //copy the table in a 1-row array 
    553582    faceArray=malloc(faceSize*sizeof(unsigned long)); 
    554     for(i=0;i<faceSize;++i) 
     583    if (!faceArray) return(0); 
     584    for (i=0; i<faceSize; ++i) 
    555585    { 
    556586      faceArray[i]=Table_Index(faceTable, 0, i); 
     
    561591    //read each row of the table and concatenate in a 1-row array 
    562592    faceArray=malloc(polySize*(faceSize)*sizeof(unsigned long)); 
    563     for(i=0;i<polySize;++i) 
    564     { 
    565       for(j=0;j<faceSize;++j) 
     593    if (!faceArray) return(0); 
     594    for(i=0; i<polySize; ++i) 
     595    { 
     596      for(j=0; j<faceSize; ++j) 
    566597        faceArray[i*(faceSize)+j]=Table_Index(faceTable, i, j); 
    567598    } 
     
    572603  long indNormal=0;//index in polyArray 
    573604  i=0;    //index in faceArray 
    574   while(i<faceSize) 
     605  while (i<faceSize) 
    575606  {   
    576     int nbVertex=faceArray[i];//nb of vertices of this polygon 
     607    int    nbVertex=faceArray[i];//nb of vertices of this polygon 
    577608    double vertices[3*nbVertex]; 
    578609    int j; 
    579610   
    580     for(j=0;j<nbVertex;++j) 
     611    for (j=0; j<nbVertex; ++j) 
    581612    { 
    582613      unsigned long indVertPj=faceArray[i+j+1]; 
    583       vertices[3*j]=vtxArray[indVertPj].x; 
     614      vertices[3*j]  =vtxArray[indVertPj].x; 
    584615      vertices[3*j+1]=vtxArray[indVertPj].y; 
    585616      vertices[3*j+2]=vtxArray[indVertPj].z; 
     
    587618     
    588619    polygon p;     
    589     p.p=vertices; 
     620    p.p   =vertices; 
    590621    p.npol=nbVertex; 
    591622    off_normal(&(p.normal),p); 
     
    593624    normalArray[indNormal]=p.normal; 
    594625   
    595     i+=nbVertex+1; 
     626    i += nbVertex+1; 
    596627    indNormal++;   
    597628   
    598629  } 
    599630 
    600    
    601   if(ratiox!=ratioy || ratiox!=ratioz || ratioy!=ratioz) 
    602     printf("Warning: Aspect ratio of the sample were modified.\n" 
     631  if (ratiox!=ratioy || ratiox!=ratioz || ratioy!=ratioz) 
     632    printf("Warning: Aspect ratio of the sample was modified.\n" 
    603633           "         If you want to keep the originial proportions, specifiy only one of the dimensions.\n"); 
    604634  printf("  Bounding box dimensions:\n"); 
    605   printf("    Length=%f (%.3f%%)\n",rangex*ratiox,ratiox*100); 
    606   printf("    Width= %f (%.3f%%)\n",rangey*ratioy,ratioy*100); 
    607   printf("    Depth= %f (%.3f%%)\n",rangez*ratioz,ratioz*100); 
    608  
    609   datas->vtxArray=vtxArray; 
    610   datas->normalArray=normalArray; 
    611   datas->faceArray=faceArray; 
    612   datas->vtxSize=vtxSize; 
    613   datas->polySize=polySize; 
    614   datas->faceSize=faceSize; 
     635  printf("    Length=%f (%.3f%%)\n", rangex*ratiox, ratiox*100); 
     636  printf("    Width= %f (%.3f%%)\n", rangey*ratioy, ratioy*100); 
     637  printf("    Depth= %f (%.3f%%)\n", rangez*ratioz, ratioz*100); 
     638 
     639  data->vtxArray   = vtxArray; 
     640  data->normalArray= normalArray; 
     641  data->faceArray  = faceArray; 
     642  data->vtxSize    = vtxSize; 
     643  data->polySize   = polySize; 
     644  data->faceSize   = faceSize; 
    615645  return(polySize); 
    616 } 
    617  
    618  
    619 int off_intersect(double* t0, double* t3, double x, double y, double z, double vx, double vy, double vz, off_struct datas ) 
    620 { 
    621     intersection t[MAX_INTERSECTION_SIZE]; 
     646} /* off_init */ 
     647 
     648/******************************************************************************* 
     649* int off_intersect(double* t0, double* t3,  
     650     Coords *n0, Coords *n3, 
     651     double x, double y, double z,  
     652     double vx, double vy, double vz,  
     653     off_struct data ) 
     654* ACTION: computes intersection of neutron trajectory with an object.  
     655* INPUT:  x,y,z and vx,vy,vz are the position and velocity of the neutron 
     656*         data points to the OFF data structure 
     657* RETURN: the number of polyhedra which trajectory intersects 
     658*         t0 and t3 are the smallest incoming and outgoing intersection times 
     659*         n0 and n3 are the corresponding normal vectors to the surface 
     660*******************************************************************************/ 
     661int off_intersect(double* t0, double* t3,  
     662     Coords *n0, Coords *n3, 
     663     double x,  double y,  double z,  
     664     double vx, double vy, double vz,  
     665     off_struct data ) 
     666{ 
     667    intersection t[CHAR_BUF_LENGTH]; 
    622668    Coords A={x, y, z}; 
    623669    Coords B={x+vx, y+vy, z+vz}; 
    624670    int t_size=off_clip_3D_mod(t, A, B, 
    625       datas.vtxArray, datas.vtxSize, datas.faceArray, datas.faceSize, datas.normalArray ); 
    626     qsort(t,t_size,sizeof(intersection),off_compare); 
    627     off_cleanDouble(t,&t_size); 
    628     off_cleanInOut(t,&t_size); 
    629  
    630     if(t_size>1)   
    631     {     
    632       *t0 = t[0].time; 
    633       *t3 = t[1].time; 
     671      data.vtxArray, data.vtxSize, data.faceArray, data.faceSize, data.normalArray ); 
     672    qsort(t, t_size, sizeof(intersection),  off_compare); 
     673    off_cleanDouble(t, &t_size); 
     674    off_cleanInOut(t,  &t_size); 
     675 
     676    if(t_size>0) 
     677    { 
     678      int i=0; 
     679      if (t0) *t0 = t[0].time; 
     680      if (n0) *n0 = t[0].normal;; 
     681      if(t_size>1) { 
     682        for (i=1; i < t_size; i++) 
     683          if (t[i].time > 0 && t[i].time > t[0].time) break; 
     684        if (t3) *t3 = t[i].time; 
     685        if (n3) *n3 = t[i].normal; 
     686      } 
    634687      return t_size; 
    635688    } 
    636689    return 0; 
    637 } 
    638  
    639 void off_display(off_struct datas) 
    640 { 
    641   int step=ceil((double)datas.vtxSize/N_VERTEX_DISPLAYED); 
     690} /* off_intersect */ 
     691 
     692/******************************************************************************* 
     693* void off_display(off_struct data) 
     694* ACTION: display up to N_VERTEX_DISPLAYED polygons from the object 
     695*******************************************************************************/ 
     696void off_display(off_struct data) 
     697{ 
    642698  unsigned int i; 
    643   for (i=0; i<datas.vtxSize-1; i+=step) { 
    644     double x1,y1,z1,x2,y2,z2; 
    645     x1 = datas.vtxArray[i].x; 
    646     y1 = datas.vtxArray[i].y; 
    647     z1 = datas.vtxArray[i].z; 
    648     x2 = datas.vtxArray[i].x+.0001; 
    649     y2 = datas.vtxArray[i].y+.0001; 
    650     z2 = datas.vtxArray[i].z+.0001; 
    651  
    652     mcdis_line(x1,y1,z1,x2,y2,z2); 
    653   } 
    654 } 
     699  double ratio=(double)(N_VERTEX_DISPLAYED)/(double)data.faceSize; 
     700  for (i=0; i<data.faceSize-1; i++) { 
     701    int j; 
     702    int nbVertex = data.faceArray[i]; 
     703    double x0,y0,z0; 
     704    x0 = data.vtxArray[data.faceArray[i+1]].x; 
     705    y0 = data.vtxArray[data.faceArray[i+1]].y; 
     706    z0 = data.vtxArray[data.faceArray[i+1]].z; 
     707    if (ratio > 1 || rand01() < ratio) { 
     708      double x1=x0,y1=y0,z1=z0; 
     709      for (j=2; j<=nbVertex; j++) { 
     710        double x2,y2,z2; 
     711        x2 = data.vtxArray[data.faceArray[i+j]].x; 
     712        y2 = data.vtxArray[data.faceArray[i+j]].y; 
     713        z2 = data.vtxArray[data.faceArray[i+j]].z; 
     714        mcdis_line(x1,y1,z1,x2,y2,z2); 
     715        x1 = x2; y1 = y2; z1 = z2; 
     716      } 
     717      mcdis_line(x1,y1,z1,x0,y0,z0); 
     718    } 
     719    i += nbVertex; 
     720  } 
     721} /* off_display */ 
     722 
    655723/* end of interoff-lib.c */ 
    656724