Beispiel zu Anziehungskräften vervollständigt

This commit is contained in:
ngb
2022-01-04 11:42:02 +01:00
parent ee3c85d6eb
commit ba90f7d041
4 changed files with 455 additions and 95 deletions

View File

@@ -0,0 +1,94 @@
import schule.ngb.zm.Zeichenmaschine;
import java.util.LinkedList;
public class Atoms extends Zeichenmaschine {
/**
* Liste der beweglichen Objekte in der Welt.
*/
private LinkedList<Mover> movers = new LinkedList<>();
/**
* Liste der Gravitationsquellen in der Welt.
*/
private LinkedList<Attractor> attractors = new LinkedList<>();
/**
* Erstellt die {@link Mover}- und {@link Attractor}-Objekte.
*/
public void setup() {
addAttractor( width / 2, height / 2, 20 );
attractors.getFirst().setMovable(false);
attractors.getFirst().setActive(false);
attractors.getFirst().hide();
addAttractor( width*.4, height*.4, 8 );
addAttractor( width*.6, height*.6, 8 );
for( int i = 0; i < 10; i++ ) {
Mover m = new Mover(random(10, width - 10), random(10, height - 10));
movers.add(m);
shapes.add(m);
}
}
private void addAttractor( double pX, double pY, int pMass ) {
Attractor a = new Attractor((int)pX, (int)pY, pMass);
attractors.add(a);
movers.add(a);
shapes.add(a);
}
/**
* Aktualisiert die Beschleunigung der {@link Mover}-Objekte durch Anwenden
* der einwirkenden Kräfte und aktualisiert dann die Position entsprechend
* der Beschleunigung.
* <p>
* Die Position des ersten {@link Attractor} wird auf die Mausposition
* gesetzt.
*
* @param delta
*/
public void update( double delta ) {
// Erste Gravitationsquelle auf Mausposition setzen.
Attractor mouseFollow = attractors.get(0);
if( mouseFollow.isActive() ) {
mouseFollow.moveTo(mouseX, mouseY);
}
// Kräfte anwenden
for( Attractor a : attractors ) {
if( a.isActive() ) {
for( Mover m : movers ) {
if( m.isActive() ) {
a.attract(m);
}
}
}
}
// Position aktualisieren
for( Mover m : movers ) {
if( m.isActive() ) {
m.update(delta);
}
}
}
/**
* Setzt die Position und Beschleunigung aller {@link Mover}-Objekte in der
* Welt zurück.
*/
public void mouseClicked() {
for( Mover m : movers ) {
m.moveTo(random(10, width - 10), random(10, height - 10));
m.setVelocity(0, 0);
}
}
public static void main( String[] args ) {
new Atoms();
}
}

View File

@@ -1,27 +1,110 @@
import schule.ngb.zm.Vector;
import schule.ngb.zm.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
/**
* Gravitationsquelle in der Simulation.
* <p>
* Eine Gravitationsquelle zieht mit einer Anziehungskraft proportional zu
* seiner Masse alle {@link Mover}-Objekte an. Dabei kommt die Newtonsche
* Gravitationsformel zur Anwendung.
* <p>
* Ein <code>Attractor</code> ist auch ein {@link Mover} und wird von anderen
* Gravitationsquellen beeinflusst. Dieses Verhalten kann durch Setzen von
* <code>setMovable(false)</code> abgeschaltet werden.
*/
public class Attractor extends Mover {
private int mass = 0;
/**
* Gravitationskonstante
* <p>
* Beeinflusst die Stärke der Anziehungskraft der {@link Attractor}en.
*/
public static final int G = 25;
public Attractor( int x, int pY, int pMass ) {
this(x, pY, pMass, new Vector());
}
/**
* Ob dieser <code>Attractor</code> auch von anderen Kräften beeinflusst wird.
*/
private boolean movable = true;
public Attractor( int x, int pY, int pMass, Vector pVelocity ) {
super(x, pY, pVelocity);
mass = pMass;
/**
* Erstellt einen <code>Attractor</code> an der angegebenen Position mit der angegebenen
* Masse.
*
* @param pX x-Koordinate des Objektes.
* @param pY y-Koordinate des Objektes.
* @param pMass Masse des Objektes.
*/
public Attractor( int pX, int pY, int pMass ) {
this(pX, pY, pMass, new Vector());
}
setFillColor(YELLOW);
}
/**
* Erstellt einen <code>Attractor</code> an der angegebenen Position
*
* @param pX x-Koordinate des Objektes.
* @param pY y-Koordinate des Objektes.
* @param pMass Masse des Objektes.
* @param pVelocity Initialgeschwindigkeit des Objektes.
*/
public Attractor( int pX, int pY, int pMass, Vector pVelocity ) {
super(pX, pY, pVelocity);
mass = pMass;
public void attract( Mover pMover ) {
if( pMover != this ) {
Vector force = new Vector(this.x, this.y);
force.sub(pMover.getX(), pMover.getY()).scale(mass*Gravity.G).limit(0, 50*Gravity.G);
pMover.applyForce(force);
}
}
setFillColor(randomColor());
}
/**
* Stellt ein, ob dieser <code>Attractor</code> auch von anderen Kräften
* beeinflusst wird, oder ob er starr an einer Position bleibt.
*
* @param pMovable <code>true</code> oder <code>false</code>.
*/
public void setMovable( boolean pMovable ) {
this.movable = pMovable;
}
/**
* Wendet die Anziehungskraft des <code>Attractor</code> auf einen
* <code>Mover</code> an.
*
* @param pMover Das Objekt, das angezogen wird.
*/
public void attract( Mover pMover ) {
if( pMover != this && isActive() ) {
Vector force = new Vector(this.x, this.y);
force.sub(pMover.getX(), pMover.getY());
double v = G * mass / force.lenSq();
force.setLen(v).limit(1.0, 4 * G);
pMover.applyForce(force);
}
}
/**
* Aktualisiert die momentante Geschwindigkeit und Position des Objektes und
* setzt die Beschleunigung zurück.
*
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
*/
@Override
public void update( double delta ) {
if( movable ) {
super.update(delta);
}
}
@Override
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
double m = 2.0*mass;
AffineTransform at = graphics.getTransform();
graphics.transform(pVerzerrung);
graphics.setColor(new java.awt.Color(255,193,64,66));
graphics.fillOval((int)(-.5*m), (int)(-.5*m), (int)(2*getRadius()+m), (int)(2*getRadius()+m));
graphics.setTransform(at);
super.draw(graphics, pVerzerrung);
}
}

