Skip to main content Skip to navigation

Lab 1 - The basics

In these labs, we will be using the Processing development environment. Processing is built on top of the Java programming language, so it will use many of the concepts you are familiar with and uses the same syntax. It is an open source environment for people who want to program images, animation and sound.

The first lab will introduce some of the basic building blocks. Over the term you will be combining these building blocks in order to represent and understand data and systems.

https://processing.org/ has a number of tutorials and a very useful reference. You can also download the software.

There are also a number of very useful books in the library, for example:

Maintaining sketchbook

The assessment of this module is 100% coursework. It will require you to produce sketches but also write a justification of the choices you have made when coding your sketch. You should get in the practice of maintaining a sketchbook - this can be a handwritten notebook, word document, PDF file, HTML webpage, or a blog. Write about what you do, and why. Where you can, justify the decisions you make with material from the lectures and your independent study. Include paper versions of what you envision your design will be, screen shots of the visualisation as it progresses, descriptive notes, and where you can, references. This is not assessed but it is good practice.

Getting started with Processing

Open Processing by typing "processing" (case sensitive) in the search bar and clicking "Run Processing".

Pieces of software written in Processing are called sketches. Sketches are written in the text editor. There is also a message area which gives you feedback while saving and exporting and also displays errors. The console displays text output by Processing programs.

Each Processing sketch has it's own folder. The main program file for each sketch has the same name as the folder and is found inside. For example if the sketch is called my_sketch, the folder will be called my_sketch and the main file will be called my_sketch.pde.

A sketch folder sometimes contains other folders. Files containing images, sounds or other data can be added to a sketch by selecting "Sketch > Add File" from the menu or by dragging the file into the text editor. When a file is added to a sketch, a data folder is created.

We are going to be creating visuals on the screen. Essentially we are treating the screen like a piece of graph paper. Each pixel is at a coordinate (x (horizontal), y (vertical)).


Simple sketches

Processing is designed so that you can start creating sketches with minimal coding. For example:

size(600, 600); //sets the size of the display window
line(100,200,350,500); //draws a line from x1(100), y1(200), to x2(350), y2(500)

This code will draw a line starting at coordinate (100, 200) and ending at coordinate (350, 500). The coordinate system for pixels in a computer window is reversed along the y axis. (0,0) is in the top left.

screen coordinates

This is Processing in static mode - but we might want our sketches to change over time (dynamic mode) so lets introduce a template with the following functions - template.pde:

  • setup() - we do this when the program first starts
  • draw() – we do this continuously. One image frame is drawn to the display window at the end of each loop through draw(). The draw() function is displayed at a preset frequency of sixty images per second but this can be reset using frameRate();
  • size() -specifies the size of the display window you want to create. size() takes two arguments - width and height. The size() function should always be the first line of code in setup()
void setup(){
size(500, 500);
}

void draw(){

}

Graphical Elements in Processing

The simple.pde code file contains examples for drawing points, lines, triangles, rectangles, and ellipses. The comments inside the file explain the format of the individual commands; however, here is a short summary of some of the instructions:

  • point(x, y) - draws a point at coordinate x, y
  • line(x1, y1, x2, y2) - draws a line from x1, y1 to x2, y2
  • rect(x, y, w, h) - draws a rectangle at x, y (coordinate for the top left corner of the rectangle) with width w and height h
  • ellipse(x, y, w, h) - draws an ellipse at x, y (coordinate for the center of the ellipse) with width w and height h
  • triangle(x1, y1, x2, y2, x3, y3)

EX1: Play around with simple.pde to familiarise yourself with the different graphical elements


Stroke and Colour in Processing

In Processing every shape has a stroke() or a fill() or both. The stroke() is the colour of the shape's outline and fill() is the colour of the interior. If you forget to specify a colour Processing will use black (0) for the stroke() and white (255) for the fill(). By adding stroke() and fill() functions before the shape is drawn you can set the colour. stroke() or fill() can be eliminated with noStroke() or noFill()

There is also a background() function which sets the background colour for the display window.

Digital colours are constucted by mixing R (red), G (green), and B (blue). The amount of each colour is expressed as a range 0 (none of that colour) - 255 (as much as possible). Processing has a colour selector to aid in choosing colours. Access this via "Tools > Color Selector" (from the menu bar).

