Butterflies.java

From CompSciWiki
Revision as of 09:49, 8 December 2009 by SamuelP (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
/******************************************************************************
 * Butterflies                                                                *
 * Copyright (C) 2009 Samuel Pauls                                            *
 * www.samuelpauls.com                                                        *
 *                                                                            *
 * Permission is granted to copy, distribute and/or modify this document      *
 * under the terms of the GNU Free Documentation License, Version 1.2 or any  *
 * later version published by the Free Software Foundation; with no Invariant *
 * Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the     *
 * license is included in the section entitled "GNU Free Documentation        *
 * License".                                                                  *
 *                                                                            *
 * A screensaver that draws a rose and Temple H. Fay's butterfly curve.       *
 ******************************************************************************/

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JOptionPane;

public class Butterflies extends Screensaver {
  public static void main (String[] args) {
    // args contains arguments passed to the program as it starts.  For example,
    // if the screensaver is run as "java Butterflies /c", args[0] will contain
    // the first argument, "/c".
    if (args.length > 0 && args[0].startsWith ("/c")) {
      // Show an about dialog in the place of screensaver options.
      final String TITLE = "About Butterflies";
      final String MESSAGE =
        "Butterflies\n" +
        "Copyright 2009 by Samuel Pauls\n" +
        "www.samuelpauls.com\n" +
        "\n" +
        "A screensaver that draws a rose and Temple H. Fay's butterfly" +
          " curve.\n" +
        "\n" +
        "Permission is granted to distribute and modify this program, as long" +
          " as\n" +
        "you attribute changes to yourself and give others credit where due." +
          "  No\n" +
        "warranty is provided.\n";
      JOptionPane.showMessageDialog (null,
                                     MESSAGE, TITLE,
                                     JOptionPane.INFORMATION_MESSAGE);
    } else if (args.length > 0 && args[0].startsWith ("/p")) {
      // Do nothing when a preview is requested for the monitor in Windows'
      // screensaver dialog.
    } else {
      // Start the screensaver.
      final int SECONDS = 1;
      setFrameDelay (SECONDS);
      new Butterflies();
    }
  }

  // Draw a frame of this screensaver.
  public void drawFrame (Graphics g) {
    // Clear the background to black.
    g.setColor (Color.BLACK);
    g.fillRect (0, 0, getWidth(), getHeight());

    // Setup the transformation values of the object.
    double scale = random (60, 400);
    double radius = scale / 2.0;
    double centerX = random (radius, getWidth() - radius);
    double centerY = random (radius, getHeight() - radius);

    // Choose a random color for the object.
    float red = (float)Math.random();
    float green = (float)Math.random();
    float blue = (float)Math.random();
    g.setColor (new Color (red, green, blue));

    // Draw an object.
    if (Math.random() < 0.5) {
      drawButterfly (g, scale, centerX, centerY);
    } else {
      drawRose (g, scale, centerX, centerY);
    }
  }

  // Return a random number within the specified inclusive range.
  public static double random (double minimum, double maximum) {
    final double RANGE = maximum - minimum;
    return minimum + Math.random() * RANGE;
  }

  // Draw Temple H. Fay's butterfly curve.
  public static void drawButterfly (Graphics g,
                                    double scale,
                                    double centerX, double centerY) {
    // Draw many of the points along the curve.
    for (double t = 0; t < 2 * Math.PI; t = t + 0.001) {
      // Exchange the t value for x and y points on the butterfly curve.
      double cache = (Math.exp (Math.cos (t)) - 2 * Math.cos (4 * t) -
                     Math.pow (Math.sin (t / 12), 5));
      double x = Math.sin (t) * cache;
      double y = Math.cos (t) * cache;

      // At this point, the butterfly is upside down.  Flip it about the x-axis.
      y = y * -1;

      // Normalize the butterfly's size to a 1x1 rectangle.
      // This simplifies the code needed to randomly place the object on the
      // screen, such that it doesn't go over an edge.
      x = x / 6;
      y = y / 6;

      drawPoint (g, x, y, scale, centerX, centerY);
    }
  }

  // Draw a rose.
  public static void drawRose (Graphics g,
                               double scale,
                               double centerX, double centerY) {
    // Draw many of the points along the curve.
    for (double t = 0; t < 2 * Math.PI; t = t + 0.001) {
      // Exchange the t value for x and y points on the rose.
      double cache = Math.sin (2 * t);
      double x = Math.sin (t) * cache;
      double y = Math.cos (t) * cache;

      // Normalize the rose's size to a 1x1 rectangle.
      // This simplifies the code needed to randomly place the object on the
      // screen, such that it doesn't go over an edge.
      x = x / 2;
      y = y / 2;

      drawPoint (g, x, y, scale, centerX, centerY);
    }
  }

  // Draw a point of a scaled and translated object.
  public static void drawPoint (Graphics g,
                                double x, double y,
				double scale,
				double centerX, double centerY) {
    // Scale the point.
    x = x * scale;
    y = y * scale;

    // Translate the point.
    x = x + centerX;
    y = y + centerY;

    // Draw the point as a circle to give the eventual line some thickness.
    final int DIAMETER = 4;
    g.fillOval ((int)x, (int)y, DIAMETER, DIAMETER);
  }
} // Butterflies