/****
 *
 * StringArt 
 *
 * draws figures like those you get by wrapping colored string around nails
 * set in a cirle.
 *
 ****/

import java.awt.*;
import jpb.*;

class StringArt {


    // The various dimensions and what-not.
    private final static int WINDOW_SIZE	= 400;
    private final static String WINDOW_TITLE	= "String Art";

    // This should be prime.
    private final static int NPOINTS		= 31;

    // Arrays of (x,y) coordinates.
    private static double[] x			= new double[NPOINTS+1];
    private static double[] y			= new double[NPOINTS+1];

    private final static double X_MAX		= 1.1;
    private final static double X_MIN		= -1.1;
    private final static double Y_MAX		= 1.1;
    private final static double Y_MIN		= -1.1;

    // These two variables are used by all the various subroutines.
    // Make sure they're initialized (in main()) before doing anything else.
    private static DrawableFrame df;
    private static Graphics g;


    // Convert from (x,y) coordinates to pixels in the horizontal direction.
    private static int xToPix(double x){
	return (int)( ( x - X_MIN ) / ( X_MAX - X_MIN ) * WINDOW_SIZE);
    }

    // Convert from (x,y) coordinates to pixels in the vertical direction.
    private static int yToPix(double y){
	return (int)( ( Y_MAX - y ) / ( Y_MAX - Y_MIN ) * WINDOW_SIZE);
    }

    private static void myLine(double x1, double y1, double x2, double y2){
	g.drawLine( xToPix(x1), yToPix(y1), xToPix(x2), yToPix(y2) );
    }

    // Evenly spaced points around a circle.
    private static void initArrays(){
	for (int i=0; i<NPOINTS; i++){
	    double theta = (2.0*Math.PI*i)/NPOINTS;
	    x[i] = Math.cos(theta);
	    y[i] = Math.sin(theta);
	}
	x[NPOINTS] = x[0];
	y[NPOINTS] = y[0];
    }

    private static void layer(int skip, int R, int G, int B){
	g.setColor( new Color(R,G,B) );
	for (int i=0; i<NPOINTS; i++){
	    int j1 = (i*skip) % NPOINTS;
	    int j2 = ((i+1)*skip) % NPOINTS;
	    myLine( x[j1], y[j1], x[j2], y[j2] );
	}
	df.repaint();
    }

    public static void main(String[] args){

	// Create window "df", set its size, and make it white.
	df = new DrawableFrame(WINDOW_TITLE);
	df.show();
	df.setSize(WINDOW_SIZE, WINDOW_SIZE);

	// Create the graphics object "g".
	// Set it up so that odd number of passes through any given pixel
	// will be white, even number will be the given color.
	g = df.getGraphicsContext();


	// Play with background and XOR color.
	// (I'm not entirely sure I understand exactly what this XOR color does.)
	g.setColor(Color.white);
	g.fillRect(0,0,WINDOW_SIZE,WINDOW_SIZE);
	//g.setXORMode(Color.white);

	// Variations:
	// (1) vary setColor and XORMode between white and black.
	// (2) Put the fillRect() before or after the setXORMode
	// (3) Up the number of points to 401, and do one layer with skip=198,
	//     with XOR.  See the pretty moire as it plays with screen resolution...

	// Set the values for the (x,y) points around a circle.
	initArrays();

	// with NPOINTS=31 :
	layer(14,  220, 220, 0 );	// yellow center
	layer(12,  0, 180, 0 );		// greenish outward
	layer(10,  0, 0, 250 );		// three outer blue layers
	layer(9,   0, 0, 200 );
	layer(8,   0, 0, 150 );

    }


}


syntax highlighted by Code2HTML, v. 0.9.1