import java.applet.*;
import java.awt.*;
import java.awt.image.*;
public class Trajektorie extends Applet{
//so eine art "struct",
//das die koordinaten eines Punktes in 2D speichert
//um die Werte, die von der funktion erzeugt werden,
//zu representieren
public static class Vector2D{
public double x,y;
public Vector2D(double _x, double _y){x=_x; y=_y;}
}
//irgendeine funktion... R->R^2
private static abstract class Function{
public Color color;
public Function(Color c){
color=c;
}
public abstract Vector2D calculate(double t);
}
//thread, der alles zeichnet
private static class AnimationThread extends Thread{
private static class ScreenCoords{
public int pixel_x,pixel_y;
public ScreenCoords(ScreenCoords s){pixel_x=s.pixel_x; pixel_y=s.pixel_y;}
public ScreenCoords(int _x, int _y){pixel_x=_x; pixel_y=_y;}
}
//member vars
Component component; //referenz zum Graphics-Objekt des Applets
Dimension dim; //größe des backbuffers
//ecken eines 2D-Quaders, der dargestellt werden soll:
Vector2D minVertex, maxVertex;
//zu zeichnende funktionen
Function[] functions;
//back buffer
BufferedImage backBuffer;
public AnimationThread(Component _component,
Vector2D _minVertex,
Vector2D _maxVertex,
Dimension _dim,
Function[] _f){
component=_component;
minVertex=_minVertex;
maxVertex=_maxVertex;
dim=_dim;
functions=_f;
backBuffer=new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
}
public void run(){
//particle gibt an, wo sich der partikel sich gerade
//befindet, trajektorie ist ja nicht einfach die Bahn,
//es muss ja die abhängigkeit von der zeit dargestellt werden
Vector2D[] particle = new Vector2D[functions.length];
//initialisieren:
for(int i=0; i<particle.length; i++){
particle[i]=functions[i].calculate(0);
}
//hier screenCoords vom start und endpunkt einer gezeichneten strecke
ScreenCoords start,end;
Graphics g=backBuffer.getGraphics();
//hintergrund löschen
g.setColor(new Color(0,0,0));
g.fillRect(0,0,dim.width,dim.height);
//koordinatenachsen zeichnen
g.setColor(Color.BLACK);
//y-achse
start=toScreenCoords(new Vector2D(0,minVertex.y));
end=toScreenCoords(new Vector2D(0,maxVertex.y));
g.drawLine(start.pixel_x, start.pixel_y, end.pixel_x, end.pixel_y);
//x-achse
start=toScreenCoords(new Vector2D(minVertex.x,0));
end=toScreenCoords(new Vector2D(maxVertex.x,0));
g.drawLine(start.pixel_x, start.pixel_y, end.pixel_x, end.pixel_y);
//zeit
double t=0;
double dt=0.1;
while(true){
for(int i=0; i<particle.length; i++){
start=toScreenCoords(particle[i]);
particle[i]=functions[i].calculate(t+dt);
end=toScreenCoords(particle[i]);
g.setColor(functions[i].color);
g.drawLine(start.pixel_x, start.pixel_y, end.pixel_x, end.pixel_y);
}
t+=dt;
component.getGraphics().drawImage(backBuffer,0,0,
component.getWidth(),
component.getHeight(),
component);
try{
sleep(2);
}catch(InterruptedException e){}
}
}
//hilfsfunktion zum umrechnen in die bildschirmkoordinaten
private ScreenCoords toScreenCoords(Vector2D v){
return new ScreenCoords(
(int)((v.x-minVertex.x)*dim.width/(maxVertex.x-minVertex.x)),
(int)((v.y-minVertex.y)*dim.height/(maxVertex.y-minVertex.y)));
}
private Vector2D toRealCoords(ScreenCoords s){
return new Vector2D(
minVertex.x+(s.pixel_x)*(maxVertex.x-minVertex.x)/dim.width,
minVertex.y+(s.pixel_y)*(maxVertex.y-minVertex.y)/dim.height);
}
}//ende der Thread-definition
//Applet
public void init(){
//haufen funktionen
Function[] functions={
new Function(new Color(255,0,0,120)){
public Vector2D calculate(double t){
double r=1/(1+0.7*Math.cos(0.9*t));
return new Vector2D(r*Math.cos(t)+6, r*Math.sin(t)-3);
}
},
new Function(new Color(0,0,255,120)){
public Vector2D calculate(double t){
double r=0.5+2*Math.sin(t/7)+3*Math.cos(5*t);
return new Vector2D(r*Math.cos(t)+5, r*Math.sin(t)+3);
}
},
new Function(new Color(255,255,0,120)){
public Vector2D calculate(double t){
double r=1+4*Math.cos(13*t/24);
return new Vector2D(r*Math.cos(t)-4, r*Math.sin(t)-2);
}
}
};
AnimationThread t=new AnimationThread(this,
new Vector2D(-10,-10),
new Vector2D(10,10),
new Dimension(this.getSize()),
functions);
t.start();
}
}