> show canvas only <


/* built with Studio Sketchpad: 
 *   http://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   http://studio.sketchpad.cc/sp/pad/view/ro.ANCb0XN5Hn$/rev.3225
 * 
 * authors: 
 *   
 *   Rui Gil

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   http://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// mouse to create oscillators
// space to clear canvas
// '1', '2' or '3' for presets 

float grid[][];
int page = 0;
float waveSpeed = 0.5;
int gridSize = 256;
ArrayList oscilators = new ArrayList();

public void setup() {
  size(512, 512, P2D);
  colorMode(HSB);
  grid = new float[2][gridSize*gridSize];
  loadPixels();
}

// http://www.mtnmath.com/whatrh/node66.html
void draw() {
    int yoffset = gridSize;
    for(int n=0; n<oscilators.size(); n++) {
        oscilators.get(n).tick();
    }
    for(int i=1; i<gridSize-2; i++) {
        for(int j=1; j<gridSize-2; j++) {
            float current = grid[page][yoffset+j];
            float previous = grid[page^1][yoffset+j];
            float dx =  grid[page][yoffset-gridSize+j] + grid[page][yoffset+gridSize+j];
            float dy =  grid[page][yoffset+j-1] + grid[page][yoffset+j+1];
            float value = 2*current - previous + waveSpeed*(dx+dy-4*current);
            grid[page^1][yoffset+j] = value;
            int hue = min(max(40 + value*40,0),255);
            paintPixel(i,j,color(hue,255,255));
        }
        yoffset += gridSize;
    }
    page ^= 1;
    updatePixels();
}

void paintPixel(int i, int j, int color) {
    i<<=1; j<<=1;
    int offset = i*width;
    pixels[offset+j] = color;
    pixels[offset+j+1] = color;
    pixels[offset+width+j] = color;
    pixels[offset+width+j+1] = color;
}

class Oscilator {
    int ox, oy; 
    float phase = 0;
    float step;

    Oscilator(int cx, int cy, float s) {
        ox = cx; oy = cy; step = s;
    }
    
    void tick() {
        grid[page][oy*gridSize+ox] = sin(phase);
        grid[page^1][oy*gridSize+ox] = 0;
        phase += step;
    }
}

void mousePressed() {
    oscilators.add(new Oscilator(int(mouseX/2),int(mouseY/2), PI/pow(2,random(3,6))));
}

void keyPressed() {
    if (key == ' ') {
        oscilators.clear();
        grid = new float[2][gridSize*gridSize];
    }
    if (key == '1') {
        oscilators.add(new Oscilator(127,127, PI/64));
    }
    if (key == '2') {
        oscilators.add(new Oscilator(31,31, PI/32));
        oscilators.add(new Oscilator(223,31, PI/32));
        oscilators.add(new Oscilator(31,223, PI/32));
        oscilators.add(new Oscilator(223,223, PI/32));
    }
    if (key == '3') {
        oscilators.add(new Oscilator(31,127, PI/16));
        oscilators.add(new Oscilator(223,127, PI/16));
    }
}