Draw a low resolution circle

394 Views Asked by At

I'm really stuck and out of ideas regarding this, I'm supposed to paint a circle, which goes fine. But it's going to be able to be painted in different resolutions, and I'm getting nowhere, please help! The code I show you here is not trying to work with differnet resolutions, but I have no ideas left on what to do.

I'll put up the class I'm having trouble with, and then I'll put up the rest of the program. Also a quick note, the program will later on be used for Mandlebrot sets.

The problem is, the circle works fine with High resolution, but once I try to decrease it, I get weird line patterns, like it only paints certain lines, and then paint lines it isn't supposed to, I'm suspecting the problem is the method render(). I also suspect the problem more specifically are the for-loops, or the index of my vectors. If I'm unclear in my explanation please tell me.

The RESOLUTION_VERY_HIGH to RESOLUTION_VERY_LOW have values 2048, 1024, ..., 128.

package mandelbrot;
import java.awt.Color;

import se.lth.cs.ptdc.fractal.MandelbrotGUI;

public class Generator {
    public Generator() {

    }

    public void render(MandelbrotGUI w) {
        w.disableInput();
        int resolution = 1;

         switch (w.getResolution()) {
            case MandelbrotGUI.RESOLUTION_VERY_HIGH:
             resolution = 1;
             break;
            case MandelbrotGUI.RESOLUTION_HIGH:
              resolution = 3;
              break;
            case MandelbrotGUI.RESOLUTION_MEDIUM:
              resolution = 5;
              break;
            case MandelbrotGUI.RESOLUTION_LOW:
              resolution = 7;
              break;
            case MandelbrotGUI.RESOLUTION_VERY_LOW:
              resolution = 9;
              break;
            }

        Complex complex[][] = mesh(w.getMinimumReal(), w.getMaximumReal(), w.getMinimumImag(),
                w.getMaximumImag(), w.getWidth(), w.getHeight());

        Color[][] picture = new Color[w.getHeight()][w.getWidth()];

        for (int i = 0; i<w.getHeight(); i+=resolution) {
            for (int j = 0; j<w.getWidth(); j+=resolution) {
                if ((complex[i][j]).getAbs()>1) {
                    picture[i][j] = Color.WHITE;
                }
                else {
                    picture[i][j] = Color.BLUE;
                }
            }
        }

        w.putData(picture, 1, 1);
        w.enableInput();
    }

    private Complex[][] mesh(double minReal, double maxReal, double minImaginary,
                                double maxImaginary, int width, int height) {

        Complex[][] matrice = new Complex[height][width];
        for (int i = 0; i<height; i++) {
            for (int j = 0; j<width; j++) {
                matrice[i][j] = new Complex((minReal + ((maxReal-minReal)/width)*j),
                                            ((maxImaginary - (((maxImaginary - minImaginary)/height)*i))));

            }
        }
        return matrice;
    }
}

I doubt you need them, but here are the other classes;

My main;

package mandelbrot;
import se.lth.cs.ptdc.fractal.MandelbrotGUI;

public class Mandelbrot {
    public static void main (String[] args) {
        MandelbrotGUI w = new MandelbrotGUI();
        Generator generator = new Generator();
        boolean zoomValue = false;

        while (true) {
            switch(w.getCommand()) {

                case MandelbrotGUI.QUIT: System.exit(0);
                break;

                case MandelbrotGUI.RENDER:
                    generator.render(w);
                break;

                case MandelbrotGUI.RESET:
                w.clearPlane();
                w.resetPlane();
                zoomValue = false;
                break;

                case MandelbrotGUI.ZOOM:
                    if (zoomValue) {
                            w.clearPlane();
                            generator.render(w);
                            break;
                    }
                    else {break;}
            }
        }
    }
}

and here is the Complex class I wrote;

package mandelbrot;

public class Complex {
    double real;
    double imaginary;

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

    double getReal() {
        return real;
    }
    double getImaginary() {
        return imaginary;
    }

    double getAbs() {
        return Math.hypot(real, imaginary);
    }

    void add(Complex c) {
        real += c.getReal();
        imaginary += c.getImaginary();
    }

    void multiply(Complex c) {
        real = (real*c.getReal()) - (imaginary*c.getImaginary());
        imaginary = (real*c.getImaginary()) + (imaginary*c.getReal());
    }
}

The specifications for the GUI you can find here; http://fileadmin.cs.lth.se/cs//Education/EDA016/javadoc/cs_eda016_doc/

Thanks for any help, very much appreciated! :)

2

There are 2 best solutions below

0
On

Well I seem to have solved the problem, the method render is supposed to look like this;

public void render(MandelbrotGUI w) {
    w.disableInput();
    int resolution = 1;

     switch (w.getResolution()) {
        case MandelbrotGUI.RESOLUTION_VERY_HIGH:
         resolution = 1;
         break;
        case MandelbrotGUI.RESOLUTION_HIGH:
          resolution = 3;
          break;
        case MandelbrotGUI.RESOLUTION_MEDIUM:
          resolution = 5;
          break;
        case MandelbrotGUI.RESOLUTION_LOW:
          resolution = 7;
          break;
        case MandelbrotGUI.RESOLUTION_VERY_LOW:
          resolution = 9;
          break;
        }

    Complex complex[][] = mesh(w.getMinimumReal(), w.getMaximumReal(), w.getMinimumImag(),
            w.getMaximumImag(), w.getWidth(), w.getHeight());

    Color[][] picture = new Color[w.getHeight()/resolution + 1][w.getWidth()/resolution + 1];

    for (int i = 0; i<w.getHeight(); i+=resolution) {
        for (int j = 0; j<w.getWidth(); j+=resolution) {
            if ((complex[i][j]).getAbs()>1) {
                picture[i/resolution][j/resolution] = Color.WHITE;
            }
            else {
                picture[i/resolution][j/resolution] = Color.BLUE;
            }
        }
    }

    w.putData(picture, resolution, resolution);
    w.enableInput();
}

The increment was j+=resolution and i+=resolution, I also put the index of Color[][] to w.getHeight/resolution + 1, and w.getWidth/resolution + 1.

The explanation being that I only compare every "resolution" row (eg, every third row for resolution 3), and every "resolution" pixel on that row. Thus I need only w.getWidth/resolution + 1 elements (and the same for w.getHeight).

Then I took picture[i/resolution][j/resolution], I think the problem before was that I saved too many elements, and then when the pixelsize was increased, I had too many pixels.

Also, w.putData(picture, resolution, resolution);, which meant I expanded the pixelsize, and so the resolution was lower.

Thanks for all the trouble the people here went throught to help me.

1
On

If I follow your code correctly and the operation of the GUI class. There are two things you need to do.

1) When in a resolution other than VERY_HIGH, you only set the color for every resolution points. This may work but only if you change the size of the pixel you are painting with. Without the GUI class, there is not enough information to say. I get the feeling though that the if statement if ((complex[i][j]).getAbs()>1 should read if ((complex[i][j]).getAbs()>resolution and the increment for i and j should be 1. Again, without the GUI class, I can't say.

2) To change the size of the pizel, all you should need to change is the w.putData(picture,1,1); command to read w.putData(picture,resolution,resolution);.

If this is incorrect, a link to the GUI source or adding pictures of the results you are currently getting will help.