import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/** Het SlingerPaneel is het model van de
* eigenlijke slinger.
* @author Lieven Smits
* @version 1.1 7/9/2000
*/
class SlingerPaneel extends Panel {
/* 1. fysische basisparameters - de initialisaties geven slechts
standaardwaarden voor wanneer een appletparameter
op de webpagina ontbreekt */
/** Massa van de bol in kg. */
double massa = 1;
/** Lengte van het touw in m. */
double lengte = 1;
/** Valversnelling in meter per seconde kwadraat. */
double valversnelling = 9.81;
/** Maximale uitwijking van de slinger, uitgedrukt
* in radialen (een volledige cirkel van 360 graden
* bevat 2 pi radialen, dus 1 radiaal is ongeveer
* 57 graden).
*/
double amplitude = 1;
/* 2. display-opties */
/** Bepaalt of de hulplijntjes getekend moeten worden. */
boolean toonHulplijnen;
/** Bepaalt of de blauwe pijl met de gewichtsvector en zijn
* ontbinding in een radiale en een tangentiele component
* getekend moeten worden. */
boolean toonKracht;
/** Bepaalt of de rode, horizontale positievector
* getekend moet worden. */
boolean toonPositie;
/** Bepaalt of de groene snelheidsvector getekend moet worden. */
boolean toonSnelheid;
/** Bepaalt of de gele versnellingsvector getekend moeten worden. */
boolean toonVersnelling;
/* 3. hulpveranderlijken */
/** Lengte van de slinger in pixels. */
double straal;
/** Duur van de slingerperiode in seconden. */
double periode;
/** Aantal radialen van de periodieke beweging per MILLIseconde. */
double hoeksnelheid; /*
/** Horizontale positie van het vaste punt van de slinger
* in pixels.
*/
int beginX;
/** Verticale positie van het vaste punt van de slinger
* in pixels.
*/
int beginY;
/** Minimumaantal milliseconden tussen twee opeenvolgende
* animatiebeelden.
*/
public long delay;
/** Straal van de bol in pixels. */
double r;
/** Gewicht van de slingermassa in Newton. */
double gewicht;
/* 4. schaalconstanten voor het tekenen van fysische grootheden */
/** Lengtes en posities in pixels per m. */
final double schaalL = 100;
/** Snelheid in pixels per m/s. */
final double schaalV = 150;
/** Versnelling in pixels per m/s2. */
final double schaalA = 50000;
/** Inverse derdemacht van de massadichtheid van de bol.
* Deze laatste is uitgedrukt in kg per kubieke pixel.
* Deze schaalfactor bepaalt hoe groot de bol getekend
* wordt, afhankelijk van de massa van de slinger.
*/
final double schaalMassa = 5;
/** Kracht in pixels per Newton. */
final double schaalGewicht = 6;
/* 5. systeemtijd en fase */
/** Systeemtijd bij het begin van het huidige experiment,
* of op het moment van de laatste parameterwijziging.
*/
public long startTijd;
/** Fasehoek van de periodieke beweging bij het begin van
* het huidige experiment, of op het moment van de laatste
* parameterwijziging.
*/
public double startCycle;
/** Huidige fasehoek van de periodieke beweging.
* Die moet public property zijn, zodat
* de event handlers de startfase ermee kunnen
* initialiseren.
*/
public double huidigeCycle = 0;
/* 6. Beeld in voorbereiding */
/** Off line graphics context. */
Graphics offGraphics;
/** Off-linebeeld (in voorbereiding). */
Image offImage;
/** Construeer het slingerpaneel met gegeven fysische
* parameters.
* @param massa
* Massa van de bol in kg.
* @param lengte
* Lengte van het touw in m.
* @param valversnelling
* Grootte van de zwaartekracht, uitgedrukt in m/s2.
* @param amplitude
* Maximale uitwijking van de slinger in radialen.
*/
SlingerPaneel(double massa, double lengte,
double valversnelling, double amplitude) {
super();
this.massa = massa;
this.lengte = lengte;
this.valversnelling = valversnelling;
this.amplitude = amplitude;
toonHulplijnen = true;
toonKracht = true;
toonPositie = true;
toonSnelheid = true;
toonVersnelling = true;
berekenHulpveranderlijken();
}
/** Wijzig de massa van de bol.
* @param massa
* De nieuwe massa in kg.
*/
void zetMassa(double massa) {
this.massa = massa;
berekenHulpveranderlijken();
}
/** Geef de massa van de bol.
* @return
* De massa van de bol in kg.
*/
double geefMassa() {
return massa;
}
/** Wijzig de lengte van het touw.
* @param lengte
* De nieuwe lengte in m.
*/
void zetLengte(double lengte) {
this.lengte = lengte;
berekenHulpveranderlijken();
startChrono();
}
/** Geef de lengte van het touw.
* @return
* De lengte van het touw in m.
*/
double geefLengte() {
return lengte;
}
/** Wijzig de valversnelling.
* @param valversnelling
* De nieuwe valversnelling in meter per seconde
* kwadraat.
*/
void zetValversnelling(double valversnelling) {
this.valversnelling = valversnelling;
berekenHulpveranderlijken();
startChrono();
}
/** Geef de valversnelling.
* @return
* De valversnelling in meter per seconde kwadraat.
*/
double geefValversnelling() {
return valversnelling;
}
/** Wijzig de maximale uitwijking (amplitude).
* @param amplitude
* De nieuwe amplitude van de slinger in radialen.
*/
void zetAmplitude(double amplitude) {
this.amplitude = amplitude;
berekenHulpveranderlijken();
}
/** Geef de maximale uitwijking (amplitude).
* @return
* De amplitude van de slinger in radialen.
*/
double geefAmplitude() {
return amplitude;
}
/** Stel de display-opties in.
* @param hulplijnen
* Bepaalt of de hulplijntjes getekend moeten worden.
* @param kracht
* Bepaalt of de blauwe pijl met de gewichtsvector en zijn
* ontbinding in een radiale en een tangentiele component
* getekend moeten worden.
* @param positie
* Bepaalt of de rode, horizontale positievector
* getekend moet worden.
* @param snelheid
* Bepaalt of de groene snelheidsvector getekend moet worden.
* @param versnelling
* Bepaalt of de gele versnellingsvector getekend moeten worden.
*/
void stelVlaggen(boolean hulplijnen, boolean kracht,
boolean positie, boolean snelheid, boolean versnelling) {
toonHulplijnen = hulplijnen;
toonKracht = kracht;
toonPositie = positie;
toonSnelheid = snelheid;
toonVersnelling = versnelling;
}
/** Bepaal of de hulplijntjes getekend moeten worden.
* @param hulplijnen
* true als ze getekend moeten worden.
*/
void stelHulplijnen(boolean hulplijnen) {
toonHulplijnen = hulplijnen;
}
/** Bepaal of de krachtvector getekend moet worden.
* @param kracht
* true als hij getekend moet worden.
*/
void stelKracht(boolean kracht) {
toonKracht = kracht;
}
/** Bepaal of de horizontale positievector getekend moet worden.
* @param positie
* true als hij getekend moet worden.
*/
void stelPositie(boolean positie) {
toonPositie = positie;
}
/** Bepaal of de snelheidsvector getekend moet worden.
* @param snelheid
* true als hij getekend moet worden.
*/
void stelSnelheid(boolean snelheid) {
toonSnelheid = snelheid;
}
/** Bepaal of de versnellingsvector getekend moet worden.
* @param versnelling
* true als hij getekend moet worden.
*/
void stelVersnelling(boolean versnelling) {
toonVersnelling = versnelling;
}
/** Bereken een aantal hulpgetallen die constant
* zijn voor een slingerbeweging.
*/
void berekenHulpveranderlijken() {
straal = lengte * schaalL;
periode = 2 * Math.PI * Math.sqrt(lengte / valversnelling);
hoeksnelheid = Math.sqrt(valversnelling / lengte) / 1000;
delay = 50;
r = Math.pow(massa, 1.0/3) * schaalMassa;
gewicht = massa * valversnelling;
beginX = 245;
beginY = 30;
}
/** Registreer het begin van een slingerbeweging. */
long startChrono() {
startTijd = System.currentTimeMillis();
startCycle = huidigeCycle;
return startTijd;
}
/** Bereken de huidige toestand van de slinger
* en teken hem.
* @param g
* De grafische context om de slinger te tekenen.
*/
public void update(Graphics g) {
long tijd = System.currentTimeMillis();
huidigeCycle = (tijd - startTijd) * hoeksnelheid + startCycle;
// verminder met aantal hele periodes d.i. veelvouden van 2 Pi
huidigeCycle -= ((int)(huidigeCycle / 2 / Math.PI)) * 2 * Math.PI;
/* Opmerking met betrekking tot toekomstige uitbreiding.
De volgende lijn is bijna de enige die wat moeilijker wordt
als we de fysische (= niet-harmonische) slinger
willen implementeren. Zoek echter verder op het sleutelwoord
HARMONISCH */
double argument = amplitude * Math.cos(huidigeCycle);
double sinArg = Math.sin(argument);
double cosArg = Math.cos(argument);
/* pixelcoordinaten van het middelpunt van
de slingermassa */
double eindX = beginX + straal * sinArg;
double eindY = beginY + straal * cosArg;
Dimension d = getSize();
if (offGraphics == null) {
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();
}
offGraphics.clearRect(0, 0, d.width, d.height);
// plafond met arcering
offGraphics.setColor(Color.black);
offGraphics.drawLine(0, beginY, 2 * beginX + 1, beginY);
for (int i = 0; i * 5 < 2 * beginX + 1; i++)
offGraphics.drawLine(i * 5, (int) beginY,
i * 5 + 5, (int) beginY - 5);
// verticale maatlijn links
offGraphics.drawLine(7, beginY, 7, (int)(beginY + straal));
offGraphics.drawLine(7, beginY, 4, beginY + 3);
offGraphics.drawLine(7, beginY, 10, beginY + 3);
offGraphics.drawLine(7, (int)(beginY + straal),
4, (int)(beginY + straal) - 3);
offGraphics.drawLine(7, (int)(beginY + straal),
10, (int)(beginY + straal) - 3);
// letter "L" bij verticale maatlijn links
offGraphics.drawString( "L", 10, (int)(beginY + straal / 2));
if (toonHulplijnen) {
offGraphics.setColor(Color.darkGray);
// grijs verticaal streepje centrale as
offGraphics.drawLine(beginX, beginY,
beginX, (int)(beginY + straal / 2));
// dwarsstreepje op verticale maatlijn links
offGraphics.drawLine(4,
(int)(beginY + straal), 10, (int)(beginY + straal));
// boogje naar centrale as
int x = (int)(beginX - straal / 2);
int y = (int)(beginY - straal / 2);
int a = (int)(argument * 180 / Math.PI);
offGraphics.drawArc(x, y, (int) straal, (int) straal, 270, a);
}
// koord
offGraphics.setColor(Color.black);
offGraphics.drawLine(beginX, beginY, (int) eindX, (int) eindY);
// bruine bol met zwart randje
offGraphics.setColor(new Color(144, 96, 0)); // bruin
offGraphics.fillOval((int) (eindX - r), (int) (eindY - r),
(int) (2 * r), (int) (2 * r));
offGraphics.setColor(Color.black);
offGraphics.drawOval((int) (eindX - r), (int) (eindY - r),
(int) (2 * r), (int) (2 * r));
if (toonKracht) {
// blauwe pijl gewicht + symbool Fz
double pijlLengte = gewicht * schaalGewicht;
offGraphics.setColor(Color.blue);
offGraphics.drawLine((int) eindX, (int) eindY,
(int) eindX, (int)(eindY + pijlLengte));
offGraphics.drawLine((int) eindX - 3,
(int)(eindY + pijlLengte) - 3,
(int) eindX, (int)(eindY + pijlLengte));
offGraphics.drawLine((int) eindX + 3,
(int)(eindY + pijlLengte) - 3,
(int) eindX, (int)(eindY + pijlLengte));
offGraphics.drawString("Fz",
(int) eindX, (int)(eindY + pijlLengte) + 12);
offGraphics.drawLine((int) eindX, (int) eindY,
(int)(eindX + pijlLengte * sinArg * cosArg),
(int)(eindY + pijlLengte * cosArg * cosArg));
offGraphics.drawLine((int) eindX, (int) eindY,
(int)(eindX - pijlLengte * cosArg * sinArg),
(int)(eindY + pijlLengte * sinArg * sinArg));
if (toonHulplijnen) {
offGraphics.setColor(Color.darkGray);
offGraphics.drawLine(
(int)(eindX + pijlLengte * sinArg * cosArg),
(int)(eindY + pijlLengte * cosArg * cosArg),
(int) eindX, (int)(eindY + pijlLengte));
offGraphics.drawLine(
(int)(eindX - pijlLengte * cosArg * sinArg),
(int)(eindY + pijlLengte * sinArg * sinArg),
(int) eindX, (int)(eindY + pijlLengte));
}
}
if (toonPositie) {
// rode pijl X-positie + symbool x
double pijlLengte = gewicht * schaalGewicht;
offGraphics.setColor(Color.red);
offGraphics.drawLine(
beginX, (int)(beginY + straal + 1.5 * pijlLengte),
(int) eindX, (int)(beginY + straal + 1.5 * pijlLengte));
if (eindX - beginX > 3) {
offGraphics.drawLine(
(int) eindX, (int)(beginY + straal + 1.5 * pijlLengte),
(int) eindX - 3,
(int)(beginY + straal + 1.5 * pijlLengte) - 3);
offGraphics.drawLine(
(int) eindX, (int)(beginY + straal + 1.5 * pijlLengte),
(int) eindX - 3,
(int)(beginY + straal + 1.5 * pijlLengte) + 3);
}
else if (eindX - beginX < -3) {
offGraphics.drawLine(
(int) eindX, (int)(beginY + straal + 1.5 * pijlLengte),
(int) eindX + 3,
(int)(beginY + straal + 1.5 * pijlLengte) - 3);
offGraphics.drawLine(
(int) eindX, (int)(beginY + straal + 1.5 * pijlLengte),
(int) eindX + 3,
(int)(beginY + straal + 1.5 * pijlLengte) + 3);
}
offGraphics.drawString("x",
(int) (beginX + (eindX - beginX) * 0.6),
(int)(beginY + straal + 1.5 * pijlLengte + 12));
offGraphics.setColor(Color.darkGray);
offGraphics.drawLine(
beginX, (int)(beginY + straal + 1.5 * pijlLengte - 3),
beginX, (int)(beginY + straal + 1.5 * pijlLengte + 3));
}
if (toonSnelheid) {
// HARMONISCH
double alfaDash =
-amplitude * Math.sin(huidigeCycle) * hoeksnelheid;
double beginPijlVX = (straal + 5) * sinArg + beginX;
double beginPijlVY = (straal + 5) * cosArg + beginY;
double vX = straal * cosArg * alfaDash * schaalV;
double vY = -straal * sinArg * alfaDash * schaalV;
double eindPijlVX = beginPijlVX + vX;
double eindPijlVY = beginPijlVY + vY;
offGraphics.setColor(Color.green);
offGraphics.drawLine((int) beginPijlVX, (int) beginPijlVY,
(int) eindPijlVX, (int) eindPijlVY);
if (vX * vX + vY * vY > 9) {
// bovenste streepje
double streep1X = 3 * Math.cos(argument + Math.PI / 4);
double streep1Y = -3 * Math.sin(argument + Math.PI / 4);
// onderste streepje
double streep2X = 3 * Math.cos(argument - Math.PI / 4);
double streep2Y = -3 * Math.sin(argument - Math.PI / 4);
if (vX > 0) {
offGraphics.drawLine((int) eindPijlVX, (int) eindPijlVY,
(int)(eindPijlVX - streep1X), (int)(eindPijlVY - streep1Y));
offGraphics.drawLine((int) eindPijlVX, (int) eindPijlVY,
(int)(eindPijlVX - streep2X), (int)(eindPijlVY - streep2Y));
}
else {
offGraphics.drawLine((int) eindPijlVX, (int) eindPijlVY,
(int)(eindPijlVX + streep1X), (int)(eindPijlVY + streep1Y));
offGraphics.drawLine((int) eindPijlVX, (int) eindPijlVY,
(int)(eindPijlVX + streep2X), (int)(eindPijlVY + streep2Y));
}
}
offGraphics.drawString("v", (int) eindPijlVX, (int) eindPijlVY + 12);
}
if (toonVersnelling) {
// HARMONISCH
double alfaDash =
-amplitude * Math.sin(huidigeCycle) * hoeksnelheid;
// HARMONISCH
double alfaDoubleDash = -argument * hoeksnelheid * hoeksnelheid;
double beginPijlAX = (straal - 5) * sinArg + beginX;
double beginPijlAY = (straal - 5) * cosArg + beginY;
double aX = straal * schaalA
* (-sinArg * alfaDash * alfaDash + cosArg * alfaDoubleDash);
double aY = straal * schaalA
* (-cosArg * alfaDash * alfaDash - sinArg * alfaDoubleDash);
double eindPijlAX = beginPijlAX + aX;
double eindPijlAY = beginPijlAY + aY;
double aAbs = Math.sqrt(aX*aX+aY*aY);
double aCos = aX / aAbs;
double aSin = aY / aAbs;
double root = 1 / Math.sqrt(2);
double aPijlCos = aCos * root + aSin * root;
double aPijlSin = aCos * root - aSin * root;
offGraphics.setColor(Color.yellow);
offGraphics.drawLine((int) beginPijlAX, (int) beginPijlAY,
(int) eindPijlAX, (int) eindPijlAY);
offGraphics.drawString("a",
(int) (eindPijlAX - 5 * argument), (int) eindPijlAY - 3);
offGraphics.drawLine((int) eindPijlAX, (int) eindPijlAY,
(int)(eindPijlAX - aPijlCos * 3),
(int)(eindPijlAY + aPijlSin * 3));
offGraphics.drawLine((int) eindPijlAX, (int) eindPijlAY,
(int)(eindPijlAX - aPijlSin * 3),
(int)(eindPijlAY - aPijlCos * 3));
}
g.drawImage(offImage, 0, 0, this);
}
/** Teken de slinger. We hebben het eigenlijke
* tekenwerk in de methode update geplaatst
* om flikkeringen te elimineren.
* @param g
* De grafische context om de slinger te tekenen.
*/
public void paint(Graphics g) {
update(g);
}
}
/** Een Maatbalk bestaat uit een verticale
* schuifbalk met een gegeven tekst rechts
* onderaan en rechts bovenaan. In tegenstelling
* tot een gewone schuifbalk drukt hij zijn
* waarden uit als doubles en (zucht) is
* de maximumwaarde ook de hoogst mogelijke
* waarde.
* @author Lieven Smits
* @version 1.0 25/7/2000
*/
class Maatbalk extends Panel {
/** Hoogte van de regelschuif, in aantal stappen. */
private static int dikte = 1;
/** Laagste waarde die door de maatbalk gemodelleerd wordt. */
private double minimum;
/** Hoogste waarde die door de maatbalk gemodelleerd wordt. */
private double maximum;
/** Aantal stappen tussen de hoogste en de laagste waarde. */
private int aantalStappen;
/** AWT-schuifbalk waaromheen we een laag schrijven. */
private Scrollbar deBalk;
/** Naam van de maatbalk. Verschijnt onderaan. */
private Label lblTitel;
/** Merkje van de ondergrens. */
private Label lblOndergrens;
/** Merkje van de bovengrens. */
private Label lblBovengrens;
/** Construeer een maatbalk met gegeven parameters.
* @param minimum
* Laagste waarde die door de maatbalk gemodelleerd wordt.
* @param maximum
* Hoogste waarde die door de maatbalk gemodelleerd wordt.
* @param aantalStappen
* Aantal stappen tussen de hoogste en de laagste waarde.
* @param initieel
* Beginwaarde.
* @param titel
* Naam van de maatbalk.
* @param minTekst
* Merktekst van de ondergrens.
* @param maxTekst
* Merktekst van de bovengrens.
*/
public Maatbalk(double minimum, double maximum,
int aantalStappen, double initieel,
String titel, String minTekst, String maxTekst) {
this.aantalStappen = aantalStappen;
this.minimum = minimum;
this.maximum = maximum;
deBalk = new Scrollbar(Scrollbar.VERTICAL,
(int)((maximum - initieel) / (maximum - minimum) * aantalStappen),
dikte, 0, aantalStappen + dikte);
lblTitel = new Label(titel);
lblOndergrens = new Label(minTekst);
lblBovengrens = new Label(maxTekst);
setLayout(null); // absolute positionering
deBalk.setLocation(0, 0);
deBalk.setSize(19, 250);
add(deBalk);
lblTitel.setLocation(0, 250);
lblTitel.setSize(60, 15);
add(lblTitel);
lblOndergrens.setLocation(22, 227);
lblOndergrens.setSize(38, 15);
add(lblOndergrens);
lblBovengrens.setLocation(22, 9);
lblBovengrens.setSize(38, 15);
add(lblBovengrens);
}
/** Plaats rechts van de maatbalk een smalle drukknop
* om een bepaalde, vaak voorkomende standaardwaarde
* in te stellen. De tekst op de knop hoeft geen
* getal te zijn.
* @param waarde
* De waarde die door de knop ingesteld wordt. Bepaalt
* tevens de verticale positie van de knop langsheen
* de schuifbalk.
* @param tekst
* Tekst op de knop.
* @return
* De pas geconstrueerde drukknop.
*/
public Button voegKnopToe(double waarde, String tekst) {
Button b = new Button(tekst);
/* Een beetje rekenen met pixels:
we positioneren de knop zo dat zijn verticale
midden ongeveer overeenkomt met de juiste stand van
de schuifbalk.
We gaan ervan uit dat de pijlknoppen bovenaan en onderaan
elk ongeveer 16 pixels hoog zijn en de helft van
het verschuifbare deel ongeveer vier pixels.
beschikbare hoogte = 250 - 2 * 20 = 210
offset = 20 - 15 / 2 = 12.5
*/
b.setLocation(30,
(int)((maximum - waarde) / (maximum - minimum) * 210 + 12.5));
b.setSize(60, 15);
add(b);
/* Maak wat meer ruimte voor teksten */
lblTitel.setSize(120, 15);
lblOndergrens.setSize(78, 15);
lblBovengrens.setSize(78, 15);
return b;
}
/** Geef de huidige stand van de maatbalk.
* @return
* De huidige gemodelleerde waarde.
*/
public double geefWaarde() {
return
maximum - deBalk.getValue() * (maximum - minimum) / aantalStappen;
}
/** Stel de maatbalk op een nieuwe waarde in.
* @param nieuw
* De gewenste nieuwe waarde.
*/
public void stelWaarde(double nieuw) {
int temp = (int)
((maximum - nieuw) / (maximum - minimum) * aantalStappen);
deBalk.setValue(temp);
}
/** Selecteer een object om gebeurtenissen met betrekking
* tot de stand van de schuifbalk op te vangen.
* Deze methode is gewoon een dunne verpakking rond
* de methode addAdjustmentListener van de klasse
* Scrollbar.
* @param a
* Het object dat de gebeurtenissen zal opvangen.
*/
public void stelAdjustmentListener(AdjustmentListener a) {
deBalk.addAdjustmentListener(a);
}
}
/** Applet die een animatie toont van een harmonische,
* eendimensionale slinger. De applet bestaat uit twee
* panelen: links de eigenlijke tekening van de slinger,
* rechts een besturingspaneel om de parameters van de
* animatie te wijzigen.
* @author Lieven Smits
* @version 1.0 25/7/2000
*/
public class SlingerApplet extends Applet implements Runnable {
/** Massa van de bol in kilogram. */
double massa = 1;
/** Lengte van het touw in meter. */
double lengte = 1;
/** Valversnelling in meter per seconde kwadraat. */
double valversnelling = 9.81;
/** Maximale uitwijking van de slinger in radialen. */
double amplitude = 1;
/** Linkerpaneel met tekening. */
SlingerPaneel slinger;
/** Rechterpaneel met besturing. */
Panel dashboard;
/** Schuifregelaar voor de massa. */
Maatbalk mbMassa;
/** Schuifregelaar voor de lengte. */
Maatbalk mbLengte;
/** Schuifregelaar voor de valversnelling. */
Maatbalk mbValversnelling;
/** Schuifregelaar voor de amplitude. */
Maatbalk mbAmplitude;
/** Aanvinkvakje voor de display-optie "hulplijnen". */
Checkbox cbHulplijnen;
/** Aanvinkvakje voor de display-optie "krachtvector". */
Checkbox cbKracht;
/** Aanvinkvakje voor de display-optie "horizontale positievector". */
Checkbox cbPositie;
/** Aanvinkvakje voor de display-optie "snelheidsvector". */
Checkbox cbSnelheid;
/** Aanvinkvakje voor de display-optie "versnellingsvector". */
Checkbox cbVersnelling;
/** Parallel proces voor de animatie. */
Thread deAnimatie;
/** Initialiseer de applet. Lees en interpreteer de appletparameters
* en construeer de grafische gebruikersinterface.
*/
public void init() {
// Interpreteer appletparameters
String massaString = getParameter("massa");
if (massaString != null)
try {
massa = (new Double(massaString)).doubleValue();
} catch (NumberFormatException e) { }
String lengteString = getParameter("lengte");
if (lengteString != null)
try {
lengte = (new Double(lengteString)).doubleValue();
} catch (NumberFormatException e) { }
String valversnellingString = getParameter("valversnelling");
if (valversnellingString != null)
try {
valversnelling =
(new Double(valversnellingString)).doubleValue();
} catch (NumberFormatException e) { }
String amplitudeString = getParameter("amplitude");
if (amplitudeString != null)
try {
amplitude = (new Double(amplitudeString)).doubleValue();
} catch (NumberFormatException e) { }
setBackground(Color.lightGray);
setLayout(null); // absolute positionering
slinger = new SlingerPaneel(massa, lengte, valversnelling,
amplitude);
slinger.setLocation(0, 10);
slinger.setSize(490, 600);
add(slinger);
dashboard = new Panel();
dashboard.setLocation(490, 10);
dashboard.setSize(300, 600);
dashboard.setBackground(Color.lightGray);
add(dashboard);
dashboard.setLayout(null); // absolute positionering
mbMassa = new Maatbalk(1, 50, 98, massa,
"massa", "1 kg", "50 kg");
mbLengte = new Maatbalk(0.5, 3, 105, lengte,
"lengte", "0.5 m", "3 m");
mbValversnelling = new Maatbalk(0.01, 30, 100, valversnelling,
"valversnelling", "0.01 m/s2", "30 m/s2");
mbAmplitude = new Maatbalk(0, Math.PI / 4, 90, amplitude,
"amplitude", "0°", "45°");
mbMassa.setLocation(0, 0);
mbMassa.setSize(60, 265);
mbLengte.setLocation(60, 0);
mbLengte.setSize(60, 265);
mbValversnelling.setLocation(120, 0);
mbValversnelling.setSize(120, 265);
mbAmplitude.setLocation(240, 0);
mbAmplitude.setSize(60, 265);
cbHulplijnen = new Checkbox("hulplijnen", true);
cbKracht = new Checkbox("kracht", true);
cbPositie = new Checkbox("positie", true);
cbSnelheid = new Checkbox("snelheid", true);
cbVersnelling = new Checkbox("versnelling", true);
cbHulplijnen.setLocation(0, 285);
cbHulplijnen.setSize(100, 15);
cbKracht.setLocation(0, 305);
cbKracht.setSize(100, 15);
cbPositie.setLocation(100, 285);
cbPositie.setSize(100, 15);
cbSnelheid.setLocation(100, 305);
cbSnelheid.setSize(100, 15);
cbVersnelling.setLocation(200, 285);
cbVersnelling.setSize(100, 15);
mbMassa.stelAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
slinger.zetMassa(mbMassa.geefWaarde());
slinger.repaint();
}
});
mbLengte.stelAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
slinger.zetLengte(mbLengte.geefWaarde());
slinger.repaint();
}
});
mbValversnelling.stelAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
slinger.zetValversnelling(mbValversnelling.geefWaarde());
slinger.repaint();
}
});
mbAmplitude.stelAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
slinger.zetAmplitude(mbAmplitude.geefWaarde());
slinger.repaint();
}
});
cbHulplijnen.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
slinger.stelHulplijnen(cbHulplijnen.getState());
slinger.repaint();
}
});
cbKracht.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
slinger.stelKracht(cbKracht.getState());
slinger.repaint();
}
});
cbPositie.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
slinger.stelPositie(cbPositie.getState());
slinger.repaint();
}
});
cbSnelheid.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
slinger.stelSnelheid(cbSnelheid.getState());
slinger.repaint();
}
});
cbVersnelling.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
slinger.stelVersnelling(cbVersnelling.getState());
slinger.repaint();
}
});
mbValversnelling.voegKnopToe(26.39,
"Jupiter").addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mbValversnelling.stelWaarde(26.39);
slinger.zetValversnelling(26.39);
slinger.repaint();
}
});
mbValversnelling.voegKnopToe(9.81,
"Aarde").addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mbValversnelling.stelWaarde(9.81);
slinger.zetValversnelling(9.81);
slinger.repaint();
}
});
mbValversnelling.voegKnopToe(1.62,
"Maan").addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mbValversnelling.stelWaarde(1.62);
slinger.zetValversnelling(1.62);
slinger.repaint();
}
});
dashboard.add(mbMassa);
dashboard.add(mbLengte);
dashboard.add(mbValversnelling);
dashboard.add(mbAmplitude);
dashboard.add(cbHulplijnen);
dashboard.add(cbKracht);
dashboard.add(cbPositie);
dashboard.add(cbSnelheid);
dashboard.add(cbVersnelling);
slinger.startChrono();
slinger.setBackground(Color.lightGray);
/* en starten maar */
deAnimatie = new Thread(this);
}
/** Begin de animatie. */
public void start() {
deAnimatie.start();
}
/** Onderbreek de animatie. */
public void stop() {
deAnimatie.interrupt();
}
/** Oneindige animatielus. */
public void run() {
while (true) {
slinger.repaint();
try {
Thread.sleep(slinger.delay);
} catch (InterruptedException e) {
break;
}
}
}
}