[Home]MandelbrotSet/PeterJava

ec2-13-58-151-231.us-east-2.compute.amazonaws.com | ToothyWiki | MandelbrotSet | RecentChanges | Login | Webcomic

This is in two classes because I wanted multi-threading for the Mandelbrot/Julia set interaction. You can see two instances of the applet working side-by-side at [1] (or, if it's down, which it seems to be half the time nowadays, on the5k.org, in the 2002 section. This, incidentally, is the reason for the naming of the applets - I wanted the names to take up as little space as possible, although I wasn't quite willing to call my fields f, ff, fff, ffff, etc).
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class F extends Applet
               implements MouseListener,
                          MouseMotionListener
{
    // Some useful constants
    final static int screenSize=400;
    final static int s2=screenSize/2;
    double midX=0.0;
    double midY=0.5;
    double range=0.5;
    final static int LIMIT=250;
    int mouseFunction;
    Color[] lup;
    
    // Cursors
    Cursor crosshair = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
    Cursor hand = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
    Cursor arrow = Cursor.getDefaultCursor();
    
    // Other mouse stuff
    int mousex, mousey;et = false;
    // Is this a Mandelbrot instantiation or a Julia instantiation?
    boolean mbrot;

    // A Julia instantiation needs the coefficient - default give pretty set
    double jreal = 0.07;
    double jimag = 0.6275;
    
    // The two complex numbers used for the computation and one temp
    double zr;
    double newzr;
    double zi;
    double cr;
    double ci;
    
    // Two images for buffering: the first for the fractal, the second for
    // drawing the magnifying glass without flicker
    Image image;
    Image bufimage;
    
    // A thread to do the drawing
    Thread ff;
    
    public void init()
    {   
        // I want mouse capability 
            this.addMouseListener(this);
        this.addMouseMotionListener(this);
        
        // Check whether this is a Mandelbrot or Julia instantiation.
        mbrot = !(getParameter("t").equals("J"));
        
        // Initialise the mouse function and the pointer
        if (mbrot)
        {
            mouseFunction = 0;
            setCursor(crosshair);
        }
        else
        {
            mouseFunction = 1;
            setCursor(hand);
        }
        
        // Set up the colour lookup table
        lup = new Color[LIMIT + 2];
        for (int i = 0; i < LIMIT; i++)
        {
            lup[i] = Color.getHSBColor((float)(i%64)/64.0f,
                                                   (float)(0.6 + 0.4* Math.cos((double)i/40.0)),
                                                   1.0f);
        }
        lup[LIMIT] = Color.black;
        lup[LIMIT + 1] = Color.black;
        
        // Initialise the image
        image = createImage(400, mbrot ? 440 : 460);
        bufimage = createImage(400, mbrot ? 440 : 460);
        plot();
        
        // Start drawing
        plot();
    }    
    
    // Provide the MouseListener interface
    public void mousePressed(MouseEvent e) 
    {
        // If the mouse was clicked in an area with y-coord less than 400, that's in the
        // picture.  Otherwise it's a button at the bottom.
        int x = e.getX();
        int y = e.getY();

        // calculate creal and cimag
        // I use screenSize-y because Im increases up the screen
        double creal = midX - range + (double)x/s2*range;
        double cimag = midY - range + (double)(screenSize-y)/s2*range;

        // round to precise figures as poss
            double rounding = screenSize/range;
            creal = Math.rint(rounding*creal)/rounding;
            cimag = Math.rint(rounding*cimag)/rounding;

        if (y < 400)
        {
            switch (mouseFunction)
            {
                case 0:
                    // If this is a Mandelbrot, call the Julia applet
                    if (mbrot)
                    {
                        ((F)getAppletContext().getApplet("J")).j(creal, cimag);
                    }
                    break;
                    
                case 1:
                    // Recenter on the clicked area
                    midX = creal;
                    midY = cimag;
                    plot();
                    break;
                    
                case 2:
                    // Zoom in
                    midX = creal;
                    midY = cimag;
                    range /= 2;
                    plot();
                    break;
                    
                case 3:
                    // Zoom out
                    range *= 2;
                    plot();
                    break;
                    
                default:
                    // do nothing;
                    break;
            }
        }
        else if (y < 440)
        {
            // Function = x / 100
            if (mbrot || x > 99)
            {
                mouseFunction = x / 100;
                drawButtons();
                
                switch (mouseFunction)
                {
                    case 0:   
                        setCursor(crosshair);
                        break;
                        
                    case 1:
                        setCursor(hand);
                        break;
                        
                    case 2:
                    case 3:
                        setCursor(arrow);
                }
            }
        }
    }

    // I don't want to use most of the mouse stuff yet
    public void mouseReleased(MouseEvent e) {} 
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    
    public void mouseExited(MouseEvent e)
    {
        mouseInApplet = false;
        paint(this.getGraphics());
    }

    // Method by which new co-ords can be passed to a Julia instance
    public void j(double creal, double cimag)
    {
        jreal = creal;
        jimag = cimag;
        plot();
    }

    // Paint method
    public void paint(Graphics g)
    {
        if (mouseInApplet && getCursor() == arrow)
        {
            // Draw the magnifying glass
            Graphics g2 = bufimage.getGraphics();
            g2.setColor(Color.black);
            g2.drawImage(image, 0, 0, null);
            g2.drawOval(mousex + 12, mousey - 1, 8, 8);
            g2.drawLine(mousex + 18, mousey + 5, mousex + 22, mousey + 11);
            g2.drawLine(mousex + 21, mousey, mousex + 25, mousey);
            if (mouseFunction == 2)
            {
                g2.drawLine(mousex + 23, mousey - 2, mousex + 23, mousey + 2);
            }
            g.drawImage(bufimage, 0, 0, null);
        }
        else
        {
            g.drawImage(image, 0, 0, null);
        }
    }
     
    void drawButtons()
    {
        // Get Graphics object from image
        Graphics g = image.getGraphics();
        
        // Add the buttons at the bottom
        g.setColor(Color.cyan);
        g.fillRect(0, 400, 400, 60);
        g.setColor(Color.blue);
        g.fillRect(100 * mouseFunction, 400, 100, 40);
        
        // Text on the buttons
        g.setColor(Color.black);
        g.setFont(new Font("Monospaced",Font.PLAIN, 14));
        
        if (mbrot)
        {
            g.drawString("Julia",25,425);
        }
        else
        {
            StringBuffer parameter = new StringBuffer();
            parameter.append("Parameter: ");
            if (jreal != 0.0)
                parameter.append(jreal);
            if (jimag > 0)
                parameter.append("+" + jimag + "i");
            else if (jimag < 0)
                parameter.append(jimag + "i");
            else if (jreal == 0)
                parameter.append("0");
            
            g.drawString(parameter.toString(),
                         10,
                         455);
        }
        g.drawString("Centre", 125, 425);
        g.drawString("Zoom in", 225, 425);
        g.drawString("Zoom out", 325, 425);

        // Paint applet
        paint(this.getGraphics());
    }
    
    // MouseMotionListener events
        public void mouseMoved(MouseEvent evt) 
        {
            updateMousePosition(evt);
        }

        public void mouseDragged(MouseEvent evt)
        {
        }

        public void updateMousePosition(MouseEvent evt)
        {
            mousex = evt.getX();
            mousey = evt.getY();
            mouseInApplet = true;
            paint(this.getGraphics());
        }    
    
    // Destroy any existing thread, and create a new one
    void plot()
    {
        if (ff != null)
        {
            ff.stop();
        }
        ff = new Ff(this);
        ff.start();
    }
}

