Spirograph.java


Below is the syntax highlighted version of Spirograph.java from §3.6 Case Study: Purple America.


/******************************************************************************
 *  Compilation:  javac Spirograph.java
 *  Execution:    java Spirograph
 *  Dependencies: Draw.java LabeledSlider.java
 *
 *  Draw a curve formed by rolling a smaller circle of radius r inside
 *  a larger circle or radius R. If the pen offset of the pen point in
 *  the moving circle is a, then the equation of the resulting curve
 *  at time t is
 *
 *     x = (R+r)*cos(t) - (r+a)*cos(((R+r)/r)*t)
 *     y = (R+r)*sin(t) - (r+a)*sin(((R+r)/r)*t)
 *
 *  Mathematically, these are hypotrochoids.
 *
 *  Reference: http://www.wordsmith.org/~anu/java/spirograph.html
 *
 ******************************************************************************/

import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

public class Spirograph implements ChangeListener {
    private Draw draw = new Draw();
    private JFrame frame = new JFrame();
    private LabeledSlider sliderR = new LabeledSlider(  1, 100, 37);
    private LabeledSlider sliderS = new LabeledSlider(-50,  50,  3);
    private LabeledSlider sliderA = new LabeledSlider(  0, 100, 71);

    // create the frame with an empty image
    public Spirograph() {

        // a panel for the 3 sliders
        draw.setXscale(-4, +4);
        draw.setYscale(-4, +4);
        draw.enableDoubleBuffering();
        JPanel sliders = new JPanel();
        sliders.add(sliderR);
        sliders.add(sliderS);
        sliders.add(sliderA);
        sliderR.addChangeListener(this);
        sliderS.addChangeListener(this);
        sliderA.addChangeListener(this);

        // add components to the frame
        JLabel canvas = draw.getJLabel();
        frame.add(canvas,  BorderLayout.CENTER);
        frame.add(sliders, BorderLayout.NORTH);

        frame.setTitle("Spirograph");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.pack();
        stateChanged(null);   // draw default spirograph
        frame.setVisible(true);
    }

    public void stateChanged(ChangeEvent e) {
        double R = Math.toRadians(sliderR.getValue());
        double r = Math.toRadians(sliderS.getValue());
        double a = Math.toRadians(sliderA.getValue());
        sliderR.setLabel("R = " + sliderR.getValue());
        sliderS.setLabel("r = " + sliderS.getValue());
        sliderA.setLabel("a = " + sliderA.getValue());
        draw.clear(Color.BLACK);
        draw.setPenColor(Color.getHSBColor((float) Math.random(), 1.0f, 1.0f));
        draw.show();

        for (double t = 0.0; t < 80; t += 0.02) {
            if (r == 0) r = 0.01;  // avoid divide-by-zero
            double x = (R+r) * Math.cos(t) - (r+a) * Math.cos(((R+r)/r)*t);
            double y = (R+r) * Math.sin(t) - (r+a) * Math.sin(((R+r)/r)*t);
            draw.point(x, y);
        }
        draw.show();
        frame.repaint();   // repaints sliders and canvas
    }


    // create one frame object
    public static void main(String[] args) {
        new Spirograph();
    }
}


Copyright © 2000–2022, Robert Sedgewick and Kevin Wayne.
Last updated: Sun Dec 11 15:41:59 EST 2022.