Ich habe ein paar kleinere Verbessungern an dem Programm vorgenommen, auch was die Lesbarkeit des Quelltextes angeht.
Dateianhang:
Dateikommentar: Blitzgerät und Lichtausbreitung gemäß SRT (v = 0,600c)
LightSphere-c600.gif [ 465.2 KiB | 7110-mal betrachtet ]
Dateianhang:
Dateikommentar: Blitzgerät und Lichtausbreitung gemäß SRT (v = 0,866c)
LightSphere-c866.gif [ 460.24 KiB | 7054-mal betrachtet ]
Datei LightSphere.java:
Code:
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
/**
* Erstellt eine GIF-Datei.
* <p>
* Das animierte Bild zeigt die Ausbreitung eines Lichtblitzes in Form einer Lichtsphäre vom
* Ursprung eines Laborsystems aus sowie die Ausbreitung desselben Lichtblitzes in bezug auf ein zum
* Laborsystem relativ bewegtes, gestrichenes System.
* </p>
* <p>
* Man rufe die {@link #main(String...)}-Methode auf.
* </p>
*
* @author Faber
* @version 1.1
*/
public class LightSphere
{
/** Breite des Bildes in Pixeln. */
private final int w = 256 + 128;
/** Höhe des Bildes in Pixeln. */
private final int h = 512;
/** Lichtgeschwindigkeit in m/s. */
private final double c = 300E6;
/** Relative Schnelligkeit der Bezugssysteme. */
private final double v = 0.6 * c;
/** Gamma-Faktor der Lorentztransformation. */
private final double gamma = 1.0 / Math.sqrt(1 - (v * v) / (c * c));
/**
* Erstellt die Bilddatei.
*
* @see #main(String...)
*/
private LightSphere()
{
final String sv = String.format("%.3f", v / c).substring(2);
final String fileName = String.format("%s-c%s.gif", LightSphere.class.getSimpleName(), sv);
final AnimatedGifEncoder gifenc = new AnimatedGifEncoder();
gifenc.setQuality(10);
gifenc.setRepeat(0);
gifenc.setDelay(100);
gifenc.start(fileName);
final double t0 = 0; // Startzeitpunkt in Sekunden
final double t1 = 1 / c; // Endzeitpunkt in Sekunden
final double dt = (t1 - t0) / 50;
for (double t = t0; t <= t1; t += dt)
{
final BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
final Graphics2D graphics2D = image.createGraphics();
try
{
{ // Hintergrund
graphics2D.setColor(new Color(0xE0E0E0));
graphics2D.fillRect(0, 0, w, h);
}
{ // Bilder
paint(graphics2D, t, true);
paint(graphics2D, t, false);
}
}
finally
{
graphics2D.dispose();
}
gifenc.addFrame(image);
}
gifenc.finish();
}
/**
* Malt ein Phasenbild der Animation.
*
* @param graphics2D
* Grafik-Kontext.
* @param t
* Zeitpunkt in Sekunden.
* @param labor
* Zeigt an, ob in bezug auf das Laborsystem gemalt wird.
*/
private void paint(final Graphics2D graphics2D, final double t, final boolean labor)
{
final int R = h / 4;
final int mx = 3 * R / 2;
final int my = labor ? R : 3 * R;
final double scale = 0.9 * R;
final double u = 1.0 / scale; // gibt die Breite eines Pixels in Metern an
final double meterPerDiv = 0.25;
final AffineTransform transform = new AffineTransform();
transform.translate(mx, my);
transform.scale(scale, scale);
final AffineTransform originalTransform = graphics2D.getTransform();
try
{
graphics2D.setTransform(transform);
graphics2D.setStroke(new BasicStroke((float) u));
{ // Gitter malen
graphics2D.setColor(new Color(0xA0A0A0));
for (double x = -1.0; x <= 1.0; x += meterPerDiv)
{
graphics2D.draw(new Line2D.Double(x, -1, x, 1));
}
for (double y = -1.0; y <= 1.0; y += meterPerDiv)
{
graphics2D.draw(new Line2D.Double(-1, y, 1, y));
}
}
}
finally
{
graphics2D.setTransform(originalTransform);
}
{ // Achsen und Text malen.
final int d = 12;
graphics2D.setColor(Color.BLACK);
graphics2D.setStroke(new BasicStroke());
graphics2D.draw(new Line2D.Double(mx + R, my, mx - R, my));
graphics2D.draw(new Line2D.Double(mx + R - d, my + d, mx + R, my));
graphics2D.draw(new Line2D.Double(mx + R - d, my - d, mx + R, my));
graphics2D.draw(new Line2D.Double(mx, my + R, mx, my - R));
graphics2D.draw(new Line2D.Double(mx - d, my - R + d, mx, my - R));
graphics2D.draw(new Line2D.Double(mx + d, my - R + d, mx, my - R));
graphics2D.drawRect(0, my - R, w - 1, 2 * R - 1);
final Font font = new Font("Verdana", Font.BOLD, 12);
final String text = String.format("%s = %.3fm\n", labor ? "ct" : "ct'", c * t);
final Rectangle2D r = font.getStringBounds(text, graphics2D.getFontRenderContext());
final int th = (int) (r.getHeight() + 0.5);
final int tw = (int) (r.getWidth() + 0.5);
graphics2D.setFont(font);
graphics2D.drawString(String.format("%.2fm/div", meterPerDiv), w - tw - th, my + R - th);
graphics2D.drawString(text, w - tw - th, my + R - 2 * th);
if (!labor)
{
graphics2D.drawString(String.format("v = %.3fc", v / c), w - tw - th, my + R - 3 * th);
}
graphics2D.drawString(labor ? "Laborsystem" : "Gestr. System", th, my - R + th);
graphics2D.drawString(labor ? "X" : "X'", (int) (mx + scale + 0.5 * th), (int) (my - 0.5 * th));
graphics2D.drawString(labor ? "Y" : "Y'", (int) (mx + 1.0 * th), (int) (my - scale - 0.0 * th));
}
try
{
graphics2D.setTransform(transform);
graphics2D.setStroke(new BasicStroke((float) u));
final Color color = labor ? new Color(0x00A000) : new Color(0xA00000);
final double xBlitz = labor ? 0 : -v * t;
final double yBlitz = 0;
final int noOfPhotons = 8;
final double[] xPhoton = new double[noOfPhotons];
final double[] yPhoton = new double[noOfPhotons];
{ // Photonen berechnen
for (int k = 0; k < noOfPhotons; k++)
{
final double alpha = 2 * Math.PI * k / noOfPhotons;
xPhoton[k] = labor ? xLabor(alpha, t) : xStrich(alpha, t);
yPhoton[k] = labor ? yLabor(alpha, t) : yStrich(alpha, t);
}
}
{ // Kreis malen.
final double x = 0;
final double y = 0;
final double r = c * t;
final Composite originalComposite = graphics2D.getComposite();
try
{
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
graphics2D.setColor(color);
graphics2D.draw(new Ellipse2D.Double(x - r, y - r, 2 * r + u, 2 * r + u));
}
finally
{
graphics2D.setComposite(originalComposite);
}
}
{ // Verbindungslinien Blitzgerät-Photonen malen.
final Composite originalComposite = graphics2D.getComposite();
try
{
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
for (int k = 0, N = 8; k < N; k++)
{
final double x = xPhoton[k];
final double y = yPhoton[k];
{
graphics2D.setColor(color);
graphics2D.draw(new Line2D.Double(x, y, xBlitz, yBlitz));
}
}
}
finally
{
graphics2D.setComposite(originalComposite);
}
}
{ // Blitzgerät malen.
final double x = xBlitz;
final double y = yBlitz;
{
final double r = 4 / scale;
graphics2D.setColor(new Color(0x404040));
graphics2D.fill(new Rectangle2D.Double(x - r, y - r, 2 * r + u, 2 * r + u));
}
{
final double r = 2 / scale;
graphics2D.setColor(color);
graphics2D.fill(new Ellipse2D.Double(x - r, y - r, 2 * r + u, 2 * r + u));
}
}
{ // Photonen malen.
for (int k = 0, N = 8; k < N; k++)
{
final double x = xPhoton[k];
final double y = yPhoton[k];
{
final double r = 3 / scale;
graphics2D.setColor(color);
graphics2D.fill(new Ellipse2D.Double(x - r, y - r, 2 * r + u, 2 * r + u));
}
}
}
}
finally
{
graphics2D.setTransform(originalTransform);
}
}
/**
* Liefert die x-Komponente der Trajektorie eines Photons.
*
* @param alpha
* Richtung, in die das Photon im Laborsystem vom Ursprung aus fliegt, in Radian.
* @param t
* Zeitpunkt t im Laborsystem, in Sekunden.
* @return die x-Position des Photons zum Zeitpunkt t in Metern.
*/
public double xLabor(final double alpha, final double t)
{
return c * t * Math.cos(alpha);
}
/**
* Liefert die y-Komponente der Trajektorie eines Photons.
*
* @param alpha
* Richtung, in die das Photon im Laborsystem vom Ursprung aus fliegt, in Radian.
* @param t
* Zeitpunkt t im Laborsystem, in Sekunden.
* @return die y-Position des Photons zum Zeitpunkt t in Metern.
*/
public double yLabor(final double alpha, final double t)
{
return c * t * Math.sin(alpha);
}
/**
* Liefert die x'-Komponente der Trajektorie eines Photons.
* <p>
* Herleitung siehe <a href="http://www.mahag.com/neufor/viewtopic.php?p=20494#p20494">hier</a>.
* </p>
*
* @param alpha
* Richtung, in die das Photon im Laborsystem vom Ursprung aus fliegt, in Radian.
* @param tStrich
* Zeitpunkt t' im gestrichenen System, in Sekunden.
* @return die x'-Position des Photons zum Zeitpunkt t' in Metern.
*/
public double xStrich(final double alpha, final double tStrich)
{
final double denominator = (c - v * Math.cos(alpha));
return c * tStrich * (c * Math.cos(alpha) - v) / denominator;
}
/**
* Liefert die y'-Komponente der Trajektorie eines Photons.
* <p>
* Herleitung siehe <a href="http://www.mahag.com/neufor/viewtopic.php?p=20494#p20494">hier</a>.
* </p>
*
* @param alpha
* Richtung, in die das Photon im Laborsystem vom Ursprung aus fliegt, in Radian.
* @param tStrich
* Zeitpunkt t' im gestrichenen System, in Sekunden.
* @return die y'-Position des Photons zum Zeitpunkt t' in Metern.
*/
public double yStrich(final double alpha, final double tStrich)
{
final double denominator = (c - v * Math.cos(alpha)) * gamma;
return c * tStrich * (c * Math.sin(alpha)) / denominator;
}
/**
* Programmeinstiegspunkt.
*
* @param args
* wird ignoriert.
*/
public static void main(final String... args)
{
new LightSphere();
}
}
Frohe Weihnacht
Faber