//Classe de curseur horizontal valeur réelle
class Hslider
{
int swidth, sheight; // largeur et hauteur du curseur
int xpos, ypos; // positions de l'extrémité gauche de la barre du curseur
int spos, newspos; // x position du curseur
float val,valMin,valMax,valPrec; //valeur associée à la position du curseur comprise entre valmin et valmax
boolean over; // is the mouse over the slider?
boolean locked;
String label;
Hslider (int xp, int yp, int sw, int sh, String lb, float vMin, float vMax) {
swidth = sw;
sheight = sh;
xpos = xp;
ypos = yp-sheight/2;
spos = xpos + swidth/2;
newspos = spos;
valMin = vMin;
valMax = vMax;
val = valMin + (spos-xpos)*(valMax-valMin)/swidth;
valPrec = val;
label=lb;
}
void update() {
if(over()) {
over = true;
} else {
over = false;
}
if(mousePressed && over) {
locked = true;
}
if(!mousePressed) {
locked = false;
}
if(locked) {
newspos = rampe(mouseX, xpos, xpos+swidth);
}
if(abs(newspos - spos) > 1) {
spos = spos + (newspos-spos)/2;
val = valMin + (spos-xpos)*(valMax-valMin)/swidth;
}
}
int rampe(int xx, int xxMin, int xxMax) {
return min(max(xx, xxMin), xxMax);
}
boolean over() {
if(mouseX >= xpos && mouseX <= xpos+swidth &&
mouseY >= ypos-sheight/2 && mouseY <= ypos+sheight/2) {
return true;
} else {
return false;
}
}
void draw() {
rectMode(CENTER);
stroke(0);
line(xpos,ypos,swidth+xpos,ypos);
for(int i=1;i<2;i++){
stroke(163,105,211,200-100*(i-1));
line(xpos,ypos+i,swidth+xpos,ypos+i);
line(xpos,ypos-i,swidth+xpos,ypos-i);
}
if(over || locked) {
fill(163,105,211,120);
stroke(255,255,255);
} else {
stroke(163,105,211);
fill(255,255,255);
}
rect(spos, ypos, sheight, sheight);
fill(0);
text(label,xpos,ypos-sheight);
text(val,xpos,ypos+2*sheight);
rectMode(CORNER);
}
float getVal() {
// donne la valeur associée au curseur.
return val;
}
boolean change() {
if(valPrec!=val) {
valPrec=val;return true;
} else {
return false;
}
}
}
//coin_air
//Franges du coin d'air simulés : Une source de largeur spectrale deltaLambda et de longueur d'onde moyenne LambdaMoy est envoyé sur un interféromètre de Michelson configuré en coin d'air.
//La simulation montre l'influence de l'angle du coin d'air sur l'interfrange et celle de la largeur spectrale sur le contraste (notion d'incohérence temporelle)
//des curseurs permettent de faire varier l'angle, la longueur d'onde, la largeur spectrale.
//J.roussel
//Juillet 2009
int N; //nombre de raies spectrales
int L; //demi-largeur de l'interférogramme
int H; //hauteur de l'interférogramme
float lambdaMoy; //longeur d'onde centrale de la source spectrale (en nm)
float deltaLambda; //largeur spectrale de la source (en nm)
float Alpha; // angle du coin d'air
float IR,IG,IB;//3 composantes RGB pour une raie spectrale
//curseurs horizontaux
Hslider slider1;
Hslider slider2;
Hslider slider3;
//police
PFont fontA;
void setup() {
size(600,400);
frameRate(15);
L=int(width/2);
H=int(height/2);
background(0);
N=100;
//curseurs
slider1=new Hslider(10,7*H/4,100,10,"lambda[nm]",380,780);
slider2=new Hslider(210,7*H/4,100,10,"deltaLambda[nm]",0,400);
//rappel: l'interfrange vaut lambda/2alpha. il faut alpha assez petit pour que l'interfrange soit supérieur à un pixel
slider3=new Hslider(410,7*H/4,100,10,"angle en minutes d'arc",0,20);
//Titres et echelles
fontA = loadFont("Helvetica-24.vlw");
textFont(fontA, 20);
textAlign(CENTER);
text("Franges du coin d'air",L,0.2*H);
textAlign(CORNER);
textFont(fontA, 12);
stroke(255);
line(1.5*L,0.2*H,1.5*L+10,0.2*H);
text("100microns",1.5*L+20,0.2*H);
}
void draw() {
//******************************
//panneau de commandes
//*****************************
noStroke();
fill(100);
rect(0,int(1.6*H),2*L,50);
fill(255);
slider1.update();
slider1.draw();
slider2.update();
slider2.draw();
slider3.update();
slider3.draw();
lambdaMoy=slider1.getVal();
deltaLambda=slider2.getVal();
Alpha=(slider3.getVal()*PI/10800);
//****************************
//tracé de l'interférogramme
//***************************
pushMatrix();
translate(L,H);//centrage de l'origine du repère
traceFranges(lambdaMoy,deltaLambda,Alpha);
popMatrix();
}
//**************************
//conversion lambda->RGB
//*************************
void lambdaToRgb(float x)
{
float R=1;
float G=1;
float B=1;
float sat=1;
if(x<440. && x>=380.){
R=(440.-x)/60;
G=0;
B=1.;
}
if(x<490. && x>=440.){
R=0;
G=(x-440.)/50.;
B=1.;
}
if(x<510. && x>=490.){
R=0;
G=1.;
B=(510.-x)/20.;
}
if(x<580. && x>=510.){
R=(x-510.)/70.;
G=1.;
B=0;
}
if(x<645. && x>=580.){
R=1;
G=(645.-x)/65.;
B=0;
}
if(x<780. && x>=645.){
R=1.;
G=0;
B=0;
}
if(x>700.){
sat=0.3+0.7*(780.-x)/80.;
}
if(x<420.){
sat=0.3+0.7*(x-380.)/40.;
}
IR=(255*sat*R);
IG=(255*sat*G);
IB=(255*sat*B);
}
//donne l'éclairement d'une raie de longueur d'onde ll(en micron) en un point d'abscisse xx(en pixel) du coin d'air
float eLambda(int xx, float ll, float angle){
return(1+cos(4*PI*tan(angle)*10000*xx/ll));
}
void traceFranges(float lm,float dl,float aa){
float lambdaK,eclairement;
for (int i=-L+1;i<L;i++){
float doseR=0;
float doseG=0;
float doseB=0;
for (int k=1;k<=N;k++){
lambdaK=lm+dl*(2*k-N-1)/(2*N-2);
lambdaToRgb(lambdaK);
eclairement=eLambda(i,lambdaK,aa);
doseR+=IR*eclairement;
doseG+=IG*eclairement;
doseB+=IB*eclairement;
}
stroke(doseR/(2*N),doseG/(2*N),doseB/(2*N));
line(i,-H/2,i,H/2);
}
}
For explanations, go to :
http://perso.ensc-rennes.fr/jimmy.roussel/simuler/coin_air/applet/index.html