/* // Chunk 54 - Sine in Action // Plots a sine function by colouring surrounding pixels // in relation to their proximity to the sine wave */
float theta0 ; //Start angle float dTheta0; // Increment start angle 'angular velocity' float dTheta; // Value for incrementing theta, a function of period
float amplitude; // maximum height of wave float amplitude0; //intial undamped amplitude float damping; //decrase in height over period of wave float frequency; //repetitions of wave within 2Pi radians
int count = 1;//use to reverse gradient int range; //range for vertical movement of function int colorChoice; //colour type to plot int adjustmentChoice; // choice of funtion to adjust postion of sine wave
PImage img; void setup() { size(500, 500); frameRate(20); img = createImage(250,250,RGB);
noSmooth(); setOptions(); }
void draw() { background(255); amplitude = amplitude0; theta0 += dTheta0; //increment initial angle
if ( frameCount % range == 0){ count = -count; }
//set colours of image float theta = theta0; //set initial angle for calculating sin wave int intColor; // value of colour to plot at x,y color c; //colour of plotted point x,y based on intColor float adjSinWave; // y value to plot colour around
//plot sin function by colouring surrounding points for (int x = 0; x < img.width; x++) { adjSinWave = adjustment(x, adjustmentChoice) + plotSinWave(theta);
for ( int y= 0; y < img.height; y++){ intColor = getColorValue(adjSinWave, y); c= getColor(intColor,colorChoice); img.set(x,y,c); } theta += dTheta; }
// display the results image(img,0,0,width,height); }
void setOptions(){ float period = 450.0; // How many pixels before the wave repeats //values for plotting sine wave theta0 = 0; dTheta0 = 0.01; dTheta = TWO_PI / period; //change in angle plotted between x and x+1 amplitude0 = img.height/2; //amplitude looks best close to height/2 damping = 0.987; //keep close to 1, or sine function becomes quickly flat frequency = 6; range = img.height; colorChoice = 2; // 1- grayscale, 2 - colour shift, adjustmentChoice = 3; //1 - constant, 2 - linear, 3 - sin & linear }
float plotSinWave(float angle){ //main sine wave to plot everything else round // float result = 0; //for testing colour distibution float result = amplitude * sin (frequency * angle); amplitude = amplitude * damping; return result; }
float adjustment(float xPos, int choice){ //adjustment to position of sine wave float result = 0;
if (choice == 1){ //constant
result = img.height/2;
} else if (choice ==2) { //simple linear function
int intersect = 0; float gradient ; float gradientChange =0;
if (count > 0 ){ //count switches from positive to negative when framecount % range is reached //increase intersect up to range gradientChange = frameCount % (range); } else {//decrease intersect from range to zero gradientChange = range - frameCount % (range); }
gradient = (img.height - gradientChange) / img.width; result = intersect + gradient * xPos ;
} else if (choice == 3){//combination of sin and linear functions
float amp1 = 0.25; int freq1 = 1; int period1 = img.width; float amp2 = 5; int freq2= 2; int period2 = img.width/3; int intersect = 0; float gradient;
gradient = amp1 * sin(freq1 * (xPos * TWO_PI/period1)); if (count > 0 ){ //count switches from positive to negative when framecount % range is reached //increase intersect up to range intersect = frameCount % (range); } else {//decrease intersect from range to zero intersect = range - frameCount % (range); }
//linear function with variable intersect and gradient float result1 = intersect + gradient * xPos; float result2 = amp2 * sin(freq2 * (xPos * TWO_PI/period2));
result = result1 + result2;
} return result;
}
int getColorValue(float maxValue, float value){ //colors plotted around sine wave // returns int value between 0 & 255 based on distance from maxValue
float h = img.height; float temp = 0; int result; float minValue; float rangeColor;
// if maxValue > h/2 then minValue is 0 else minValue 2 * maxValue - h minValue = min(0, 2* maxValue - h); //color increasing to maxValue if ( value <= maxValue){ temp = value - minValue ; } else { //color decreasing from maxValue temp = 2 * maxValue - (value + minValue ); }
rangeColor = max(maxValue, h - maxValue); //range over which colour varies between 0 and 255 temp = scaleValue(temp, 0, rangeColor); //scale value to be between 0 and 255 result = round(temp); //convert scaled value to int
return result; }
float scaleValue(float z, float minVal, float maxVal){
//adjust values to ensure minimum equals 0 float adjZ = z - minVal; //Scale values to ensure new max equals 255 float adjMaxZ = maxVal - minVal; float scaledZ = adjZ * (255/adjMaxZ);
return scaledZ; }
color getColor(int colorVal, int choice){
int tempColor; int redVal = 0; int greenVal =0; int blueVal =0;
if (choice == 1){ //grayscale
redVal = greenVal = blueVal = colorVal;
} else if (choice == 2 ){// Smooth transition of color from blue to green to yellow to red //subdivide colour selection based on range of values
if ( colorVal >= 0 && colorVal <= 63){ tempColor = 4 * colorVal; redVal = 0; greenVal = tempColor; blueVal = 255; } else if ( colorVal > 63 && colorVal <= 127){ tempColor = 4 * (colorVal - 64); redVal = 0; greenVal = 255; blueVal = 255 - tempColor; } else if ( colorVal > 127 && colorVal <= 191){ tempColor = 4 * (colorVal - 128); redVal = tempColor; greenVal = 255; blueVal = 0; } else if ( colorVal > 191 && colorVal <= 255){ tempColor = 4 * (colorVal - 192); redVal = 255; greenVal = 255 - tempColor; blueVal = 0; } }
return color(redVal,greenVal,blueVal);
} |