/** * * Draw a picture of rounder-router * I was going to rotate 45 degrees but instead I did bricks. * * Steve Witham ess double you at tiac remove_this dot net * April 15, 2008 * Version 2 December 26, 2008 -- * Multiple machine descriptions, click "flag" to change machines. */ import java.lang.Math; int nrows_max = 600; int cellhigh; int nrows; int cellhspacing; int linewide; int cellwide; color[] cellcolors = { color(0,255,255), color(255,0,255), color(255,255,0), color(0,0,255), color(0,255,0), color(255,0,0) }; // Background, counter position, and number-of-states "flag" position: PImage counter_bgd; PFont font; int counterx = 40; int countery = 0; int counterw = 100; int counterh = 21; int flagx = 300 - 5; // Right side of flag int flagy = 2; // top int flagw; // width changes int flagh = 19; int drawing = 1; // SET UP THE RULES HERE int N_MACHINES = 2; // Two different machines described here... int [] MACHINES_N_STATES = { 3, 2 }; // One has 3 states, the other 2. // cellcolors[] and go_right_afters[ i ][] must have at least // MACHINES_N_STATES[ i ] entries. // go_right_after[ i ] means go right as you transition from i to i+1, // so the index is a state, not a number of iterations. boolean [][] go_right_afters = { { true, false, true }, // movement rules for 3-state machine { true, false } // movement rules for 2-state machine }; int MACHINE = 0; boolean [] go_right_after; int N_STATES; // index of these cumulative arrays is a # of iterations, not a state: int [] cumulative_right_after; int [] cumulative_left_after; int total_right, total_left; double zoomdelay = 1.5; int [] [] cells = new int [nrows_max][nrows_max]; void setup() { cellhigh = 15; nrows = nrows_max / cellhigh; cellhspacing = cellhigh; linewide = 1; cellwide = 2 * cellhspacing; go_right_after = go_right_afters[ MACHINE ]; N_STATES = MACHINES_N_STATES[ MACHINE ]; cumulative_right_after = new int [ N_STATES + 1 ]; cumulative_left_after = new int [ N_STATES + 1 ]; cumulative_right_after[ 0 ] = 0; cumulative_left_after[ 0 ] = 0; for( int i = 1; i <= N_STATES; i++ ) { cumulative_right_after[ i ] = cumulative_right_after[ i - 1 ] + ( go_right_after[ i - 1 ]? 1 : 0 ); cumulative_left_after[ i ] = N_STATES - cumulative_right_after[ i ]; } total_right = cumulative_right_after[ N_STATES ]; total_left = cumulative_left_after[ N_STATES ]; size( (nrows+1) * cellhspacing / 2, nrows*cellhigh ); font = loadFont( "AmericanTypewriter-18.vlw" ); colorMode(RGB, 255); // fill_cells( 5494 ); init_cells( 0 ); cells[1][1] = -11; // Start countdown--see draw(). } void mousePressed() { if( pmouseX > flagx - flagw && pmouseX < flagx && pmouseY > flagy && pmouseY < flagy + flagh ) { MACHINE = ( MACHINE + 1 ) % N_MACHINES; loop(); drawing = 1; setup(); } else { if( drawing == 1 ) { noLoop(); drawing = 0; } else { loop(); drawing = 1; } } } void show_counter() { textFont( font, 18 ); noStroke(); image( counter_bgd, counterx, countery, counterw, counterh ); fill( 255, 255, 255 ); text( "" + cells[1][1], counterx + 3, countery + counterh - 5 ); // "Flag" showing the number of states, heh: int border = 2; int sq = flagh - 2 * border; flagw = N_STATES * (sq + border) + border; fill( 0, 0, 0 ); rect( flagx - flagw, flagy, flagw, flagh ); for( int i = 0; i < N_STATES; i++ ) { fill( cellcolors[ i ] ); int sqx = flagx - flagw + i * ( sq + border ) + border; int sqy = flagy + border; int swx = go_right_after[ i ]? sq - 1 : 0; rect( sqx, sqy, sq, sq ); fill( 0, 0, 0 ); quad( sqx + sq/2, sqy + sq/2, sqx + sq/2 + 1, sqy + sq/2, sqx + swx + 1, sqy + sq, sqx + swx, sqy + sq ); } } void init_sizes( ) { nrows = nrows_max / cellhigh; cellhspacing = cellhigh; linewide = ( cellhspacing + 2 ) / 4; cellwide = 2 * cellhspacing; counterx = (int) ( counterh * 1.5 ) + cellwide; frameRate( 15.0 / cellhigh ); } // This sets the array to the state after n particles have been added. void init_cells( int n ) { init_sizes( ); cells[1][1] = n; for( int t = 2; t < nrows_max - 1; t++ ) { // Odd and even rows alternate indentation: for( int i = 2 - t % 2; i <= t; i += 2 ) { // These cells record total # of particles that have gone through them, // not just the current state, which is (# of particles) % N_STATES. // Contribution from block above left: cells[t][i] = ( cells[t-1][i-1] / N_STATES ) * total_right + cumulative_left_after[ cells[t-1][i-1] % N_STATES ] // Contribution from blocks above right: + ( cells[t-1][i+1] / N_STATES ) * total_left + cumulative_right_after[ cells[t-1][i+1] % N_STATES ]; } } } void incr_cells( ) { int x, y, x2, y2; int i = 1; noStroke(); for( int t = 1; i > 0 && t < nrows_max - 1; t++ ) { cells[t][i]++; if( t < nrows - 1 ) { fill( cellcolors[ cells[t][i] % N_STATES ] ); rect( i * cellhspacing, t * cellhigh, cellwide, cellhigh ); if( linewide > 0 ) { x = i * cellhspacing + cellhspacing - linewide/2; y = t * cellhigh; // Line shows where the *next* particle will go: if( go_right_after[ cells[t][i] % N_STATES ] ) { x2 = x + cellhspacing; } else { x2 = x - cellhspacing; } fill( 0 ); y2 = y + cellhigh; quad( x,y, x+linewide,y, x2+linewide,y2, x2,y2 ); } } // Where *this* particle *does* go: if( go_right_after[ ( cells[t][i] - 1 ) % N_STATES ] ) i++; else i--; } show_counter(); } // draw() is called by the Processing runtime once for every // animation frame... void draw() { if( cells[1][1] < 0 ) { if( cells[1][1] < -10 ) { cells[1][1] = 0; render(); cells[1][1] = -10; show_counter(); delay( 1000 ); } else { cells[1][1]++; show_counter(); } } else { incr_cells(); if( cells[1][1] > nrows * zoomdelay && cellhigh > 1 ) { cellhigh--; init_sizes( ); render(); } } } void render() { int x, y, x2, y2; PImage clouds; noStroke(); fill( 96, 64, 64 ); rect( 0, 0, width, height ); clouds = loadImage( "Clouds_320.jpg" ); image( clouds, 0, 0, width, width ); counterw = width - counterx; counter_bgd = get( counterx, countery, counterw, counterh ); noFill(); for( int t = 1; t < nrows - 1; t++ ) { // Odd and even rows alternate indentation: for( int i = 2 - t % 2; i <= t; i += 2 ) { noStroke(); fill( cellcolors[ cells[t][i] % N_STATES ] ); rect( i * cellhspacing, t * cellhigh, cellwide, cellhigh ); } if( linewide > 0 ) { fill( 0 ); // Odd and even rows alternate indentation: for( int i = 2 - t % 2; i <= t; i += 2 ) { x = i * cellhspacing + cellhspacing - linewide/2; y = t * cellhigh; // Line shows where the next particle will go: if( go_right_after[ cells[t][i] % N_STATES ] ) { x2 = x + cellhspacing; } else { x2 = x - cellhspacing; } y2 = y + cellhigh; quad( x,y, x+linewide,y, x2+linewide,y2, x2,y2 ); } } } show_counter(); }