// Global variables float[] mar, barh, barghost, xlim, ylim; int numbars; float maxval; // Setup the Processing Canvas void setup(){ size(1280, 720); numbars = 10; maxval = 100; // Set xlim and ylim xlim = new float[2]; xlim[0] = 0.5; xlim[1] = numbars + 0.5; ylim = new float[2]; ylim[0] = 0; ylim[1] = maxval; // Have rectangles draw like in R // (specifying two corner co-ords) rectMode(CORNERS); // Make text larger textSize(18); // Specify margins // To keep indices in line with R // will use 4 -> 0, and rest as in R. mar = new float[4]; mar[1] = height * 0.10; mar[2] = width * 0.05; mar[3] = height * 0.05; mar[0] = width * 0.05; // Starting bar heights barh = new float[numbars]; for(int i = 0; i < numbars; i = i + 1) barh[i] = random(maxval); // Init ghost bar // barghost[0] = x pos (0, 1, ..., numbars - 1) // barghost[1] = height barghost = new float[2]; for(int i = 0; i < 2; i = i + 1) barghost[i] = ylim[0]; } // Main draw loop void draw(){ // Clear image background(#FBFBFB); // Draw graph area drawgr(); // Draw x axis drawxax(); // Draw y axis drawyax(); // Draw title drawtitle(); // noLoop(); } float garx(float x){ // Take a co-ordinate on the x scale // for the graph area, and convert to // actual co-ordinates. return((width - mar[2] - mar[0]) * (x - xlim[0])/(xlim[1] - xlim[0]) + mar[2]); } float gary(float y){ // Take a co-ordinate on the y scale // for the graph area, and convert to // actual co-ordinates. return(height - mar[1] - (height - mar[1] - mar[3]) * (y - ylim[0])/(ylim[1] - ylim[0])); } void drawgr(){ // draw white rect // to setup graph area fill(#F0F0F0); rect(garx(xlim[0]), gary(ylim[0]), garx(xlim[1]), gary(ylim[1])); // draw bars fill(#555555); for(int i = 0; i < numbars; i = i + 1) rect(garx(0.65 + i), gary(0), garx(1.35 + i), gary(barh[i])); // draw ghost bar // if height is non-zero if(barghost[1] > ylim[0]){ fill(#BB5555); rect(garx(0.75 + barghost[0]), gary(0), garx(1.25 + barghost[0]), gary(barghost[1])); } } void drawxax(){ // draw x axis // Change colour to black fill(#000000); // Set alignment to centre textAlign(CENTER, CENTER); for(int i = 0; i < numbars; i = i + 1) text(i, garx(1 + i), height - mar[1]/2); } void drawyax(){ // draw y axis // Change colour to black fill(#000000); // Set alignment to right-align textAlign(RIGHT, CENTER); for(int i = 0; i <= maxval; i = i + maxval/10) text(i, mar[2] * 0.9, gary(i)); } void drawtitle(){ // draw title // Change colour to black fill(#000000); // Set alignment to left textAlign(LEFT, CENTER); text("Max y value: " + maxval, garx(xlim[0]), mar[3]/2); // Set alignment to right textAlign(RIGHT, CENTER); text("Number of bars: " + numbars, garx(xlim[1]), mar[3]/2); } float invgarx(float x){ // Inverse garx // Take actual co-ords and convert // to x scale on graph area return((xlim[1] - xlim[0]) * (x - mar[2]) / (width - mar[2] - mar[0]) + xlim[0]); } float invgary(float y){ // Inverse gary // Take actual co-ords and convert // to y scale on graph area return((ylim[1] - ylim[0]) * (1 - (y - mar[3]) / (height - mar[1] - mar[3])) + ylim[0]); } // Set ghost bar details on mouse move void mouseMoved(){ barghost[0] = floor(invgarx(mouseX) - 0.5); barghost[1] = invgary(mouseY); if(barghost[0] < 0 | barghost[0] >= numbars | barghost[1] < ylim[0] | barghost[1] > ylim[1]) barghost[1] = ylim[0]; } // Save ghost bar details on mouse press void mousePressed(){ if(barghost[1] > ylim[0]) barh[barghost[0]] = barghost[1]; } void mouseDragged(){ mouseMoved() mousePressed() }