Codice Java dell'applicazione Coulomb
/*
* @(#)Coulomb.java ver 1.0 20/12/95 Francesco Benvenuti
*/
import java.awt.*;
import java.applet.*;
import java.util.Date;
/**
* Una applicazione didattica sulle linee di forza del campo
elettrostatico
* generato da tre cariche elettriche puntiformi. Questa applicazione
* puo' essere eseguita sia da sola (con l'interprete Java), sia come
applet
* sotto Netscape Navigator (versione 2.0 o successiva)
*/
class QFrame extends Frame { /*QFrame sottoclasse di Frame con
gestione di WINDOWS_DESTROY */
public QFrame(String titolo) {
super(titolo);
}
public boolean handleEvent(Event e) {
if (e.id == Event.WINDOW_DESTROY) {
System.out.println("\n\n******************************");
System.out.println("Grazie per l'uso del programma");
System.out.println("******************************\n\n");
System.exit(0);
}
return true;
}
}
class DFrame extends Frame { /* dFrame sottoclasse di Frame con
gestione di WINDOWS_DESTROY */
Font font, font2;
Date date = new Date();
public DFrame(String titolo) {
super(titolo);
}
public void paint(Graphics g) {
Rectangle r = bounds();
int i = (int)Math.round(r.width/15);
int xc = (int)Math.round(r.width);
int yc = (int)Math.round(r.height);
g.setColor(Color.yellow);
g.fillRect(0, 0, r.width, r.height);
g.setColor(Color.black);
int diam = r.width/20;
int dist = r.width/15;
g.fillOval(dist/2, dist/2, diam, diam);
g.fillOval(dist/2, r.height - dist, diam, diam);
g.fillOval(r.width - dist , r.height - dist, diam, diam);
g.fillOval(r.width - dist, dist/2, diam, diam);
font = new Font("Helvetica", Font.PLAIN, i);
g.setColor(Color.red);
g.setFont(font);
g.drawString("Autore: Francesco Benvenuti", xc/9, 2*yc/3);
font2 = new Font("Arial", Font.ITALIC, i-3);
g.setFont(font2);
g.setColor(Color.blue);
g.drawString("Oggi e' " + date, xc/20, yc/3);
}
public boolean handleEvent(Event e) {
if(e.id == Event.WINDOW_DESTROY) {
Coulomb.mostra(false); /* Coulomb.mostra e' metodo statico:
non c'e' bisogna di istanziare
Coulomb in un nuovo oggetto
con new */
}
return true;
}
}
public class Coulomb extends Applet { /* Coulomb come Applet */
CoulombControls1 controls;
CoulombControls2 controls2;
static Frame f;
public void init() { /* metodo di inizio in ambiente Web */
setLayout(new BorderLayout());
CoulombCanvas c = new CoulombCanvas();
add("North", controls2 = new CoulombControls2(c));
add("Center", c);
add("South", controls = new CoulombControls1(c, controls2));
f = new DFrame("Informazioni");
}
public static void mostra(boolean a) { /* il metodo mostra non
necessita di essere
istanziato: vedi DFrame
*/
if(a){
f.resize(200, 100);
f.show();
} else {
f.hide();
}
}
public void start() {
controls.enable();
controls2.enable();
}
public void stop() {
controls.disable();
controls2.disable();
}
public static void main(String args[]) { /* main e' metodo di
inizio quando
l'applicazione non
gira in ambiente Web
*/
Frame f = new QFrame("Linee di forza elettrostatiche");
Coulomb coulomb = new Coulomb();
coulomb.init(); /* si richiama init() */
coulomb.start();
f.add("Center", coulomb);
f.resize(500, 400);
f.show();
}
}
class CoulombCanvas extends Canvas { /* genera la finestra con le
linee di forza */
double x, y, xp, yp, xi, yi, xd, yd, xr, yr, r1, r2, E, Ex, Ey,
Ex1, Ey1, Ex2, Ey2, Ex3, Ey3, theta;
double h;
boolean rossa = true;
boolean verde = false;
boolean gialla = false;
boolean no_auto = false;
int car1 = 3;
int car2 = 1;
int car3 = -10;
int x_car1 = -150;
int y_car1 = 20;
int x_car2 = 0;
int y_car2 = 0;
int x_car3 = 150;
int y_car3 = -30;
int carex1, carex2, carey1, carey2;
int max_x, max_y;
int passo = 1000;
public void paint(Graphics g) {
Rectangle r = bounds();
max_x = r.width / 2;
max_y = r.height / 2;
int hlines = r.height / 10;
int vlines = r.width / 10;
g.setColor(Color.pink);
for (int i = 1; i <= hlines; i++) {
g.drawLine(0, i * 10, r.width, i * 10);
}
for (int i = 1; i <= vlines; i++) {
g.drawLine(i * 10, 0, i * 10, r.height);
}
g.setColor(Color.red);
g.fillOval(max_x + x_car1, max_y - y_car1, 4, 4);
g.setColor(Color.green);
g.fillOval(max_x + x_car2, max_y - y_car2, 4, 4);
g.setColor(Color.yellow);
g.fillOval(max_x + x_car3, max_y - y_car3, 4 ,4);
if(rossa) {
xi = x_car1; yi = y_car1;
carex1 = x_car2; carex2 = x_car3;
carey1 = y_car2; carey2 = y_car3;
if(car1<0) {car1=-car1; car2=-car2; car3=-car3;}
}
if(verde) {
xi = x_car2; yi = y_car2;
carex1 = x_car1; carex2 = x_car3;
carey1 = y_car1; carey2 = y_car3;
if(car2<0) {car1=-car1; car2=-car2; car3=-car3;}
}
if(gialla) {
xi = x_car3; yi = y_car3;
carex1 = x_car1; carex2 = x_car2;
carey1 = y_car1; carey2 = y_car2;
if(car3<0) {car1=-car1; car2=-car2; car3=-car3;}
}
g.setColor(Color.black);
if(!no_auto) {
for(theta = 0.523; theta < 6.28; theta=theta+0.523) {
/* 12 condizioni iniziali coordinate x e y pb di Cauchy a
2 eqq. (angolo di 30 gradi) */
h = 100;
x = Math.cos(theta) * 5 + xi;
y = Math.sin(theta) * 5 + yi;
do {
xd = x - x_car1;
yd = y - y_car1;
r2 = xd*xd + yd*yd;
r1 = Math.sqrt(r2);
E = car1/r2;
Ex1 = E * xd/r1;
Ey1 = E * yd/r1;
xd = x - x_car2;
yd = y - y_car2;
r2 = xd*xd + yd*yd;
r1 = Math.sqrt(r2);
E = car2/r2;
Ex2 = E * xd/r1;
Ey2 = E * yd/r1;
xd = x - x_car3;
yd = y - y_car3;
r2 = xd*xd + yd*yd;
r1 = Math.sqrt(r2);
E = car3/r2;
Ex3 = E * xd/r1;
Ey3 = E * yd/r1;
/* si memorizzano i vecchi valori di coordinate prima di
assegnare quelli nuovi */
xp= x;
yp= y;
Ex = Ex1 + Ex2 + Ex3;
Ey = Ey1 + Ey2 + Ey3;
xd = Ex * h;
yd = Ey * h;
if(Math.abs(xd) > 2 || Math.abs(yd) > 2) {
h = h/10;
xd = Ex * h;
yd = Ey * h;
} else
if(Math.abs(xd) < 0.5 || Math.abs(yd) < 0.5) {
h = h * 10;
xd = Ex * h;
yd = Ey * h;
}
x = x + xd;
y = y + yd;
xr = x - xp;
yr = y - yp;
if(Math.abs((carex1 - xp)/xr - (carey1 - yp)/yr) <
0.01) break;
if(Math.abs((carex2 - xp)/xr - (carey2 - yp)/yr) <
0.01) break;
g.drawLine( (int)Math.round(xp) + max_x , max_y -
(int)Math.round(yp),
(int)Math.round(x) + max_x, max_y -
(int)Math.round(y));
} while(Math.abs(x) < max_x && Math.abs(y) < max_y);
}
} else {
h = passo;
for(theta = 0.523; theta < 6.28; theta=theta+0.523) {
/* 12 condizioni iniziali coordinate x e y pb di Cauchy a
2 eqq. (angolo di 30 gradi) */
x = Math.cos(theta) * 5 + xi;
y = Math.sin(theta) * 5 + yi;
do {
xd = x - x_car1;
yd = y - y_car1;
r2 = xd*xd + yd*yd;
r1 = Math.sqrt(r2);
E = car1/r2;
Ex1 = E * xd/r1;
Ey1 = E * yd/r1;
xd = x - x_car2;
yd = y - y_car2;
r2 = xd*xd + yd*yd;
r1 = Math.sqrt(r2);
E = car2/r2;
Ex2 = E * xd/r1;
Ey2 = E * yd/r1;
xd = x - x_car3;
yd = y - y_car3;
r2 = xd*xd + yd*yd;
r1 = Math.sqrt(r2);
E = car3/r2;
Ex3 = E * xd/r1;
Ey3 = E * yd/r1;
/* si memorizzano i vecchi valori di coordinate prima di
assegnare quelli nuovi */
xp = x;
yp = y;
x = x + (Ex1 + Ex2 + Ex3) * h;
y = y + (Ey1 + Ey2 + Ey3) * h;
xr = x - xp;
yr = y - yp;
if(Math.abs((carex1 - xp)/xr - (carey1 - yp)/yr) <
0.01) break;
if(Math.abs((carex2 - xp)/xr - (carey2 - yp)/yr) <
0.01) break;
g.drawLine( (int)Math.round(xp) + max_x , max_y -
(int)Math.round(yp),
(int)Math.round(x) + max_x, max_y -
(int)Math.round(y));
} while(Math.abs(x) < max_x && Math.abs(y) < max_y);
}
}
}
public void redraw(int x_car1, int y_car1,
int x_car2, int y_car2,
int x_car3, int y_car3 ) {
this.x_car1 = x_car1;
this.y_car1 = y_car1;
this.x_car2 = x_car2;
this.y_car2 = y_car2;
this.x_car3 = x_car3;
this.y_car3 = y_car3;
repaint();
}
public void redraw2(int car1, int car2, int car3) {
this.car1 = car1;
this.car2 = car2;
this.car3 = car3;
}
public void redraw3(boolean rossa, boolean verde, boolean gialla,
boolean no_auto, int passo) {
this.rossa = rossa;
this.verde = verde;
this.gialla = gialla;
this.no_auto = no_auto;
this.passo = passo;
}
}
class CoulombControls1 extends Panel { /* Controlli inferiori */
TextField x_car1;
TextField y_car1;
TextField x_car2;
TextField y_car2;
TextField x_car3;
TextField y_car3;
CoulombCanvas canvas;
CoulombControls2 cont;
public CoulombControls1(CoulombCanvas canvas, CoulombControls2
cont) {
this.canvas = canvas;
this.cont = cont;
add(x_car1 = new TextField("-150", 4));
add(y_car1 = new TextField("20", 4));
add(x_car2 = new TextField("0", 4));
add(y_car2 = new TextField("0", 4));
add(x_car3 = new TextField("150", 4));
add(y_car3 = new TextField("-30", 4));
add(new Button("Disegna..."));
}
public boolean action(Event ev, Object arg) {
if (ev.target instanceof Button) {
canvas.redraw(
Integer.parseInt(x_car1.getText().trim()),
Integer.parseInt(y_car1.getText().trim()),
Integer.parseInt(x_car2.getText().trim()),
Integer.parseInt(y_car2.getText().trim()),
Integer.parseInt(x_car3.getText().trim()),
Integer.parseInt(y_car3.getText().trim()));
cont.tValori();
return true;
}
return false;
}
}
class CoulombControls2 extends Panel { /* Controlli superiori */
TextField car1;
TextField car2;
TextField car3;
TextField passo;
Checkbox ck1;
Checkbox ck2;
Checkbox ck3;
Checkbox no_auto;
CoulombCanvas canvas;
public CoulombControls2(CoulombCanvas canvas) {
this.canvas = canvas;
add(car1 = new TextField("3", 2));
add(car2 = new TextField("1", 2));
add(car3 = new TextField("-10", 2));
CheckboxGroup ckg = new CheckboxGroup();
ck1 = new Checkbox("Rossa", ckg, true);
ck2 = new Checkbox("Verde", ckg, false);
ck3 = new Checkbox("Gialla", ckg, false);
add(ck1);
add(ck2);
add(ck3);
no_auto = new Checkbox("passo");
add(no_auto);
add(passo = new TextField("1000", 5));
add(new Button("Info"));
}
public boolean action(Event ev, Object arg) {
if (ev.target instanceof Button) {
Coulomb.mostra(true);
return true;
}
return false;
}
public void tValori() {
canvas.redraw2(Integer.parseInt(car1.getText().trim()),
Integer.parseInt(car2.getText().trim()),
Integer.parseInt(car3.getText().trim()));
canvas.redraw3(ck1.getState(), ck2.getState(), ck3.getState(),
no_auto.getState(),
Integer.parseInt(passo.getText().trim()));
}
}