Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Java: Mandelbrot in java

Sami [28.09.2003 14:34:22]

#

Eli siis perässä on ohjelma, joka piirtää tunnettua mandelbrotin fraktaalia. Zoomauskin on mukana.

Hieman tuosta muutettu versio (appletti) on nähtävillä osoitteessa http://www.paivola.net/~sami/mandel/mandel.html

Mandelbrot.java

import java.awt.Color;

public class Mandelbrot
{
	public static double lev = 500;
	public static double kork = 500;
	public static double leftTopX = -2;
	public static double leftTopY = 2;
	public static double rightBottomX = 2;
	public static double rightBottomY = -2;

	public static double ar = 0;
	public static double ag = 0;
	public static double ab = 0;
	public static double lr = 255;
	public static double lg = 255;
	public static double lb = 0;

	public static int iteraatioita = 256;

	public static Color v[] = new Color[iteraatioita+1];

	public static void main (String[] args)
	{

		for (int i=0; i < iteraatioita; i++)
		{
			v[i] = new Color((int)(ar+(lr-ar)/iteraatioita*i),(int)(ag+(lg-ag)/iteraatioita*i),(int)(ab+(lb-ab)/iteraatioita*i));
			v[i] = new Color((int)(ar+(lr-ar)/iteraatioita*i),(int)(ag+(lg-ag)/iteraatioita*i),(int)(ab+(lb-ab)/iteraatioita*i));
		}
		v[iteraatioita] = new Color(255,255,255);


		piirtopinta.initGraphics((int)lev, (int)kork);
		Mandel();


		while (true)
		{
			int[] piste = piirtopinta.getPoint();
			int x = piste[0];
			int y = piste[1];


			double tmpLeftTopX = leftTopX + x*(rightBottomX-leftTopX)/lev;
			double tmpLeftTopY = leftTopY + y*(rightBottomY-leftTopY)/kork;

			piirtopinta.setColor (Color.black);
			System.out.println ("X: " + tmpLeftTopX + "   Y: " + tmpLeftTopY);


			int[] piste2 = piirtopinta.getPoint();
			x = piste2[0];
			y = piste2[1];

			rightBottomX = leftTopX + x*(rightBottomX-leftTopX)/lev;
			leftTopX = tmpLeftTopX;
			leftTopY = tmpLeftTopY;
			rightBottomY = leftTopY + (leftTopX-rightBottomX);

			System.out.println ("X: " + rightBottomX + "   Y: " + rightBottomY + "\n");
			Mandel();
		}
	}


	public static void Mandel()
	{
		// Piirtopinnan tyhjääminen
		piirtopinta.clear();

		// Kokeillaan mitkä pisteet kuuluvat mandelbrotin joukkoon
		for (int x = 0; x <= lev; x++)
		{
			for (int y = 0; y <= kork; y++)
			{
			ComplexNumber iterationComplex = new ComplexNumber(0,0);
			ComplexNumber currentComplex = new ComplexNumber(leftTopX + x*(rightBottomX-leftTopX)/lev,
				leftTopY + y*(rightBottomY-leftTopY)/kork);

				int iteraatio=0;
				for ( ; iteraatio<iteraatioita; iteraatio++)
				{
					iterationComplex = iterationComplex.multiply(iterationComplex);
					iterationComplex = iterationComplex.add(currentComplex);

					if (iterationComplex.abs() > 2) break;
				}
				piirtopinta.setColor(v[iteraatio]);
				piirtopinta.drawPoint(x,y);
			}
			if (x%50 == 0) piirtopinta.repaint();
		}
		piirtopinta.repaint();
	}
}

piirtopinta.java

import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;

public class piirtopinta {

    private static int width;
    private static int height;

    private static BufferedImage i;
    private static Graphics2D g;
    private static Frame frame;
    private static Insets insets;

    private static Point mousePoint;
    private static Object lock = new Object();

    static class OurFrame extends Frame {

        public OurFrame() {
            super("Graphics window");
            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
            addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    synchronized(lock) {
                        mousePoint = e.getPoint();
                        lock.notifyAll();
                    }
                }
            });
        }

        public void paint(Graphics g) {
            if (i != null) {
                g.drawImage(i, insets.left, insets.top, this);
            }
        }

    }

    public static void initGraphics(int w, int h) {
        width = w;
        height = h;
        frame = new OurFrame();
        frame.setSize(width, height);
        frame.setVisible(true);
        frame.show();

        insets = frame.getInsets();
        frame.setSize(width + insets.left + insets.right,
                      height + insets.top + insets.bottom);

        i = (BufferedImage) frame.createImage(width, height);
        g = i.createGraphics();
        g.setBackground(frame.getBackground());
        clear();
    }

	public static void drawPoint(int x, int y) {
		g.drawRect(x, y, 0, 0);
	}

	public static void repaint()
	{
		frame.repaint();
	}

    public static void setColor(Color c) {
        g.setColor(c);
    }

    public static void clear() {
        g.clearRect(0, 0, width, height);
        frame.repaint();
    }

    public static int[] getPoint() {
        synchronized(lock) {
            mousePoint = null;
            while (mousePoint == null) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            return new int[] { (int) mousePoint.getX()-insets.left,
                               (int) mousePoint.getY()-insets.top };
        }
    }
}