View File

@@ -1,50 +1,91 @@
import schule.ngb.zm.Vector;
import schule.ngb.zm.Zeichenmaschine;
import java.util.LinkedList;
import schule.ngb.zm.*;
/**
* Hauptklasse der Simulation.
*/
public class Gravity extends Zeichenmaschine {
public static final int G = 1;
private LinkedList<Mover> movers = new LinkedList<>();
private LinkedList<Attractor> attractors = new LinkedList<>();
public void setup(){
for( int i = 0; i < 10; i++ ) {
Mover m = new Mover(random(10, width-10), random(10, height-10));
movers.add(m);
shapes.add(m);
}
attractors.add(new Attractor(width/2, height/2, 10));
shapes.add(attractors.get(0));
}
public void update( double delta ) {
Attractor mouseFollow = attractors.get(0);
mouseFollow.moveTo(mouseX, mouseY);
for( Attractor a: attractors ) {
for( Mover m: movers ) {
a.attract(m);
}
}
for( Mover m: movers ) {
m.update(delta);
}
shapes.clear();
}
public void mouseClicked() {
for( Mover m: movers ) {
m.moveTo(random(10, width-10), random(10, height-10));
m.setVelocity(0, 0);
}
}
/**
* Liste der beweglichen Objekte in der Welt.
*/
private LinkedList<Mover> movers = new LinkedList<>();
private final Vector gravity = new Vector(0, 6.734);
/**
* Erstellt die {@link Mover}-Objekte.
*/
public void setup() {
for( int i = 0; i < 4; i++ ) {
//Mover m = new Mover(random(10, width - 10), 30);
Mover m = new Mover(10 + (i*30), 30, 5*(i+1));
movers.add(m);
shapes.add(m);
}
}
/**
* Aktualisiert die Beschleunigung der {@link Mover}-Objekte durch Anwenden
* der einwirkenden Kräfte und aktualisiert dann die Position entsprechend
* der Beschleunigung.
* <p>
* Die Position des ersten {@link Attractor} wird auf die Mausposition
* gesetzt.
*
* @param delta
*/
public void update( double delta ) {
// Kräfte anwenden
for( Mover m : movers ) {
if( m.isActive() ) {
m.applyForce(gravity);
}
}
// Position aktualisieren
for( Mover m : movers ) {
if( m.isActive() ) {
m.update(delta);
// Abprallen Boden
if( m.getY() >= height ) {
m.setY(height-1);
m.getVelocity().y *= -1;
double s = 9.0 / m.getMass();
m.getVelocity().scale(limit(s, 0.0, 1.0));
}
// Abprallen rechter Rand
if( m.getX() >= width ) {
m.setX(width-1);
m.getVelocity().x *= -1;
}
// Abprallen linker Rand
if( m.getX() <= 0) {
m.setX(1);
m.getVelocity().x *= -1;
}
}
}
}
/**
* Setzt die Position und Beschleunigung aller {@link Mover}-Objekte in der
* Welt zurück.
*/
public void mouseClicked() {
for( Mover m : movers ) {
m.moveTo(random(10, width - 10), 30);
m.setVelocity(mouseX-m.getX(), mouseY-m.getY());
m.getVelocity().setLen(4.0);
}
}
public static void main( String[] args ) {
new Gravity();
}
}

View File

@@ -1,42 +1,184 @@
import schule.ngb.zm.Updatable;
import schule.ngb.zm.Vector;
import schule.ngb.zm.shapes.Arrow;
import schule.ngb.zm.shapes.Circle;
import schule.ngb.zm.*;
import schule.ngb.zm.shapes.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
/**
* Ein bewegliches Objekt in der Simulation.
*
* <code>Mover</code> werden durch Kräfte beeinflusst. Diese Kräfte können von
* unterschiedlichen Quellen ausgehen. Die {@link Attractor}en wirken zum
* Beispiel mit ihrer Anziehungskraft auf die <code>Mover</code> ein.
*/
public class Mover extends Circle implements Updatable {
private Vector velocity;
private Vector acceleration = new Vector();
/**
* Größe der Objekte in der Simulation.
*/
public static final int SIZE = 10;
public Mover( int x, int pY ) {
this(x, pY, new Vector());
}
public Mover( int x, int pY, Vector pVelocity ) {
super(x, pY, 10);
this.velocity = pVelocity.copy();
}
public void setVelocity(double dx, double dy) {
velocity.set(dx, dy);
}
public void applyForce( Vector force ) {
acceleration.add(force);
}
public boolean isActive() {
return true;
}
public void update( double delta ) {
acceleration.scale(delta);
velocity.add(acceleration);
acceleration.scale(0.0);
this.x += velocity.x;
this.y += velocity.y;
/**
* Ob die momentane Geschwindigkeit der Objekte als Pfeil dargestellt werden soll.
*/
public static final boolean SHOW_VELOCITY = false;
}
/**
* Masse des Objektes.
*/
protected double mass = 10.0;
/**
* Ob dieses Objekt an der Simulation beteiligt ist.
*/
protected boolean active = true;
/**
* Momentane Geschwindigkeit des Objektes.
*/
private Vector velocity;
/**
* Momentane Beschleunigung des Objektes.
*/
private Vector acceleration = new Vector();
/**
* Erstellt einen Mover an der angegebenen Position mit der momentanen
* Geschwindigkeit <code>(0, 0)</code>.
*
* @param pX x-Position des Objektes.
* @param pY y-Position des Objektes.
*/
public Mover( int pX, int pY ) {
this(pX, pY, new Vector());
}
/**
* Erstellt einen <code>Attractor</code> an der angegebenen Position mit der angegebenen
* Masse.
*
* @param pX x-Koordinate des Objektes.
* @param pY y-Koordinate des Objektes.
* @param pMass Masse des Objektes.
*/
public Mover( int pX, int pY, int pMass ) {
this(pX, pY, pMass, new Vector());
}
/**
* Erstellt einen Mover an der angegebenen Position mit der angegebenen
* Initialgeschwindigkeit.
*
* @param pX x-Position des Objektes.
* @param pY y-Position des Objektes.
* @param pVelocity Momentane Geschwindigkeit des Objektes.
*/
public Mover( int pX, int pY, Vector pVelocity ) {
super(pX, pY, SIZE);
velocity = pVelocity.copy();
}
/**
* Erstellt einen <code>Attractor</code> an der angegebenen Position
*
* @param pX x-Koordinate des Objektes.
* @param pY y-Koordinate des Objektes.
* @param pMass Masse des Objektes.
* @param pVelocity Initialgeschwindigkeit des Objektes.
*/
public Mover( int pX, int pY, int pMass, Vector pVelocity ) {
super(pX, pY, SIZE);
mass = pMass;
velocity = pVelocity.copy();
}
/**
* Gibt die Masse des Objektes zurück.
*
* @return Die Masse des Objektes.
*/
public double getMass() {
return mass;
}
/**
* Gibt die momentane Geschwindigkeit zurück.
* @return Die momentane Geschwindigkeit als Vektor.
*/
public Vector getVelocity() {
return velocity;
}
/**
* Setzt die momentane Geschwindigkeit des Objektes.
*
* @param pDx Momentane Geschwindigkeit in x-Richtung.
* @param pDy Momentane Geschwindigkeit in y-Richtung.
*/
public void setVelocity( double pDx, double pDy ) {
velocity.set(pDx, pDy);
}
/**
* Addiert eine Kraft zur momentanen Beschleunigung des Objektes. Die
* Beschleunigung wird einmal pro Update auf die Geschwindigkeit angewandt
* und dann wieder auf <code>(0, 0)</code> gesetzt.
*
* @param force Ein Vektor, der die Kraft darstellt.
*/
public void applyForce( Vector force ) {
acceleration.add(force);
}
/**
* Ob dieses Objekt aktiv ist und Updates erhalten soll.
*
* @return Ob das Objekt simuliert wird.
*/
public boolean isActive() {
return active;
}
/**
* Aktiviert / Deaktiviert das Objekt.
* @param pActive
*/
public void setActive( boolean pActive ) {
this.active = pActive;
}
/**
* Aktualisiert die momentante Geschwindigkeit und Position des Objektes und
* setzt die Beschleunigung zurück.
*
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
*/
public void update( double delta ) {
acceleration.scale(delta);
velocity.add(acceleration);
acceleration.scale(0.0);
this.x += velocity.x;
this.y += velocity.y;
}
@Override
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
if( SHOW_VELOCITY ) {
Vector v = velocity.copy().scale(10);
Arrow ar = new Arrow(v);
AffineTransform af = new AffineTransform(pVerzerrung);
af.translate(radius, radius);
ar.draw(graphics, af);
}
super.draw(graphics, pVerzerrung);
}
}