ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/fprism.c
Revision: 2.1
Committed: Wed Sep 29 10:40:31 1993 UTC (30 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

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