In addition to the red, green, and blue components of each colour, there is an optional fourth component, referred to as the colour's "alpha" (a) - alpha refers to the colour's opacity and is useful when you want things to appear partially see-through. Opacity is also expressed in the range 0 (completely transparent) - 255 (completely opaque).

  • background(r, g, b)
  • stroke(r, g, b, a)
  • fill(r, g, b, a)
  • strokeWeight(weight)
  • noStroke()
  • noFill()

When you draw a shape, Processing will use the most recently specified stroke() and fill(), reading the code from top to bottom.

You can also specify colours in colorMode(HSB)which takes three arguments (hue, saturation, brightness).

  • Hue—The colour type, ranges from 0 to 255 by default.
  • Saturation—The vibrancy of the colour, 0 to 255 by default.
  • Brightness—The, well, brightness of the colour, 0 to 255 by default

The colour selector also gives you the H, S, B values for a chosen colour


EX2: Modify your code in simple.pde to add colour using both colorMode(RGB) and colorMode(HSB)


Things to note

  • Processing commands are case sensitive
  • You can write comments in your code (and you are expected to). Single line comments are created with two forward slashes //. Multiline comments start with /* and end with */
  • Some errors are noted in the code by a red squiggly line where Processing believes the mistake to be. An error message will also appear in the grey bar at the bottom of the input window.

Saving the output of a sketch

You can use "File > Export" to package your current sketch. However, you may just want to create an image of the output. Images are saved with the saveFrame() function. Adding saveFrame() at the end of draw() will produce a numbered sequence of TIFF-format images of the program's output, saving a new file each time draw is run (be careful as this can quickly fill your sketch folder with hundreds of files. You can also specify your own name and file type using saveFrame("output.png").

Saving frames can also be combined with event listeners, for example the following code will save a frame when the "s" key is pressed:

void keyPressed(){
if(key == 's'){
println("Saving...");
save("output.png");
println("Done saving.");
}
}

Variables and Loops

Variables in Processing work much like variables in most other common programming languages. There are different types of variables, for example strings, integers and floating point numbers.

Processing has a number of built-in variables which might be useful, these include:

  • width - width (in pixels) of sketch window
  • height - width (in pixels) of sketch window

Processing provides several data types for various kinds of information. The most important are:

  • boolean - Boolean values
  • int - integers
  • float - floating point value
  • char - single character
  • String - character string
  • color - colour

The variables.pde code illustrates how variables are declared and initialised in Processing. The syntax for loops is also the same as in Java. It should look pretty familiar.


EX3: Modify the code in variables.pde to create a pattern of transparent circles on a black background duplicating the circles to fill the sketch in both dimensions. Hint: nest one loop inside another.

L1EX3output


Arrays

The array.pde code file creates an array of grayscale values for each column of pixels in a sketch in the setup() function, then draws those pixel columns in the draw() function. Note that the array storing the grayscale values needs to be global in order to be accessible by each function.

Also note that the function uses the random() function to generate each of the grayscale values. This function, as you would expect, selects a random floating-point value between the upper and lower bounds provided to the function.


EX4: Modify the code in array.pde to fill the sketch with horizontal lines of a randomly generated colour

L1EX4output


If-statements, conditionals and logical operators

The ifelse.pde code file contains the code to move a circle horizontally across the centre of the screen.


EX5: Modify the code in ifelse.pde so that the circle moves in both the x and y directions. Use if statements to make sure that when the circle reaches the edge of the sketch it bounces back. The usual mathematical and logical operators are available (+ - * / = % ! || &&) in Processing.

L1EX5output


Classes and objects

The simplest object we might want to draw is a data point. We want to design a Point object that both keeps track of its location on the screen (where it exists on the screen) and has the capability to perform certain actions (such as draw itself or take a step).

Defining the Point Class

The point.pde code gets us started. The point only needs two pieces of data—a number for its x-location and one for its y-location.

class Point{
//data
float x;
float y;

Every class must have a constructor, a special function that is called when the object is first created.

   //constructor
Point() {
//initialise the position
x = width/2;
y = height/2;
} //constructor

in addition to data, classes can be defined with functionality. A Point needs only one function - the ability to draw itself (in this case as a white circle).

