Changeset 2913 for trunk/lib/share/interoff-lib.c
- Timestamp:
- 08/26/10 14:42:43 (21 months ago)
- Files:
-
- 1 modified
-
trunk/lib/share/interoff-lib.c (modified) (31 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/share/interoff-lib.c
r2416 r2913 15 15 * Version: McStas X.Y 16 16 * 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. 18 31 * 19 32 *******************************************************************************/ … … 23 36 #endif 24 37 38 double 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 42 char 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 ****************************************************************** 25 49 //gives the normal vector of p 26 50 void off_normal(Coords* n, polygon p) 27 51 { 28 //using Newell method29 int i ,j;52 //using Newell method 53 int i=0,j=0; 30 54 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++) 32 56 { 33 57 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]; 36 60 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]; 39 63 // n is the cross product of v1*v2 40 64 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 ****************************************************************** 47 71 //based on http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html 48 72 //return 0 if the vertex is out … … 51 75 int off_pnpoly(polygon p, Coords v) 52 76 { 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 *********************************************************** 115 137 //gives the intersection vertex between ray [a,b) and polygon p and its parametric value on (a b) 116 138 //based on http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm … … 118 140 { 119 141 //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}; 124 143 125 144 //the normal vector to the polygon 126 145 Coords normale=p.normal; 127 //off_normal(&normale, p); 146 //off_normal(&normale, p); done at the init stage 128 147 129 148 //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]}; 134 150 135 151 //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); 137 153 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 139 158 { 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; 142 161 else return 0; // ray disjoint from plane (no solution) 143 162 } … … 146 165 inter->time = nw0 / ndir; //parametric value the point on line (a,b) 147 166 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); 152 170 153 171 int res=off_pnpoly(p,inter->v); 154 172 155 173 inter->edge=(res==-1); 156 if (ndir<0)157 inter->in_out=1; //the negative dot product means we enter the surface174 if (ndir<0) 175 inter->in_out=1; //the negative dot product means we enter the surface 158 176 else 159 177 inter->in_out=-1; … … 161 179 inter->normal=p.normal; 162 180 163 return res; //true if the intersection point lies inside the poly164 } 165 166 167 181 return res; //true if the intersection point lies inside the poly 182 } /* off_intersectPoly */ 183 184 185 // off_getBlocksIndex ********************************************************** 168 186 /*reads the indexes at the beginning of the off file as this : 169 187 line 1 OFF … … 172 190 long off_getBlocksIndex(char* filename, long* vtxIndex, long* vtxSize, long* faceIndex, long* polySize ) 173 191 { 174 if (!filename) return(0);192 if (!filename) return(0); 175 193 if (strlen(filename) == 0) return (0); 176 194 if (!strcmp(filename,"NULL") || !strcmp(filename,"0")) return(0); 177 195 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]; 181 199 182 200 if (!f) … … 192 210 f = fopen(mc_rt_path, "r"); 193 211 } 194 if (!f)212 if (!f) 195 213 { 196 214 fprintf(stderr, "Error: Could not open input file '%s' (interoff/off_getBlocksIndex)\n", filename); … … 199 217 } 200 218 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 f printf(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); 217 235 return(0); 218 236 } … … 220 238 *vtxIndex+= strlen(line); 221 239 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) 226 244 { 227 245 fprintf(stderr, "Error: Can not read line in file %s (interoff/off_getBlocksIndex)\n", filename); … … 229 247 } 230 248 *vtxIndex+= strlen(line); 231 } 232 while(line[0]=='#'); 249 } while (line[0]=='#'); 233 250 234 251 //line = nblines of vertex,faces and edges arrays … … 236 253 237 254 *faceIndex=*vtxIndex; 238 int i ;239 for (i=0;i<*vtxSize;)255 int i=0; 256 for (i=0; i<*vtxSize; ) 240 257 { 241 ret=fgets(line, buf,f);242 if (ret == NULL)258 ret=fgets(line,CHAR_BUF_LENGTH,f); 259 if (ret == NULL) 243 260 { 244 261 fprintf(stderr, "Error: Can not read vertex %i in file %s (interoff/off_getBlocksIndex)\n", i, filename); … … 246 263 } 247 264 *faceIndex+=strlen(line); 248 if (line[0]!='#')i++;265 if (line[0]!='#') i++; 249 266 } 250 267 251 268 fclose(f); 252 269 return(*vtxIndex); 253 } 254 255 270 } /* off_getBlocksIndex */ 271 272 // off_init_planes ************************************************************* 256 273 //gives the equations of 2 perpandicular planes of [ab] 257 274 void off_init_planes(Coords a, Coords b, … … 262 279 263 280 //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; 265 282 *C1=-dir.x; 266 283 if(*A1!=0 || *C1!=0) 267 *D1=-(a.x)* *A1-(a.z)**C1;284 *D1=-(a.x)*(*A1)-(a.z)*(*C1); 268 285 else 269 286 { 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'' 271 288 *A1=1; 272 289 //B1=dir.x=0 … … 274 291 } 275 292 //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; 277 294 *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' 282 299 *B2=1; 283 300 //B1=dir.x=0 … … 285 302 } 286 303 else { 287 if (dir.z==0)304 if (dir.z==0) 288 305 { 289 306 //the planes are the same, take the one parallel to 'z' 290 *A2= dir.y;307 *A2= dir.y; 291 308 *B2=-dir.x; 292 *D2=-(a.x)* *A2-(a.y)**B2;309 *D2=-(a.x)*(*A2)-(a.y)*(*B2); 293 310 } 294 311 else 295 312 *D2=-(a.y)**B2-(a.z)**C2; 296 313 } 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 ************************************************************* 302 317 int off_clip_3D_mod(intersection* t, Coords a, Coords b, 303 318 Coords* vtxArray, unsigned long vtxSize, unsigned long* faceArray, 304 319 unsigned long faceSize, Coords* normalArray) 305 320 { 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); 308 323 309 324 int t_size=0; 310 325 //unsigned long vtxSize=vtxTable.rows, faceSize=faceTable.columns; //Size of the corresponding tables 311 326 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)); 317 332 } 318 333 319 334 //exploring the polygons : 320 i= 0;indPoly=0;321 while (i<faceSize)322 { 335 i=indPoly=0; 336 while (i<faceSize) 337 { 323 338 polygon pol; 324 pol.npol =faceArray[i];//nb vertex of polygon325 326 pol. p=popol;327 unsigned long indVertP1=faceArray[++i]; //polygon's first vertex index in vtxTable339 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 328 343 int j=1; 329 while (j<pol.npol)330 { 331 //polygon's j-th vertex index in vtxTable332 if (sg[indVertP1]!=sg[faceArray[i+j]])//if the plane intersect the polygon344 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 333 348 break; 334 349 … … 336 351 } 337 352 338 if ((j<pol.npol)) //ok, let's test with the second plane339 { 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 plane353 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 341 356 342 j=1; 343 while (j<pol.npol)357 j=1; 358 while (j<pol.npol) 344 359 { 345 360 //unsigned long indVertPi=faceArray[i+j]; //polyg's j-th vertex index in vtxTable 346 361 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 polygon362 if (sg1!=off_sign(off_F(vertPi.x,vertPi.y,vertPi.z,A2,B2,C2,D2)))//if the plane intersect the polygon 348 363 break; 349 364 ++j; 350 365 } 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) 354 369 { 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); 357 372 } 358 373 //both planes intersect the polygon, let's find the intersection point 359 374 //our polygon : 360 375 int k; 361 for (k=0;k<pol.npol;++k)376 for (k=0; k<pol.npol; ++k) 362 377 { 363 378 Coords vertPk=vtxArray[faceArray[i+k]]; 364 pol.p[3*k] =vertPk.x;379 pol.p[3*k] =vertPk.x; 365 380 pol.p[3*k+1]=vertPk.y; 366 381 pol.p[3*k+2]=vertPk.z; 367 382 } 368 pol.normal=normalArray[indPoly]; 383 pol.normal=normalArray[indPoly]; 369 384 intersection x; 370 if (off_intersectPoly(&x, a, b, pol))385 if (off_intersectPoly(&x, a, b, pol)) 371 386 { 372 387 t[t_size++]=x; 373 388 } 374 } 375 } 376 i +=pol.npol;389 } /* if (j<pol.npol) */ 390 } /* if (j<pol.npol) */ 391 i += pol.npol; 377 392 indPoly++; 378 } 393 } /* while i<faceSize */ 379 394 return t_size; 380 } 381 382 383 395 } /* off_clip_3D_mod */ 396 397 398 // off_compare ***************************************************************** 384 399 int off_compare (void const *a, void const *b) 385 400 { … … 387 402 intersection const *pb = b; 388 403 389 return sign(pa->time - pb->time); 390 } 391 404 return off_sign(pa->time - pb->time); 405 } /* off_compare */ 406 407 // off_cleanDouble ************************************************************* 392 408 //given an array of intesction throw those which appear several times 393 409 //returns 1 if there is a possibility of error … … 395 411 { 396 412 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) 400 415 { 401 416 int j=i; 402 417 //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) 404 419 { 405 420 //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) 407 422 { 408 423 int k; 409 for (k=j+1;k<*t_size;++k)424 for (k=j+1; k<*t_size; ++k) 410 425 { 411 426 t[k-1]=t[k]; … … 421 436 } 422 437 return 1; 423 } 424 425 426 //given an array of intes ctionthrow those which enter and exit in the same time438 } /* off_cleanDouble */ 439 440 // off_cleanInOut ************************************************************** 441 //given an array of intesections throw those which enter and exit in the same time 427 442 //Meaning the ray passes very close to the volume 428 443 //returns 1 if there is a possibility of error … … 430 445 { 431 446 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) 435 449 { 436 450 //if two intersection have the same time but one enters and the other exits erase both 437 451 //(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) 442 456 { 443 457 t[j-2]=t[j]; … … 452 466 } 453 467 } 454 return 1;455 } 468 return (*t_size); 469 } /* off_cleanInOut */ 456 470 457 471 /* PUBLIC functions ******************************************************** */ 458 472 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 *******************************************************************************/ 482 long 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; 469 490 t_Table vtxTable, faceTable; 470 long vtxIndex, faceIndex;471 491 472 492 double minx=FLT_MAX,maxx=-FLT_MAX,miny=FLT_MAX,maxy=-FLT_MAX,minz=FLT_MAX,maxz=-FLT_MAX; 473 493 474 494 // get the indexes 475 if ( off_getBlocksIndex(offfile,&vtxIndex,&vtxSize,&faceIndex, &polySize) <=0)495 if (!data || off_getBlocksIndex(offfile,&vtxIndex,&vtxSize,&faceIndex, &polySize) <=0) 476 496 return(0); 477 printf(" Number of polygons: %ld\n",polySize);478 497 479 498 //read vertex table = [x y z | x y z | ...] … … 484 503 485 504 //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) 492 516 { 493 517 vtxArray[i].x=Table_Index(vtxTable, i,0); … … 496 520 497 521 //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 } 510 537 511 538 double rangex=-minx+maxx, 512 rangey=-miny+maxy,513 rangez=-minz+maxz;539 rangey=-miny+maxy, 540 rangez=-minz+maxz; 514 541 515 542 double ratiox=1,ratioy=1,ratioz=1; 516 543 517 if (xwidth)544 if (xwidth && rangex) 518 545 { 519 546 ratiox=xwidth/rangex; … … 522 549 } 523 550 524 if (yheight)551 if (yheight && rangey) 525 552 { 526 553 ratioy=yheight/rangey; … … 529 556 } 530 557 531 if (zdepth)558 if (zdepth && rangez) 532 559 { 533 560 ratioz=zdepth/rangez; … … 536 563 } 537 564 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); 546 575 } 547 576 548 577 549 578 //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) 551 580 { 552 581 //copy the table in a 1-row array 553 582 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) 555 585 { 556 586 faceArray[i]=Table_Index(faceTable, 0, i); … … 561 591 //read each row of the table and concatenate in a 1-row array 562 592 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) 566 597 faceArray[i*(faceSize)+j]=Table_Index(faceTable, i, j); 567 598 } … … 572 603 long indNormal=0;//index in polyArray 573 604 i=0; //index in faceArray 574 while (i<faceSize)605 while (i<faceSize) 575 606 { 576 int nbVertex=faceArray[i];//nb of vertices of this polygon607 int nbVertex=faceArray[i];//nb of vertices of this polygon 577 608 double vertices[3*nbVertex]; 578 609 int j; 579 610 580 for (j=0;j<nbVertex;++j)611 for (j=0; j<nbVertex; ++j) 581 612 { 582 613 unsigned long indVertPj=faceArray[i+j+1]; 583 vertices[3*j] =vtxArray[indVertPj].x;614 vertices[3*j] =vtxArray[indVertPj].x; 584 615 vertices[3*j+1]=vtxArray[indVertPj].y; 585 616 vertices[3*j+2]=vtxArray[indVertPj].z; … … 587 618 588 619 polygon p; 589 p.p =vertices;620 p.p =vertices; 590 621 p.npol=nbVertex; 591 622 off_normal(&(p.normal),p); … … 593 624 normalArray[indNormal]=p.normal; 594 625 595 i +=nbVertex+1;626 i += nbVertex+1; 596 627 indNormal++; 597 628 598 629 } 599 630 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" 603 633 " If you want to keep the originial proportions, specifiy only one of the dimensions.\n"); 604 634 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 data s->vtxArray=vtxArray;610 data s->normalArray=normalArray;611 data s->faceArray=faceArray;612 data s->vtxSize=vtxSize;613 data s->polySize=polySize;614 data s->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; 615 645 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 *******************************************************************************/ 661 int 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]; 622 668 Coords A={x, y, z}; 623 669 Coords B={x+vx, y+vy, z+vz}; 624 670 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 } 634 687 return t_size; 635 688 } 636 689 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 *******************************************************************************/ 696 void off_display(off_struct data) 697 { 642 698 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 655 723 /* end of interoff-lib.c */ 656 724
