/****
*
* 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;
y[NPOINTS] = y;
}

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