Apfelmänchen wird nur verzerrt gezeichnet.

Prophet05

Erfahrenes Mitglied
Hallo,

ich habe versucht mir ein Programm zu schreiben das mir ein Apfelmänchen zeichnet. Das Programm an sich funktionert und die Ursprungsversion (in Scheme) klappte ebenfalls, nur jetzt wo ich es in Java geschrieben habe wird es irgendwie verzerrt. Ich bin mit zu 99% sicher das ich alles richtig berechne, allerdings wird das Bild irgendwie verzerrt. Ich vermute es liegt an irgendwelchen Rundungsfehlern, aber ich finde einfach keine Lösung für das Problem. Es gab ja schon andere die Apfelmännchen mit Java gezeichnet haben. Vielleicht könnt ihr mir ja helfen.

Der Zeichner:
Java:
import java.awt.Color;
import java.awt.Graphics2D;

public class MandelbrotPainter {
    
    private int width = 100;
    private int height = 100;
    
    private double left   = -2;
    private double right  = 1;
    private double top    = 1.5;
    private double bottom = -1.5;
    
    private int iterations = 100;
    
    private double getRealFromPixel(final int pixelX) {
        return this.getLeft() + ((double)pixelX / (double)this.getWidth()) * (this.getRight() - this.getLeft());
    }
    
    private double getImaginaryFromPixel(final int pixelY) {
        return -(this.getTop() + ((double)pixelY / (double)this.getHeight()) * (this.getBottom() - this.getTop()));
    }
    
    private double getMagnitude(final double real, final double imag) {
        return Math.sqrt(real * real + imag * imag);
    }
    
    private int calculateSequence(final double real, final double imag) {
        double zReal = 0.0d;
        double zImag = 0.0d;
        
        for(int n = 0; n <= this.getIterations(); n++) {
            if(this.getMagnitude(zReal, zImag) > 2) {
                return n;
            }
            else {
                zReal = zReal * zReal - zImag * zImag + real;
                zImag = 2 * zReal * zImag + imag;
            }
        }
        
        return 0;
    }
    
    private Color generateColor(int n) {
//        return new Color(
//                (float)(n * n) / (float)(this.getIterations() * this.getIterations()),
//                (float)n / (float)this.getIterations(),
//                (float)(n*n*n) / (float)(this.getIterations() * this.getIterations() * this.getIterations()));
        return new Color(
                (float)n / (float)this.getIterations(),
                (float)n / (float)this.getIterations(),
                (float)n / (float)this.getIterations());
    }
    
    public void render(Graphics2D g2) {
        for(int y = 0; y < this.getHeight(); y++) {
            for(int x = 0; x < this.getWidth(); x++) {
                final int n = this.calculateSequence(
                        this.getRealFromPixel(x), 
                        this.getImaginaryFromPixel(y));
                
                g2.setColor(this.generateColor(n));
                g2.drawLine(x, y, x, y);
            }
        }
    }
    
    public int getWidth() {
        return this.width;
    }
    
    public void setWidth(int width) {
        this.width = width;
    }
    
    public int getHeight() {
        return this.height;
    }
    
    public void setHeight(int height) {
        this.height = height;
    }
    
    public double getLeft() {
        return this.left;
    }
    
    public void setLeft(double left) {
        this.left = left;
    }
    
    public double getRight() {
        return this.right;
    }
    
    public void setRight(double right) {
        this.right = right;
    }
    
    public double getTop() {
        return this.top;
    }
    
    public void setTop(double top) {
        this.top = top;
    }
    
    public double getBottom() {
        return this.bottom;
    }
    
    public void setBottom(double bottom) {
        this.bottom = bottom;
    }
    
    public int getIterations() {
        return this.iterations;
    }
    
    public void setIterations(int iterations) {
        this.iterations = iterations;
    }
}

Das Programm zum Starten:
Java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MandelbrotPanel extends JPanel {
    
    private static final long serialVersionUID = -138220849693387138L;
    
    private final MandelbrotPainter painter = new MandelbrotPainter();
    
    private BufferedImage image = new BufferedImage(600, 600, BufferedImage.TYPE_INT_RGB);
    
    public MandelbrotPanel() {
        this.painter.setIterations(30);
        this.painter.setHeight(this.image.getHeight());
        this.painter.setWidth(this.image.getWidth());
        this.painter.render(this.image.createGraphics());
    }
    
    public static void main(String[] args) {
        
        MandelbrotPanel panel = new MandelbrotPanel();
        
        JFrame frame = new JFrame("Mandelbrot");
        
        frame.add(panel);
        frame.pack();
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    
    @Override
    public Dimension getMinimumSize() {
        return new Dimension(this.image.getWidth(), this.image.getHeight());
    }
    
    @Override
    public Dimension getPreferredSize() {
        return this.getMinimumSize();
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        g.drawImage(this.image, 0, 0, this);
    }
    
}

Vielleicht gehört das hier auch in den Algorithmen-Bereich, ich weiß es nicht.
 
Zuletzt bearbeitet:
Ich bin mit zu 99% sicher das ich alles richtig berechne, allerdings wird das Bild irgendwie verzerrt. Ich vermute es liegt an irgendwelchen Rundungsfehlern, aber ich finde einfach keine Lösung für das Problem.
Es sind keine Rundungsfehler, die Berechnung ist tatsächlich falsch. Du darfst bei der Berechnung des neuen imaginären Anteils nicht den neuen reellen Anteil verwenden. Richtig wäre es z.B. so:
Java:
double zRealNew = zReal * zReal - zImag * zImag + real;
zImag = 2 * zReal * zImag + imag;
zReal = zRealNew;
Grüße, Matthias
 

Neue Beiträge

Zurück