BeautyExplosion

Edward Lee



This is my art project, written mostly in Java, but includes in this website HTML, javascript, and jQuery. The visual is a graphics program that has two color spectrums, a spiral, a sine curve, a cosine curve, a word circle, a colorful mouse tail, and a 3D cube that can be rotated by dragging the mouse. Enjoy!
// Beauty can mean a variety of things to different people. Something beautiful to one
// particular person might be considered ugly to another. However, my programmer who
// wrote me and my beautiful graphics rendering skills thinks that computer programming
// is an art with beauty, that code is poetry. He can express himself through programs,
// objects of his creation. Amazingly he never gets bored of it and this devotion and
// passion enforces his view that programming is beautiful. Like a piece of writing is
// to a writer, everything has to be perfect and follow central themes and a timeline;
// each word must be carefully chosen to make up the sentence, each sentence to the
// paragraph, and ultimately each paragraph to the entire piece of writing. Likewise,
// every symbol or keyword must be chosen and functions and methods must be planned
// and follow an algorithm. A simple error can cause the whole thing to collapse and
// not work as planned. In another way, this is where the beauty also comes in. Just
// because something does not work the way it is supposed to does not mean it is a
// failure. Others can see some other meaning that is likewise as important or
// noteworthy.

// Furthermore, programming is beautiful because it teaches people to work together
// and think hard to solve programs. Almost all major software written nowadays is
// written in teams, so there must be a tight communication between teammates. Each
// teammate has to write a particular section of the final project. Furthermore, all
// the sections have to be combined at the end and must fit in or else the finished
// product would not work. Programming teaches people to be able to make very specific
// instructions, nothing vague and no missing steps. The beauty here is that it allows
// people to realize that even the most complex of programs is really simple and
// straightforward at its central core. Programming in general has changed the face
// of the planet by things like how we work in the office. For example, in today's
// world, communication has become vastly digital because of advances in software
// such as word processors. The result is beautiful as more work can be done more
// efficiently and faster. Other programs that do not do anything specific are also
// beautiful, such as myself, a graphics program that might be made into a screensaver
// in the future. After all, not everything has to have a practical purpose to be
// beautiful, just as expressed in "Art for Art's Sake."

// Word Count: 414

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.lang.Math;

class Point3D
{
    public int x, y, z;
    public Point3D(int X, int Y, int Z){x = X;  y = Y;  z = Z;}
}

class Edge
{
    public int a, b;
    public Edge(int A, int B){a = A; b = B;}
}

public class BeautyExplosion extends Applet implements MouseListener, MouseMotionListener
{
    int width, height;
    int x, y;
    int arcSpectrumN = 30;
    Color[] arcSpectrum;
    Color[] arcSpectrum2;

    int wordCircleN = 27;
    Color[] wordCircleSpectrum;

    Vector mouseXYList;

    int mx, my, new_mx, new_my;
    double t = 0;

    int azimuth = 35, elevation = 30;
    Point3D[] vertices;
    Edge[] edges;

    Image backBuffer;
    Graphics backGround;

