forked from srieger/verteilte-systeme-bsc-ai-examples
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
8.3 KiB
345 lines
8.3 KiB
package verteiltesysteme.mandelbrot;
|
|
|
|
//Mandelbot Example A. Gepperth
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Graphics;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseListener;
|
|
import java.awt.event.MouseMotionListener;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import javax.swing.ImageIcon;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JSlider;
|
|
import javax.swing.event.ChangeEvent;
|
|
import javax.swing.event.ChangeListener;
|
|
|
|
class Complex {
|
|
double r;
|
|
double i;
|
|
|
|
Complex() {
|
|
r = 0.0;
|
|
i = 0.0;
|
|
}
|
|
|
|
Complex(double r, double i) {
|
|
this.r = r;
|
|
this.i = i;
|
|
}
|
|
|
|
void mulBy(Complex other) {
|
|
double rTmp = this.r * other.r - this.i * other.i;
|
|
this.i = this.r * other.i + this.i * other.r;
|
|
this.r = rTmp;
|
|
}
|
|
|
|
void add(Complex other) {
|
|
this.r += other.r;
|
|
this.i += other.i;
|
|
}
|
|
|
|
void sub(Complex other) {
|
|
this.r -= other.r;
|
|
this.i -= other.i;
|
|
}
|
|
|
|
double absValue() {
|
|
return Math.sqrt(this.r * this.r + this.i * this.i);
|
|
}
|
|
}
|
|
|
|
class MandelbrotCalculations {
|
|
// hier wird das Ergebnis von iterateAll() gespeichert
|
|
protected int[] result = null;
|
|
|
|
// der augenblicklich gewaehlte Ausschnitt
|
|
//double ULx = -2, ULy = -2, LRx = 2, LRy = 2;
|
|
double ULx = -0.16099999999999995, ULy = -0.9365333333333333, LRx = -0.03533333333333327, LRy = -0.8108666666666666;
|
|
|
|
int iterateOnePoint(Complex c, int maxIterations, double maxModulus) {
|
|
Complex z = new Complex(0., 0.);
|
|
|
|
for (int i = 0; i < maxIterations; i++) {
|
|
z.mulBy(z);
|
|
z.add(c);
|
|
double m = z.absValue();
|
|
if (m > maxModulus) {
|
|
return i;
|
|
}
|
|
}
|
|
return maxIterations;
|
|
}
|
|
|
|
void iterateAllPoints(int maxIterations, double nrPointsX, double nrPointsY) {
|
|
|
|
this.result = new int[(int) (nrPointsX * nrPointsY)];
|
|
|
|
int counter = 0;
|
|
double stepX = (this.LRx - this.ULx) / nrPointsX;
|
|
double stepY = (this.LRy - this.ULy) / nrPointsY;
|
|
double i = this.ULy;
|
|
for (int cy = 0; cy < nrPointsY; cy++) {
|
|
double r = this.ULx;
|
|
for (int cx = 0; cx < nrPointsX; cx++) {
|
|
Complex c = new Complex(r, i);
|
|
this.result[counter] = maxIterations - this.iterateOnePoint(c, maxIterations, 2.0);
|
|
counter += 1;
|
|
r += stepX;
|
|
}
|
|
i += stepY;
|
|
}
|
|
}
|
|
|
|
public int[] getResult() {
|
|
return this.result;
|
|
}
|
|
|
|
public double getULx() {
|
|
return this.ULx;
|
|
}
|
|
|
|
public double getLRx() {
|
|
return this.LRx;
|
|
}
|
|
|
|
public double getULy() {
|
|
return this.ULy;
|
|
}
|
|
|
|
public double getLRy() {
|
|
return this.LRy;
|
|
}
|
|
|
|
public void setView(double ULx, double ULy, double LRx, double LRy) {
|
|
this.ULx = ULx;
|
|
this.ULy = ULy;
|
|
this.LRx = LRx;
|
|
this.LRy = LRy;
|
|
}
|
|
|
|
}
|
|
|
|
class MyJLabel extends JLabel {
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private static final long serialVersionUID = -5184881932223853807L;
|
|
int boxULx, boxULy, boxW, boxH;
|
|
|
|
MyJLabel() {
|
|
super();
|
|
}
|
|
|
|
MyJLabel(String s) {
|
|
super(s);
|
|
}
|
|
|
|
void setBox(int boxULx, int boxULy, int boxW, int boxH) {
|
|
this.boxULx = boxULx;
|
|
this.boxULy = boxULy;
|
|
this.boxW = boxW;
|
|
this.boxH = boxH;
|
|
}
|
|
|
|
@Override
|
|
protected void paintComponent(Graphics g) {
|
|
super.paintComponent(g);
|
|
g.setColor(Color.black);
|
|
g.drawRect(this.boxULx, this.boxULy, this.boxW, this.boxH);
|
|
}
|
|
|
|
}
|
|
|
|
public class MGui implements ActionListener, ChangeListener, MouseListener, MouseMotionListener {
|
|
|
|
// GUI elements
|
|
JFrame frame;
|
|
JPanel panel;
|
|
JButton endButton;
|
|
JButton backButton;
|
|
JButton calcButton;
|
|
JSlider maxIterations;
|
|
MyJLabel view;
|
|
int nrIterations;
|
|
|
|
// box management
|
|
int boxULx, boxULy, boxW, boxH;
|
|
boolean dragging = false;
|
|
|
|
// this one does all the calculating work
|
|
MandelbrotCalculations calcObj;
|
|
|
|
// how many points in the image?
|
|
// change if you want a higher resolution
|
|
public static final int RESX = 600;
|
|
public static final int RESY = 600;
|
|
|
|
MGui() {
|
|
// set up GUI
|
|
this.frame = new JFrame("Mandelbrotmenge");
|
|
this.panel = new JPanel();
|
|
this.endButton = new JButton("Ende");
|
|
this.panel.add(this.endButton);
|
|
this.backButton = new JButton("Zurueck");
|
|
this.panel.add(this.backButton);
|
|
this.calcButton = new JButton("Rechnen");
|
|
this.panel.add(this.calcButton);
|
|
this.frame.add(this.panel);
|
|
this.frame.setSize(500, 500);
|
|
this.frame.setVisible(true);
|
|
this.view = new MyJLabel("Platzhalter");
|
|
this.maxIterations = new JSlider(0, 50, 30);
|
|
this.panel.add(this.maxIterations);
|
|
this.panel.add(this.view);
|
|
|
|
this.endButton.addActionListener(this);
|
|
this.backButton.addActionListener(this);
|
|
this.calcButton.addActionListener(this);
|
|
this.maxIterations.addChangeListener(this);
|
|
|
|
this.maxIterations.setMajorTickSpacing(10);
|
|
this.maxIterations.setPaintTicks(true);
|
|
this.maxIterations.setPaintLabels(true);
|
|
|
|
this.view.addMouseListener(this);
|
|
this.view.addMouseMotionListener(this);
|
|
|
|
this.boxULx = 0;
|
|
this.boxULy = 0;
|
|
this.boxW = MGui.RESX;
|
|
this.boxH = MGui.RESY;
|
|
|
|
// Non-Gui stuff
|
|
this.calcObj = new MandelbrotCalculations();
|
|
this.nrIterations = 1000;
|
|
}
|
|
|
|
// visualization related stuff, do not touch!
|
|
int[] generateLookupTable(int nrHues) {
|
|
int[] tmp = new int[nrHues + 1];
|
|
int cycle = 2048;
|
|
for (int i = 0; i < nrHues; i++) {
|
|
float hue = 1 * ((float) (i % cycle)) / cycle/* ((float)nrHues) */ ;
|
|
tmp[i] = Color.HSBtoRGB(hue, 0.8f, 1.0f);
|
|
}
|
|
tmp[0] = Color.HSBtoRGB(0f, 1.0f, 0.0f);
|
|
return tmp;
|
|
}
|
|
|
|
// visualization
|
|
static void applyLookupTable(int[] data, int[] dest, int[] lookupTable) {
|
|
for (int i = 0; i < data.length; i++) {
|
|
dest[i] = lookupTable[data[i]];
|
|
}
|
|
}
|
|
|
|
// here we check what the buttons do
|
|
public void actionPerformed(ActionEvent ae) {
|
|
if (ae.getSource() == this.endButton) {
|
|
System.out.println("Ende");
|
|
System.exit(0);
|
|
} else
|
|
|
|
if (ae.getSource() == this.backButton) {
|
|
System.out.println("Zurueck");
|
|
} else
|
|
|
|
if (ae.getSource() == this.calcButton) {
|
|
System.out.println("Rechnen");
|
|
long timestampStart = System.currentTimeMillis();
|
|
|
|
double ULx = this.calcObj.getULx();
|
|
double ULy = this.calcObj.getULy();
|
|
double LRx = this.calcObj.getLRx();
|
|
double LRy = this.calcObj.getLRy();
|
|
double w = LRx - ULx;
|
|
double h = LRy - ULy;
|
|
ULx = ULx + w * this.boxULx / (double) MGui.RESX;
|
|
ULy = ULy + h * this.boxULy / (double) MGui.RESY;
|
|
w *= this.boxW / (double) (RESX);
|
|
h *= this.boxH / (double) (RESX);
|
|
LRx = ULx + w;
|
|
LRy = ULy + h;
|
|
System.out.println(ULx + "/" + ULy + "/" + LRx + "/" + LRy);
|
|
this.boxULx = 0;
|
|
this.boxULy = 0;
|
|
this.boxW = MGui.RESX;
|
|
this.boxH = MGui.RESY;
|
|
this.calcObj.setView(ULx, ULy, LRx, LRy);
|
|
this.calcObj.iterateAllPoints(this.maxIterations.getValue() * 1000, MGui.RESX, MGui.RESY);
|
|
int[] lookupTable = generateLookupTable(this.maxIterations.getValue() * 1000);
|
|
int[] colors = new int[MGui.RESX * MGui.RESY];
|
|
MGui.applyLookupTable(calcObj.getResult(), colors, lookupTable);
|
|
|
|
BufferedImage colorImage = new BufferedImage(MGui.RESX, MGui.RESY, BufferedImage.TYPE_INT_ARGB);
|
|
colorImage.setRGB(0, 0, MGui.RESX, MGui.RESY, colors, 0, MGui.RESX);
|
|
this.view.setIcon(new ImageIcon(colorImage));
|
|
|
|
long timestampEnd = System.currentTimeMillis();
|
|
|
|
String timeElapsed = "Zeit: " + ((timestampEnd - timestampStart) / 1000.0) + " sec";
|
|
System.out.println(timeElapsed);
|
|
this.view.setText(timeElapsed);
|
|
}
|
|
}
|
|
|
|
public void mousePressed(MouseEvent e) {
|
|
this.boxULx = e.getX();
|
|
this.boxULy = e.getY();
|
|
this.boxW = 1;
|
|
this.boxH = 1;
|
|
this.view.setBox(this.boxULx, this.boxULy, this.boxW, this.boxH);
|
|
}
|
|
|
|
public void mouseDragged(MouseEvent e) {
|
|
this.boxW = e.getX() - this.boxULx + 1;
|
|
this.boxH = e.getY() - this.boxULy + 1;
|
|
int m = Math.min(boxW, boxH);
|
|
this.boxW = m;
|
|
this.boxH = m;
|
|
this.view.setBox(this.boxULx, this.boxULy, this.boxW, this.boxH);
|
|
this.view.repaint();
|
|
}
|
|
|
|
public void mouseReleased(MouseEvent e) {
|
|
|
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
|
this.view.repaint();
|
|
}
|
|
}
|
|
|
|
public void mouseMoved(MouseEvent e) {
|
|
}
|
|
|
|
public void mouseExited(MouseEvent e) {
|
|
}
|
|
|
|
public void mouseEntered(MouseEvent e) {
|
|
}
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
|
}
|
|
|
|
// process a new slider value
|
|
public void stateChanged(ChangeEvent ce) {
|
|
if (ce.getSource() == this.maxIterations) {
|
|
//System.out.println("Neuer Wert");
|
|
this.nrIterations = this.maxIterations.getValue() * 1000;
|
|
}
|
|
}
|
|
|
|
// main, just instantiate an MGui object, gives control to the Gui
|
|
public static void main(String[] args) {
|
|
@SuppressWarnings("unused")
|
|
MGui gui = new MGui();
|
|
}
|
|
}
|