cell_analysis_code

code format="java" /** * ORIGINAL CODE: Cellular Automata 2 * by Mike Davis. * * A short program for alife experiments. Click in the window to restart. * Each cell is represented by a pixel on the display as well as an entry in * the array 'cells'. Each cell has a run method, which performs actions * based on the cell's surroundings. Cells run one at a time (to avoid conflicts * like wanting to move to the same space) and in random order. * * Created 9 January 2003 * * NEW CODE: by gshowman and fbitonti * February, 2007 * Adding the following features: * 1. Vector analysis of pixel intensities -- creates Node objects * 2. Providing a UI (through ControlP5 library) to control this analysis * 2. Export of .dxf files through the dxf exporter * * * CONTENTS OF THIS FILE: * - various global declarations * - usual setup and draw functions * - original Cellular Automata code (may have some additions by gs/fb) * - new vector analysis code, including Node class, DXF export * - new UI code, covering mouse and keyboard events * */

// gshowman: Control library import controlP5.*; ControlP5 controlP5; public int sliderValue = 3; ControlWindow controlWindow; Controller AnalyzeButton;

//make DXF import processing.dxf.*; boolean g_exportDXF;

// gshowman: control variables float match_factor = 0.75; float node_scalefactor = 0.3; int g_search_radius = 15; int g_button_pressed = 0; // duplicate of screen state color[] g_pixbuffer; int g_switch = -1; int g_button_count = 4; boolean g_analyze = false; boolean g_resume = false; boolean g_show_nodes = false; boolean g_z_mode = false;

// gshowman: a list of all analytic Nodes we are creating Vector node_list = new Vector;

// original CA stuff: World w; int numcells = 0; int maxcells = 4700; boolean paused = false; Cell[] cells = new Cell[maxcells]; color spore_color; // set lower for smoother animation, higher for faster simulation int runs_per_loop = 10000; color black = color(0, 0, 0);

void setup { size(200, 200,P3D); frameRate(24); clearscr; w = new World; spore_color = color(172, 255, 128); seed; g_button_count = 3; g_analyze = false; g_resume = false; g_exportDXF = false; node_list = new Vector;

// gshowman controlP5 = new ControlP5(this); controlWindow = controlP5.addControlWindow("controlP5window",100,100,400,200); controlWindow.setBackground(color(40)); Controller radiusSlider = controlP5.addSlider("g_search_radius",0,20,40,40,100,10); radiusSlider.setWindow(controlWindow); Controller matchSlider = controlP5.addSlider("match_factor",0.0,1.0,144,40,100,10); matchSlider.setWindow(controlWindow);

AnalyzeButton = controlP5.addButton("Analyze",0,40,100,80,20); AnalyzeButton.setWindow(controlWindow); Controller SaveFrameButton = controlP5.addButton("Clear_Analysis",1,124,100,80,20); SaveFrameButton.setWindow(controlWindow); Controller ExportDXFButton = controlP5.addButton("Export_DXF",2,208,100,80,20); ExportDXFButton.setWindow(controlWindow); Controller ShowNodesButton = controlP5.addButton("Show_Nodes",2,40,124,80,20); ShowNodesButton.setWindow(controlWindow); Controller ZModeButton = controlP5.addButton("Z_Mode",2,124,124,80,20); ZModeButton.setWindow(controlWindow); g_pixbuffer = new color[width*height]; }

void seed { int mynumcells = 0;

// Add cells at random places for (int i = 0; i < maxcells; i++) { int cX = (int)random(width); int cY = (int)random(height); if (w.getpix(cX, cY) == black) { w.setpix(cX, cY, spore_color); cells[mynumcells] = new Cell(cX, cY); mynumcells++; } }

numcells = mynumcells; }

void draw { controlP5.draw; if (g_analyze) { // run the analysis. println ("Running the vector analysis..."); vectorize(spore_color);

paused = true; g_analyze = false; }

if (g_resume) { // we're going to re-start -- let's re-load the state prior // to vectorization println("re-instating conditions prior to analysis"); clearscr; for (int i=0; i < width*height; i++) { w.setpix((i)%width, int ((i)/height), g_pixbuffer[i]); } paused = false; g_resume = false; }

if (paused) { // draw the analysis (just once) draw_connections; } else { // (this is the default state of the system) // Run cells in random order for (int i = 0; i < runs_per_loop; i++) { int selected = min((int)random(numcells), numcells - 1); cells[selected].run; }

}

// note: so when paused == true, nothing happens }

// // CELLULAR AUTOMATA CODE (MOSTLY, IF NOT TOTALLY, ORIGINAL... I.E. 2003) //

void clearscr { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) {

set(x, y, color(0)); } } }

class Cell { int x, y; Cell(int xin, int yin) { x = xin; y = yin; }

// Perform action based on surroundings void run { // Fix cell coordinates while(x < 0) { x+=width; } while(x > width - 1) { x-=width; } while(y < 0) { y+=height; } while(y > height - 1) { y-=height; }

// Cell instructions if (w.getpix(x + 1, y) == black) { move(0, 1); } else if (w.getpix(x, y - 1) != black && w.getpix(x, y + 1) != black) { move((int)random(9) - 4, (int)random(9) - 4); }

//draw geometry based on contextual situation //Frank's Addition /*int iterationCounter = 10;

for(int drawCount = 0; drawCount < iterationCounter; drawCount++){

// draw POLY instructions if (w.getpix(x + 10, y + 10) == spore_color) { if (w.getpix(x + 20, y + 10) == spore_color) { if (w.getpix(x + 30, y + 10) == spore_color) { if (w.getpix(x + 40, y + 10) == spore_color) {

ellipse(x, y, 10, 10); point(30, 20);

} } } } }*/ } //end Frank's addition

