How do you draw the Mandelbrot Set in Java using SWING/AWT?

1

I'm trying to draw the Mandelbrot Set, with points in the set as black, and everything else as white. In this initial version, I do not wish to be able to zoom in but rather just create a static image.

I created a ComplexNumber class, as shown below, to handle squaring and adding complex numbers together.

public class ComplexNumber {

    private double real;
    private double imaginary;

    public ComplexNumber(double real, double imaginary){
        this.real = real;
        this.imaginary = imaginary;
    }

    public ComplexNumber times(ComplexNumber number){

        double a = this.real*number.real;
        double b = this.imaginary*number.real;
        double c = this.real*number.imaginary;
        double d = this.imaginary*number.imaginary*-1;

        double newReal = a+d;
        double newImaginary = b+c;


        ComplexNumber newComplexNumber = new ComplexNumber(newReal, newImaginary);
        return newComplexNumber;
    }

    public ComplexNumber add(ComplexNumber number){

        double newReal = this.real+number.real;
        double newImaginary = this.imaginary+number.imaginary;

        return new ComplexNumber(newReal, newImaginary);

    }

    public double abs(){
        return Math.hypot(this.real, this.imaginary);
    }

    public double getReal() {
        return real;
    }

    public double getImaginary() {
        return imaginary;
    } 
}

And here is the code where I render the GUI and actually calculate the points in the Mandelbrot Set.

    import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class MandelBrotSet extends JComponent {

    public static final int WIDTH = 800;
    public static final int HEIGHT = 800;
    public static final int ITERATIONS = 100;

    public static final double startX = -2;
    public static final double width = 4;
    public static final double startY = 2;
    public static final double height = 4;

    public static final double dx = width/(WIDTH-1);
    public static final double dy = height/(HEIGHT-1);

    private BufferedImage buffer;


    public MandelBrotSet() {

        buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

        JFrame frame = new JFrame("Mandelbrot Set");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(true);
        frame.getContentPane().add(this);

        frame.pack();
        frame.setVisible(true);


    }

    @Override
    public void addNotify() {
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(buffer, 0, 0, null);
    }

    public void render(){

        for (int x=0; x<WIDTH; x++){
            for (int y=0; y<HEIGHT; y++){
                int color = calculatePoint(x, y);
                buffer.setRGB(x, y, color);
            }
        }
    }



    public int calculatePoint(int x, int y){

        ComplexNumber number = convertToComplex(x, y);
        ComplexNumber z = number;
        int i;
        for (i=0; i<ITERATIONS; i++){

            z = z.times(z).add(number);

            if (z.abs()>2.0){
                break;
            }

        }

        if (i==ITERATIONS) {
            return 0x00000000;
        }
        else {
            return 0xFFFFFFFF;
        }

    }

    public static ComplexNumber convertToComplex(int x, int y){

        double real = startX + x*dx;
        double imaginary = 2 - y*dy;
        return new ComplexNumber(real, imaginary);

    }




    public static void main(String[] args) {

        MandelBrotSet mandy = new MandelBrotSet();
        mandy.render();

    }


}

After running this code, I'm getting the image below. There seems to be a small glimpse of the Mandelbrot set, but then it's obscured by a ton of black. What am I doing wrong?

enter image description here

Updated Solution Below. Thanks for the help.

enter image description here

java
swing
awt
mandelbrot
asked on Stack Overflow Nov 21, 2019 by Michael • edited Nov 21, 2019 by Michael

1 Answer

0

The rendering of your image takes longer than displaying the MandelBrotSet-Object, and it is never updated afterwards. You create an object of type MandelBrotSet, then immediately call it's render method. During the creation of that object, you put it in a JFrame which you immediately display. When the frame is displayed, the rendering is incomplete, which is why your ImageBuffer is not yet filled (it takes longer to build the mandelbrot-form).

To solve this, you could repaint the involved components and the frame. My understanding of awt's repaint functions is not good enough to tell you how exactly to do it right (maybe someone else can help there), but adding this to the end of your render method should help:

revalidate();
repaint();

Either revalidate or repaint can probably be omitted.

Would be cool, if you updated your question with the done image :)

answered on Stack Overflow Nov 21, 2019 by TreffnonX • edited Nov 21, 2019 by TreffnonX

User contributions licensed under CC BY-SA 3.0