   void display() {
stroke(0);
ellipse(x, y, 50, 50);
}//end display

In the main part of our sketch, we declare one global variable of type Point, and then create the object in setup(). Then, during each cycle of the draw() function, the Point draws a circle.

Point point; // Declare object

void setup() {
size(600, 600);
point = new Point(); // Create object
} //setup

void draw() {
point.display();
} //draw

Points on a graph

To begin with we are going to make sure that we can arrange an array of Point objects along an x and y axis.

  • The first step is to create an array of 10 Point objects
  • Add an identifier (ID) to each Point object
  • Specify a colour for each point object
  • x position - for now you want to equally space your points along the x axis - we can do this in a number of ways e.g. scaling the objects manually using the ID or use the map() function - this re-maps a number from one range to another - in this case re-mapping between 0 and the population/sample size to 0 and the width of the display. For now set the x value to the ID and use the map function in your display method
  • y position - for now we'll equally space the points along the y axis too using the same method (set the y value to the ID and use the map function in your display method). Remember that the origin is in the top left
  • Finally in the main part of our sketch, display the points

EX6 Modify your point.pde code as detailed above. It should look something a bit like this:

point


Ok, so that doesnt look that great. So lets work on making it look more like a graph.

Set the boundaries for the plot location

Create the global variables plotX1, plotY1, plotX2, plotY2 to define the corners of the plot area and draw a filled white rectangle for the plotting area. To provide a nice margin you should set plotX1 to 50 and plotX2 to width-50. The same technique is used for plotY1 and plotY2.

void drawPlotArea() {
fill(255);
noStroke();
rectMode(CORNERS);
rect(plotX1, plotY1, plotX2, plotY2);
}

The rect() function normally takes the form rect(x, y, width, height), but rectMode(CORNERS) changes the parameters to rect(left, top, right, bottom).

We can use those variables in the map function within the display method to plot our points within the plot area.

void display() {
noStroke();
fill(255, 0 ,0);
float tempx = map(x, minX, maxX, plotX1, plotX2);
float tempy = map(y, minY, maxY, plotY2, plotY1);
ellipse(tempx, tempy, dia, dia);
} //end display

EX7 Set the background to light grey and draw a filled white rectangle for the plotting area. Plot the points in the plotting area

draw in area


Giving it a title

The font.pde code shows an example of working with fonts in Processing

PFont font;

void setup() {
size(630, 120);
font = createFont("SansSerif", 20);
textFont(font);
} //setup

void draw() {
background(102);
textSize(36);
text("Hello world", 27, 90);
} //draw

The text line draws the text at coordinate (27, 90). The createFont() function is used to create a font from one of the built-in typefaces.

Processing can display text in many fonts other than the default. However, before you can display text in a different font, you need to convert one of the fonts on your computer to the VLW format, which stores each letter as a small image. To do this, select Tools > Create Font to open the dialog box. Specify the font you want to convert, as well as the size and whether you want it to be smooth (anti-aliased). When you click the OK button in the Create Font tool, the VLW font is created and placed in the sketch's data folder. Now it is possible to load the font and add words to a sketch. See https://processing.org/reference/PFont.html

Once we have added the font, we can create a function to give our graph a title

void drawTitle(){
fill(0);
textSize(36);
textAlign(LEFT, BOTTOM);
text("My Plot", plotX1, plotY1-10);
}

EX8 Give your plot a title

title


Labelling the axes

Labelling the axes is straightforward. You will need to decide on an interval and add this to the code before setup(). Then the following function can be used.

void drawXlabels() {
fill(0);
textSize(10);
textAlign(CENTER, TOP);
for (int i = 0; i <= maxX; i++) {
if (points[i].id % Xinterval == 0) {
float x = map(points[i].id, 0, maxX, plotX1, plotX2);
text(points[i].id, x, plotY2 + 10);
}
}
}

The fill colour is black, the text size 10 and the alignment to the CENTER so that the label centers on the position of the relevant data point. The alignment TOP sets the vertical alignment of the text.

The %, or modulo, operator is used to only draw a label when the remainder is 0 so if Xinterval was set to 3 it would draw 0, 3, 6, and 9.


EX8 Add axis labels

axis label


Next steps

In the next lab we'll look at time series. If you have finished early take some time to look at the Processing reference and have a go at some of the Tutorials. You can also look at the examples of code available at https://www.openprocessing.org/browse/#