Second class: the thread which does the painting.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Ff extends Thread
{
    F f;
    final static int screenSize=400;
    final static int s2=screenSize/2;
    final static int LIMIT=250;
    
    // The two complex numbers used for the computation and one temp
    double zr;
    double newzr;
    double zi;
    double cr;
    double ci;    
    
    double midX;
    double midY;
    double range;
    
    // A Julia instantiation needs the coefficient
    double jreal;
    double jimag;
    
    boolean mbrot;

    Ff(F f)
    {
        this.f = f;
        this.midX = f.midX;
        this.midY = f.midY;
        this.range = f.range;
        this.jreal = f.jreal;
        this.jimag = f.jimag;
        this.mbrot = f.mbrot;
    }
    
    public void run()
    {
        // Used for saving calls to g.setColor
        int oldn = -1;

        // Get Graphics object from image
        Graphics g = f.image.getGraphics();

        // First redraw the buttons
        f.drawButtons();

        // Draw onto image
        for (int y = screenSize; y > 0; y--)
        {
            for (int x = 0; x < screenSize; x++)
            {
                // For a Mandelbrot applet, we want
                //         z = 0
                //         c = (range*(x-s2))/s2+midX + (range*(y-s2))/s2+midY*i
                //
                // For a Julia applet, we want
                //         z = (range*(x-s2))/s2+midX + (range*(y-s2))/s2+midY*i
                //         c = jreal + jimag*i
                if (mbrot)
                {
                    zr = 0;
                    zi = 0;
                    cr = (range*(x-s2))/s2+midX;
                    ci = (range*(y-s2))/s2+midY;
                }
                else
                {
                    zr = (range*(x-s2))/s2+midX;
                    zi = (range*(y-s2))/s2+midY;
                    cr = jreal;
                    ci = jimag;
                }
                        
                        // Test to see whether the point is in the set
                int n = 0;
                while (n++ <LIMIT && (zr*zr + zi*zi) < 4.0)
                {
                    // z = z*z + c;
                    newzr = zr*zr - zi*zi +cr;
                    zi = 2*zr*zi + ci;
                        zr = newzr;
                    }

                        // Set a colour appropriate to the divergence time
                // Now uses lookup table
                if (n != oldn)
                    g.setColor(f.lup[n]);
                oldn = n;

                // Draw a rectangle in this colour at the appropriate position
                        g.fillRect(x,screenSize-y,1,1);
            }

            // Paint the image with this line drawn in
            f.paint(f.getGraphics());
            }
    }
}


ec2-13-58-151-231.us-east-2.compute.amazonaws.com | ToothyWiki | MandelbrotSet | RecentChanges | Login | Webcomic
This page is read-only | View other revisions | Recently used referrers
Last edited September 8, 2003 1:15 pm (viewing revision 1, which is the newest) (diff)
Search: