//©J.Roussel
//
//champs créés par un condensateur plan (on résout l'équation de Laplace) entouré par un conducteur carré porté au potentiel nul.
//le condensateur est portée à une tension 2V0 et l'espacement vaut 2a. Donc, pour avoir un champ électrique de l'ordre de l'unité il faut prendre V0=a/2.
int N;
int ell;//demi-largeur du condensateur
int a;//demi-espacement des condensateurs`
int b;//demi largeur du conducteur carré (la masse) entourant le condensateur
int V0;//potentiel des armatures = ±V0
int decX,decY;//l'origine de cadre que l'on visualise est décalée par rapport à l'origine du carré formant la masse
float[][] V;//potentiel
boolean afficheMagnitude=false;
ArrayList lignes,equipot;
Plaque armatureP,armatureN;
boolean over1,over2 = false;
boolean move1,move2 = false;
int Ligne=1;
void setup() {
size(300, 200);
b=250;//frontière V=0 de dimension 2b x 2b
N=2*b;//reseau NxN
//X=b-width/2+x et Y=b-height/2+y
decX=b-width/2;
decY=b-height/2;
V = new float[2*b+1][2*b+1];//champ potentiel V(X,Y)
a=20;//demi-espacement entre les armatures
V0=10;//potentiel de l'armature. Prendre V0=a/2
ell=99;//demi-largeur des armatures
// On centre les armatures à l'écran
armatureP=new Plaque(b,b-a,2*ell,6,V0,false);
armatureN=new Plaque(b,b+a,2*ell,6,-V0,false);
lignes = new ArrayList();//liste de lignes de champs
equipot= new ArrayList();//liste d'équipotentielles
InitialisationBord();//on porte la frontière au potentiel nul
initialisation();//on fixe la valeur de V pour les points situées sur les armatures.
relaxation_rapide(200);// on applique la méthode de relaxation pour résoudre l'équation de Laplace
relaxation(10);// on applique la méthode de relaxation pour résoudre l'équation de Laplace
}
void draw() {
relaxation_rapide(50);// on applique la méthode de relaxation pour résoudre l'équation de Laplace
relaxation(2);//idem (plus précis)
draw_champ(decX,decY);//représente la carte du champ électrique
if(!NoFrontiere(decX+mouseX,decY+mouseY,armatureP) && !afficheMagnitude){over1 = true;armatureP.inverted=true;}
else {over1 = false;armatureP.inverted=false;}
if(move1) {armatureP.x = decX+mouseX;armatureP.y = decY+mouseY;initialisation();}
if(!NoFrontiere(decX+mouseX,decY+mouseY,armatureN) && !afficheMagnitude){over2 = true;armatureN.inverted=true;}
else {over2 = false;armatureN.inverted=false;}
if(move2) {armatureN.x = decX+mouseX;armatureN.y = decY+mouseY;initialisation();}
//maping du champ si demandé
if (afficheMagnitude) {map_champE(decX,decY);}//carte d'intensité
//tracé des lignes de champ
for (int i = lignes.size()-1; i >= 0; i--) {LigneDeChamp LDC = (LigneDeChamp) lignes.get(i);LDC.display();}
for (int i = equipot.size()-1; i >= 0; i--) {Equipotentielle EQP = (Equipotentielle) equipot.get(i);EQP.display();}
armatureP.display();//trace l'armature positive
armatureN.display();//dessine l'armature négative
}
//procédure pour savoir si le point M se trouve sur une armature
boolean NoFrontiere(int x,int y, Plaque p){
if(abs(x-p.x)<(p.largeur)/2 && abs(y-p.y)
= 0; i--) {lignes.remove(i);}
for (int i = equipot.size()-1; i >= 0; i--) {equipot.remove(i);}
}
//méthode de relaxation appliqué M fois sur tous les points du réseau (gain en précision précision)
void relaxation(int M) {
for (int k=0; kN-2 || yy<2 || yy>N-2){return new PVector(0,0);}
else{return new PVector(V[xx-1][yy]-V[xx+1][yy], V[xx][yy-1]-V[xx][yy+1]);}
}
// tracé de la carte de champs
void draw_champ(int posX, int posY) {
PVector vector;
background(255);
strokeWeight(1);
stroke(153);
float arrowsize = 4;
float len=10;
for (int i=0; i=0.57) {
b=1;
} else {
b=z/0.32-0.78125;
}
R=255*b;
if (z<=0.42) {
b=0;
} else if (z>=0.92) {
b=1;
} else {
b=2*z-0.84;
}
G=255*b;
if (z<=0.42) {
b=4*z;
} else if (z>=0.92) {
b=z/0.08-11.5;
} else {
b=-2*z+1.84;
}
B=255*b;
return color(R, G, B);
}
void setLigne(int n){Ligne=n;}
void mousePressed() {
// if (mouseButton == LEFT && !over1 && !over2)
if (Ligne==1 && !over1 && !over2)
{
// une nouvelle ligne de champ est ajoutée à la liste (à la fin par défaut)
lignes.add(new LigneDeChamp(mouseX, mouseY,2));
}
//if (mouseButton == RIGHT && !over1 && !over2)
if (Ligne == 2 && !over1 && !over2)
{
equipot.add(new Equipotentielle(mouseX, mouseY, 4));
}
if(over1) {move1 = true;}
if(over2) {move2 = true;}
}
void EffaceLignes(){
for (int i = lignes.size()-1; i >= 0; i--) {
lignes.remove(i);
}
for (int i = equipot.size()-1; i >= 0; i--) {
equipot.remove(i);
}
}
void ChangeAfficheMagnitude(){
afficheMagnitude=!afficheMagnitude;
}
// void keyPressed() {
// if (key=='r') {
// for (int i = lignes.size()-1; i >= 0; i--) {
// lignes.remove(i);
// }
// for (int i = equipot.size()-1; i >= 0; i--) {
// equipot.remove(i);
// }
// } else {
// afficheMagnitude=!afficheMagnitude;
// }
//}
void mouseReleased() {
move1 = false; move2=false;
}
//--- OBJETS ---
class Plaque {
int x;
int y;
int largeur;
int hauteur;
int potential;//potentiel
boolean inverted;
Plaque(int xx,int yy, int ll, int hh, int pp, boolean ii) {
x=xx;
y=yy;
largeur=ll;
hauteur=hh;
potential=pp;
inverted=ii;
}
void display() {
strokeWeight(hauteur);
if(inverted){stroke(250,0,230);}
else{stroke(153);}
line(x-decX-largeur/2,y-decY,x-decX+largeur/2,y-decY);
stroke(250);
strokeWeight(2);
if(potential>0){
line(x-decX-hauteur/2,y-decY,x-decX+hauteur/2,y-decY);
line(x-decX,y-decY-hauteur/2,x-decX,y-decY+hauteur/2);
}
else{line(x-decX-hauteur/2,y-decY,x-decX+hauteur/2,y-decY);}
}
}
class LigneDeChamp {
int x0;
int y0;
int pas;
LigneDeChamp(int posX, int posY, int ppas) {
x0=posX;
y0=posY;
pas= ppas;
}
//méthode Euler (le pas est suffisament petit)
void display() {
strokeWeight(2);
stroke(153);
//stroke(0, 153, 204, 150);
fill(0, 153, 204, 150);
int xxx1,yyy1;
float xx1, yy1;
float angle;
xx1=x0;
yy1=y0;
xxx1=decX+x0;
yyy1=decY+y0;
pushMatrix();
translate(x0, y0);
angle=champ(xxx1,yyy1).heading2D();
rotate(angle);
beginShape(TRIANGLES);
vertex(-6, 2);
vertex(0, 0);
vertex(-6, -2);
endShape();
rotate(-angle);
while (NoFrontiere(xxx1,yyy1,armatureN) & NoFrontiere(xxx1,yyy1,armatureP) & champ(xxx1,yyy1).mag()!=0)
{
angle=champ(xxx1, yyy1).heading2D();
xx1+=pas*cos(angle);
yy1+=pas*sin(angle);
xxx1=int(decX+xx1);
yyy1=int(decY+yy1);
line(0, 0, pas*cos(angle), pas*sin(angle));
translate(pas*cos(angle), pas*sin(angle));
}
popMatrix();
xx1=x0;
yy1=y0;
xxx1=decX+x0;
yyy1=decY+y0;
pushMatrix();
translate(xx1, yy1);
while (NoFrontiere(xxx1,yyy1,armatureN) & NoFrontiere(xxx1,yyy1,armatureP) & champ(xxx1,yyy1).mag()!=0)
{
angle=champ(xxx1, yyy1).heading2D();
xx1+=pas*cos(angle+PI);
yy1+=pas*sin(angle+PI);
xxx1=int(decX+xx1);
yyy1=int(decY+yy1);
line(0, 0, pas*cos(angle+PI), pas*sin(angle+PI));
translate(pas*cos(angle+PI), pas*sin(angle+PI));
}
popMatrix();
}
}
class Equipotentielle {
int x0;
int y0;
int pas;
Equipotentielle(int posX, int posY, int ppas) {
x0=posX;
y0=posY;
pas= ppas;
}
//méthode RK2
void display() {
strokeWeight(1);
stroke(255,157,0);
//stroke(0, 153, 204, 150);
float xx1, yy1,ddist,distance;
float angle;
int compteur=0;
boolean stop=false;
xx1=x0;
yy1=y0;
while (!stop) {
angle=champ(int(decX+xx1), int(decY+yy1)).heading2D()+HALF_PI;
angle=champ(int(decX+xx1+.5*pas*cos(angle)),int(decY+yy1+.5*pas*sin(angle))).heading2D()+HALF_PI;
if (compteur%2==0) {
line(xx1, yy1, xx1+pas*cos(angle), yy1+pas*sin(angle));
}
compteur++;
ddist=-dist(xx1,yy1,x0,y0);
xx1+=pas*cos(angle);
yy1+=pas*sin(angle);
distance=dist(xx1,yy1,x0,y0);
ddist+=distance;
if (distance<2*pas && ddist<0 || compteur>300) {stop=true;}
}
}
}