ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/fprism.c
Revision: 2.6
Committed: Mon Aug 4 22:37:53 2003 UTC (20 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +2 -2 lines
Log Message:
Added prototype for LIBR function pointer in calcomp.h

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.6 static const char RCSid[] = "$Id: fprism.c,v 2.5 2003/04/23 00:52:34 greg Exp $";
3 greg 2.1 #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 greg 2.3 #define term(a,b) a/Sqrt(a*a+b*b)
103 greg 2.1 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 greg 2.3 det = Sqrt( (YY(v)*YY(v)+ZZ(v)*ZZ(v))*(YY(v)*YY(v)+ZZ(v)*ZZ(v))+
209 greg 2.1 (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 greg 2.3 det = Sqrt( (ZZ(v)*ZZ(v)+YY(v)*YY(v)) );
227 greg 2.1 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 greg 2.2 static int
367     compare(r1,r2,marge)
368     TRAYON r1, r2;
369     double marge;
370 greg 2.1
371 greg 2.2 {
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 greg 2.1 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 greg 2.5 else ray = (TRAYON *)realloc((void *)ray, (nbrayons+1)*(sizeof(TRAYON)));
404 greg 2.1 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 greg 2.3 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 greg 2.1 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 greg 2.3 if(sinus > Sqrt(rapport) || r_incident.dest == tot_ref)
448 greg 2.1 {
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 greg 2.3 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 greg 2.1 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 greg 2.3 if (sinus <= Sqrt(rapport) && r_incident.dest != tot_ref)
487 greg 2.1 {
488     X(r_transmis) = (X(r_incident)/(fabs(X(r_incident))))*
489 greg 2.3 (Sqrt(1.-(Y(r_incident)*Y(r_incident)+Z(r_incident)*
490 greg 2.1 Z(r_incident))/rapport));
491 greg 2.3 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 greg 2.1 - sinus*sinus));
497 greg 2.3 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 greg 2.1 - sinus*sinus));
501 greg 2.3 r_transmis.e = (r_incident.e/2)*(Sqrt(rapport-sinus*sinus)/cosinus)
502 greg 2.1 *(((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 greg 2.2
729    
730     static double
731 greg 2.6 l_get_val(char *nm)
732 greg 2.2
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 greg 2.1
784     setprismfuncs()
785     {
786     funset("fprism_val", 3, '=', l_get_val);
787     }