// The Nature of Code // Daniel Shiffman // http://natureofcode.com // Flow Field Following class FlowField { // A flow field is a two dimensional array of PVectors PVector[][] field; int cols, rows; // Columns and Rows int resolution; // How large is each "cell" of the flow field FlowField(int r) { resolution = r; // Determine the number of columns and rows based on sketch's width and height cols = width/resolution; rows = height/resolution; field = new PVector[cols][rows]; init(); } void init() { // Reseed noise so we get a new flow field every time for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { int x = i*resolution; int y = j*resolution; int c = img.pixels[x + y * img.width]; // Map brightness to an angle float theta = 0;//map(brightness(c),0,255,0,PI/2); // Polar to cartesian coordinate transformation to get x and y components of the vector field[i][j] = PVector.fromAngle(theta); // Map magnitude to an angle (how fast is the desired velocity in the flow field) float m = map(brightness(c),0,255,0,1); field[i][j].mult(m); } } } // Draw every vector void display() { for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { drawVector(field[i][j],i*resolution,j*resolution,resolution-2); } } } // Renders a vector object 'v' as an arrow and a location 'x,y' void drawVector(PVector v, float x, float y, float scayl) { pushMatrix(); float arrowsize = 4; // Translate to location to render vector translate(x,y); strokeWeight(2); stroke(255,0,0); // Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate rotate(v.heading2D()); // Calculate length of vector & scale it to be bigger or smaller if necessary float len = v.mag()*scayl; // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) line(0,0,len,0); //line(len,0,len-arrowsize,+arrowsize/2); //line(len,0,len-arrowsize,-arrowsize/2); popMatrix(); } PVector lookup(PVector lookup) { int column = int(constrain(lookup.x/resolution,0,cols-1)); int row = int(constrain(lookup.y/resolution,0,rows-1)); return field[column][row].get(); } }