Introduction Emergence
On 27 April 2018, we spent a week in Almere. We made daily trips to special places like: Urk and Schokland. At a certain moment we saw this phenomenon. We thought it was a small sandstorm at the top of the dike. But dikes are not made of sand. Getting closer, we saw that it were swarms of mosquitoes. An example of emergence.
Having written the text for this publication, I got the idea that I had been on the wrong track. In fact, I did not adhere to what was the essence of this chapter at all. It was emergence. To emerge is to loom up or suddenly appear. In our lives, there are many examples of this.
A swarm of mosquitoes or a flight of starlings, for example. The behaviour of a flock of sheep. The ‘wave’ of the crowd in a football stadium or a school of herrings. When a car brakes in a traffic jam, you get a compaction of cars moving backwards like a wave. This phenomenon is emergent because it is a property of the totality of cars and does not exist at the level of the cars themselves.
But also our life, in the biological sense, is considered an emergent property. A cell consists of many organic molecules. The individual organic molecules are not alive, but the complex interactions between all those organic molecules enable the cell to keep itself alive.
Thus, the characteristics of the emergent phenomenon relate exclusively to the whole and not to the parts that compose it: ‘The whole is more than the sum of its parts’. That was the essence the sixt chapter. Unfortunately, I only found that out when I started writing this introduction and finished this publication. But actually, the idea ‘chapter’ is also emergent :)
Henk LamersPlease note that all code in this publication refers to Matt Pearson's original code in his publication: Generative Art. A practical guide using Processing.
LFMP_06_01_01
Draw circles with mouse clicks
To begin with, this is a very simple program. The program draws ten circles at a random location in the display window with every mouse click. I have otherwise changed very little to Matt Pearson's original program. First, let‘s see if it becomes clear how it works.
int NumberOfObjects = 10;
The initialisation of the number of circles. In this case, 10.
DrawCircles ();
In setup, the usual things happen like: size, background, smooth, strokeWeight and stroke. Something new is the drawCircles function. In setup it is called once so that ten circles already appear in the display window without a mouse click.
void draw ()
This code block is empty but is only there to keep the program running. Mouse and keyboard events only work when a program has draw(). Without draw(), the code is only run once and then stops listening for events.
void mouseReleased () {
The mouseReleased () function is called every time a mouse button is released.
drawCircles ();-
With every mouse click, the drawCircles function is called.
void drawCircles () {
This function consists of a for next loop that is executed ten times. It randomly generates an x and y coordinate where two ellipses are placed with a radius of 32 + 16 pixels.
int NumberOfObjects = 128;
The first change I made was to increase the number of objects from 10 to 128.
float x = random (width - 200);
float y = random (height - 400);
You want the image to be displayed within the display window. Hence width – 200 and height – 400.
float radius = random (16) + 8;
The radius of the ellipse have been reduced by half.
fill (255, 32);
The ellipses have extremely high transparency. But clicking the mouse several times makes them less transparent.
ellipseMode (CENTER);
The ellipseMode (CENTER) is the default, which interprets the first two parameters of ellipse () as the shape‘s center point, while the third and fourth parameters are its width and height. I used it here for clarity for myself.
ellipse (x + 100, y + 200, radius / 8, radius * 16);
This is the biggest change. Horizontal locations are shifted 100 pixels. Vertical locations are shifted 200 pixels. The horizontal radius is divided by 8 leading to a huge narrow line. In addition, the vertical radius is extended 10 times. This gives a vertical body of high transparency. If you repeat that enough times, you get a totally different image than the original program shows.
LFMP_06_01_02
Draw
LFMP_06_01_03
LFMP_06_01_04
LFMP_06_01_05
LFMP_06_01_06
int NumberOfObjects = 128;
The first change I made was to increase the number of objects from 10 to 128.
float x = random (width - 200);
float y = random (height - 400);
You want the image to be displayed within the display window. Hence width – 200 and height – 400.
float radius = random (16) + 8;
The radius of the ellipse have been reduced by half.
fill (255, 32);
The ellipses have extremely high transparency. But clicking the mouse several times makes them less transparent.
ellipseMode (CENTER);
The ellipseMode (CENTER) is the default, which interprets the first two parameters of ellipse () as the shape‘s center point, while the third and fourth parameters are its width and height. I used it here for clarity for myself.
ellipse (x + 100, y + 200, radius / 8, radius * 16);
This is the biggest change. Horizontal locations are shifted 100 pixels. Vertical locations are shifted 200 pixels. The horizontal radius is divided by 8 leading to a huge narrow line. In addition, the vertical radius is extended 10 times. This gives a vertical body of high transparency. If you repeat that enough times, you get a totally different image than the original program shows.
ellipse (x + 200, y + 100, radius * 16, radius / 8);
The x and y dates swapped. This produces horizontal lines instead of vertical ones.
translate (300, 50);
rotate (radians (45));
Of course, it is also possible to put this object at an angle. Translate and rotate are the functions for this.
rotate (radians (-45));
The –45 angle produces the mirror image of the previous program.
ellipse (x - 300, y + 175, radius * 16, radius / 8); Making the x coordinate -300 and the y coordinate +175 moves the object to the top right.
rotate (radians (90));
As a result, the lines are displayed vertically.
LFMP_06_03_01
The circle class in OOP
LFMP_06_03_02
LFMP_06_03_04
LFMP_06_03_05
LFMP_06_03_06
LFMP_06_03_07
Matt Pearson‘s publication pays ample attention to OOP (Object Oriented Programming). Listing 6.2 shows how to convert Listing 6.1 to OOP. Therefore, I decided to use OOP but not to make variations of it. Because the output in OOP is the same as the program written without OOP. I continue here immediately with Listing 6.3
fillcol = color (random (255), random (255), random (255)); The original program used coloured lines. But I don't use those. Hence I commented out that programme line. Fillcol does the job here.
fill (fillcol, 64);
There is a transparency of 64. That‘s a 75 per cent.
ellipse (x - 1200, y, radius * 16, radius / 16); Random coloured lines are drawn from left to right.
ellipse (x + 600, y, radius * 16, radius / 16);
Random coloured lines are drawn from right to left.
fillcol = color (random (10), random (100), random (100)); I narrowed the range of colours slightly to reddish-like colours.
ellipse (x + 1200, y, radius * 16, radius / 16);
The lines are now built up from the bottom.
fillcol = color (random (100, 110), random (100), random (100)); Only greenish colours.
rotate (radians (135));
The colours are now built up from the bottom-left corner.
rotate (radians (225));
Purpleish colours are now built up from the top left corner.
LFMP_06_03_08
LFMP_06_03_09
LFMP_06_03_10
The circle class
LFMP_06_03_11
LFMP_06_03_12
LFMP_06_03_15
rotate (radians (45)); Lines diagonally across the display window.
rotate (radians (135)); Diagonal lines flipped horizontally.
background (BackgroundImage);
Here I put one of the images from previous programs in the background. Then generated lines on the right side via mouse clicks. This creates an interesting black inner shape.
ellipse (x + 500, y, radius * 8, radius / 16);
Same principle as previous program but the lines come from the right side.
- ellipse (x + 500, y, radius * 8, radius / 16);
Same principle with a background image. With the newly generated lines perpendicular to it. Together, they form the letter K.
rotate (radians (0));
A slightly less successful variant of the previous program. With a rotation of 0 and lines built from the right side.
LFMP_06_03_16
LFMP_06_03_17
LFMP_06_03_18
The circle class in OOP
rotate (radians (180));
A background image constructed from the bottom left. Lines generated via mouse clicks from the right side.
rotate (radians (45));
A background image built from the top left corner. Opposite lines from the bottom right corner.
rotate (radians (135));
The same background image as in the previous program. But now the lines are generated from bottom left to top right.
LFMP_06_04_01
Moving circles with OOP
As usual, this is a logical update of the previous program Listing 6.3. Listing 6.4 adds some new things like an array to store all the circles. Each circle gets a movement factor in the x and y directions. And we give each circle an updateMe method, called every frame by the draw loop. Although this is a program with animation, I have also created material suitable to show as a screendump and say something about it.
Circle [] CircleArray = {};
Define an array of circles.
CircleArray = (Circle []) append (CircleArray, thisCircle); Add an object to the array.
float xmove;
float ymove;
In the class Circle, these are the variables to set the steps in each frame.
xmove = random (10) - 5; ymove = random (10) - 5;
In the object constructor, we generate random steps.
void updateMe () { An update function has been added.
x += xmove;
y += ymove; Move every frame. Furthermore, a number of if statements are executed to restart circles at the edges of the display window. Then the drawMe function is executed. This results in a field of colour-filled circles moving randomly through the display window. And new circles are added with every mouse click aswell.
LFMP_06_04_02
LFMP_06_04_03
LFMP_06_04_04
ellipse (x, y, radius * 16, radius / 16); Again, I used stretched ellipses. In the x direction, everything is stretched. In the y direction, everything is flattened.
//stroke (linecol, alph);
//noFill ();
//ellipse (x, y, 10, 10);
These three functions are commented out.
radius = random (100) + 10;
The radius enlarges. But because it is random, the possibility of it actually enlarging a lot is slightly less.
ellipse (x, y, radius * 16, radius / 24); Reduced the radius of y from 16 to 24.
rotate (radians (45));
The horizontal lines were getting a bit boring so I angled them. That makes the image more interesting.
LFMP_06_04_05
LFMP_06_04_06
LFMP_06_04_07
LFMP_06_04_08
xmove = random (1); ymove = random (1);
Xmove and ymove limited in their location. That means the ellipses will rotate around a location and repeat themselves.
rotate (radians (y));
Using y for rotation gives you spirographic images. A spirograph is an instrument used to draw geometric patterns. The spirograph was invented by Denys Fisher (1918 - 2002), an English engineer, and sold from 1965. In 1967, the spirograph was voted toy of the year in the UK.
ellipse (x, y, radius * 16, radius / 326);
Reduced the radius in the y-direction considerably.
ellipse (x, y, radius / 32, radius * 16);
Added a second ellipse.
ellipse (x, y, radius * 16, radius / 8);
The first ellipse (which are actually lines) is exactly the opposite of the second ellipse.
ellipse (x, y, radius / 8, radius * 16);
Curiously, this leads to structures formed by squares.
xmove = random (0.1); ymove = random (0.1); Reduced the x- and ymove.
rotate (radians (x));
That is random from the width (1000 pixels).
translate (1000, -1000);
To keep everything reasonably within the display window, I ended up with these extreme numbers.
rotate (radians (y));
This is a random number from the height (1000 pixels).
ellipse (x, y, radius / 32, radius * 16); This change produces unpredictable images. They take about two to three minutes to render a nice composition. The compositions are different every run. It is chaotic but not too chaotic.
LFMP_06_06_01
The updateMe method with circles in OOP
So we started in this publication with a simple program that draws circles. They animate randomly through the display window. And then we gave those circles a behaviour. There is now interaction between the circles themselves. This is done by calculating how far apart circles are. Whether they overlap by comparing their centres. Those calculations have been added in the Circle class.
for (int i = 0; i < CircleArray.length; i++) { Circle otherCirc = CircleArray [i]; This is a loop through the circles.
float dis = dist (x, y, otherCirc.x, otherCirc.y); Here, the distance between the circles is calculated.
float overlap = dis - radius - otherCirc.radius; This is where the overlap is calculated.
if (overlap < 0) {
If the overlap is smaller than 0, the circles touch.
midx = (x + otherCirc.x) / 2; midy = (y + otherCirc.y) / 2; Calculates the centre point.
ellipse (midx, midy, overlap, overlap); Then the ellipse is depicted.
LFMP_06_06_02
//linecol = color (random (255));
//fillcol = color (random (255), random (255), random (255)); Commented out linecol en fillcol
//noStroke ();
//fill (fillcol, alph);
//ellipse (x, y, radius * 2, radius * 2); Commented out these too.
//ellipse (x, y, 10, 10); And finally commented out these ellipses too.
stroke (linecol, 64); Changed 0 in linecol. And 100 in 64.
overlap *= -0.1; Changed the overlap from -1 into -0.1. Now this had nothing to do with the original LFMP_06_06_01 program but after running this for five minutes you get an interesting pattern.
LFMP_06_06_03
int NumberOfObjects = 100; Changed 10 into 100.
LFMP_06_06_04
The updateMe method with circles in OOP
LFMP_06_06_05
int NumberOfObjects = 4; From 100 to 4.
radius = random (10) + 1; From 10 to 1.
lineColor = color (random (255), random (255), random (255)); fillColor = color (random (255), random (255), random (255)); Added lineColor and fillColor again.
xmove = random (10) - 1; ymove = random (10) - 1; Made the speed of xmove and ymove the same.
fill (fillColor); Added fill again.
ellipse (x, y, radius * 2, radius * 2); Added another range of ellipses.
rotate (radians (1)); Added rotate but in retrospect this didn‘t look like a good idea.
ellipse (x, y, 40, 40); Whether a circle rotates or not you can't tell.
stroke (lineColor, alphaChannel); AlphaChannel was 64 in the previous program.
overlap *= -0.5; This is probably going to give big changes.
ellipse (midx, midy, overlap * 16, overlap); I thought this would change a lot but it ends up delivering a rather boring pattern.
int NumberOfObjects = 10; Upgraded to 10. As it was.
noStroke (); fill (0, 6); rect (0, 0, width, height); In draw: added a rectangle with high transparency making the objects fade out slowly.
//background (0); Commented out the background.
xmove = random (10) - 8; ymove = random (10) - 5; Returned to their original settings.
//fill (fillcol, alph); //ellipse (x, y, radius * 2, radius * 2); Commented out both lines.
LFMP_06_06_05
stroke (lineColor);
Added the strokeColor again. And removed the unnecessary rotation.
ellipse (x, y, 1, 1);
This gives tiny dotted lines that suddenly explode into a pile of coloured circles. fill (lineColor);
Added in the midpoint codeblock.
noStroke ();
You don‘t want lines.
overlap *= -1.9;
The overlap reduced from –0.5 to –1.9
LFMP_06_06_06
int NumberOfObjects = 100;
Increased this number considerably, reducing the number of mouse clicks.
radius = random (10) + 10;
Within the 1000 x 1000 I thought this was a nice ratio for the objects.
xmove = random (1) - random (2);
ymove = random (1) - random (2);
These settings make the objects all swarm together instead of all going one way.
overlap *= -3.6;
Don‘t ask me why I ended up with –3.6. In the end, that was the number that best suited the shape. These changes were rather disappointing. Until I found out that you had to mouse click in quick succession. Then you get interesting structures. So eventually when you get above 600 objects then it gets interesting. Unfortunately, it has nothing to do with what Matt Pearson was trying to explain. I just went down a different path.