// Will move the cell (dx, dy) units if that space is empty void move(int dx, int dy) { if (w.getpix(x + dx, y + dy) == black) { w.setpix(x + dx, y + dy, w.getpix(x, y)); w.setpix(x, y, color(0)); x += dx; y += dy; } } }

// The World class simply provides two functions, get and set, which access the // display in the same way as getPixel and setPixel. The only difference is that // the World class's get and set do screen wraparound ("toroidal coordinates"). class World { void setpix(int x, int y, int c) { while(x < 0) x+=width; while(x > width - 1) x-=width; while(y < 0) y+=height; while(y > height - 1) y-=height; set(x, y, c); }

color getpix(int x, int y) { while(x < 0) x+=width; while(x > width - 1) x-=width; while(y < 0) y+=height; while(y > height - 1) y-=height; return get(x, y); } }

// // ANALYSIS CODE (new stuff by gshowman and fbitonti) //

//NODE class Node { int x, y, z, radius;

Node (int xin, int yin, int rad) { x = xin; y = yin; radius = rad; z = rad; // yes... the 'rad' is really an abstractd 'intensity', which can // be interpreted as a z-coordinate }

void draw_radius { stroke(255,50,0,150); noFill; ellipse(x, y, radius*node_scalefactor, radius*node_scalefactor); } }

class NodeComparer implements Comparator { public int compare(Object n1, Object n2) { return ((Node) n1).radius - ((Node) n2).radius; } }

int find_matches_within(int xx, int yy, int radius, color c) { int matches = 0; int x = 0; int y = 0;

int xlim = min(width, xx+radius); int ylim = min(height, yy+radius);

for (x = max(0,xx-radius); x < xlim; x++) { for (y = max(0,yy-radius); y < ylim; y++) { if (get(x,y) == c) { matches++; } } }

return matches; }

//nodes are created void create_node(int x, int y, int intensity) { Node A = new Node(x,y,intensity); node_list.add(A); }

void vectorize(color c) { int x = 0; int y = 0;

// 1. take a copy of the current state. for (int i = 0; i < width*height; i++) { g_pixbuffer[i] = w.getpix(i%width, int (i/height)); }

int radius = g_search_radius; int match_limit = int(match_factor * (PI) * radius*radius);

for (x=0; x < width; x++) { for (y=0; y < height; y++) {

if (get(x,y) == c) { int matches = 0; //match -- check your neighbors matches += find_matches_within(x, y, radius, c); if (matches >= match_limit) { create_node(x, y, matches); println ("Created Node at " + x + ", " + y + " with intensity " + matches); } }

} } }

void draw_connections { //DXF export... begin recording geometry if (g_exportDXF) { beginRaw("processing.dxf.RawDXF", "C:\\output.dxf"); }

int nodeListSize = node_list.size ; int[] connectionArray = new int[nodeListSize]; int[] connectionArrayX = new int[nodeListSize]; int[] connectionArrayY = new int[nodeListSize]; int connectCount = 0;

// gshowman: sort the vector by intensity Collections.sort(node_list, new NodeComparer);

// Connect all nodes in descending order of intensity/radius stroke(255,50,0,150);

int last_x = 0; int last_y = 0; int last_z = 0;

if (!node_list.isEmpty) { Iterator it = node_list.iterator ; Node N = (Node) it.next; last_x = N.x; last_y = N.y; last_z = N.z;

if (g_show_nodes) { N.draw_radius; }

while (it.hasNext) { Node nextNode = (Node) it.next ; if (g_z_mode) { // use intensity as z-coordinate line(last_x, last_y, last_z, nextNode.x, nextNode.y, nextNode.z); } else { line(last_x, last_y, nextNode.x, nextNode.y); }

last_x = nextNode.x; last_y = nextNode.y; last_z = nextNode.z;

if (g_show_nodes) { nextNode.draw_radius; } } }

//dxf End recording if (g_exportDXF) { endRaw; g_exportDXF = false; } }

// // UI CODE //

void mousePressed { setup; }

void Analyze(int theIrrelevantValue) { println("Analyze button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

if (paused) { // raise the flag to end the analysis (see draw function) g_resume = true; AnalyzeButton.setLabel("Analyze"); } else { // raise the flag for the analysis (see the draw function) g_analyze = true; AnalyzeButton.setLabel("Resume"); } }

void Clear_Analysis(int theIrrelevantValue) { println("Clear_Analysis button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

// just empty the node_list node_list.clear; }

void Export_DXF(int theIrrelevantValue) { println("Export_DXF button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

g_exportDXF = true; }

void Show_Nodes(int theIrrelevantValue) { println("Show_Nodes button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

if (g_show_nodes) { g_show_nodes = false; println("Turning nodes off"); } else { g_show_nodes = true; println("Turning nodes on"); } }

void Z_Mode(int theIrrelevantValue) { println("Z_Mode button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

if (g_z_mode) { g_z_mode = false; println("Turning Z_Mode off"); } else { g_z_mode = true; println("Turning Z_Mode on"); } }

code