ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/fprism.c
Revision: 2.5
Committed: Wed Apr 23 00:52:34 2003 UTC (21 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.4: +1 -1 lines
Log Message:
Added (void *) cast to realloc calls

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /* Ce programme calcule les directions et les energies des rayons lumineux
5 resultant du passage d'un rayon au travers d'un vitrage prismatique
6
7 1991, LESO - EPFL, R. Compagnon - F. Di Pasquale */
8
9 #include "standard.h"
10
11 #ifdef NOSTRUCTASSIGN
12 static double err = "No structure assignment!"; /* generate compiler error */
13 #endif
14
15
16 static double
17 Sqrt(x)
18 double x;
19 {
20 if (x < 0.)
21 return(0.);
22 return(sqrt(x));
23 }
24
25 /* definitions de macros utiles */
26
27 #define ALPHA 0
28 #define BETA 1
29 #define GAMMA 2
30 #define DELTA 3
31 #define AUCUNE 4
32 #define X(r) r.v[0]
33 #define Y(r) r.v[1]
34 #define Z(r) r.v[2]
35 #define XX(v) v[0]
36 #define YY(v) v[1]
37 #define ZZ(v) v[2]
38 #define alpha_beta(v_alpha,v_beta) tfm(matbt,v_alpha,v_beta)
39 #define beta_alpha(v_beta,v_alpha) tfm(matb,v_beta,v_alpha)
40 #define alpha_gamma(v_alpha,v_gamma) tfm(matct,v_alpha,v_gamma)
41 #define gamma_alpha(v_gamma,v_alpha) tfm(matc,v_gamma,v_alpha)
42 #define prob_alpha_gamma(r) (1.-prob_alpha_beta(r))
43 #define prob_beta_gamma(r) (1.-prob_beta_alpha(r))
44 #define prob_gamma_beta(r) (1.-prob_gamma_alpha(r))
45 #define prob_delta_gamma(r) (1.-prob_delta_beta(r))
46 #define prob_beta_delta(r) (prob_beta_alpha(r))
47 #define prob_gamma_delta(r) (prob_gamma_alpha(r))
48 #define prob_delta_beta(r) (prob_alpha_beta(r))
49
50
51 /* Definitions des types de donnees */
52
53 typedef struct { FVECT v; /* direction */
54 double ppar1,pper1,
55 ppar2,pper2; /* polarisations */
56 double e; /* energie */
57 double n; /* milieu dans lequel on se propage */
58 int orig,dest; /* origine et destination */
59 } TRAYON;
60
61 typedef struct { double a,b,c,d; /* longueurs caracteristiques */
62 double np; /* indice de refraction */
63 } TPRISM;
64
65
66 /* Definitions des variables globales */
67
68 static TPRISM prism; /* le prisme ! */
69 static MAT4 matb = MAT4IDENT; /* matrices de changement de bases */
70 static MAT4 matbt = MAT4IDENT;
71 static MAT4 matc = MAT4IDENT;
72 static MAT4 matct = MAT4IDENT;
73 static double seuil; /* seuil pour l'arret du trace */
74 static double sinus,cosinus; /* sin et cos */
75 static double rapport; /* rapport entre les indices des
76 milieux refracteur et incident */
77 static int tot_ref; /* flag pour les surfaces
78 reflechissantes */
79 static double fact_ref[4]={1.0,1.0,1.0,1.0}; /* facteurs de reflexion */
80 static double tolerance; /* degre de tol. pour les amalgames */
81 static double tolsource; /* degre de tol. pour les sources */
82 static double Nx;
83 static int bidon;
84 #define BADVAL (-10)
85 static long prismclock = -1;
86 static int nosource; /* indique que l'on ne trace pas
87 en direction d'une source */
88 static int sens; /* indique le sens de prop. du ray.*/
89 static int nbrayons; /* indice des rayons sortants */
90 static TRAYON *ray; /* tableau des rayons sortants */
91 static TRAYON *raytemp; /* variable temporaire */
92 static TRAYON rtemp; /* variable temporaire */
93
94 extern double argument();
95 extern double varvalue();
96 extern double funvalue();
97 extern long eclock;
98
99
100 /* Definition des routines */
101
102 #define term(a,b) a/Sqrt(a*a+b*b)
103 static
104 prepare_matrices()
105 {
106 /* preparation des matrices de changement de bases */
107
108 matb[0][0] = matbt[0][0] = matb[1][1] = matbt[1][1] = term(prism.a,prism.d);
109 matb[1][0] = matbt[0][1] = term(-prism.d,prism.a);
110 matb[0][1] = matbt[1][0] = term(prism.d,prism.a);
111 matc[0][0] = matct[0][0] = matc[1][1] = matct[1][1] = term(prism.b,prism.d);
112 matc[1][0] = matct[0][1] = term(prism.d,prism.b);
113 matc[0][1] = matct[1][0] = term(-prism.d,prism.b);
114 return;
115 }
116 #undef term
117
118
119 static
120 tfm(mat,v_old,v_new)
121 MAT4 mat;
122 FVECT v_old,v_new;
123 {
124 /* passage d'un repere old au repere new par la matrice mat */
125 FVECT v_temp;
126
127 multv3(v_temp,v_old,mat);
128 normalize(v_temp);
129 VCOPY(v_new,v_temp);
130 return;
131 }
132
133 #define A prism.a
134 #define B prism.b
135 #define C prism.c
136 #define D prism.d
137
138
139 static double
140 prob_alpha_beta(r)
141 TRAYON r;
142 {
143 /* calcul de la probabilite de passage de alpha a beta */
144 double prob,test;
145
146 if ( X(r) != 0. )
147 {
148 test = Y(r)/X(r);
149 if ( test > B/D ) prob = 1.;
150 else if ( test >= -A/D ) prob = (A+test*D)/(A+B);
151 else prob = 0.;
152 }
153 else prob = 0.;
154 return prob;
155 }
156
157
158 static double
159 prob_beta_alpha(r)
160 TRAYON r;
161 {
162 /* calcul de la probabilite de passage de beta a aplha */
163 double prob,test;
164
165 if ( X(r) != 0. )
166 {
167 test = Y(r)/X(r);
168 if ( test > B/D ) prob = (A+B)/(A+test*D);
169 else if ( test >= -A/D ) prob = 1.;
170 else prob = 0.;
171 }
172 else prob = 0.;
173 return prob;
174 }
175
176
177 double prob_gamma_alpha(r)
178 TRAYON r;
179 {
180 /* calcul de la probabilite de passage de gamma a alpha */
181 double prob,test;
182
183 if ( X(r) != 0. )
184 {
185 test = Y(r)/X(r);
186 if ( test > B/D ) prob = 0.;
187 else if ( test >= -A/D ) prob = 1.;
188 else prob = (A+B)/(B-test*D);
189 }
190 else prob = 0.;
191 return prob;
192 }
193
194 #undef A
195 #undef B
196 #undef C
197 #undef D
198
199
200 static
201 v_par(v,v_out)
202 FVECT v,v_out;
203 /* calcule le vecteur par au plan d'incidence lie a v */
204 {
205 FVECT v_temp;
206 double det;
207
208 det = Sqrt( (YY(v)*YY(v)+ZZ(v)*ZZ(v))*(YY(v)*YY(v)+ZZ(v)*ZZ(v))+
209 (XX(v)*XX(v)*YY(v)*YY(v))+(XX(v)*XX(v)*ZZ(v)*ZZ(v)) );
210 XX(v_temp) = (YY(v)*YY(v)+ZZ(v)*ZZ(v))/det;
211 YY(v_temp) = -( XX(v)*YY(v) )/det;
212 ZZ(v_temp) = -( XX(v)*ZZ(v) )/det;
213 VCOPY(v_out,v_temp);
214 return;
215 }
216
217
218 static
219 v_per(v,v_out)
220 FVECT v,v_out;
221 /* calcule le vecteur perp au plan d'incidence lie a v */
222 {
223 FVECT v_temp;
224 double det;
225
226 det = Sqrt( (ZZ(v)*ZZ(v)+YY(v)*YY(v)) );
227 XX(v_temp) = 0.;
228 YY(v_temp) = -ZZ(v)/det;
229 ZZ(v_temp) = YY(v)/det;
230 VCOPY(v_out,v_temp);
231 return;
232 }
233
234
235 static TRAYON
236 transalphabeta(r_initial)
237 /* transforme le rayon r_initial de la base associee a alpha dans
238 la base associee a beta */
239 TRAYON r_initial;
240 {
241 TRAYON r_final;
242 FVECT vpar_temp1,vpar_temp2,vper_temp1,vper_temp2;
243
244 r_final = r_initial;
245 alpha_beta(r_initial.v,r_final.v);
246 if ((Y(r_initial) != 0. || Z(r_initial) != 0.)&&(Y(r_final) !=0. || Z(r_final)!= 0.))
247 {
248 v_par(r_initial.v,vpar_temp1);
249 alpha_beta(vpar_temp1,vpar_temp1);
250 v_per(r_initial.v,vper_temp1);
251 alpha_beta(vper_temp1,vper_temp1);
252 v_par(r_final.v,vpar_temp2);
253 v_per(r_final.v,vper_temp2);
254 r_final.ppar1 = (r_initial.ppar1*fdot(vpar_temp1,vpar_temp2))+
255 (r_initial.pper1*fdot(vper_temp1,vpar_temp2));
256 r_final.pper1 = (r_initial.ppar1*fdot(vpar_temp1,vper_temp2))+
257 (r_initial.pper1*fdot(vper_temp1,vper_temp2));
258 r_final.ppar2 = (r_initial.ppar2*fdot(vpar_temp1,vpar_temp2))+
259 (r_initial.pper2*fdot(vper_temp1,vpar_temp2));
260 r_final.pper2 = (r_initial.ppar2*fdot(vpar_temp1,vper_temp2))+
261 (r_initial.pper2*fdot(vper_temp1,vper_temp2));
262 }
263 return r_final;
264 }
265
266
267 static TRAYON
268 transbetaalpha(r_initial)
269 /* transforme le rayon r_initial de la base associee a beta dans
270 la base associee a alpha */
271 TRAYON r_initial;
272 {
273 TRAYON r_final;
274 FVECT vpar_temp1,vpar_temp2,vper_temp1,vper_temp2;
275
276 r_final = r_initial;
277 beta_alpha(r_initial.v,r_final.v);
278 if ((Y(r_initial) != 0. || Z(r_initial) != 0. )&&(Y(r_final) != 0. || Z(r_final)!= 0.))
279 {
280 v_par(r_initial.v,vpar_temp1);
281 beta_alpha(vpar_temp1,vpar_temp1);
282 v_per(r_initial.v,vper_temp1);
283 beta_alpha(vper_temp1,vper_temp1);
284 v_par(r_final.v,vpar_temp2);
285 v_per(r_final.v,vper_temp2);
286 r_final.ppar1 = (r_initial.ppar1*fdot(vpar_temp1,vpar_temp2))+
287 (r_initial.pper1*fdot(vper_temp1,vpar_temp2));
288 r_final.pper1 = (r_initial.ppar1*fdot(vpar_temp1,vper_temp2))+
289 (r_initial.pper1*fdot(vper_temp1,vper_temp2));
290 r_final.ppar2 = (r_initial.ppar2*fdot(vpar_temp1,vpar_temp2))+
291 (r_initial.pper2*fdot(vper_temp1,vpar_temp2));
292 r_final.pper2 = (r_initial.ppar2*fdot(vpar_temp1,vper_temp2))+
293 (r_initial.pper2*fdot(vper_temp1,vper_temp2));
294
295 }
296 return r_final;
297 }
298
299
300 static TRAYON
301 transalphagamma(r_initial)
302 /* transforme le rayon r_initial de la base associee a alpha dans
303 la base associee a gamma */
304 TRAYON r_initial;
305 {
306 TRAYON r_final;
307 FVECT vpar_temp1,vpar_temp2,vper_temp1,vper_temp2;
308
309 r_final = r_initial;
310 alpha_gamma(r_initial.v,r_final.v);
311 if (( Y(r_initial) != 0. || Z(r_initial) != 0. )&&(Y(r_final)!= 0. || Z(r_final) !=0.))
312 {
313 v_par(r_initial.v,vpar_temp1);
314 alpha_gamma(vpar_temp1,vpar_temp1);
315 v_per(r_initial.v,vper_temp1);
316 alpha_gamma(vper_temp1,vper_temp1);
317 v_par(r_final.v,vpar_temp2);
318 v_per(r_final.v,vper_temp2);
319 r_final.ppar1 = (r_initial.ppar1*fdot(vpar_temp1,vpar_temp2))+
320 (r_initial.pper1*fdot(vper_temp1,vpar_temp2));
321 r_final.pper1 = (r_initial.ppar1*fdot(vpar_temp1,vper_temp2))+
322 (r_initial.pper1*fdot(vper_temp1,vper_temp2));
323 r_final.ppar2 = (r_initial.ppar2*fdot(vpar_temp1,vpar_temp2))+
324 (r_initial.pper2*fdot(vper_temp1,vpar_temp2));
325 r_final.pper2 = (r_initial.ppar2*fdot(vpar_temp1,vper_temp2))+
326 (r_initial.pper2*fdot(vper_temp1,vper_temp2));
327
328 }
329 return r_final;
330 }
331
332
333 static TRAYON
334 transgammaalpha(r_initial)
335 /* transforme le rayon r_initial de la base associee a gamma dans
336 la base associee a alpha */
337 TRAYON r_initial;
338 {
339 TRAYON r_final;
340 FVECT vpar_temp1,vpar_temp2,vper_temp1,vper_temp2;
341
342 r_final = r_initial;
343 gamma_alpha(r_initial.v,r_final.v);
344 if (( Y(r_initial) != 0. || Z(r_initial) != 0. )&&(Y(r_final) !=0. || Z(r_final) != 0.))
345 {
346 v_par(r_initial.v,vpar_temp1);
347 gamma_alpha(vpar_temp1,vpar_temp1);
348 v_per(r_initial.v,vper_temp1);
349 gamma_alpha(vper_temp1,vper_temp1);
350 v_par(r_final.v,vpar_temp2);
351 v_per(r_final.v,vper_temp2);
352 r_final.ppar1 = (r_initial.ppar1*fdot(vpar_temp1,vpar_temp2))+
353 (r_initial.pper1*fdot(vper_temp1,vpar_temp2));
354 r_final.pper1 = (r_initial.ppar1*fdot(vpar_temp1,vper_temp2))+
355 (r_initial.pper1*fdot(vper_temp1,vper_temp2));
356 r_final.ppar2 = (r_initial.ppar2*fdot(vpar_temp1,vpar_temp2))+
357 (r_initial.pper2*fdot(vper_temp1,vpar_temp2));
358 r_final.pper2 = (r_initial.ppar2*fdot(vpar_temp1,vper_temp2))+
359 (r_initial.pper2*fdot(vper_temp1,vper_temp2));
360 }
361 return r_final;
362 }
363
364
365
366 static int
367 compare(r1,r2,marge)
368 TRAYON r1, r2;
369 double marge;
370
371 {
372 double arctg1, arctg2;
373
374 arctg1 = atan2(Y(r1),X(r1));
375 arctg2 = atan2(Y(r2),X(r2));
376 if ((arctg1 - marge <= arctg2) && (arctg1 + marge >= arctg2)) return 1;
377 else return 0;
378 }
379
380
381
382
383 static
384 sortie(r)
385 TRAYON r;
386 {
387 int i = 0;
388 int egalite = 0;
389
390
391 if(r.e > seuil)
392 {
393 while (i < nbrayons && egalite == 0)
394 {
395 raytemp = &ray[i];
396 egalite = compare(r,*raytemp,tolerance);
397 if (egalite) raytemp->e = raytemp->e + r.e;
398 else i = i + 1;
399 }
400 if (egalite == 0)
401 {
402 if (nbrayons == 0) ray = (TRAYON *)calloc(1,sizeof(TRAYON));
403 else ray = (TRAYON *)realloc((void *)ray, (nbrayons+1)*(sizeof(TRAYON)));
404 if (ray == NULL)
405 error(SYSTEM, "out of memory in sortie\n");
406 raytemp = &ray[nbrayons];
407 raytemp->v[0] = X(r);
408 raytemp->v[1] = Y(r);
409 raytemp->v[2] = Z(r);
410 raytemp->e = r.e;
411 nbrayons++;
412 }
413 }
414 return;
415 }
416
417
418 static
419 trigo(r)
420 TRAYON r;
421 /* calcule les grandeurs trigonometriques relatives au rayon incident
422 et le rapport entre les indices du milieu refracteur et incident */
423 {
424 double det;
425
426 det = Sqrt(X(r)*X(r)+Y(r)*Y(r)+Z(r)*Z(r));
427 sinus = Sqrt(Y(r)*Y(r)+Z(r)*Z(r))/det;
428 cosinus = Sqrt(X(r)*X(r))/det;
429 if (r.n == 1.) rapport = prism.np * prism.np;
430 else rapport = 1./(prism.np * prism.np);
431 return;
432 }
433
434
435 static TRAYON
436 reflexion(r_incident)
437 TRAYON r_incident;
438 {
439 /* calcul du rayon reflechi par une face */
440 TRAYON r_reflechi;
441
442 r_reflechi = r_incident;
443 trigo(r_incident);
444 X(r_reflechi) = -X(r_incident);
445 Y(r_reflechi) = Y(r_incident);
446 Z(r_reflechi) = Z(r_incident);
447 if(sinus > Sqrt(rapport) || r_incident.dest == tot_ref)
448 {
449 r_reflechi.ppar1 = r_incident.ppar1;
450 r_reflechi.pper1 = r_incident.pper1;
451 r_reflechi.ppar2 = r_incident.ppar2;
452 r_reflechi.pper2 = r_incident.pper2;
453 r_reflechi.e = r_incident.e * fact_ref[r_incident.dest];
454 }
455 else
456 {
457 r_reflechi.ppar1 = r_incident.ppar1*(rapport*cosinus-Sqrt(rapport-
458 (sinus*sinus)))/(rapport*cosinus+Sqrt(rapport-(sinus*sinus)));
459 r_reflechi.pper1 = r_incident.pper1*(cosinus-Sqrt
460 (rapport-(sinus*sinus)))/(cosinus+Sqrt(rapport-(sinus*sinus)));
461 r_reflechi.ppar2 = r_incident.ppar2*(rapport*cosinus-Sqrt(rapport-
462 (sinus*sinus)))/(rapport*cosinus+Sqrt(rapport-(sinus*sinus)));
463 r_reflechi.pper2 = r_incident.pper2*(cosinus-Sqrt
464 (rapport-(sinus*sinus)))/(cosinus+Sqrt(rapport-(sinus*sinus)));
465 r_reflechi.e = r_incident.e *(((r_reflechi.ppar1*r_reflechi.ppar1+
466 r_reflechi.pper1*r_reflechi.pper1)/(r_incident.ppar1*r_incident.ppar1+
467 r_incident.pper1*r_incident.pper1))+((r_reflechi.ppar2*r_reflechi.ppar2
468 +r_reflechi.pper2*r_reflechi.pper2)/(r_incident.ppar2*r_incident.ppar2
469 +r_incident.pper2*r_incident.pper2)))/2;
470 }
471
472 /* a la sortie de cette routine r_transmis.orig et .dest ne sont pas definis!*/
473 return r_reflechi;
474 }
475
476
477 static TRAYON
478 transmission(r_incident)
479 TRAYON r_incident;
480 {
481 /* calcul du rayon refracte par une face */
482 TRAYON r_transmis;
483
484 r_transmis = r_incident;
485 trigo(r_incident);
486 if (sinus <= Sqrt(rapport) && r_incident.dest != tot_ref)
487 {
488 X(r_transmis) = (X(r_incident)/(fabs(X(r_incident))))*
489 (Sqrt(1.-(Y(r_incident)*Y(r_incident)+Z(r_incident)*
490 Z(r_incident))/rapport));
491 Y(r_transmis) = Y(r_incident)/Sqrt(rapport);
492 Z(r_transmis) = Z(r_incident)/Sqrt(rapport);
493 r_transmis.ppar1 = r_incident.ppar1*2.*Sqrt(rapport)*cosinus/
494 (Sqrt(rapport-sinus*sinus)+rapport*cosinus);
495 r_transmis.pper1 = r_incident.pper1*2.*cosinus/(cosinus+Sqrt(rapport
496 - sinus*sinus));
497 r_transmis.ppar2 = r_incident.ppar2*2.*Sqrt(rapport)*cosinus/
498 (Sqrt(rapport-sinus*sinus)+rapport*cosinus);
499 r_transmis.pper2 = r_incident.pper2*2.*cosinus/(cosinus+Sqrt(rapport
500 - sinus*sinus));
501 r_transmis.e = (r_incident.e/2)*(Sqrt(rapport-sinus*sinus)/cosinus)
502 *(((r_transmis.ppar1*r_transmis.ppar1+r_transmis.pper1*
503 r_transmis.pper1)
504 /(r_incident.ppar1*r_incident.ppar1+r_incident.pper1*
505 r_incident.pper1))+
506 ((r_transmis.ppar2*r_transmis.ppar2+r_transmis.pper2*r_transmis.pper2)
507 /(r_incident.ppar2*r_incident.ppar2+r_incident.pper2*r_incident.pper2)));
508 if(r_incident.n == 1.) r_transmis.n = prism.np;
509 else r_transmis.n = 1.;
510 }
511 else r_transmis.e = 0.;
512
513 /* a la sortie de cette routine r_transmis.orig et .dest ne sont pas definis!*/
514
515 return r_transmis;
516 }
517
518
519
520
521 #define ensuite(rayon,prob_passage,destination) r_suite = rayon; \
522 r_suite.e = prob_passage(rayon)*rayon.e; \
523 r_suite.dest = destination; \
524 if ( r_suite.e > seuil ) trace_rayon(r_suite)
525
526
527 static
528 trace_rayon(r_incident)
529 TRAYON r_incident;
530 {
531 /* trace le rayon donne */
532 TRAYON r_reflechi,r_transmis,r_suite;
533
534 switch (r_incident.dest)
535 {
536 case ALPHA:
537 if ( r_incident.orig == ALPHA )
538 {
539 r_reflechi = reflexion(r_incident);
540 sortie(r_reflechi);
541
542 r_transmis = transmission(r_incident);
543 r_transmis.orig = ALPHA;
544
545 ensuite(r_transmis,prob_alpha_beta,BETA);
546 ensuite(r_transmis,prob_alpha_gamma,GAMMA);
547 }
548 else
549 {
550 r_reflechi = reflexion(r_incident);
551 r_reflechi.orig = ALPHA;
552 ensuite(r_reflechi,prob_alpha_beta,BETA);
553 ensuite(r_reflechi,prob_alpha_gamma,GAMMA);
554
555 r_transmis = transmission(r_incident);
556 sortie(r_transmis);
557 }
558 break;
559 case BETA:
560 r_reflechi = transbetaalpha(reflexion(transalphabeta(r_incident)));
561 r_reflechi.orig = BETA;
562 r_transmis = transbetaalpha(transmission(transalphabeta
563 (r_incident)));
564 r_transmis.orig = GAMMA;
565 if ( r_incident.n > 1.0 ) /* le rayon vient de l'interieur */
566 {
567 ensuite(r_reflechi,prob_beta_alpha,ALPHA);
568 ensuite(r_reflechi,prob_beta_gamma,GAMMA);
569
570 ensuite(r_transmis,prob_beta_gamma,GAMMA);
571 ensuite(r_transmis,prob_beta_delta,DELTA);
572 }
573 else /* le rayon vient de l'exterieur */
574 {
575 ensuite(r_reflechi,prob_beta_gamma,GAMMA);
576 ensuite(r_reflechi,prob_beta_delta,DELTA);
577
578 ensuite(r_transmis,prob_beta_alpha,ALPHA);
579 ensuite(r_transmis,prob_beta_gamma,GAMMA);
580 }
581 break;
582 case GAMMA:
583 r_reflechi = transgammaalpha(reflexion(transalphagamma(r_incident)));
584 r_reflechi.orig = GAMMA;
585 r_transmis = transgammaalpha(transmission(transalphagamma
586 (r_incident)));
587 r_transmis.orig = GAMMA;
588 if ( r_incident.n > 1.0 ) /* le rayon vient de l'interieur */
589 {
590 ensuite(r_reflechi,prob_gamma_alpha,ALPHA);
591 ensuite(r_reflechi,prob_gamma_beta,BETA);
592
593 ensuite(r_transmis,prob_gamma_beta,BETA);
594 ensuite(r_transmis,prob_gamma_delta,DELTA);
595 }
596 else /* le rayon vient de l'exterieur */
597 {
598 ensuite(r_reflechi,prob_gamma_beta,BETA);
599 ensuite(r_reflechi,prob_gamma_delta,DELTA);
600
601 ensuite(r_transmis,prob_gamma_alpha,ALPHA);
602 ensuite(r_transmis,prob_gamma_beta,BETA);
603 }
604 break;
605 case DELTA:
606 if ( r_incident.orig != DELTA ) sortie(r_incident);
607 else
608 {
609 ensuite(r_incident,prob_delta_beta,BETA);
610 ensuite(r_incident,prob_delta_gamma,GAMMA);
611 }
612 break;
613 }
614 return;
615 }
616
617 #undef ensuite
618
619 static
620 inverser(r1,r2)
621 TRAYON *r1,*r2;
622
623 {
624 TRAYON temp;
625 temp = *r1;
626 *r1 = *r2;
627 *r2 = temp;
628 }
629
630
631
632 static
633 setprism()
634 {
635 double d;
636 TRAYON r_initial,rsource;
637 int i,j,k;
638
639 prismclock = eclock;
640 r_initial.ppar1 = r_initial.pper2 = 1.;
641 r_initial.pper1 = r_initial.ppar2 = 0.;
642
643 d = 1; prism.a = funvalue("arg", 1, &d);
644 if(prism.a < 0.) goto badopt;
645 d = 2; prism.b = funvalue("arg", 1, &d);
646 if(prism.b < 0.) goto badopt;
647 d = 3; prism.c = funvalue("arg", 1, &d);
648 if(prism.c < 0.) goto badopt;
649 d = 4; prism.d = funvalue("arg", 1, &d);
650 if(prism.d < 0.) goto badopt;
651 d = 5; prism.np = funvalue("arg", 1, &d);
652 if(prism.np < 1.) goto badopt;
653 d = 6; seuil = funvalue("arg", 1, &d);
654 if (seuil < 0. || seuil >=1) goto badopt;
655 d = 7; tot_ref = (int)(funvalue("arg", 1, &d) + .5);
656 if (tot_ref != 1 && tot_ref != 2 && tot_ref != 4) goto badopt;
657 if (tot_ref < 4 )
658 {
659 d = 8; fact_ref[tot_ref] = funvalue("arg", 1, &d);
660 if (fact_ref[tot_ref] < 0. || fact_ref[tot_ref] > 1.) goto badopt;
661 }
662 d = 9; tolerance = funvalue("arg", 1, &d);
663 if (tolerance <= 0.) goto badopt;
664 d = 10; tolsource = funvalue("arg", 1, &d);
665 if (tolsource < 0. ) goto badopt;
666 X(r_initial) = varvalue("Dx");
667 Y(r_initial) = varvalue("Dy");
668 Z(r_initial) = varvalue("Dz");
669 #ifdef DEBUG
670 fprintf(stderr,"dx=%lf dy=%lf dz=%lf\n",X(r_initial),Y(r_initial),Z(r_initial));
671 #endif
672
673 /* initialisation */
674 prepare_matrices();
675 r_initial.e = 1.0;
676 r_initial.n = 1.0;
677
678 if(ray!=NULL) free(ray);
679 nbrayons = 0;
680 /* determination de l'origine et de la destination du rayon initial */
681
682 if ( X(r_initial) != 0.)
683 {
684 if ( X(r_initial) > 0. )
685 {
686 r_initial.orig = r_initial.dest = ALPHA;
687 sens = 1;
688 }
689 else if ( X(r_initial) < 0. )
690 {
691 r_initial.orig = r_initial.dest = DELTA;
692 sens = -1;
693 }
694
695 normalize(r_initial.v);
696
697 trace_rayon(r_initial);
698
699 X(rsource) = varvalue("DxA");
700 Y(rsource) = varvalue("DyA");
701 Z(rsource) = varvalue("DzA");
702 nosource = ( X(rsource)==0. && Y(rsource)==0. && Z(rsource)==0. );
703 if ( !nosource )
704 {
705 for (j=0; j<nbrayons; j++)
706 {
707 if ( !compare(ray[j],rsource,tolsource) ) ray[j].e =0.;
708 }
709 }
710 for (j = 0; j < nbrayons; j++)
711 {
712 for (i = j+1; i < nbrayons; i++)
713 {
714 if (ray[j].e < ray[i].e) inverser(&ray[j],&ray[i]);
715 }
716 }
717
718 bidon = 1;
719 }
720 else bidon = 0;
721 return;
722
723 /* message puis sortie si erreur dans la ligne de commande */
724 badopt:
725 bidon = BADVAL;
726 return;
727 }
728
729
730 static double
731 l_get_val()
732
733 {
734 int val, dir, i, trouve, curseur;
735 int nb;
736 double valeur;
737 TRAYON *rayt, raynull;
738
739 if (prismclock < 0 || prismclock < eclock) setprism();
740 if (bidon == BADVAL) {
741 errno = EDOM;
742 return(0.0);
743 }
744 val = (int)(argument(1) + .5);
745 dir = (int)(argument(2) + .5);
746 nb = (int)(argument(3) + .5);
747 X(raynull) = bidon;
748 Y(raynull) = Z(raynull) = 0.;
749 raynull.e = 0.;
750 trouve = curseur = 0;
751 if ( !nosource && nb==2 ) nb=1; /* on est en train de tracer la source
752 a partir de sa seconde source virtuelle */
753 #ifdef DEBUG
754 fprintf(stderr, " On considere le rayon no: %d\n", nb);
755 #endif
756 for(i=0; i < nbrayons &&!trouve; i++)
757 {
758 if(ray[i].v[0] * dir * sens >= 0.) curseur ++;
759 if(curseur == nb)
760 {
761 rayt = &ray[i];
762 trouve = 1;
763 }
764 }
765 if(!trouve) rayt = &raynull;
766 switch(val) {
767 case 0 : valeur = rayt->v[0];
768 break;
769 case 1 : valeur = rayt->v[1];
770 break;
771 case 2 : valeur = rayt->v[2];
772 break;
773 case 3 : valeur = rayt->e;
774 break;
775 default : errno = EDOM; return(0.0);
776 }
777 #ifdef DEBUG
778 fprintf(stderr, "get_val( %i, %i, %i) = %lf\n",val,dir,nb,valeur);
779 #endif
780 return valeur;
781 }
782
783
784 setprismfuncs()
785 {
786 funset("fprism_val", 3, '=', l_get_val);
787 }