ComplexNumber.java

public class ComplexNumber {
    private double reaaliOsa;
    private double imaginaariOsa;

    // Luo uuden kompleksiluvun jonka arvo on 0,0
    public ComplexNumber() {
        reaaliOsa = 0;
        imaginaariOsa = 0;
    }

    public ComplexNumber(double a, double b) {
        reaaliOsa = a;
        imaginaariOsa = b;
    }

    public ComplexNumber(double a) {
        reaaliOsa = a;
        imaginaariOsa = 0;
    }

    // Palauttaa uuden kompleksiluvun joka on
    // tämän ja toisen kompleksiluvun summa.
    public ComplexNumber add(ComplexNumber toinen) {
        double uusiR = reaaliOsa + toinen.reaaliOsa;
        double uusiI = imaginaariOsa + toinen.imaginaariOsa;
        return new ComplexNumber(uusiR, uusiI);
    }

    // Palauttaa uuden kompleksiluvun joka on
    // tämän ja toisen kompleksiluvun tulo.
    public ComplexNumber multiply(ComplexNumber toinen) {
	double uusiR = reaaliOsa*toinen.reaaliOsa -
	    imaginaariOsa*toinen.imaginaariOsa;
	double uusiI = reaaliOsa*toinen.imaginaariOsa +
	    imaginaariOsa*toinen.reaaliOsa;
        return new ComplexNumber(uusiR, uusiI);
    }

    // Palauttaa tämän kompleksiluvun reaaliosan.
    public double getR() {
	return reaaliOsa;
    }

    // Palauttaa tämän kompleksiluvun imaginaariosan.
    public double getI() {
	return imaginaariOsa;
    }

    // Palauttaa tämän kompleksiluvun itseisarvon.
    public double abs() {
	return Math.sqrt(reaaliOsa*reaaliOsa +
			 imaginaariOsa*imaginaariOsa);
    }

    // Palauttaa tämän kompleksiluvun merkkijonona, esim "3+4.5i";
    public String toString() {
	return reaaliOsa+"+"+imaginaariOsa+"i";
    }
}

T.M. [29.09.2003 18:57:25]

#

siisti, niinkuin kaikki fraktaalit :)

Nahkis [04.10.2003 13:59:07]

#

toihan on mainio!

(nimetön) [11.05.2004 15:28:31]

#

Hieno. Maksimissaan toi suorittaa 16000000 laskutoimitusta piirtäessään fraktaalia(appletin koko 250² ja max. iteraatioita 256)? Mandelbrot.java:ssa voisi olla hieman enemmän kommenttia, jotta tuon fraktaalin idea aukenisi hieman paremmin. Kyseessä on siis kompleksilukufraktaali, jonka voi piirtää valitsemalla luku zn rekursiivisesti siten, että z1=c, z2=c²+c, z3=z2+c.. missä c on ennalta valittu kompleksiluku. Sitten tutkitaan luvun zn itseisarvoa ja jos itseisarvo ylittää kakkosen, piirretään sen kohdalle mustaa. Valkoisen kohdalla itseisarvo ei ole missään vaiheessa ylittänyt lukua 2.

tsuriga [11.05.2004 15:33:40]

#

Hieno. Voisi olla hieman enemmän kommentoitu, jotta fraktaalin idea aukenisi. Maksimissaan tuo taitaa tehdä 250²*256 (16000000) laskutoimitusta fraktaalia piirtäessään (tilanne, jossa kuvio on täysin valkoinen). Fraktaalin idea on seuraavanlainen: Valitaan kompleksiluku c ja määritellään luku zn = z(n-1)+c (z0=0). Sitten testataan onko luvun zn itseisarvo ylittänyt arvon kaksi ja jos on, piirretään sille kohtaa musta piste, muuten piirretään valkoinen. Värejä ohjelmaan saadaan lisäämällä tiettyjä rajoja iteraatiolle (esim. jos on ylitetty vaikka tuhannen raja, vaihdetaan piirtoväriksi punainen), missä väriä vaihdetaan.

Metabolix [19.02.2012 11:48:31]

#

Tämä on oikein hyvä aihe vinkille, mutta koodia pitäisi hieman selventää ja kommentoida – ehtisitkö? Hassusti tässä on kommentoitu vain helpot kohdat ja jätetty vaikeimmat osat täysin selittämättä. Samoin muuttujien nimet "reaaliOsa" ja "imaginaariOsa" ovat melkoisia ylilyöntejä mutta esimerkiksi "ar", "ag" ja "ab" saisivat olla selvempiä. Lisäksi sisennykset pitäisi tehdä yhtenäisesti joko tabeilla tai välilyönneillä ja kielen olisi hyvä olla yhtenäisesti joko suomi tai englanti.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta