ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/fprism.c
Revision: 2.2
Committed: Mon Dec 12 12:22:48 1994 UTC (29 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +71 -71 lines
Log Message:
rearranged declarations

File Contents

# User Rev Content
1 greg 2.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 greg 2.2 static int
371     compare(r1,r2,marge)
372     TRAYON r1, r2;
373     double marge;
374 greg 2.1
375 greg 2.2 {
376     double arctg1, arctg2;
377    
378     arctg1 = atan2(Y(r1),X(r1));
379     arctg2 = atan2(Y(r2),X(r2));
380     if ((arctg1 - marge <= arctg2) && (arctg1 + marge >= arctg2)) return 1;
381     else return 0;
382     }
383    
384    
385    
386    
387 greg 2.1 static
388     sortie(r)
389     TRAYON r;
390     {
391     int i = 0;
392     int egalite = 0;
393    
394    
395     if(r.e > seuil)
396     {
397     while (i < nbrayons && egalite == 0)
398     {
399     raytemp = &ray[i];
400     egalite = compare(r,*raytemp,tolerance);
401     if (egalite) raytemp->e = raytemp->e + r.e;
402     else i = i + 1;
403     }
404     if (egalite == 0)
405     {
406     if (nbrayons == 0) ray = (TRAYON *)calloc(1,sizeof(TRAYON));
407     else ray = (TRAYON *)realloc(ray, (nbrayons+1)*(sizeof(TRAYON)));
408     if (ray == NULL)
409     error(SYSTEM, "out of memory in sortie\n");
410     raytemp = &ray[nbrayons];
411     raytemp->v[0] = X(r);
412     raytemp->v[1] = Y(r);
413     raytemp->v[2] = Z(r);
414     raytemp->e = r.e;
415     nbrayons++;
416     }
417     }
418     return;
419     }
420    
421    
422     static
423     trigo(r)
424     TRAYON r;
425     /* calcule les grandeurs trigonometriques relatives au rayon incident
426     et le rapport entre les indices du milieu refracteur et incident */
427     {
428     double det;
429    
430     det = sqrt(X(r)*X(r)+Y(r)*Y(r)+Z(r)*Z(r));
431     sinus = sqrt(Y(r)*Y(r)+Z(r)*Z(r))/det;
432     cosinus = sqrt(X(r)*X(r))/det;
433     if (r.n == 1.) rapport = prism.np * prism.np;
434     else rapport = 1./(prism.np * prism.np);
435     return;
436     }
437    
438    
439     static TRAYON
440     reflexion(r_incident)
441     TRAYON r_incident;
442     {
443     /* calcul du rayon reflechi par une face */
444     TRAYON r_reflechi;
445    
446     r_reflechi = r_incident;
447     trigo(r_incident);
448     X(r_reflechi) = -X(r_incident);
449     Y(r_reflechi) = Y(r_incident);
450     Z(r_reflechi) = Z(r_incident);
451     if(sinus > sqrt(rapport) || r_incident.dest == tot_ref)
452     {
453     r_reflechi.ppar1 = r_incident.ppar1;
454     r_reflechi.pper1 = r_incident.pper1;
455     r_reflechi.ppar2 = r_incident.ppar2;
456     r_reflechi.pper2 = r_incident.pper2;
457     r_reflechi.e = r_incident.e * fact_ref[r_incident.dest];
458     }
459     else
460     {
461     r_reflechi.ppar1 = r_incident.ppar1*(rapport*cosinus-sqrt(rapport-
462     (sinus*sinus)))/(rapport*cosinus+sqrt(rapport-(sinus*sinus)));
463     r_reflechi.pper1 = r_incident.pper1*(cosinus-sqrt
464     (rapport-(sinus*sinus)))/(cosinus+sqrt(rapport-(sinus*sinus)));
465     r_reflechi.ppar2 = r_incident.ppar2*(rapport*cosinus-sqrt(rapport-
466     (sinus*sinus)))/(rapport*cosinus+sqrt(rapport-(sinus*sinus)));
467     r_reflechi.pper2 = r_incident.pper2*(cosinus-sqrt
468     (rapport-(sinus*sinus)))/(cosinus+sqrt(rapport-(sinus*sinus)));
469     r_reflechi.e = r_incident.e *(((r_reflechi.ppar1*r_reflechi.ppar1+
470     r_reflechi.pper1*r_reflechi.pper1)/(r_incident.ppar1*r_incident.ppar1+
471     r_incident.pper1*r_incident.pper1))+((r_reflechi.ppar2*r_reflechi.ppar2
472     +r_reflechi.pper2*r_reflechi.pper2)/(r_incident.ppar2*r_incident.ppar2
473     +r_incident.pper2*r_incident.pper2)))/2;
474     }
475    
476     /* a la sortie de cette routine r_transmis.orig et .dest ne sont pas definis!*/
477     return r_reflechi;
478     }
479    
480    
481     static TRAYON
482     transmission(r_incident)
483     TRAYON r_incident;
484     {
485     /* calcul du rayon refracte par une face */
486     TRAYON r_transmis;
487    
488     r_transmis = r_incident;
489     trigo(r_incident);
490     if (sinus <= sqrt(rapport) && r_incident.dest != tot_ref)
491     {
492     X(r_transmis) = (X(r_incident)/(fabs(X(r_incident))))*
493     (sqrt(1.-(Y(r_incident)*Y(r_incident)+Z(r_incident)*
494     Z(r_incident))/rapport));
495     Y(r_transmis) = Y(r_incident)/sqrt(rapport);
496     Z(r_transmis) = Z(r_incident)/sqrt(rapport);
497     r_transmis.ppar1 = r_incident.ppar1*2.*sqrt(rapport)*cosinus/
498     (sqrt(rapport-sinus*sinus)+rapport*cosinus);
499     r_transmis.pper1 = r_incident.pper1*2.*cosinus/(cosinus+sqrt(rapport
500     - sinus*sinus));
501     r_transmis.ppar2 = r_incident.ppar2*2.*sqrt(rapport)*cosinus/
502     (sqrt(rapport-sinus*sinus)+rapport*cosinus);
503     r_transmis.pper2 = r_incident.pper2*2.*cosinus/(cosinus+sqrt(rapport
504     - sinus*sinus));
505     r_transmis.e = (r_incident.e/2)*(sqrt(rapport-sinus*sinus)/cosinus)
506     *(((r_transmis.ppar1*r_transmis.ppar1+r_transmis.pper1*
507     r_transmis.pper1)
508     /(r_incident.ppar1*r_incident.ppar1+r_incident.pper1*
509     r_incident.pper1))+
510     ((r_transmis.ppar2*r_transmis.ppar2+r_transmis.pper2*r_transmis.pper2)
511     /(r_incident.ppar2*r_incident.ppar2+r_incident.pper2*r_incident.pper2)));
512     if(r_incident.n == 1.) r_transmis.n = prism.np;
513     else r_transmis.n = 1.;
514     }
515     else r_transmis.e = 0.;
516    
517     /* a la sortie de cette routine r_transmis.orig et .dest ne sont pas definis!*/
518    
519     return r_transmis;
520     }
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
637     setprism()
638     {
639     double d;
640     TRAYON r_initial,rsource;
641     int i,j,k;
642    
643     prismclock = eclock;
644     r_initial.ppar1 = r_initial.pper2 = 1.;
645     r_initial.pper1 = r_initial.ppar2 = 0.;
646    
647     d = 1; prism.a = funvalue("arg", 1, &d);
648     if(prism.a < 0.) goto badopt;
649     d = 2; prism.b = funvalue("arg", 1, &d);
650     if(prism.b < 0.) goto badopt;
651     d = 3; prism.c = funvalue("arg", 1, &d);
652     if(prism.c < 0.) goto badopt;
653     d = 4; prism.d = funvalue("arg", 1, &d);
654     if(prism.d < 0.) goto badopt;
655     d = 5; prism.np = funvalue("arg", 1, &d);
656     if(prism.np < 1.) goto badopt;
657     d = 6; seuil = funvalue("arg", 1, &d);
658     if (seuil < 0. || seuil >=1) goto badopt;
659     d = 7; tot_ref = (int)(funvalue("arg", 1, &d) + .5);
660     if (tot_ref != 1 && tot_ref != 2 && tot_ref != 4) goto badopt;
661     if (tot_ref < 4 )
662     {
663     d = 8; fact_ref[tot_ref] = funvalue("arg", 1, &d);
664     if (fact_ref[tot_ref] < 0. || fact_ref[tot_ref] > 1.) goto badopt;
665     }
666     d = 9; tolerance = funvalue("arg", 1, &d);
667     if (tolerance <= 0.) goto badopt;
668     d = 10; tolsource = funvalue("arg", 1, &d);
669     if (tolsource < 0. ) goto badopt;
670     X(r_initial) = varvalue("Dx");
671     Y(r_initial) = varvalue("Dy");
672     Z(r_initial) = varvalue("Dz");
673     #ifdef DEBUG
674     fprintf(stderr,"dx=%lf dy=%lf dz=%lf\n",X(r_initial),Y(r_initial),Z(r_initial));
675     #endif
676    
677     /* initialisation */
678     prepare_matrices();
679     r_initial.e = 1.0;
680     r_initial.n = 1.0;
681    
682     if(ray!=NULL) free(ray);
683     nbrayons = 0;
684     /* determination de l'origine et de la destination du rayon initial */
685    
686     if ( X(r_initial) != 0.)
687     {
688     if ( X(r_initial) > 0. )
689     {
690     r_initial.orig = r_initial.dest = ALPHA;
691     sens = 1;
692     }
693     else if ( X(r_initial) < 0. )
694     {
695     r_initial.orig = r_initial.dest = DELTA;
696     sens = -1;
697     }
698    
699     normalize(r_initial.v);
700    
701     trace_rayon(r_initial);
702    
703     X(rsource) = varvalue("DxA");
704     Y(rsource) = varvalue("DyA");
705     Z(rsource) = varvalue("DzA");
706     nosource = ( X(rsource)==0. && Y(rsource)==0. && Z(rsource)==0. );
707     if ( !nosource )
708     {
709     for (j=0; j<nbrayons; j++)
710     {
711     if ( !compare(ray[j],rsource,tolsource) ) ray[j].e =0.;
712     }
713     }
714     for (j = 0; j < nbrayons; j++)
715     {
716     for (i = j+1; i < nbrayons; i++)
717     {
718     if (ray[j].e < ray[i].e) inverser(&ray[j],&ray[i]);
719     }
720     }
721    
722     bidon = 1;
723     }
724     else bidon = 0;
725     return;
726    
727     /* message puis sortie si erreur dans la ligne de commande */
728     badopt:
729     bidon = BADVAL;
730     return;
731     }
732 greg 2.2
733    
734     static double
735     l_get_val()
736    
737     {
738     int val, dir, i, trouve, curseur;
739     int nb;
740     double valeur;
741     TRAYON *rayt, raynull;
742    
743     if (prismclock < 0 || prismclock < eclock) setprism();
744     if (bidon == BADVAL) {
745     errno = EDOM;
746     return(0.0);
747     }
748     val = (int)(argument(1) + .5);
749     dir = (int)(argument(2) + .5);
750     nb = (int)(argument(3) + .5);
751     X(raynull) = bidon;
752     Y(raynull) = Z(raynull) = 0.;
753     raynull.e = 0.;
754     trouve = curseur = 0;
755     if ( !nosource && nb==2 ) nb=1; /* on est en train de tracer la source
756     a partir de sa seconde source virtuelle */
757     #ifdef DEBUG
758     fprintf(stderr, " On considere le rayon no: %d\n", nb);
759     #endif
760     for(i=0; i < nbrayons &&!trouve; i++)
761     {
762     if(ray[i].v[0] * dir * sens >= 0.) curseur ++;
763     if(curseur == nb)
764     {
765     rayt = &ray[i];
766     trouve = 1;
767     }
768     }
769     if(!trouve) rayt = &raynull;
770     switch(val) {
771     case 0 : valeur = rayt->v[0];
772     break;
773     case 1 : valeur = rayt->v[1];
774     break;
775     case 2 : valeur = rayt->v[2];
776     break;
777     case 3 : valeur = rayt->e;
778     break;
779     default : errno = EDOM; return(0.0);
780     }
781     #ifdef DEBUG
782     fprintf(stderr, "get_val( %i, %i, %i) = %lf\n",val,dir,nb,valeur);
783     #endif
784     return valeur;
785     }
786    
787 greg 2.1
788     setprismfuncs()
789     {
790     funset("fprism_val", 3, '=', l_get_val);
791     }