    public void init()
    {
        width = getSize().width;
        height = getSize().height;
        setBackground(Color.black);

        mouseXYList = new Vector();

        vertices = new Point3D[8];
        vertices[0] = new Point3D(-1, -1, -1);
        vertices[1] = new Point3D(-1, -1, 1);
        vertices[2] = new Point3D(-1, 1, -1);
        vertices[3] = new Point3D(-1, 1, 1);
        vertices[4] = new Point3D(1, -1, -1);
        vertices[5] = new Point3D(1, -1, 1);
        vertices[6] = new Point3D(1, 1, -1);
        vertices[7] = new Point3D(1, 1, 1);

        edges = new Edge[12];
        edges[0] = new Edge(0, 1);
        edges[1] = new Edge(0, 2);
        edges[2] = new Edge(0, 4);
        edges[3] = new Edge(1, 3);
        edges[4] = new Edge(1, 5);
        edges[5] = new Edge(2, 3);
        edges[6] = new Edge(2, 6);
        edges[7] = new Edge(3, 7);
        edges[8] = new Edge(4, 5);
        edges[9] = new Edge(4, 6);
        edges[10] = new Edge(5, 7);
        edges[11] = new Edge(6, 7);

        arcSpectrum = new Color[arcSpectrumN];
        arcSpectrum2 = new Color[arcSpectrumN];

        backBuffer = createImage(width, height);
        backGround = backBuffer.getGraphics();

        for(int i = 1; i <= arcSpectrumN; ++i)
        {
            arcSpectrum[i - 1] = new Color(i / (float)(arcSpectrumN), i / (float)(arcSpectrumN), i / (float)(arcSpectrumN));
            arcSpectrum2[i - 1] = new Color(i / (float)(arcSpectrumN), (arcSpectrumN - i) / (float)(arcSpectrumN), 0);
        }

        wordCircleSpectrum = new Color[wordCircleN];

        for(int i = 0; i < wordCircleN; ++i)
            wordCircleSpectrum[i] = new Color(Color.HSBtoRGB(i / (float)(wordCircleN), 1, 1));

        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mouseClicked(MouseEvent e){}
    public void mousePressed(MouseEvent e)
    {
        mx = e.getX();
        my = e.getY();
        e.consume();
    }

    public void mouseReleased(MouseEvent e){}
    public void mouseMoved(MouseEvent e)
    {
        if(mouseXYList.size() >= 50) mouseXYList.removeElementAt(0);
        mouseXYList.addElement(new Point(e.getX(), e.getY()));
        repaint();
        e.consume();
    }

    public void mouseDragged(MouseEvent e)
    {
        new_mx = e.getX();
        new_my = e.getY();
        azimuth -= new_mx - mx;
        elevation += new_my - my;
        repaint();
        e.consume();
    }

    void drawWireframe(Graphics g)
    {
        double theta = Math.PI * azimuth / 180.0;
        double phi = Math.PI * elevation / 180.0;
        float cosT = (float)(Math.cos(theta));
        float sinT = (float)(Math.sin(theta));
        float cosP = (float)(Math.cos(phi));
        float sinP = (float)(Math.sin(phi));
        float cosTcosP = cosT * cosP;
        float cosTsinP = cosT * sinP;
        float sinTcosP = sinT * cosP;
        float sinTsinP = sinT * sinP;

        Point[] points;
        points = new Point[vertices.length];
        int j;
        int scaleFactor = width / 7;
        float near = 10;
        float nearToObj = 1.5f;
        for(j = 0; j < vertices.length; ++j)
        {
            int x0 = vertices[j].x;
            int y0 = vertices[j].y;
            int z0 = vertices[j].z;

            float x1 = cosT * x0 + sinT * z0;
            float y1 = -sinTsinP * x0 + cosP * y0 + cosTsinP * z0;

            float z1 = cosTcosP * z0 - sinTcosP * x0 - sinP * y0;
            x1 = x1 * near / (z1 + near + nearToObj);
            y1 = y1 * near / (z1 + near + nearToObj);

            points[j] = new Point((int)(width / 2 + scaleFactor * x1 + 0.5), (int)(height / 2 - scaleFactor * y1 + 0.5));
        }

        backGround.setColor(Color.gray);
        for(j = 0; j < edges.length; ++j)
            drawLine(backGround, points[edges[j].a].x, points[edges[j].a].y, points[edges[j].b].x, points[edges[j].b].y, 4);
    }

    public void drawLine(Graphics g, int x1, int y1, int x2, int y2, int thickness)
    {
        int dX = x2 - x1;
        int dY = y2 - y1;

        double lineLength = Math.sqrt(dX * dX + dY * dY);
        double scale = (double)(thickness) / (2 * lineLength);

        double ddx = -scale * (double)(dY);
        double ddy = scale * (double)(dX);
        ddx += (ddx > 0) ? 0.5 : -0.5;
        ddy += (ddy > 0) ? 0.5 : -0.5;
        int dx = (int)ddx;
        int dy = (int)ddy;

        int xPoints[] = new int[4];
        int yPoints[] = new int[4];

        xPoints[0] = x1 + dx; yPoints[0] = y1 + dy;
        xPoints[1] = x1 - dx; yPoints[1] = y1 - dy;
        xPoints[2] = x2 - dx; yPoints[2] = y2 - dy;
        xPoints[3] = x2 + dx; yPoints[3] = y2 + dy;

        g.fillPolygon(xPoints, yPoints, 4);
    }

    public void update(Graphics g)
    {
        backGround.setColor(Color.black);
        backGround.fillRect(0, 0, width, height);
        backGround.setColor(Color.white);

        int arcSpectrumStep = 90 / arcSpectrumN;
        for(int i = 0; i < arcSpectrumN; ++i)
        {
            backGround.setColor(arcSpectrum[i]);
            backGround.fillArc(width / -4, height / 3, width / 2, height / 2, i * arcSpectrumStep, arcSpectrumStep + 1);
        }

        int N = 30, W = 10;
        int x1 = 0, y1 = 0, x2, y2;
        backGround.setColor(Color.green);
        for(int i = 1; i <= W * N; ++i)
        {
            double angle = 2 * Math.PI * i / (double)(N);
            double radius = i / (double)(N) * width / 2 / (W + 1);
            x2 = (int)(radius * Math.cos(angle));
            y2 = -(int)(radius * Math.sin(angle));
            backGround.drawLine(width / 2 + x1, height / 2 + y1, width / 2 + x2, height / 2 + y2);
            x1 = x2;
            y1 = y2;
        }

        for(int i = 0; i < arcSpectrumN; ++i)
        {
            backGround.setColor(arcSpectrum2[i]);
            backGround.fillArc(width / 4, height / 4, 6 * width / 4, 6 * height / 4, 90 + i * arcSpectrumStep, arcSpectrumStep + 1);
        }

        int middleXPixel = 3 * getWidth() / 4;
        int middleYPixel = 3 * getHeight() / 4;
        double startAngle = -180.0;
        for(int i = 0; i < 360; i++)
        {
            for(int j = 0; j <= 1; j++)
            {
                double calculation = Math.toRadians(startAngle + i);
                if(j == 0) calculation = Math.sin(calculation);
                else calculation = Math.cos(calculation);

                int ypixel = middleYPixel - (int)(calculation * 100.0);
                int xpixel = middleXPixel - 180 + i;

                if(j == 0) backGround.setColor(Color.RED);
                else backGround.setColor(Color.BLUE);
                backGround.fillRect(xpixel, ypixel, 2, 2);
            }
        }

        int wordCircleRadius = width / 3;
        backGround.setFont(new Font("Cursive", Font.PLAIN, 18));
        for(int i = 0; i < wordCircleN; ++i)
        {
            double angle = 2 * Math.PI * i / (double)(wordCircleN);
            int x = (int)(wordCircleRadius * Math.cos(angle));
            int y = (int)(wordCircleRadius * Math.sin(angle));

            backGround.setColor(wordCircleSpectrum[i]);
            backGround.drawString("Beauty", width / 2 + x, height / 2 + y);
        }

        backGround.setColor(Color.white);
        for (int j = 1; j < mouseXYList.size(); ++j)
        {
            Point A = (Point)(mouseXYList.elementAt(j - 1));
            Point B = (Point)(mouseXYList.elementAt(j));
            backGround.setColor(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256)));
            drawLine(backGround, A.x, A.y, B.x, B.y, 2);
        }

        drawWireframe(backGround);
        mx = new_mx;
        my = new_my;

        g.drawImage(backBuffer, 0, 0, this);
    }

    public void paint(Graphics g){update(g);}
}