Here's a little applet that creates Fresnel ring moiré patterns. Overlapping Fresnel rings create moiré patterns that are either straight lines or "ghost" Fresnel rings. The animation moves the two Fresnel rings together and apart at a constant rate, but the moiré patterns accelerate and decelerate. It's hypnotic (at least to me).
I embedded it as a Processing applet into a WordPress blog, worth a post in itself, but since I can't yet post links to this forum, you'll have to make do with my code.
Code:
/**
* fresnel rings moire
* created by Paul Hertz, 2010, free for any use
* move mouse to change spacing between two sets of fresnel rings
* type 'm' to control with mouse
* type 'a' to animate
* type 'p' to save to PDF
*/
import processing.pdf.*;
/** number of rings */
int rings = 64;
/** array of ring diameters */
float[] diameters = new float[rings];
/** initial distance of two sets of rings from center of window */
float space = 20;
float oldSpace = space;
/** variable for width of each ring */
float ringwidth = 0;
/** colors for alternating rings */
color c1 = color(233, 55, 21, 192);
color c2 = color(21, 123, 233, 96);
boolean trackMouse = false;
boolean increasing = true;
float increment = 1.5;
/**
* Do standard setup call.
* Calculate diameters of N Fresnel rings at distances proportional to square root of k where 0 < k <= N.
*/
void setup() {
size(400, 400);
background(255);
smooth();
double max_radius = Math.sqrt(height * height + width * width);
float max_diameter = (float) (max_radius / Math.sqrt(rings));
// println(max_radius + " " + max_diameter);
for (int i = 0; i < rings; i++) {
diameters[i] = (float) Math.sqrt(i + 1) * max_diameter;
}
}
void draw() {
if (trackMouse) {
oldSpace = space;
space = width/2 - mouseX;
}
else {
animate();
}
background(255);
fresnel();
if (keyPressed) {
if (key == 'a' || key == 'A') {
// start the animation only if we're not animating already
if (trackMouse) {
trackMouse = false;
space = 0;
}
}
if (key == 'm' || key == 'M') {
trackMouse = true;
}
if (key == 'p' || key == 'P') {
beginRecord(PDF, "Fresnel.pdf");
background(255);
smooth();
fresnel();
endRecord();
}
}
}
void animate() {
oldSpace = space;
if (increasing) {
space += increment;
}
else {
space -= increment;
}
if (space > width/2.0 || space < 0) {
increasing = !increasing;
space = oldSpace;
}
}
/**
* Draw two copies of the rings offset from center of window by distance "space."
*/
void fresnel() {
for (int j = rings - 1; j >= 0; j--) {
if (j != 0) {
ringwidth = abs(diameters[j] - diameters[j - 1])/2.0;
// println("ringwidth " + j + ": " + ringwidth);
}
if (j == 0 ) {
// println("j == 0");
noStroke();
fill(c1);
}
else if (j % 2 == 1) {
// println("j % 2 == 1");
stroke(c2);
strokeWeight(ringwidth);
// fill(255, 127);
noFill();
}
else {
// println("j % 2 == 0");
stroke(c1);
strokeWeight(ringwidth);
// fill(0, 255);
noFill();
}
ellipse(width/2.0 - space, height/2.0, diameters[j], diameters[j]);
ellipse(width/2.0 + space, height/2.0, diameters[j], diameters[j]);
}
}
cheers,
-- Ignotus