tag:blogger.com,1999:blog-20449720502769994662024-03-13T03:35:20.414-07:00Algorithmic ArtAlgorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.comBlogger39125tag:blogger.com,1999:blog-2044972050276999466.post-86742443198271960252019-11-22T16:50:00.003-08:002019-11-22T16:50:14.944-08:00Simulating Lots of Things with Objects and ClassesThis month's Cornwall <a href="https://www.meetup.com/Algorithmic-Art/events/266327241/" target="_blank">meetup</a> was an introduction to objects and classes, a technique that allows us to intuitively and easily model many many similar things.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZjayUSrALRc4Np52Gx9jtuF2voZUoH3i5tXC4E_hm3c_uwrhdroRjArMdyfBrOJoGGzelaOLFXO0h4zjisPDokyxKU69lCKOER2EJozrhVBCeVJ-j6jMAhCyogmTea4xO8AA8OTARjdZ4/s1600/algo_obj_class.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="945" data-original-width="1260" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZjayUSrALRc4Np52Gx9jtuF2voZUoH3i5tXC4E_hm3c_uwrhdroRjArMdyfBrOJoGGzelaOLFXO0h4zjisPDokyxKU69lCKOER2EJozrhVBCeVJ-j6jMAhCyogmTea4xO8AA8OTARjdZ4/s320/algo_obj_class.png" width="320" /></a></div>
<br />
<br />
The slides for the tutorial are here: [<a href="https://tinyurl.com/vtahtzg" target="_blank">link</a>].<br />
<br />
<br />
<h3>
Approach</h3>
This session was a continuation of our journey learning creative coding for beginners, specifically with the p5js javascript language using openrprocessing.org. Over months we have worked through key topics such as colour models and recursion from this course designed for newcomers:<br />
<br />
<ul>
<li><a href="https://sites.google.com/view/creative-coding-for-kids" target="_blank">https://sites.google.com/view/creative-coding-for-kids</a></li>
</ul>
<br />
<br />
<a href="https://en.wikipedia.org/wiki/Object-oriented_programming" target="_blank">Object oriented programming</a> (OOP) is important in the world of programming, and can be very useful for creative coding. Is sometimes seen as complicated, plagued by jargon and without clear reasons for using them.<br />
<br />
So the approach taken here is to start with a very simple familiar example, and then try to scale that until we hit a challenge, to which the the solution is objects and classes.<br />
<br />
<br />
<h3>
A Simple Moving Ball</h3>
We started with the simplest example of a ball displayed on the screen as a circle. We talked about the information that ball required - its location in terms of x and y coordinates, for example.<br />
<br />
We then considered how the ball might move, with additional information required about its speed in the horizontal and vertical directions. We considered some very simple code that animated this movement - you can explore the code here: (<a href="https://www.openprocessing.org/sketch/798491" target="_blank">sketch</a>).<br />
<br />
Finally we considered how we might simulate the effect of gravity. Whereas speed updates location, gravity updates speed - a simple way to think about the physics without exploring Newton's equations of motion.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU_piaSsIAQdKpVNs6mHD4Ru-Fvm2GsKBzTKe9Mzqc4yYjRoj21eVyHZ76-P-Sn5GFB8hjCtsd-p-IEkaI3dlYJr-NakeBzyKaT-lvbY84ZSdxfUtDwV8hUCsk8M97RjkhiW2DCdxkTPYh/s1600/Simulating+Lots+Of+Things+With+Objects+%2526+Classes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU_piaSsIAQdKpVNs6mHD4Ru-Fvm2GsKBzTKe9Mzqc4yYjRoj21eVyHZ76-P-Sn5GFB8hjCtsd-p-IEkaI3dlYJr-NakeBzyKaT-lvbY84ZSdxfUtDwV8hUCsk8M97RjkhiW2DCdxkTPYh/s400/Simulating+Lots+Of+Things+With+Objects+%2526+Classes.png" width="400" /></a></div>
<br />
This gave more realistic motion of a ball thrown up and then falling.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizHjcBzPDOQV68WmpCTAU19DEd-bge4sdrRAjGlXivz3kD9U0bGUDDrY6kx777WW1h8a3WO_qicdCUzSZD_27gYKjguuF5bkES1UAb0Xz5X1QBbEHjqsZlTAbFGNHW7Bjlj6GmhRjYCSyx/s1600/ezgif.com-gif-maker.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="600" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizHjcBzPDOQV68WmpCTAU19DEd-bge4sdrRAjGlXivz3kD9U0bGUDDrY6kx777WW1h8a3WO_qicdCUzSZD_27gYKjguuF5bkES1UAb0Xz5X1QBbEHjqsZlTAbFGNHW7Bjlj6GmhRjYCSyx/s400/ezgif.com-gif-maker.gif" width="400" /></a></div>
<br />
You can explore the code here - (<a href="https://www.openprocessing.org/sketch/798494" target="_blank">sketch</a>).<br />
<br />
So far we have very simple familiar code that models a ball in motion under gravity.<br />
<br />
<br />
<h3>
Challenge - Lots of Balls</h3>
If we wanted to model, not one but 10, or 100, or even 1000 balls, how would be do that?<br />
<br />
We don't want to have 1000 different x and y variables to code individually.<br />
<br />
One way of minimising duplication is to take advantage of commonality in the many things we're modelling.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgLkHo3IiRJLtXhbQc5V9BQ8-H7x56YXWMmeQM3f_fSlC9_qmKiw8aFHg3kjy8gaMAoMEyRiQlZ8s2BMAWMNJAHBOpj_L2J-DOfaQIvm-78KoPmuHRlzX-OmFU2lmiitfA1Hc-n3ljy9ac/s1600/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgLkHo3IiRJLtXhbQc5V9BQ8-H7x56YXWMmeQM3f_fSlC9_qmKiw8aFHg3kjy8gaMAoMEyRiQlZ8s2BMAWMNJAHBOpj_L2J-DOfaQIvm-78KoPmuHRlzX-OmFU2lmiitfA1Hc-n3ljy9ac/s400/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25281%2529.png" width="400" /></a></div>
<br />
We can see that all these balls have (x,y) coordinates and (x_speed, y_speed) information. They also happen to be the same colour and size.<br />
<br />
So we can take these common things and include them into a <b>blueprint</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivszOG0bYfW-pyGWj1pfudQbROIk4lgf3WdkpXNgvmMaaPIuR7I351xrxo9yKr_ZsbzwuaGfSFmEmYDBzDMsyLMGWlhq-NXpq7ye4QFEtOBdy1SoCtKuc9vXLG_Aq5Gx_9lUkj7uBuOwYx/s1600/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivszOG0bYfW-pyGWj1pfudQbROIk4lgf3WdkpXNgvmMaaPIuR7I351xrxo9yKr_ZsbzwuaGfSFmEmYDBzDMsyLMGWlhq-NXpq7ye4QFEtOBdy1SoCtKuc9vXLG_Aq5Gx_9lUkj7uBuOwYx/s400/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25282%2529.png" width="400" /></a></div>
<br />
That blueprint we can make many instances of the ball, each with their own position and velocity. The actual numbers for position and velocity can be different but they all have this information.<br />
<br />
This is the basic idea of object oriented programming. We define blueprints, from which we can make many instances.<br />
<br />
Conceptually, that's how we solve the challenge of modelling many balls.<br />
<br />
<br />
<h3>
Classes and Objects</h3>
In programming languages, the blueprints are often called <b>classes</b>. And instances created from a class are called <b>objects</b>.<br />
<br />
The classes can contain information like position and velocity. These are just like normal variables, but associated with the class. This information is often called object or class <b>data</b>.<br />
<br />
Classes can also contain functions! Yes, that's right. A blueprint for a a thing, like a ball, can have functions associated with that thing. For example, we might have a <b>move()</b> or <b>show()</b> function for a ball. For a computer game character we might have a function <b>explode()</b>. These functions, when associated with classes or objects, are sometimes called <b>methods</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwoC57ksIR9D2OoNLYzBGbMooYQE_o2KCuunQOi2AH6ySM1g__MQhtNUL5rQsyLBYzKIBz7lmxMcizC9R8aVkc3XJh6BMZWvmX0BEOfZbDXjrIvbhpoql_6W1l8cy7CAcYNndTZtHOxKj2/s1600/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwoC57ksIR9D2OoNLYzBGbMooYQE_o2KCuunQOi2AH6ySM1g__MQhtNUL5rQsyLBYzKIBz7lmxMcizC9R8aVkc3XJh6BMZWvmX0BEOfZbDXjrIvbhpoql_6W1l8cy7CAcYNndTZtHOxKj2/s400/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25283%2529.png" width="400" /></a></div>
<br />
Let's see what this looks like in code. The following shows an example of a class which has both <b>data</b> and <b>methods</b>. You can see it has x and y coordinates for its position. It also has a show() method which draws a circle.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCXxUxJ2fcQHCaEeFShN7VbDhstSEOdb052UYUgoT0wy_UubYuK7UJSUoq2hvl-9AzDH6DFXjDnN1Z4YqbB9as11yrWC8os4dZu3TEW3cQxUteYf3g1IIGQpuqMct_zhi87HVM1hM_ABiH/s1600/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCXxUxJ2fcQHCaEeFShN7VbDhstSEOdb052UYUgoT0wy_UubYuK7UJSUoq2hvl-9AzDH6DFXjDnN1Z4YqbB9as11yrWC8os4dZu3TEW3cQxUteYf3g1IIGQpuqMct_zhi87HVM1hM_ABiH/s400/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25284%2529.png" width="400" /></a></div>
<br />
It is worth noting that the <b>constructor()</b> function is special. It is always called when an object is first created. It's the ideal place to initialise and set up the object. Here we set the x and y data.<br />
<br />
We then re-wrote the code for our simple ball as a class blueprint, and created an instance of the ball with <b>var my_ball = new Ball()</b>. We then used the animation loop to repeatedly call the object's show() and move() functions to draw the ball and update it's position.<br />
<br />
You can explore the code here - (<a href="https://www.openprocessing.org/sketch/798524" target="_blank">sketch</a>). It is instructive to see where our previous code goes in this object oriented code.<br />
<br />
<br />
<h3>
Lots of Objects!</h3>
It might appear that we've written more code just to get a ball to move under the influence of gravity. The benefit is that we can create lots of instances of the ball blueprint very easily.<br />
<br />
We saw how we can fill a list with newly created Ball objects.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzq2MCqex_tQv-LI6NtsHTqJwrcbNigncXCHK3suGKsQvWzI8ELKSqZynhltVwGXO8Bke9EF6-sgSrBVb9gx5NUSwsicLwkxR6PcPfQmirllBy-ACfzFEZ6W6R8iDYHLSsqpJezPcTIMpZ/s1600/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25285%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzq2MCqex_tQv-LI6NtsHTqJwrcbNigncXCHK3suGKsQvWzI8ELKSqZynhltVwGXO8Bke9EF6-sgSrBVb9gx5NUSwsicLwkxR6PcPfQmirllBy-ACfzFEZ6W6R8iDYHLSsqpJezPcTIMpZ/s400/Simulating+Lots+Of+Things+With+Objects+%2526+Classes+%25285%2529.png" width="400" /></a></div>
<br />
Our example code had a list of 20 balls. In the code we simply iterate over the list at every animation frame to move and show the balls.<br />
<br />
Each one of these 20 ball objects has its own position and velocity. To ensure they don't all follow the same path, we added a random element to the initial velocity in the <b>constructor()</b> in the class definition.<br />
<br />
The result is rather pleasing!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibwz6mWL_EpAS44jRrnhNEigjefYS3t2SLYBpGc_pbBrAX6c1078L-3cvAbsBwAz3QOQBy2ynbjSc0kdWZ9yXVGLomp-ITYpUASPyYSuuS7uBI4zj18fnfgDGlK2wViNyDiupHFRhZMilB/s1600/ezgif.com-gif-maker+%25281%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="600" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibwz6mWL_EpAS44jRrnhNEigjefYS3t2SLYBpGc_pbBrAX6c1078L-3cvAbsBwAz3QOQBy2ynbjSc0kdWZ9yXVGLomp-ITYpUASPyYSuuS7uBI4zj18fnfgDGlK2wViNyDiupHFRhZMilB/s400/ezgif.com-gif-maker+%25281%2529.gif" width="400" /></a></div>
<br />
You can explore the code here - (<a href="https://www.openprocessing.org/sketch/798572" target="_blank">sketch</a>).<br />
<br />
The power of objects and classes is now clear.<br />
<br />
We can easily create many objects from a single blueprint. You can see how this can be used to model many kinds of things, from flocking birds to creeping ants .. our imagination is the only limit.<br />
<br />
<br />
<h3>
Simple Examples</h3>
We looked at some simple examples, which share the same code structure, but model different scenarios.<br />
<br />
The simple balls example can be adapted to model bouncing when hitting an edge to create the effect of balls bouncing in a jar.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglWWrmj2BRtQscCovTWA7_sMsCqGHeCB5WBdy8Tz0wsVolpyZkrsiE_QLf9EROjojT-6UTBTV3ifvbSmTqRMPKYeROPOmecU0iinGXIv5sHW5lc35BgRtGTx6WLIkxLGZXPexftn-iesWk/s1600/ezgif.com-gif-maker+%25282%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="600" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglWWrmj2BRtQscCovTWA7_sMsCqGHeCB5WBdy8Tz0wsVolpyZkrsiE_QLf9EROjojT-6UTBTV3ifvbSmTqRMPKYeROPOmecU0iinGXIv5sHW5lc35BgRtGTx6WLIkxLGZXPexftn-iesWk/s400/ezgif.com-gif-maker+%25282%2529.gif" width="400" /></a></div>
<br />
The code is here - (<a href="https://www.openprocessing.org/sketch/682218" target="_blank">sketch</a>), and worth looking at to see how easy it is to extend the blueprint to include these new effects.<br />
<br />
Once the blueprint is updated, all the balls benefit. This is good way to keep more complex coding projects tidy and manageable.<br />
<br />
The next example was a simulation of fireworks, but the core element is the same as our balls flying under the influence of gravity.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0pVVyNBuVsd1OqvesKW0gFWo2Wm6t9lEiR0O3Bk_iAH2PJ-Ne9jFrr_llUlHUI1GDmCjXVDjpAsOVW-Pyy-FEscHGZ0rH-1Zq9zvC2ZeDUoxZMUUa2ogcaq0gWIPzQFvCvHG3b-_Im1nz/s1600/ezgif.com-gif-maker+%25283%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="600" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0pVVyNBuVsd1OqvesKW0gFWo2Wm6t9lEiR0O3Bk_iAH2PJ-Ne9jFrr_llUlHUI1GDmCjXVDjpAsOVW-Pyy-FEscHGZ0rH-1Zq9zvC2ZeDUoxZMUUa2ogcaq0gWIPzQFvCvHG3b-_Im1nz/s400/ezgif.com-gif-maker+%25283%2529.gif" width="400" /></a></div>
<br />
Explore the code is here - (<a href="https://www.openprocessing.org/sketch/682243" target="_blank">sketch</a>). Most of the additional code is simply to style the moving balls.<br />
<br />
Finally we looked at an example which wasn't based on objects moving under gravity, but moving according to Perlin <a href="https://algorithmicartmeetup.blogspot.com/2019/09/creative-uses-for-not-so-random-noise.html" target="_blank">noise</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj67fj6h5-zmEB2UfPCYkUYmUJJ95lhD-imqHCwcwT5Qu3ct-osCmFJft42f-PMMlW7gawhdlVG_O5u8R3ImdpFUZp2O52VnP3n8P7ECU2C-lxQj0kiinQolGHJaK18ZFwsISceSgdf-R5r/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="600" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj67fj6h5-zmEB2UfPCYkUYmUJJ95lhD-imqHCwcwT5Qu3ct-osCmFJft42f-PMMlW7gawhdlVG_O5u8R3ImdpFUZp2O52VnP3n8P7ECU2C-lxQj0kiinQolGHJaK18ZFwsISceSgdf-R5r/s320/ezgif.com-optimize.gif" width="320" /></a></div>
<br />
<br />
You can explore the code here - (<a href="https://www.openprocessing.org/sketch/687126" target="_blank">sketch</a>). It is useful to see which code is similar to all our previous example. The definition of a blueprint, the creation of many objects in a list, and then repeatedly calling methods on those objects, is the common pattern.<br />
<br />
<br />
<h3>
Thoughts</h3>
There are many algorithmic artists, and indeed scientists and engineers, who model the behaviour of many similar things. Using classes an objects is one common way of doing this elegantly.<br />
<br />
Conceptually, the idea of being able to flexibly define "things" which have the characteristics of real or imaging things is nice. We can create, for example, dogs, which might have colour and name, and methods like run and bark.<br />
<br />
This object oriented programming is popular, and is possible in many languages, from Python to Java, from Javascript to C++. The syntax and terminology might vary, but the concepts are similar.<br />
<br />
In this session we introduced objects and classes. You can do much more with objects and classes, such as creating hierarchies of blueprints, but most algorithmic art is very effective with just the simple ideas we covered.<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-91108141638731399012019-11-06T09:58:00.001-08:002019-11-12T08:01:17.142-08:00Algorave!As part of the <a href="https://sites.google.com/view/algorithmic-art-season-2019/" target="_blank">Algorithmic Art Season 2019</a>, we held an <b><a href="https://www.meetup.com/Algorithmic-Art/events/264970740/" target="_blank">Algorave</a></b> at the <a href="https://www.fishfactoryarts.space/" target="_blank">Fish Factory Arts Space</a>, Penryn.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMOCf38-jPlu_7YY6iVkbre5Sj73MXu4f9RpUzqfPt9ow6qDJoR9r7LhcrCufRS0vYqpHjlk1DxwP05YncsdHe3YFAztKMNWE3AuhR2LFK-ycM9NXOn9kq7iSbBHyrldxhChruumT5e7Nv/s1600/algorave_poster.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1132" data-original-width="1600" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMOCf38-jPlu_7YY6iVkbre5Sj73MXu4f9RpUzqfPt9ow6qDJoR9r7LhcrCufRS0vYqpHjlk1DxwP05YncsdHe3YFAztKMNWE3AuhR2LFK-ycM9NXOn9kq7iSbBHyrldxhChruumT5e7Nv/s400/algorave_poster.png" width="400" /></a></div>
<br />
<br />
<h3>
Algorave? Live Coding?</h3>
At a typical rave, a DJ selected pre-recorded music to play. At a live music performance, musicians play instruments live for an audience.<br />
<br />
There is something magical and immediate about being in the presence of a real musician playing an instrument. It is a performance of the moment, a performance that is not like anything that happened before, or will happen again.<br />
<br />
And a key part of the magic is that the musician is using skill, reacting to the instrument and the audience, and the music is subtly infused with the particular mood and state of the mind of the musician at that time. It is a very personal experience.<br />
<br />
Sound isn't just created by pianos and violins, it can be created digitally with a computer. And a musician can instruct a computer to to synthesise and arrange sounds to make music. Those instructions are in a computer programming language, and the act of writing those instructions is often called <b>coding</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Pmv1_EnJjblCBz0mCHswk9ZGLWFePjWn8VT4QiL9plzM-vGdX-ri8WlSAq3DH8foOix9oSUK_kH1AGrptPT8Wtg3cezuHpWUd4znXMPfLQd1hmDlL9HCyZuG6fSNLoKup9BFcM2aUQkD/s1600/ezgif.com-optimize-2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="270" data-original-width="480" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Pmv1_EnJjblCBz0mCHswk9ZGLWFePjWn8VT4QiL9plzM-vGdX-ri8WlSAq3DH8foOix9oSUK_kH1AGrptPT8Wtg3cezuHpWUd4znXMPfLQd1hmDlL9HCyZuG6fSNLoKup9BFcM2aUQkD/s320/ezgif.com-optimize-2.gif" width="320" /></a></div>
<br />
<b><a href="https://en.wikipedia.org/wiki/Live_coding" target="_blank">Live-coding</a></b> is writing code in the moment, with effects that are to be experienced immediately. So live-coding music is similar to a musician performing live with a violin or piano.<br />
<br />
And when live-coding musicians get together and perform for an audience - it can be an <b><a href="https://en.wikipedia.org/wiki/Algorave" target="_blank">algorave</a></b>!<br />
<br />
<br />
<h3>
Fish Factory Art Studios</h3>
On the evening we gathered at the Fish Factory Art Studios in Penryn and experienced sets from Dave Griffiths, a pioneer of the algorave scene, Adam Russell and Barnaby Fryer.<br />
<br />
Each set was very different in both musical style and also the software being used to create music.<br />
<br />
Barnaby Fyrer orchestrated a rich and interesting soundscape that had the audience captivated and eager to hear what he was going to do next:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk2-ZKys4yW9FQJsYO2ja6bAzQHto1MSar2i61D5RTH8bVjBM83ntY-mPwFxXagQvquyg1OmzrClrKh58cCOsMwi4gCj3KqT7YoWvONEpeYY-pC-O0WA1iMzWnSDRsYyIQRMer4OGrMboa/s1600/IMG_20191101_210055-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1202" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk2-ZKys4yW9FQJsYO2ja6bAzQHto1MSar2i61D5RTH8bVjBM83ntY-mPwFxXagQvquyg1OmzrClrKh58cCOsMwi4gCj3KqT7YoWvONEpeYY-pC-O0WA1iMzWnSDRsYyIQRMer4OGrMboa/s400/IMG_20191101_210055-01.jpg" width="400" /></a></div>
<ul>
<li><a href="https://soundcloud.com/nebogeo/fish-factory-algorave-penryn-2019-barnaby-fryer" target="_blank">https://soundcloud.com/nebogeo/fish-factory-algorave-penryn-2019-barnaby-fryer</a></li>
</ul>
<br />
<br />
Adam Russell weaved a hypnotic and powerful soundscape threaded powerfully with a very relevant <a href="https://www.youtube.com/watch?v=Y8oWrF2CXF8" target="_blank">political speech</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicC_b56khJRxUr69n79xwDBaey_qdoNJl2VWAsQWQ5kw7BcfSlP_u53wz0UmlhivE-dLSrIe1B_9uQZECMgtCGlaUpH8evDynpNveALwO7IwA6aXjS3ZbXnZKgiMom_A3l1VM6UhmtK5T4/s1600/IMG_20191101_213110-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1201" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicC_b56khJRxUr69n79xwDBaey_qdoNJl2VWAsQWQ5kw7BcfSlP_u53wz0UmlhivE-dLSrIe1B_9uQZECMgtCGlaUpH8evDynpNveALwO7IwA6aXjS3ZbXnZKgiMom_A3l1VM6UhmtK5T4/s400/IMG_20191101_213110-01.jpg" width="400" /></a></div>
<ul>
<li><a href="https://soundcloud.com/nebogeo/fish-factory-algorave-penryn-2019-adam-russell" target="_blank">https://soundcloud.com/nebogeo/fish-factory-algorave-penryn-2019-adam-russell</a></li>
</ul>
<br />
<br />
Dave Griffiths performed the finale, a lively vibrant set using software he had written almost entirely himself. The interface itself is visual in showing what is being played, as well as being the means of control and composition.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTAK6BNll9iUAXJuooxzJFzgN1ATDvUDZ7TQVf2PqOn6k0udweVIw2I75CDQgqY3n0Mm2QeY4v0ba_yNJPmfFVELELQkK4QN5II447nf-cJUtO6xXHVp0XQLBtw7oP5JBnT_s4_3X1vY7o/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="270" data-original-width="480" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTAK6BNll9iUAXJuooxzJFzgN1ATDvUDZ7TQVf2PqOn6k0udweVIw2I75CDQgqY3n0Mm2QeY4v0ba_yNJPmfFVELELQkK4QN5II447nf-cJUtO6xXHVp0XQLBtw7oP5JBnT_s4_3X1vY7o/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<ul>
<li><a href="https://soundcloud.com/nebogeo/fish-factory-algorave-penryn-2019-dave-griffiths" target="_blank">https://soundcloud.com/nebogeo/fish-factory-algorave-penryn-2019-dave-griffiths</a></li>
</ul>
<br />
<br />
<a href="https://www.norahlorway.com/about" target="_blank">Dr Norah Lorway</a> is also a pioneer of the algorave movement, but sadly was unable to join us at this particular evening. You can hear her set, titled, <b>This Is How The World Will End</b>, from her previous algorave here - it is particularly sublime:<br />
<ul>
<li><a href="https://xylemrecords.bandcamp.com/album/this-is-how-the-world-will-end-2">https://xylemrecords.bandcamp.com/album/this-is-how-the-world-will-end-2</a></li>
</ul>
<br />
<br />
<h3>
Thoughts</h3>
Algorithmic art is about creating art, in all its forms, from primarily logical or mathematical processes. Live coding music is very much in this tradition, and that's why we wanted to showcase this form of art as part of the Algorithmic Art Season.<br />
<br />
We were very lucky to have such talented musicians share their passion with us. Everyone found the performances captivating, not only because there was a visual element accompanying the music, but because being in the presence of live performing musicians is always an immediate and personal experience.<br />
<br />
I was particularly impressed with how everyone came together, the musicians and Rose's team at the studios, to make this wonderful evening happen, most of it with last minute changes of plan.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7m5__VjESIQqPsbd7r_3I6IUNDPofhN7SYU00qu3gHmQreVQ5JMy449JqKS4rJGxt78jtX-OjS5zn5kDfU0Uw1NHgNhen-rGFQibwo3EYhb0l5gI2ZEnK2tzIWZ3DsgoAxg1I2KU09kUB/s1600/IMG_20191101_194740-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7m5__VjESIQqPsbd7r_3I6IUNDPofhN7SYU00qu3gHmQreVQ5JMy449JqKS4rJGxt78jtX-OjS5zn5kDfU0Uw1NHgNhen-rGFQibwo3EYhb0l5gI2ZEnK2tzIWZ3DsgoAxg1I2KU09kUB/s400/IMG_20191101_194740-01.jpg" width="400" /></a></div>
<br />
There was a a lot of interest and questions during and after the session, and I was encouraged that people wanted to hold algorave evenings again!<br />
<br />
<br />
<h3>
More Reading</h3>
<ul>
<li>The official algorave site: <a href="https://algorave.com/" target="_blank">https://algorave.com/</a></li>
<li>Mixmag article: <a href="https://mixmag.net/feature/algorave" target="_blank">https://mixmag.net/feature/algorave</a></li>
<li>Guardian article: <a href="https://www.theguardian.com/music/2017/nov/30/is-algorave-the-future-of-dance-music-sheffield-algomech-festival" target="_blank">https://www.theguardian.com/music/2017/nov/30/is-algorave-the-future-of-dance-music-sheffield-algomech-festival</a></li>
</ul>
Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-87228591291694154962019-10-29T18:42:00.001-07:002019-10-30T10:04:01.428-07:00Solandra Hands-On Tutorial & Emergent Behaviour In InsectsThis month's London <a href="https://www.meetup.com/Algorithmic-Art/events/263923747/" target="_blank">meetup</a> has two themes, a hands on tutorial on Solandra, a modern opinionated javascript framework for creative coding, and a talk on emergent behaviour in insects.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxaOthpdxOZQqm7B3Zl08Lchy98abFfHaeaI0TzxTGVQq7nSb9iB3gfTJuFXnTR5TA88FKL9kkaBa-VYacXemHq5fskL6lWTwXJk7C8R_daNmkLu_hdvKGQp-hVlAUxrdJ0iPTcWNt4tNa/s1600/curves3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="753" data-original-width="794" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxaOthpdxOZQqm7B3Zl08Lchy98abFfHaeaI0TzxTGVQq7nSb9iB3gfTJuFXnTR5TA88FKL9kkaBa-VYacXemHq5fskL6lWTwXJk7C8R_daNmkLu_hdvKGQp-hVlAUxrdJ0iPTcWNt4tNa/s400/curves3.png" width="400" /></a></div>
<br />
An overview of Solandra, including its rationale, documentation and examples, is here: [<a href="https://github.com/jamesporter/solandra-workshop" target="_blank">link</a>].<br />
<br />
A video of the talk on insects is here: [<a href="https://skillsmatter.com/skillscasts/14675-emergent-behaviour-in-insects" target="_blank">link</a>], and slides here: [<a href="https://tinyurl.com/y4t8aw7r" target="_blank">link</a>].<br />
<br />
<br />
<h3>
Solandra Principles</h3>
James Porter is an experienced technologist and an algorithmic artist. Over time he became frustrated with the limitations and API design choices of Processing and explored other options. He looked at <a href="http://quil.info/" target="_blank">Quil</a>, a Clojure wrapper for JVM Processing, but found it <a href="https://www.amimetic.co.uk/art/" target="_blank">unsatisfactory</a>. He then explored Kotlin, a more modern language that runs on the JVM. His journey ultimately led him to develop Solandra, a javascript framework that, importantly, runs in a web browser.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghAJVXisMZ6mgZAvsfW_3mJTXW2zZdMQI5HzSAYm8T2fMByNb6nCLz1z6LLpV3F-PQ0lzzmRchussOsIfDw0qHDmNRai9GkAOKyEZGKQzuzsp1VYvSJMDuz1LxL6V_PGauIvbF2nSin0b2/s1600/IMG_20191028_184533-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="990" data-original-width="1600" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghAJVXisMZ6mgZAvsfW_3mJTXW2zZdMQI5HzSAYm8T2fMByNb6nCLz1z6LLpV3F-PQ0lzzmRchussOsIfDw0qHDmNRai9GkAOKyEZGKQzuzsp1VYvSJMDuz1LxL6V_PGauIvbF2nSin0b2/s400/IMG_20191028_184533-01.jpg" width="400" /></a></div>
<br />
His experience of both coding and creative frameworks in particular, informed the principles he wanted his new framework to adhere to. You can read more <a href="https://solandra.netlify.com/" target="_blank">here</a>, but notable examples are:<br />
<br />
<ul>
<li>coordinates independent of pixel size, width is always 1.0, height depends on aspect ratio</li>
<li>simple data structure for 2-d coordinates, usable in the form [x. y]</li>
<li><a href="https://en.wikipedia.org/wiki/TypeScript" target="_blank">TypeScript</a> to support coding via autocomplete and type checking</li>
<li>control flow / iteration over common drawing-level abstractions eg tiling, partitions, exploded shapes</li>
<li>rethink counter-intuitive API orthodoxy eg for bezier curves</li>
<li>minimal dependences and quick low-friction compile cycle</li>
<li>support agility to experiment and try new ideas</li>
</ul>
<br />
James has really thought about the most common things that developers do with frameworks like p5js but aren't as simple as they should be. A good example is Solandra providing a very simple time counter, avoiding the need to calculate it indirectly.<br />
<br />
James consciously developed this framework to meet the needs of experienced coders, and didn't design for onboarding newcomers to coding.<br />
<br />
<br />
<h3>
Solandra Illustrative Examples</h3>
James led a hands-on tutorial working through key concepts. He used <b>codesandbox.io</b> a hosted environment with Solandra set up ready for use.<br />
<br />
James provides several tutorials on his website (<a href="https://solandra.netlify.com/quickstart" target="_blank">link</a>), but here we'll look at a small number of examples that illustrate key design concepts for Solandra.<br />
<br />
For the following illustrative examples, you can use Jame's <b>codesandbox</b> environment and modify the code as required: <a href="https://codesandbox.io/s/cold-butterfly-pzq67" target="_blank">link</a>.<br />
<br />
On first loading, you should see the following page with sample code running:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcbXfkGJiJL4wgvEu_UOEBMbILH4q8NVP-g_VEE1MFSs96E214kzMyP7Xxo9x4HaSppAeQQH3lYTGsTXGNs-0DElHnFFxQH9V1FQi6WTR76v56L3__ojNimP5NfV8kkL2eXyAyaJS-fZTp/s1600/Screenshot+2019-10-29+at+14.34.40.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcbXfkGJiJL4wgvEu_UOEBMbILH4q8NVP-g_VEE1MFSs96E214kzMyP7Xxo9x4HaSppAeQQH3lYTGsTXGNs-0DElHnFFxQH9V1FQi6WTR76v56L3__ojNimP5NfV8kkL2eXyAyaJS-fZTp/s400/Screenshot+2019-10-29+at+14.34.40.png" width="400" /></a></div>
<br />
We can edit the code, and it is automatically complied from typescript to javascript and executed, with the results appearing on the right.<br />
<br />
All Solandra code implements a sketch function, the contents of which decide what is drawn or animated.<br />
<br />
<pre class="lang-javascript"><code>
const sketch = (s: SCanvas) => {
// write code here
}
</code></pre>
<br />
You can see the syntax uses modern javascript for conciseness The object <b>s</b> is of type SCanvas, and is the context in which we change colours, draw shapes, and so on.<br />
<br />
Let's illustrate by setting the background colour. This is done via the <b>s</b> object.<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
// set background
s.background(60, 80, 80);
}
</code></pre>
<br />
You should see a light yellow coloured background.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk9dmEYKDWg0-RisyL5sXXDXieDQzwbTd-KtiNHvgrbajnY-yOMSD8RTJKSpyH77YOucORmCqUl9abgg_YqJdVQkzdPs1z1QvddykRmJFuYPei9AuO-pFRUkDEVx8pYGzwUTJsIUspKYfg/s1600/Screenshot+2019-10-29+at+14.53.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk9dmEYKDWg0-RisyL5sXXDXieDQzwbTd-KtiNHvgrbajnY-yOMSD8RTJKSpyH77YOucORmCqUl9abgg_YqJdVQkzdPs1z1QvddykRmJFuYPei9AuO-pFRUkDEVx8pYGzwUTJsIUspKYfg/s400/Screenshot+2019-10-29+at+14.53.17.png" width="400" /></a></div>
<br />
This simple example illustrates who we operate on the canvas via the <b>s</b> object.<br />
<br />
Let's draw a simple shape, a circle. In Soldandra, shapes are objects which we have the power to manipulate. We can choose to draw them, they aren't drawn by default.<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
// set background
s.background(60, 80, 80);
// create circle
const mycircle = new Circle({at: [0.5, 0.5], r: 0.2});
// draw it
s.draw(mycircle);
};
</code></pre>
<br />
You can see we're first creating a new circle object and calling it <b>mycircle</b>. The parameters are concisely expressed and intuitive, the circle is centred on the canvas at <b>(0.5, 0.5)</b> and has a radius of <b>0.2</b>. You should see a nice circle like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUZC9T8fao3vysp0gzMqx69zZZnjdAGZ-eptyHxnlRqdPwwnzBGI4tGK_Om6vTOMWvlyBaEu-AXAYT_qpCDazqitcjor9jrUYkvf1AS1va20gAjiFBP8r719euLFeysczN8VcMrjFEAt1K/s1600/Screenshot+2019-10-29+at+15.09.27.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUZC9T8fao3vysp0gzMqx69zZZnjdAGZ-eptyHxnlRqdPwwnzBGI4tGK_Om6vTOMWvlyBaEu-AXAYT_qpCDazqitcjor9jrUYkvf1AS1va20gAjiFBP8r719euLFeysczN8VcMrjFEAt1K/s400/Screenshot+2019-10-29+at+15.09.27.png" width="400" /></a></div>
<br />
Very often we don't need to keep the object around for further operations so it is common to create the shape and draw it immediately, like this:<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
// set background
s.background(60, 80, 80);
// draw filled circle
s.fill( new Circle({at: [0.5, 0.5], r: 0.2}) );
};
</code></pre>
<br />
You can see we've used s.fill() instead of s.draw() which draws a filled circle instead of the outline.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtgw1oDu9qqKTRu5Q9U85mq1V0ejZHDCtkGcz7BKf-Xrj9-mOiRqYVTxxWsXSfj9eBkjJ58tiB40boe2sQSK-x3rZ8mWqt5gjfbhdbisfcz-jZzPz6ETQQNApoujXwkOmP8AAVnDht04Fu/s1600/Screenshot+2019-10-29+at+15.14.22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtgw1oDu9qqKTRu5Q9U85mq1V0ejZHDCtkGcz7BKf-Xrj9-mOiRqYVTxxWsXSfj9eBkjJ58tiB40boe2sQSK-x3rZ8mWqt5gjfbhdbisfcz-jZzPz6ETQQNApoujXwkOmP8AAVnDht04Fu/s400/Screenshot+2019-10-29+at+15.14.22.png" width="400" /></a></div>
<br />
A very common task is to move over the canvas in regular steps and do something at those points. This is a basis for many works of algorithmic art. James provides a convenience function for iterating over one dimensional and two dimensional grids.<br />
<br />
It is easiest to see the code:<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
// Hue, saturation and lightness (alpha)
s.background(60, 80, 80);
s.forTiling({ n: 7, type: "square", margin: 0.1 }, (pt, [d], c, i) => {
s.setFillColor(i*5, 80, 40, 0.4);
s.fill(new Circle({ at: c, r: 0.05 }));
});
};
</code></pre>
<br />
Here the forTiling() function takes intuitive parameters, the number of grid subdivisions, the type of tiles, and size of the margin around the edge of the canvas. In return it creates variables which provide the position of each tile, its dimensions, its centre and an overall count. You can see we're using the count <b>i</b> to set a fill colour, and then drawing a circle at the centre of each imaginary tile.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQc7TkUMFTruHkjdpfiBmgNFpRoYahnTTZAQLiaJFw3rfPZV-fXdiv5anfGtd4xhhAXu18wfJKJ19USy9EF2cVCZGB1qVHJI24SpsR8_XvN-G9Uexq7fM0eCNpHeoJdCTgpF-Clq8oKLxW/s1600/Screenshot+2019-10-29+at+15.39.46.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQc7TkUMFTruHkjdpfiBmgNFpRoYahnTTZAQLiaJFw3rfPZV-fXdiv5anfGtd4xhhAXu18wfJKJ19USy9EF2cVCZGB1qVHJI24SpsR8_XvN-G9Uexq7fM0eCNpHeoJdCTgpF-Clq8oKLxW/s400/Screenshot+2019-10-29+at+15.39.46.png" width="400" /></a></div>
<br />
Such iterators with callbacks that fill in useful variables are a key design element of James' Solandra. It is useful to think how much more effortful the code to achieve this tiling pattern in plain p5.js would be.<br />
<br />
James has done a lot of <a href="https://www.amimetic.co.uk/art/bezier" target="_blank">thinking</a> about bezier curves, which are intuitive to create interactively, in vector drawing tools for example, but are more difficult to code. Solandra makes it easier to imagine curves and translate that vision to code, by focussing on what's intuitive - the key points and the curvature of the curve between those points.<br />
<br />
The following code, taken from one of Jame's online <a href="https://solandra.netlify.com/view?sketch=3&category=API%20Samples" target="_blank">sample</a> sketches, illustrates the construction of curves.<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
// Hue, saturation and lightness (alpha)
s.background(0, 0, 50);
s.forTiling({ n: 12, margin: 0.1 }, ([x, y], [dX, dY]) => {
s.setStrokeColor(20 + x * 40, 90 - 20 * y, 50)
s.draw(
Path.startAt([x, y + dY]).addCurveTo([x + dX, y + dY], {
polarlity: s.randomPolarity(),
curveSize: x * 2,
curveAngle: x,
bulbousness: y,
})
)
})
};
</code></pre>
<br />
We can see a tiling iterator dividing the canvas into a 12x12 grid. A curve, Path(), is started at a point (x, y+dY) and as the iterator moves along the grid, subsequent points (x+dX, y+dY) are added to it. Each segment has its own parameters like polarity, curve size, curve angle (approx asymmetric skew), and bulbousness around the endpoints.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8nqWBygmGP1iod9SrXDdoG0C__600HFEhwaiRM4EWBCjEzQBsYmzkR41tH8ccuu3fTbBIzwLIYXWo1BkNum_KthesfYXVkiciFmWWjoRHxaQb33IPhnv-He40_0J9zlnN_DxQN2oo56et/s1600/Screenshot+2019-10-29+at+22.44.13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="806" data-original-width="1600" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8nqWBygmGP1iod9SrXDdoG0C__600HFEhwaiRM4EWBCjEzQBsYmzkR41tH8ccuu3fTbBIzwLIYXWo1BkNum_KthesfYXVkiciFmWWjoRHxaQb33IPhnv-He40_0J9zlnN_DxQN2oo56et/s400/Screenshot+2019-10-29+at+22.44.13.png" width="400" /></a></div>
<br />
You can see that as the curves progress to the right, the curve size increases. You can experiment by changing those curve parameters to see the effect on the curves.<br />
<br />
One interesting area of flexibility is that shapes are objects before they are rendered. That means they can be operated upon or subject to filters. The following shows an example of this.<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
s.background(0, 0, 60);
s.setFillColor(0, 80, 40, 0.3);
s.lineWidth = 0.01;
const h = new RegularPolygon({at: s.meta.center, n: 8, r: 0.2});
s.setStrokeColor(220, 80, 40, 0.2);
s.draw(h);
const h2 = h.path.segmented
.flatMap(e => e.exploded({ scale: 0.8, magnitude: 1 }))
.map(e => e.rotated(s.gaussian({ sd: 0.1 })))
.forEach(e => {
s.fill(e);
})
s.lineWidth = 0.003;
s.setStrokeColor(270, 60, 40, 0.2);
s.times(40, () => {
const h3 = h.path.curvify(
() => ({
curveSize: 1+s.gaussian({ mean: 0.5, sd: 0.5 }),
curveAngle: s.gaussian({ mean: 0.0, sd: 0.5 }),
})
)
s.draw(h3);
})
};
</code></pre>
<br />
You can see that we first create a polygon <b>h</b> with <b>8</b> sides, and it is drawn as an outline. We then create a new shape <b>h2</b> from <b>h</b>. We do this by converting the octagon into paths and segmenting the shape. This collection of segments is exploded with scaling and rotated by a small random amount. Each item is plotted as a filled shape.<br />
<br />
Finally we create a new shape <b>h3</b> from <b>h</b> and this time the paths are converted from lines to curves, with some randomness in their curve size and angle. This is actually done <b>40</b> times using a times() convenience function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNWWomn-bZIsDqRloKWTeEHc_YIZUwqx88nV_lOR6-s7LPVqLIlcWmobudz6VWP5iXC0Vv45HQdvHKK6teLZPSeqBDN3rgXekHvdtqzxcoHJ5BF1Rx2yjHdiktqlhH8MYrzef-A1nPXI-Y/s1600/Screenshot+2019-10-30+at+00.56.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="806" data-original-width="1600" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNWWomn-bZIsDqRloKWTeEHc_YIZUwqx88nV_lOR6-s7LPVqLIlcWmobudz6VWP5iXC0Vv45HQdvHKK6teLZPSeqBDN3rgXekHvdtqzxcoHJ5BF1Rx2yjHdiktqlhH8MYrzef-A1nPXI-Y/s400/Screenshot+2019-10-30+at+00.56.42.png" width="400" /></a></div>
<br />
You can see the octagon, the segmented exploded shapes, as well as the curves created from the corners of the octagon.<br />
<br />
We can simplify the code to create a design using only the curves.<br />
<br />
<pre class="lang-javascript"><code>
export const sketch = (s: SCanvas) => {
s.background(0, 0, 60);
s.lineWidth = 0.01;
const h = new RegularPolygon({at: s.meta.center, n: 8, r: 0.2});
s.lineWidth = 0.002;
s.setStrokeColor(270, 60, 20, 0.1);
s.times(300, () => {
const h3 = h.path.curvify(
() => ({
curveSize: 1.0+s.gaussian({ mean: 0.5, sd: 0.5 }),
curveAngle: s.gaussian({ mean: 0.0, sd: 0.5 }),
})
)
s.draw(h3);
})
};
</code></pre>
<br />
The results are pretty effective.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaqJMjzijHYlxnCu_VZFqTArAfWjKGrRb9zik7kICGB0q8qbPPeiqLZFXdOkXqkeHfNhAwszfmrLiBpSvRGFakr7PxixVYmFbnWz8BIUc7RBvK2pWxy48AetqLmApVF6QS6oZK8GT0Efd7/s1600/curveshairy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="753" data-original-width="794" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaqJMjzijHYlxnCu_VZFqTArAfWjKGrRb9zik7kICGB0q8qbPPeiqLZFXdOkXqkeHfNhAwszfmrLiBpSvRGFakr7PxixVYmFbnWz8BIUc7RBvK2pWxy48AetqLmApVF6QS6oZK8GT0Efd7/s400/curveshairy.png" width="400" /></a></div>
<br />
<br />
<h4>
Emergent Behaviour in Insects</h4>
We also had a talk by an invited specialist in insect behaviour, Alison Rice, founder of <a href="https://www.facebook.com/TiraEco/" target="_blank">Tira Eco</a>, a biotech startup working to develop more natural and sustainable approaches to waste recycling.<br />
<br />
Given how much of algorithmic art is modelling or simulating how nature works, whether is it crystalline grown or the flocking behaviour of boids, I thought it would be interested to hear directly from a scientist working with insects directly.<br />
<br />
Her talk was fascinating and energetic, and generated a lot of interest and questions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5eN7Xm-m7p2daVbaMl1ZUUfPx-nyQuKDVAOrqmsG_VZ-es114Dk0x3WQVHbeJ3kGaqwz14BPg-f0QTRYvYiNxWqb0rTX3G_k5vyekZgxOi5z8wCeApEvAONp9yk6Rih0DOIESwwH9-21U/s1600/IMG_20191028_202018-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="779" data-original-width="1600" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5eN7Xm-m7p2daVbaMl1ZUUfPx-nyQuKDVAOrqmsG_VZ-es114Dk0x3WQVHbeJ3kGaqwz14BPg-f0QTRYvYiNxWqb0rTX3G_k5vyekZgxOi5z8wCeApEvAONp9yk6Rih0DOIESwwH9-21U/s400/IMG_20191028_202018-01.jpg" width="400" /></a></div>
<br />
Her <a href="https://tinyurl.com/y4t8aw7r" target="_blank">slides</a> include videos showing how maggots appear to self-organise once their population density increases around food. It is understood this emergent behaviour optimises overall group energy efficiency.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8uONN7jrPHbR4nQjsVMzUBMuklRk-AADb2-luSoa6HJ7PVYZzH_IHX-zzl0CoU_MKdT7luyW9EkJJRiqR0sICaYtVIkGgoW5LbOOL6I7yy2clG5cqshA3wrTuG2pM-QDnhH9vmfWwtuiN/s1600/Screenshot+2019-10-30+at+01.29.18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1256" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8uONN7jrPHbR4nQjsVMzUBMuklRk-AADb2-luSoa6HJ7PVYZzH_IHX-zzl0CoU_MKdT7luyW9EkJJRiqR0sICaYtVIkGgoW5LbOOL6I7yy2clG5cqshA3wrTuG2pM-QDnhH9vmfWwtuiN/s400/Screenshot+2019-10-30+at+01.29.18.png" width="313" /></a></div>
<br />
The emergent geometric forms are fascinating!<br />
<br />
<br />
<h3>
Thoughts</h3>
It was particularly exciting to see someone challenge the orthodoxy around APIs and coding patterns and design a modern framework for creative coding, based on the actual experience of developers who had started to hit the limits of popular frameworks like Processing and p5js.<br />
<br />
Personally, I think not enough is done to actually design programming languages and the metaphors and abstractions they give developers.<br />
<br />
One of my own needs, and of many others based on queries and web analytics, is for a creative coding framework like p5js or Solandra to output a vector drawing, in SVG for example. Perhaps this is a future project for me!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgarBuh1wDO0Re9dI1H5PRWsbvHjnytxYHDRellWuLBuP9-_So7b7i1XPxt7HE90d5_focu-d5wEsfQ77fR5IJlhjVpBZjXPeRgOLrCnKiRd9sYIdQLGNxa1yvEf6eBcSmuoC9PVWbug-KG/s1600/IMG_20191028_201335-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1004" data-original-width="1600" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgarBuh1wDO0Re9dI1H5PRWsbvHjnytxYHDRellWuLBuP9-_So7b7i1XPxt7HE90d5_focu-d5wEsfQ77fR5IJlhjVpBZjXPeRgOLrCnKiRd9sYIdQLGNxa1yvEf6eBcSmuoC9PVWbug-KG/s400/IMG_20191028_201335-01.jpg" width="400" /></a></div>
<br />
<br />
I was really pleased that the group was excited by having Alison, a specialist in her field, bring her more direct experience and expertise of the natural world into a group which very often models that world only code.<br />
<br />
Feedback strongly suggested we do that more often!<br />
<br />
<br />
<h3>
References</h3>
<ul>
<li>Solandra cheatsheet: <a href="https://github.com/jamesporter/solandra/blob/master/src/docs/cheat-sheet.md">https://github.com/jamesporter/solandra/blob/master/src/docs/cheat-sheet.md</a></li>
<li>Example sketched with source code organised by API type: <a href="https://solandra.netlify.com/api-samples">https://solandra.netlify.com/api-samples</a></li>
</ul>
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-5645392120051800722019-10-27T06:57:00.000-07:002019-10-27T06:57:14.166-07:00 Blender 3D Basics and Python CodingThis month's Cornwall <a href="https://www.meetup.com/Algorithmic-Art/events/263298578/" target="_blank">meetup</a> was a newcomer's introduction to the every powerful Blender 3D tool.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizjRYJKHXpqzAENJNsrndc8j2Ep7p-lgpZ_4xjS9Z59G_3wqE9jHyN5DobFyXj8ixCY9axdmKwLrSos4IUA8G8WfgBz2rhFvXDvUwXGunSgM8vOkQygWs-axI5a8LPSzWb4r_Fq7xbUlYn/s1600/IMG_20191024_174555.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizjRYJKHXpqzAENJNsrndc8j2Ep7p-lgpZ_4xjS9Z59G_3wqE9jHyN5DobFyXj8ixCY9axdmKwLrSos4IUA8G8WfgBz2rhFvXDvUwXGunSgM8vOkQygWs-axI5a8LPSzWb4r_Fq7xbUlYn/s400/IMG_20191024_174555.jpg" width="400" /></a></div>
<br />
Jon's notes and references for the session are here: <a href="https://tinyurl.com/y38bj4go">(pdf)</a>.<br />
<br />
<br />
<h3>
Blender 3D</h3>
<a href="https://en.wikipedia.org/wiki/Blender_(software)">Blender 3D</a> is very powerful tool for creating 3d scenes. It has been around for 20 years and has grown in popularity, capability and quality.<br />
<br />
It can be used to create 3d models and scenes, render them, animate them, use physics to control motion, and ray tracing for more realistic rendering. It can can do even more than the core function of 3d modelling, for example video editing and compositing. Until very recently, it included a game engine, but this was removed to focus more on its core strengths.<br />
<br />
The amazing thing about Blender, a professional-grade tool, is that it is free and open source. This not only makes high quality modelling and rendering accessible - it also opens up the software for inspection, modification and enables a vibrant community to grow around it.<br />
<br />
Jon Buckby is a designer and illustrator living in Cornwall who uses Blender to great effect. We were very lucky to have him provide a beginner's introduction to Blender, taking us through the process step-by-step. This was incredibly useful because Blender's interface has been intimidating for many years, and even with the recent modernisation, is still not entirely intuitive.<br />
<br />
In this blog, we won't duplicate Jon's walkthrough, but instead use the knowledge he imparted to create a simple scene for new readers to be able to follow.<br />
<br />
A key reason an algorithmic artist might explore Blender is that it has a Python interface, which means scenes can be created algorithmically. We'll also demonstrate this with the simplest example.<br />
<br />
<br />
<h3>
Simple Operations</h3>
When first launching Blender 2.80 the interface looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcdgq_r7fUWP8tXCeo2hMzT5H2OmURNWGL6CiaZbuluQYqQP2uR8fYArW-fsHWVAcQQPDBEf1eCannKDYE1GXg1O1RNdppZWmuNQXPm8GMjsPYMg2zNWDnhFhZOJAKyd3ol355i2kQsD2Y/s1600/Screenshot+2019-10-26+at+16.53.29.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="971" data-original-width="1600" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcdgq_r7fUWP8tXCeo2hMzT5H2OmURNWGL6CiaZbuluQYqQP2uR8fYArW-fsHWVAcQQPDBEf1eCannKDYE1GXg1O1RNdppZWmuNQXPm8GMjsPYMg2zNWDnhFhZOJAKyd3ol355i2kQsD2Y/s400/Screenshot+2019-10-26+at+16.53.29.png" width="400" /></a></div>
<br />
This shows a 3d scene with a pre-created cube. There are a huge number of menus and controls and buttons which can be intimidating - ignore them for now.<br />
<br />
Click on the scene and then clicking on the cube shows how objects are selected, shown visually with a light orange border. With a trackpad, two fingers can be used to rotate our own view of the scene.<br />
<br />
You can choose to set the view to be directly from the front, top, side etc, using the View menu like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidhRBqwJ2uBkNiozwV1_LfWsVh65uqkN_zRoqgOxxIFpg5ohJR9Ib-EaVthrV0d1t2H3tnIus7fe081St68tHkF17MYkAQ99n4Iu2zxhPgNZXtS6gNW9mqXtRTwOkiNvYv5r5U-l_WJDEH/s1600/Screenshot+2019-10-26+at+17.07.03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1054" data-original-width="1600" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidhRBqwJ2uBkNiozwV1_LfWsVh65uqkN_zRoqgOxxIFpg5ohJR9Ib-EaVthrV0d1t2H3tnIus7fe081St68tHkF17MYkAQ99n4Iu2zxhPgNZXtS6gNW9mqXtRTwOkiNvYv5r5U-l_WJDEH/s400/Screenshot+2019-10-26+at+17.07.03.png" width="400" /></a></div>
<br />
After selecting the front-on view, ensure the cube is selected and then make a copy. We do this by right clicking the cube to bring up a context menu, and selecting Duplicate Objects:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia_VoH4MNE8mCdPkZ-6w_Bkg0WEl-3rVWS5j123Zb0sza1Q-Pnfk3xW0oyLUGYZwoLrclE2bkEC7f1wS_eiCFbW7fqiEAYvlXtqTqPdBUmRL6TV8QNLxdjkUMvFlikihzt25XPIzmr5gGN/s1600/Screenshot+2019-10-26+at+17.10.37.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1031" data-original-width="1404" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia_VoH4MNE8mCdPkZ-6w_Bkg0WEl-3rVWS5j123Zb0sza1Q-Pnfk3xW0oyLUGYZwoLrclE2bkEC7f1wS_eiCFbW7fqiEAYvlXtqTqPdBUmRL6TV8QNLxdjkUMvFlikihzt25XPIzmr5gGN/s400/Screenshot+2019-10-26+at+17.10.37.png" width="400" /></a></div>
<br />
This will create a second cube which floats around with your pointer. We can force it to move along a single direction by pressing X, Y or Z for the axis we want to enforce. By pressing X it will only move directly to the left or right of the original cube. Once it is to the right of the original clicking will set its place.<br />
<br />
We can select multiple objects using the Shift key. Select both and move the viewpoint around so we can see the cubes at an angle.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPWyVRDRibWWSsRAYKcGf02VHYDIgjNdUDWmBRtrWDA4pqi4zFZ0KD4IwUXgkwWuM7twqc-2ji4TTMQtX2Xg-GgVhbJvFnFhb3bqPvWk6Ik6cKALFmQr6vJQpw4WZja6KfWoviPCM5GoqM/s1600/Screenshot+2019-10-26+at+17.18.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="971" data-original-width="1600" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPWyVRDRibWWSsRAYKcGf02VHYDIgjNdUDWmBRtrWDA4pqi4zFZ0KD4IwUXgkwWuM7twqc-2ji4TTMQtX2Xg-GgVhbJvFnFhb3bqPvWk6Ik6cKALFmQr6vJQpw4WZja6KfWoviPCM5GoqM/s400/Screenshot+2019-10-26+at+17.18.04.png" width="400" /></a></div>
<br />
Let's now add a sphere. Go back to the front view and use the Add->Mesh menu to add an ico sphere. If you're interested in the difference between a uv sphere and an ico sphere, here is a discussion: <a href="https://blender.stackexchange.com/questions/72/what-is-the-difference-between-a-uv-sphere-and-an-icosphere">link</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6gq0Gu44SUnDxB4nh61vRKvH5K9fJr1wNMTq50qkIkdmfPqgY6JvvqEyta99WLGFMGDTTAZHbYowUGGmd_lgWBkTOHmSefXIDBUUKUiBY0MVmRH1VbeQibD4ITGzXxLCsGZqLuQNmpwn_/s1600/Screenshot+2019-10-26+at+18.25.10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="958" data-original-width="1523" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6gq0Gu44SUnDxB4nh61vRKvH5K9fJr1wNMTq50qkIkdmfPqgY6JvvqEyta99WLGFMGDTTAZHbYowUGGmd_lgWBkTOHmSefXIDBUUKUiBY0MVmRH1VbeQibD4ITGzXxLCsGZqLuQNmpwn_/s400/Screenshot+2019-10-26+at+18.25.10.png" width="400" /></a></div>
<br />
The sphere will be added but you might have to look closely to see that it falls where the cube is. To move it we press the G key. Press X and Z to move it along and up so it is above and between the two cubes. Blender users quickly adopt key shortcuts to speed up their working, and you'll also start adopting them for the most common tasks.<br />
<br />
Rotate the view to see all three objects from an angle like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwK7tK0rVzCF7A1yWe0oFFV9t2j2h8HwK-Lt9TZqv7GK9oN4Qkw-JQimR_Q2k51iUQsHhAEvbKd4awIhc5HiOdjF1rWxtEn3Ryj_cXwAuMulKW9Tr6OYj8iN5mlG8ztpr6wlP2WEqnP2EB/s1600/Screenshot+2019-10-26+at+18.26.23.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="971" data-original-width="1600" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwK7tK0rVzCF7A1yWe0oFFV9t2j2h8HwK-Lt9TZqv7GK9oN4Qkw-JQimR_Q2k51iUQsHhAEvbKd4awIhc5HiOdjF1rWxtEn3Ryj_cXwAuMulKW9Tr6OYj8iN5mlG8ztpr6wlP2WEqnP2EB/s400/Screenshot+2019-10-26+at+18.26.23.png" width="400" /></a></div>
<br />
Let's take a look at the scene from the view of the camera, which you might have noticed floating in the scene as a wireframe pyramid-like object. Use the View menu to choose Viewport->Camera.<br />
<br />
We now see the scene from the perspective of the camera.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwffXExw3qftiGvCtWwJjuHlDAthnRIEjRMLib1G0EOEndQ7PLfE4yF7IKo86-fTMQeVb-qfGdRn_0vPt0puF4vbp_PYdHhiyfcZblHzumBva3YZ9ztmBOnle8sUHxgHeo2gYqdXXgwb5o/s1600/Screenshot+2019-10-26+at+18.47.01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1061" data-original-width="1600" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwffXExw3qftiGvCtWwJjuHlDAthnRIEjRMLib1G0EOEndQ7PLfE4yF7IKo86-fTMQeVb-qfGdRn_0vPt0puF4vbp_PYdHhiyfcZblHzumBva3YZ9ztmBOnle8sUHxgHeo2gYqdXXgwb5o/s400/Screenshot+2019-10-26+at+18.47.01.png" width="400" /></a></div>
<br />
The objects are close to the camera and so a little cropped. We could move the camera, or move the objects back, or scale them to a smaller size. Let's do the latter as it is a new operation. Select all the cubes and spheres, by shift-clicking them, or choosing them in the scene collection at the top right of the interface. Then press S to scale the objects by moving your pointer. Once they fit nicely in the view, click to finalise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIrnmG8NrPAAPunXM0kYCQ8ZyScMcrORjHz5UUdfV2xlJxfa6GFBZOtJpRxxwdBYz4FPf0_w-eLubLlFHsk7ee_SBp1n4j2tvOZf2F8Y8GcYwD3oU9njWPQ13vevb63i0afGSF2f6OBXmM/s1600/Screenshot+2019-10-26+at+18.52.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1600" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIrnmG8NrPAAPunXM0kYCQ8ZyScMcrORjHz5UUdfV2xlJxfa6GFBZOtJpRxxwdBYz4FPf0_w-eLubLlFHsk7ee_SBp1n4j2tvOZf2F8Y8GcYwD3oU9njWPQ13vevb63i0afGSF2f6OBXmM/s400/Screenshot+2019-10-26+at+18.52.02.png" width="400" /></a></div>
<br />
Let's render the scene. What we've been looking at is just a quick preview. When we have the scene arrangement as we want it, we ask Blender to take more care over how it colours the objects, taking into account colour, texture, lighting and shadows.<br />
<br />
Select Render Image from the Render menu. After a short pause, a new window will pop up with the rendered image. We can use the Image->Save menu to save the image if we wanted to export it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRZssSzYGGYUyrWrdcYzX5fwn9uAEFplpxyLiSyY5OPn4LFWzPpE1sV4bVI6J5fAyIuCSm3XMF8hu9VX2DPiqdCzLt4L8EcJrMtwMivjpNx9Y3qjACFSEmXMQlOyyGd5cwUhUL4CljM66q/s1600/Screenshot+2019-10-26+at+18.56.56.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1066" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRZssSzYGGYUyrWrdcYzX5fwn9uAEFplpxyLiSyY5OPn4LFWzPpE1sV4bVI6J5fAyIuCSm3XMF8hu9VX2DPiqdCzLt4L8EcJrMtwMivjpNx9Y3qjACFSEmXMQlOyyGd5cwUhUL4CljM66q/s400/Screenshot+2019-10-26+at+18.56.56.png" width="400" /></a></div>
<br />
The rendering does take into account light and shade. We can see the sphere casts a shadow onto the cubes. But overall the image isn't that exciting.<br />
<br />
Let's add colour to the objects. To do this we need to think more broadly about the material applies to the surface of the object, which can have many more properties than just colour.<br />
<br />
With the sphere selected, choose the material view on the right hand view of options. Add a new material as shown:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid6wy3LX0_686Athbowkd-46oYtP3FBDYDecXxT_g0VVR5ha_Pj7VCfa08zDiS0AmaslDwYS0OQvickArx2ijpENq-hCgRz7D91ZwwUpEHZBUEqoA414HI9emPiZxadMQbj5a1n0gAZTEd/s1600/Screenshot+2019-10-26+at+19.05.01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1051" data-original-width="1600" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid6wy3LX0_686Athbowkd-46oYtP3FBDYDecXxT_g0VVR5ha_Pj7VCfa08zDiS0AmaslDwYS0OQvickArx2ijpENq-hCgRz7D91ZwwUpEHZBUEqoA414HI9emPiZxadMQbj5a1n0gAZTEd/s400/Screenshot+2019-10-26+at+19.05.01.png" width="400" /></a></div>
<br />
Once a new material has been created, we see it has many options for how it behaves and appears.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB0cVwTM_PenDxWaUoqHuI3JKwB_mwCvEZhe4BoW4UR2IQUn3DuBWdqA09FcDQfCYerjGFVkEghvajenpiv2XAIlIzerUGpAqFPWwOHZHQCZh57Y093dhAmD30ixhWYE5uvjk1B0uhStBp/s1600/Screenshot+2019-10-26+at+19.06.05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1202" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB0cVwTM_PenDxWaUoqHuI3JKwB_mwCvEZhe4BoW4UR2IQUn3DuBWdqA09FcDQfCYerjGFVkEghvajenpiv2XAIlIzerUGpAqFPWwOHZHQCZh57Y093dhAmD30ixhWYE5uvjk1B0uhStBp/s400/Screenshot+2019-10-26+at+19.06.05.png" width="400" /></a></div>
<br />
<br />
Change the Base Colour to a bright red. Try changing the Metallic property to be around 50%, as shown:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjguY7mOFuMuMcg9Dd4cXXGL9d1DLhZbZnJBaSpcu-kTgXx20Y_hg5nM-Gn7RdZxCQ0tNWnuldvqnohagrxjMwuOd8O-dkFRzUSlR0tyuHnkVVA5msIzZWN_HBSP3XNtv7Fc8p863laNEAZ/s1600/Screenshot+2019-10-26+at+19.09.29.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="746" data-original-width="1105" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjguY7mOFuMuMcg9Dd4cXXGL9d1DLhZbZnJBaSpcu-kTgXx20Y_hg5nM-Gn7RdZxCQ0tNWnuldvqnohagrxjMwuOd8O-dkFRzUSlR0tyuHnkVVA5msIzZWN_HBSP3XNtv7Fc8p863laNEAZ/s400/Screenshot+2019-10-26+at+19.09.29.png" width="400" /></a></div>
<br />
Render the image again. This time we can see the sphere is now red and shiny as if it was metallic.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSkmmA_h2aiaRGeu35w0smP5X8-IRHw2bim72u6MIOfPmaRWiSJNHAAA1zPyLrw0E73c3zFRbGzqIzPBDkTJQcBP1nv2Jku-5KDQEHj8B34nFsjZIErdyJT-R5BYElzc-P0i3iu-Kcua-k/s1600/render1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSkmmA_h2aiaRGeu35w0smP5X8-IRHw2bim72u6MIOfPmaRWiSJNHAAA1zPyLrw0E73c3zFRbGzqIzPBDkTJQcBP1nv2Jku-5KDQEHj8B34nFsjZIErdyJT-R5BYElzc-P0i3iu-Kcua-k/s400/render1.png" width="400" /></a></div>
<br />
We can select the two cubes together and apply a new material to them both. Let's try a green colour but keep the metallic nature at zero.<br />
<br />
Here's the resulting rendered image.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq7X68B9PJjjHn4EVRT3Et-ghq-JzlJCB2UsCHxlqnwtggZhviOYy1_4YdZ-XKy1rYelEbE6impbYMJX_YiXyl79J_QfZTKAWJMt3bfgExVwlgcN6WxRD1i5yntxwZmwsMrQxnKmH3WYqc/s1600/render2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq7X68B9PJjjHn4EVRT3Et-ghq-JzlJCB2UsCHxlqnwtggZhviOYy1_4YdZ-XKy1rYelEbE6impbYMJX_YiXyl79J_QfZTKAWJMt3bfgExVwlgcN6WxRD1i5yntxwZmwsMrQxnKmH3WYqc/s400/render2.png" width="400" /></a></div>
<br />
That sphere doesn't really look like a sphere. You can clearly see it is made of triangles. Almost everything in Blender is made of flat surfaces, and to approximate curved objects we increase the number of such flat surfaces.<br />
<br />
In Blender, we can subdivide these triangles after the sphere has been created, but a good habit is to create the sphere with a higher number of triangles in the first place. Delete that sphere and add a new one. When you do, you'll see in the bottom left a window showing the number of subdivision to do when creating the sphere. Increase it to a higher number like 6:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFHhMrzTVXBHMl0zdVkJnRNouY-CrfFhwDmPtIZ28oe8lfWdAJarTW5-vJHJ_BdjrOqQ4yJ6Zpya8k_H6US1e2UK2NrV90hLZEi5_zb4nfW6S6EK8p00o3-kgZ_6nukiKE4zxN8FUAnwb8/s1600/Screenshot+2019-10-26+at+22.07.55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1600" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFHhMrzTVXBHMl0zdVkJnRNouY-CrfFhwDmPtIZ28oe8lfWdAJarTW5-vJHJ_BdjrOqQ4yJ6Zpya8k_H6US1e2UK2NrV90hLZEi5_zb4nfW6S6EK8p00o3-kgZ_6nukiKE4zxN8FUAnwb8/s400/Screenshot+2019-10-26+at+22.07.55.png" width="400" /></a></div>
<br />
Move the sphere to where it should be. You can scale it using the S key. Re-apply the metallic red material we created earlier. Rendering the scene now has a smoother sphere.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq8RWu4Jqj8743JkBss9JkBkVtxkS4QFZbZXlXrf-HZcTZHErNv7vmxb75jReZGEjZF4cMrrC6aa9TeO8Bl2HRQhtpyKpvo-y2rKSy6YLfiwHs2j1Jaj3xptX11kmMmI9QpbWCfgBrbgPB/s1600/render3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq8RWu4Jqj8743JkBss9JkBkVtxkS4QFZbZXlXrf-HZcTZHErNv7vmxb75jReZGEjZF4cMrrC6aa9TeO8Bl2HRQhtpyKpvo-y2rKSy6YLfiwHs2j1Jaj3xptX11kmMmI9QpbWCfgBrbgPB/s400/render3.png" width="400" /></a></div>
<br />
Now that we have the basics of how to create, move, scale and add materials to objects, it doesn't take long to create translucent materials, broaden the light source to create softer shadows, add a plane .. to give a more interesting scene.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAjune1aZZoji4OTNe3w5zhelfj8cuDFZvG4OPCa5sZC7oyFGmOR0sRcu02Alow6WjWaMlToEGxozzBAie5N64kylCTcMk70ttFuRDlPtLD_249TAnfMAj6DmVvVFdqqG9fvM2FZXq4PET/s1600/render4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAjune1aZZoji4OTNe3w5zhelfj8cuDFZvG4OPCa5sZC7oyFGmOR0sRcu02Alow6WjWaMlToEGxozzBAie5N64kylCTcMk70ttFuRDlPtLD_249TAnfMAj6DmVvVFdqqG9fvM2FZXq4PET/s400/render4.png" width="400" /></a></div>
<br />
What we've touched on here is just a small amount of what Blender is capable of.<br />
<br />
The community around Blender is large and vibrant and you'll be inspired by the wide variety of creations, and also find help in the many tutorials and forums.<br />
<br />
Jon referenced several websites, particularly those focussing on sharing pre-prepared models.<br />
<br />
Jon also briefly introduced us to creating animations, compellingly illustrated with a physically realistic cloth falling under gravity.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNzAuHcnaIBp3LZ890pIfaSWcQCfBH-RYE7EkM1_x_CmKQFWkqHB1NBnWCb4d74EfcDZqj3fel0qwvk7R97vvKhbDR9ugGU4sts55xSwzdx3U9nz58E3qsVk8C5lsKM22LJBSHKVULdIcr/s1600/IMG_20191024_192336-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNzAuHcnaIBp3LZ890pIfaSWcQCfBH-RYE7EkM1_x_CmKQFWkqHB1NBnWCb4d74EfcDZqj3fel0qwvk7R97vvKhbDR9ugGU4sts55xSwzdx3U9nz58E3qsVk8C5lsKM22LJBSHKVULdIcr/s400/IMG_20191024_192336-01.jpg" width="400" /></a></div>
<br />
<br />
<h3>
Constructing Scenes with Python</h3>
Blender has a Python interface, which means you can extend it with code you've written in Python. This can take the form of transforms applied to objects or the scene.<br />
<br />
We'll keep things simple enough to see how Python can be used to create objects algorithmically in a scene.<br />
<br />
Start a new scene in Blender and delete the starting cube so there are no objects in the scene, apart from the camera and light. On the top row menu on the right is Scripting. Select this and the view changes. Click New to create an empty source code (text) file for our Python code. Your view should look like this, with the scene preview now smaller an at the top left, and the empty text file centre-stage:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_pP3dNuKmWBNm7igVny86q7Tq-2IFML_XQxXWqsmy79MMEsaGWPqYiBYnLCz9yi2Ughg8JjXC8ADZmvc44sai9Zp8keZRicjUTquM54YsA5B8OHqaOeJo9aIA_nFbjNW7mLd_3iOJTrsE/s1600/Screenshot+2019-10-27+at+11.58.18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="971" data-original-width="1600" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_pP3dNuKmWBNm7igVny86q7Tq-2IFML_XQxXWqsmy79MMEsaGWPqYiBYnLCz9yi2Ughg8JjXC8ADZmvc44sai9Zp8keZRicjUTquM54YsA5B8OHqaOeJo9aIA_nFbjNW7mLd_3iOJTrsE/s400/Screenshot+2019-10-27+at+11.58.18.png" width="400" /></a></div>
<br />
In the empty file, let's write our first code. Type the following:<br />
<br />
<pre class="lang-python"><code>
import bpy
# simple cube
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=5)
</code></pre>
<br />
The first line imports the Blender Python interface. The next line starting with # is a comment, ignored by Python. The last line uses the bpy module to add a cube. You can see the logic - add a mesh of type primitive cube. The parameters are the (x,y,z) location and size.<br />
<br />
Your code should look like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9cL8Hy_7PH_k2GoGZ3ho-djWcxeYOoxrHN204BS38mmdXHmwhxfVM8y0BNIHdf143xCaud-VQXl82OkxZgNX7UKXGGd6bUQUlPrFzXgtnhzBxPy_DkSl6P5gJZhf7l7p7FRu2bGE61COo/s1600/Screenshot+2019-10-27+at+12.08.35.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1600" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9cL8Hy_7PH_k2GoGZ3ho-djWcxeYOoxrHN204BS38mmdXHmwhxfVM8y0BNIHdf143xCaud-VQXl82OkxZgNX7UKXGGd6bUQUlPrFzXgtnhzBxPy_DkSl6P5gJZhf7l7p7FRu2bGE61COo/s400/Screenshot+2019-10-27+at+12.08.35.png" width="400" /></a></div>
<br />
Click Run Script at the top right, and a cube should appear in the scene.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn-Dk7l0HjgbpDT_9yt6pyFSZOUCiOlLZCLwXhnNbtTuU-qd5nqjnuswUPmndlrBLbiXkCKXqGIphSFbUtpnl-4tv_xZrF4VoO3WVLk7b1TqpZ_hAQpalv3Lun3Y3ODHBSMz5MnZaUilg3/s1600/Screenshot+2019-10-27+at+12.12.50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="853" data-original-width="1600" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn-Dk7l0HjgbpDT_9yt6pyFSZOUCiOlLZCLwXhnNbtTuU-qd5nqjnuswUPmndlrBLbiXkCKXqGIphSFbUtpnl-4tv_xZrF4VoO3WVLk7b1TqpZ_hAQpalv3Lun3Y3ODHBSMz5MnZaUilg3/s400/Screenshot+2019-10-27+at+12.12.50.png" width="400" /></a></div>
<br />
Although this might not seem like much of an achievement, what we've done is pretty powerful. Instead of using the pointer and menus to manually create objects, we've used code. This opens up a whole world of possibilities because with code we can easily create many objects and use calculations to decide how they are placed according to an algorithms. Algorithmic animation is also possible but we will stay focussed on our simple example here.<br />
<br />
Let's use Python to demonstrate this. Have a look at the following still simple code.<br />
<br />
<pre class="lang-python"><code>
import bpy
for x in range(-6, 6, 2):
bpy.ops.mesh.primitive_cube_add(location=(x, 0, 0), size=1)
pass
</code></pre>
<br />
You can see we create a loop counter x which starts at -6 and increases to +6 in steps of 2. We then use this variable x to place a small cube at (x, 0, 0). You can see the results, six cubes in a line along the x axis.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKguzE_SxQKTBtjT7QUOHeLFCgruV5lJAJPmmMbDtF6v34A5ZIVnVxLbrqriTaPv6sSzFgx1kthstPK6j5WNKWB9saF4IDfnTzgBjkSa1YNqZByhTeQWgvQlwYRugEje3kSAgjr3CBZ6cJ/s1600/Screenshot+2019-10-27+at+12.23.57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="809" data-original-width="1600" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKguzE_SxQKTBtjT7QUOHeLFCgruV5lJAJPmmMbDtF6v34A5ZIVnVxLbrqriTaPv6sSzFgx1kthstPK6j5WNKWB9saF4IDfnTzgBjkSa1YNqZByhTeQWgvQlwYRugEje3kSAgjr3CBZ6cJ/s400/Screenshot+2019-10-27+at+12.23.57.png" width="400" /></a></div>
<br />
Let's introduce some maths. We can adjust the position of the cubes using a sine wave.<br />
<br />
<pre class="lang-python"><code>
import bpy
import math
import numpy
for x in numpy.arange(-6, 6, 0.5):
y = math.sin(x)
bpy.ops.mesh.primitive_cube_add(location=(x, y, 0), size=0.5)
pass
</code></pre>
<br />
The above code uses the sine() function to calculate a shift along the y-axis for each cube. The cubes are smaller and placed more frequently along the x-axis using numpy.arange() which can count in fractional steps.<br />
<br />
The results are starting to look pretty interesting!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvkhjkSCIWzBsDB_lt9bdpoYTNY_R1DFR8frASj4qVKTPtqEVsvd-8XXL_f8yPW9Wczw7F2EqWlmF9_mNh8WIl_A29osrmRENDvd6qgS6xWrFYl0grZVdHpDvwqx8RcBUurUByszYU670s/s1600/Screenshot+2019-10-27+at+12.29.15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="809" data-original-width="1600" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvkhjkSCIWzBsDB_lt9bdpoYTNY_R1DFR8frASj4qVKTPtqEVsvd-8XXL_f8yPW9Wczw7F2EqWlmF9_mNh8WIl_A29osrmRENDvd6qgS6xWrFYl0grZVdHpDvwqx8RcBUurUByszYU670s/s400/Screenshot+2019-10-27+at+12.29.15.png" width="400" /></a></div>
<br />
Let's extend the cubes in the z-direction, again using a sine wave, but this time use a calculation to diminish the amplitude of the wave.<br />
<br />
<pre class="lang-python"><code>
import bpy
import math
import numpy
for x in numpy.arange(-6, 6, 0.3):
for t in numpy.arange(0, 6, 0.3):
y = 2 * math.sin(x) / (1+t)
bpy.ops.mesh.primitive_cube_add(location=(x, y, t), size=0.3)
pass
pass
</code></pre>
<br />
This time a nested loop is used to count a variable t, which we use as height in the z direction. The wave amplitude is now doubled by divided by (1+t) so the amplitude gets smaller further up the structure.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq2T_9LTnFuozKCwqMjOf-yAXn63LbBAWg9yiHvynfJSNer3A27B8YX00DvQB6opeZoUrFMsCMYGtVC5yCZIyKdUIB6tFVi4UFxHhyphenhyphenOUCgQu6tvBEZdph_6J6GZKd3Jpp62THp6FXUc90J/s1600/Screenshot+2019-10-27+at+12.50.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="1600" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq2T_9LTnFuozKCwqMjOf-yAXn63LbBAWg9yiHvynfJSNer3A27B8YX00DvQB6opeZoUrFMsCMYGtVC5yCZIyKdUIB6tFVi4UFxHhyphenhyphenOUCgQu6tvBEZdph_6J6GZKd3Jpp62THp6FXUc90J/s400/Screenshot+2019-10-27+at+12.50.42.png" width="400" /></a></div>
<br />
That's pretty effective - and we can see how using code is a very powerful way of creating objects and scenes.<br />
<br />
There is lot that the Python interface allows us to do - but we won't cover that here.<br />
<br />
Instead we'll manually add more lights to the scene and render it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikzdYvwJoDiOD8CcMnaxHB2vLu77K_FweEkPBbB3EeYW5PeBfgRsKs9yTsdC5osfyCKWQXNOV0sqBy5kHw9zmvnGa91unneOdqoK089pxSsl2TvbjWEQpPT_qoCKl6DoVgMF0YUcPvWTmf/s1600/pytest1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikzdYvwJoDiOD8CcMnaxHB2vLu77K_FweEkPBbB3EeYW5PeBfgRsKs9yTsdC5osfyCKWQXNOV0sqBy5kHw9zmvnGa91unneOdqoK089pxSsl2TvbjWEQpPT_qoCKl6DoVgMF0YUcPvWTmf/s400/pytest1.png" width="400" /></a></div>
<br />
The results are pretty effective given the simplicity of the techniques we've used - creative and moving cubes, giving them a material, adding lights, and using code to create many cubes algorithmically.<br />
<br />
<br />
<h3>
More Reading</h3>
There is no doubt Blender is a powerful tool, but it is also difficult to learn. Luckily there is a large community around it providing tutorials and support.<br />
<ul>
<li>A nice tutorial demonstrating the use of code to create algorithmic designs <a href="https://medium.com/@behreajj/creative-coding-in-blender-a-primer-53e79ff71e">https://medium.com/@behreajj/creative-coding-in-blender-a-primer-53e79ff71e</a></li>
</ul>
<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com1tag:blogger.com,1999:blog-2044972050276999466.post-87664599627733875172019-09-19T17:32:00.000-07:002019-09-20T12:45:25.769-07:00Creative Uses for Not-So-Random NoiseThis month's <a href="https://www.meetup.com/Algorithmic-Art/events/263299802/" target="_blank">meetup</a> was about Perlin noise and its creative uses.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKHwvl3w6sGEi6LMdz5RGzgugnMhh1oXaW4kt7ONEtfNrdlGKMW3aK_pGcsxCanOwIsrcNM4BEvTFxFr9-t-Xnr1ePwXKKbZLRc6oFRWKrvAvdWNuFP6aFJMdNUWMmUMVyqMJjmZybXEM-/s1600/noise_c.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKHwvl3w6sGEi6LMdz5RGzgugnMhh1oXaW4kt7ONEtfNrdlGKMW3aK_pGcsxCanOwIsrcNM4BEvTFxFr9-t-Xnr1ePwXKKbZLRc6oFRWKrvAvdWNuFP6aFJMdNUWMmUMVyqMJjmZybXEM-/s400/noise_c.png" width="400" /></a></div>
<br />
The slides for this talk are online: <a href="https://docs.google.com/presentation/d/1akO9zv5j-eCAzBFzrTdKR2Dpb8VNcIDTi8aY_YKdrJc/edit?usp=sharing" target="_blank">link</a>.<br />
<br />
This talk had similar content to the one we held in London, so this post won't repeat the write up for that one.<br />
<br />
Here we'll focus on new themes or ideas that emerged from the discussion.<br />
<br />
It is recommended that you can read the previous write-up to provide context to this post: <a href="https://algorithmicartmeetup.blogspot.com/2018/08/creative-uses-for-not-quite-random-noise.html" target="_blank">link</a>.<br />
<br />
<br />
<h3>
Randomness v Noise</h3>
Sometimes we need a source of randomness but pure randomness is, well, just too random.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwLZdAYAkza96i4XrXeLzdi6Tf_roL-NRRUXQacLgaoj_EO7x0f3eDX9AWhyIe0TzRBb8XH0DAtKtVP0ivMilQpcFIiqbIQa_Yk1D3GDCHNpg89gJxN9tlBY6JVq8YQ_OK2mCZbgoaGPra/s1600/rnd_v_noise.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1600" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwLZdAYAkza96i4XrXeLzdi6Tf_roL-NRRUXQacLgaoj_EO7x0f3eDX9AWhyIe0TzRBb8XH0DAtKtVP0ivMilQpcFIiqbIQa_Yk1D3GDCHNpg89gJxN9tlBY6JVq8YQ_OK2mCZbgoaGPra/s400/rnd_v_noise.png" width="400" /></a></div>
<br />
For many creative applications we need a sequence of values that vary more smoothly. The above diagram compares pure randomness and Perlin noise.<br />
<br />
With pure randomness you can see there is no relation between consecutive values. If there was, the values wouldn't be truly random, independent of any other value.<br />
<br />
With Perlin noise, values next to each other are similar, so over a sequence the values appear to change smoothly.<br />
<br />
<br />
<h3>
Locally Smooth vs Globally Random</h3>
A key distillation in the session was that noise is <b>locally smooth, and globally random</b> - that is smooth at small scales, and random looking at large scales.<br />
<br />
<br />
<h3>
Applications & Techniques</h3>
We saw a range of applications of noise, from creating landscape height-fields, to textures that can be applied to surfaces.<br />
<br />
Noise can be multidimensional. Two dimensional noise varies slowly in any direction across a flat surface. Similarly, three dimensional noise varies slowly along any direction in a volume. Three-dimensional objects can be created by using a cut-off threshold for noise values.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV3iUPocS9srP7rJpJOGNK69s8QNX_00jEauFiIzIngkzcDF94O5SpCerbAsEUr7X6c_rh7J4X7CcysPA2IKyEl6kPIkcb3u1Kkj_clPipUOzDFx-4aFQ2s0oMfvu4DYURcxq5M_BAwh9u/s1600/3DNoiseGeometry.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="638" data-original-width="790" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV3iUPocS9srP7rJpJOGNK69s8QNX_00jEauFiIzIngkzcDF94O5SpCerbAsEUr7X6c_rh7J4X7CcysPA2IKyEl6kPIkcb3u1Kkj_clPipUOzDFx-4aFQ2s0oMfvu4DYURcxq5M_BAwh9u/s400/3DNoiseGeometry.jpg" width="400" /></a></div>
<br />
A popular technique is to use one of the additional dimensions as time, so the noise values vary over time, resulting in smoothly changing forms over time.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTKDLBZ495X8hMXBLwwL8TLFnXO68H8lsq0daKlpE9GbpI5v3SblrWGIA_1b5ToIJo19yiGJ1S3rczcPwSKFRwIFV01NjX6n5VApwX37alHlB5XwehxjRp0z9ysW5DyU3x8-LX_zeIDoHY/s1600/lava_perlin.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="456" data-original-width="460" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTKDLBZ495X8hMXBLwwL8TLFnXO68H8lsq0daKlpE9GbpI5v3SblrWGIA_1b5ToIJo19yiGJ1S3rczcPwSKFRwIFV01NjX6n5VApwX37alHlB5XwehxjRp0z9ysW5DyU3x8-LX_zeIDoHY/s400/lava_perlin.gif" width="400" /></a></div>
<br />
<br />
<h3>
Noise as Velocity</h3>
Most guides will focus on simply using the noise values to determine shape or position. In this session we spent a little more time exploring noise as velocity to determine the direction.<br />
<br />
The following shows the path of a collection of points whose next position is determined by noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_vsldz1prK2oZqczOBcG4ZPRNcXtYUUGokJU0LvmDsjTY5Y-BnBB7AITKT-YS31AF9uH-FRnSWCUduWiSShqWfgAyoXpIM8H7PHrTYcr4ALeuOTEW1i3GA8oytxRnggHacUY-N0NQofLU/s1600/path3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_vsldz1prK2oZqczOBcG4ZPRNcXtYUUGokJU0LvmDsjTY5Y-BnBB7AITKT-YS31AF9uH-FRnSWCUduWiSShqWfgAyoXpIM8H7PHrTYcr4ALeuOTEW1i3GA8oytxRnggHacUY-N0NQofLU/s400/path3.png" width="400" /></a></div>
<br />
This image clearly demonstrates a key feature of<br />
<br />
You can examine the simple code yourself:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/578607">https://www.openprocessing.org/sketch/578607</a></li>
</ul>
<br />
<br />
The following is an animation showing the paths of 200 'ants' which move according to direction set by noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC2RqYGUZHtLmKwxRqih-2FTgcXFQx8zhesgqlUqCKMG1hDCiEyf5xdoTp86fdk1OSiFPTzO_Mr4bJbWhuS9TT9mSWLY-pULvAPKpex3pvng7eNbqC1Vz0G7_Me2QdkEEV2ulyYypdJJe2/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="371" data-original-width="524" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC2RqYGUZHtLmKwxRqih-2FTgcXFQx8zhesgqlUqCKMG1hDCiEyf5xdoTp86fdk1OSiFPTzO_Mr4bJbWhuS9TT9mSWLY-pULvAPKpex3pvng7eNbqC1Vz0G7_Me2QdkEEV2ulyYypdJJe2/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<br />
The code is written to be read:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/687126">https://www.openprocessing.org/sketch/687126</a></li>
</ul>
<br />
<br />
<br />
<h3>
How is Perlin Noise Made?</h3>
We also spent a little more time discussing how Perlin noise is made. Again many guides explain how to use noise but don't explain how it is generated.<br />
<br />
We started by discussing the disadvantage of a sequence of random numbers. The first problem is that the values don't change smoothly. The second issue is that the values can change direction abruptly very frequently. This notion of 'frequency' is an important factor in the aesthetics of noice.<br />
<br />
We discussed ideas about using randomness to determine the changes to a random seed, a random walk. This would create smoother sequences, but doesn't directly address the issue of potentially high frequency changes.<br />
<br />
The solution, the method by which Perlin noise is generated, addresses both the issues of smooth changes and also the frequency of change elegantly.<br />
<br />
The following shows regularly spaced points from which emerge unit vectors, shown in green, each of random direction. The point <b>x</b> is the point at which we want to calculate noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2vp_Me1VzwQ40oD7Ur68kDSubU0K0FbxrZ0K_szvUTdsCL524IVtZg7TWu3vk8W8UEWBb1jGWSVhVb99J7gXSohdZ4-Px6JamoMLTD0YBU4YsxKiKBlkdZ__Wtr5WOK1XD5eUxiXmD5m-/s1600/gradient_noise.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="741" data-original-width="1200" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2vp_Me1VzwQ40oD7Ur68kDSubU0K0FbxrZ0K_szvUTdsCL524IVtZg7TWu3vk8W8UEWBb1jGWSVhVb99J7gXSohdZ4-Px6JamoMLTD0YBU4YsxKiKBlkdZ__Wtr5WOK1XD5eUxiXmD5m-/s400/gradient_noise.png" width="400" /></a></div>
<br />
The angles of the two nearest vectors from vectors pointing to x, shown in blue, are combined. It is actually the dot products that are used, not the angle, but conceptually the two are analogous. The combination can be a simple linear function but a smoothing polynomial is often used. The following shows the result of this combination.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg807z8Jku7uQ_ixG1CVl7rwW_W7YRYWqnHsomW9GGJnw4ptIysNCynZpmzwOYyZCAeA1fLDzsN8qd9RFlDnJKEL0WqyT_7H7T5kihIm2cRe0uz3MU-w6m9AddI3CWQXJ3HKmPMH8GmArHO/s1600/py_gradnoise.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="590" data-original-width="941" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg807z8Jku7uQ_ixG1CVl7rwW_W7YRYWqnHsomW9GGJnw4ptIysNCynZpmzwOYyZCAeA1fLDzsN8qd9RFlDnJKEL0WqyT_7H7T5kihIm2cRe0uz3MU-w6m9AddI3CWQXJ3HKmPMH8GmArHO/s400/py_gradnoise.png" width="400" /></a></div>
<br />
The values are constrained in height because the combination of dot products has a minimum and maximum value.<br />
<br />
The key benefit is also shown on that diagram. The worst case scenario for value flipping between peaks and troughs is two per unit. This can be seen between x=2 and x=3. The best case is once per unit, as seen between x=0 and x=1.<br />
<br />
It is not possible for the values to flip more frequently. This is the magic of this method - the frequency of the noise is naturally constrained - bandwidth limited.<br />
<br />
You can read a fuller description of how noise is generated, and also see a simple python implementation of this algorithm, here:<br />
<br />
<ul>
<li><a href="http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html">http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html</a></li>
</ul>
<br />
<br />
<br />
<h3>
Inspiration!</h3>
I was really pleased that everyone who attended were keen to go on and try using noise. Showing it in use demonstrates how simple it really is to use.<br />
<br />
One member works with projected light systems and he was inspired to use noise in his animated works.<br />
<br />
Some members appreciated the computational simplicity of the algorithm that generates Perlin noise, and for me, this is a real appreciation of the algorithm in algorithmic art!Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-61586365371991822392019-09-05T15:31:00.001-07:002019-09-05T15:42:23.632-07:00Reinforcement Learning and Creative Applications<script type="text/x-mathjax-config"> MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); </script> <script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script>
This <a href="https://www.meetup.com/Algorithmic-Art/events/261462857/" target="_blank">month</a> we had an introductory overview of <a href="https://en.wikipedia.org/wiki/Reinforcement_learning" target="_blank">Reinforcement Learning</a>, currently a very active area of research this is behind some of the most impressive achievements for machine learning.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW2JtaejNy3iIVPZzXc5n0SlvJH8_SwS11HjfQ3Ug90WhnglAFhRqshF8jCjFN12GcXJvC3qUm43SmEMF_Hw0-oNw1sMrOIqDhNWHqk9Uxzg75qAsDENqbCOvDBwWD5Knj2UgBAZiAvb6u/s1600/IMG_20190829_190346-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="998" data-original-width="1600" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW2JtaejNy3iIVPZzXc5n0SlvJH8_SwS11HjfQ3Ug90WhnglAFhRqshF8jCjFN12GcXJvC3qUm43SmEMF_Hw0-oNw1sMrOIqDhNWHqk9Uxzg75qAsDENqbCOvDBwWD5Knj2UgBAZiAvb6u/s400/IMG_20190829_190346-01.jpg" width="400" /></a></div>
<br />
The speaker's slides are similar to the UCL course slides: [<a href="http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html" target="_blank">link</a>].<br />
<br />
A video recording of the talk, including questions and answers, is online: [<a href="https://skillsmatter.com/skillscasts/14065-algorithmic-art#video" target="_blank">link</a>].<br />
<br />
In this write-up, I won't repeat closely the content of the talk, but instead provide my own summary of the key points, and examples of simple but illustrative code that uses reinforcement learning to solve a maze problem.<br />
<br />
<br />
<h3>
Reinforcement Learning?</h3>
We were lucky to have <a href="https://skillsmatter.com/legacy_profile/ali-chaudhry" target="_blank">Ali Choudhry</a>, a PhD researcher in AI and Education, and advocate for reinforcement learning, lead this session and share his expertise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjddEkpdzyJUsfKDP14f6NolebtKTbAwFLvV_Cb2HMZkhAGizq-hMtY6NeNGXkfT5mCp2Q28jbw3zgn6l_HN-1gm1fxRc8SK-DTgfTpY-9wodqssBIpazyLJtms0SVmMNCQrulWSu__pDR5/s1600/IMG_20190829_191029-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1013" data-original-width="1600" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjddEkpdzyJUsfKDP14f6NolebtKTbAwFLvV_Cb2HMZkhAGizq-hMtY6NeNGXkfT5mCp2Q28jbw3zgn6l_HN-1gm1fxRc8SK-DTgfTpY-9wodqssBIpazyLJtms0SVmMNCQrulWSu__pDR5/s400/IMG_20190829_191029-01.jpg" width="400" /></a></div>
<br />
<br />
It is a common perception that deep neural networks have been solely responsible for the huge leaps in artificial intelligence in recent years. In fact, reinforcement learning has been core to these headline grabbing advances, often in combination with neural networks.<br />
<br />
A notable example is Google DeepMind's <a href="https://deepmind.com/blog/article/alphago-zero-starting-scratch" target="_blank">AlphaGo Zero</a> which learned to play the 3,000 year old game of Go, which has simple rules but is immensely complex in its gameplay and strategy. In fact AlphaGo Zero learned new strategies thought not to have been discovered by human players during those 3000 years!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7x0RQcCR6o6-v8AhFUlohbVBBKv3dT8wwf0rLCRZLM8ft6c3wlncXFVJ6XOXC6M_wFjugEYl7FE_-uGm5lo9dCGDo6DkS-iqSUHOLr_vGMBO3yYkYoYpGb6cwlrS3xBZ4VDCrcen8BnFh/s1600/Screenshot+2019-09-04+at+15.29.45.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="884" data-original-width="1600" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7x0RQcCR6o6-v8AhFUlohbVBBKv3dT8wwf0rLCRZLM8ft6c3wlncXFVJ6XOXC6M_wFjugEYl7FE_-uGm5lo9dCGDo6DkS-iqSUHOLr_vGMBO3yYkYoYpGb6cwlrS3xBZ4VDCrcen8BnFh/s400/Screenshot+2019-09-04+at+15.29.45.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Google DeepMind's AlphaGo system used RL to learn strategies to beat<br />
the world's leading Go player.</td></tr>
</tbody></table>
<br />
Ali explained that that current trends in academic research, conferences and industrial applications, reinforcement learning is on an upward trajectory, which some believe will surpass the already significant advances from neural network-based deep learning.<br />
<br />
To help clarify the idea of reinforcement learning, Ali started by comparing it to <b>supervised</b> and <b>unsupervised</b> learning.<br />
<br />
<ul>
<li><b>Supervised Learning</b> - when a machine learning model learns from examples of question-answer pairs. <b>Neural networks</b> are commonly trained with examples.</li>
</ul>
<ul>
<li><b>Unsupervised Learning</b> - where an algorithm tries to find patterns, for example clusters, within data.</li>
</ul>
<br />
<b>Reinforcement Learning</b>, or <b>RL</b>, is the training of an agent based on its interaction with an environment, guided by rewards when it manages to navigate a good path or to a desired target.<br />
<br />
This means that the learning does depend on the path the agent takes, unlike the more data-based supervised and unsupervised learning.<br />
<br />
That description, and many you'll find in textbooks and courses, is admittedly a little abstract, so let's illustrate RL with an example.<br />
<br />
<br />
<h3>
Simple Example In Plain English</h3>
Before diving into RL methods, let's develop an intuition for how they work without using the terminology or mathematical expressions.<br />
<br />
Have a look at the following very simple maze. There is a robot which we need to train so that it travels to the reward.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzCEG6hKzJC-drzf9xesP3ZPlVRvknedg0YKv2vmljb9WVuyiC9oNT0qyweiESWH5aeyzmsMgajBA9oowFvQTdmGxMMZ68XPVaEPiOi8w8mvrjxa_V5MIH4NHiJtMbEKlH2cG0feFiGW2E/s1600/rl_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="385" data-original-width="1000" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzCEG6hKzJC-drzf9xesP3ZPlVRvknedg0YKv2vmljb9WVuyiC9oNT0qyweiESWH5aeyzmsMgajBA9oowFvQTdmGxMMZ68XPVaEPiOi8w8mvrjxa_V5MIH4NHiJtMbEKlH2cG0feFiGW2E/s400/rl_0.png" width="400" /></a></div>
<br />
Without thinking too much about the technicalities of reinforcement learning, or indeed any kind of machine learning, let's ask ourselves how we'd do if we were 10 years old.<br />
<br />
We'd probably come up with a very simple idea of "closeness" to the reward. Remember those childhood games where someone was "getting warmer" if they were closer to a hidden reward? Let's apply that same idea of warmness.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdJSAqh4UuuTzAaoVUHDlqHIsOhyphenhyphendaMOL2_87gE1PspoM-RC3EfdiORVXZaP9YyI0wyCGL3G9YiJQSp9ONQFNn4JJC141M0TZOcTTSrcJw99zHkPg16TVIw4ybSMaYhgA8ub8R27JpB-7U/s1600/rl_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="385" data-original-width="1000" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdJSAqh4UuuTzAaoVUHDlqHIsOhyphenhyphendaMOL2_87gE1PspoM-RC3EfdiORVXZaP9YyI0wyCGL3G9YiJQSp9ONQFNn4JJC141M0TZOcTTSrcJw99zHkPg16TVIw4ybSMaYhgA8ub8R27JpB-7U/s400/rl_1.png" width="400" /></a></div>
<br />
Having a value, a number, for how hot or cold each location is makes intuitive sense. Whichever location the robot is in, it just needs to move the the next one which has a hotter value. If it does this, it will get to the reward.<br />
<br />
That seems easy enough, and a concept everyone can understand.<br />
<br />
The challenge is, when we start in a new unknown environment, the robot don't know what the hotness values for each location are.<br />
<br />
This is what reinforcement learning does - it explores the environment, taking many different paths, and uses that experience, some of which is rewarded, to work out what the hotness map looks like.<br />
<br />
That's a simplified definition but it will take us far at this stage of our learning.<br />
<br />
Have a look at the following picture showing the robot moving right, one cell at a time.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJO3D5Wa6x7JAAoAzoqIEbSbkr8TpBUFNZ_d3qIQrm9slMNFqN4DfpMRbiaVFxtEJr8qoGt2ZwIics6ELHrNaJv9v6FjtqPOOv1guFFclvO-jZizvyjjqyFWjD3QQlaJzwGJDpfytihGpA/s1600/rl_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="728" data-original-width="1000" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJO3D5Wa6x7JAAoAzoqIEbSbkr8TpBUFNZ_d3qIQrm9slMNFqN4DfpMRbiaVFxtEJr8qoGt2ZwIics6ELHrNaJv9v6FjtqPOOv1guFFclvO-jZizvyjjqyFWjD3QQlaJzwGJDpfytihGpA/s400/rl_2.png" width="400" /></a></div>
<br />
When it moves right one cell, from location <b>L3</b> to <b>L4</b>, nothing has been learned. There is no reward, and no new information about whether we did a good or bad move.<br />
<br />
When it moves right again to <b>L5</b>, again there is no new information, so nothing has been learned.<br />
<br />
Finally when it moves right a third time to <b>L6</b>, the robot lands on the reward. This great! But what does it tell us? <br />
<br />
It tells us that <b>L5</b> is close to the target and should have a high "hotness" value. That's why we've coloured it a bright red.<br />
<br />
Having coloured <b>L5</b> a hot red, we look back and see that <b>L4</b> is still not coloured with a hotness value. That's because, when we visited it, we didn't know it was a good place to be, that it was close to the reward.<br />
<br />
One way to fix this is to remember our path from <b>L3</b>, and give all the cells on our path a hotness value, with <b>L5</b> being the hottest, and <b>L3</b> a lower value.<br />
<br />
Instead of having to remember our journey, which could get very long in another scenario, we could save memory and just repeat the journeys.<br />
<br />
Have a look at the next picture. It shows two more journeys, not just the progression of one journey.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4PRCF1s8GzsMaQ9I8fQjR2rYU83XNhh8o5yAHamgPZLEr6cDzQOoPyIIH7fgP9HY3HdG8yjOqEw7DNORni7vE1jmhO_xZOJ0o69rIlv3NX8gGB6KXEMnuty-Bk4FDdy7NWyzHEPPF9seM/s1600/rl_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="728" data-original-width="1000" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4PRCF1s8GzsMaQ9I8fQjR2rYU83XNhh8o5yAHamgPZLEr6cDzQOoPyIIH7fgP9HY3HdG8yjOqEw7DNORni7vE1jmhO_xZOJ0o69rIlv3NX8gGB6KXEMnuty-Bk4FDdy7NWyzHEPPF9seM/s400/rl_3.png" width="400" /></a></div>
<br />
On the second journey starting from <b>L3</b>, after the very fist one above, we reach <b>L4</b> and can see that <b>L5</b> is hot. We can use this information to give a slightly less hot value to <b>L4</b>. That's because being in <b>L4</b> is good, but not as good as <b>L5</b>.<br />
<br />
A third journey doesn't need to go anywhere because at the starting point <b>L3</b> we can see that the next cell <b>L4</b> is fairly hot. We can use this to colour our cell <b>L3</b> with a mild hot value.<br />
<br />
You can see how this process does create a "hotness / closeness" map.<br />
<br />
It's now easy to see how this method can work with a more complex maze, trying different journeys to build up a map of hotness.<br />
<br />
This very simplified example has the essence of reinforcement learning:<br />
<ul>
<li>we explore different journeys in our environment</li>
<li>if we find a reward we mark the cell that got us there with a high score</li>
<li>we repeat more journeys, and if we encounter cells with good scores, we can consider them as partial rewards, and mark the cells that got us to those with a slightly lower score</li>
</ul>
<br />
Having seen this example, we can now appreciate some of the things that set reinforcement learning apart:<br />
<br />
<ul>
<li>there is no labelled training data in the usual form (input data, output class)</li>
<li>in fact, any information that we can use to learn from, might appear after many iterations of training, or not at all</li>
<li>the training data is not independent of what the robot does, it depends on that path we take</li>
<li>we don't use lots of memory to remember the paths we took, which can potentially be very long, we limit memory use to just the positions we've visited and the value of those positions</li>
</ul>
<br />
Before we move onto the next section, have a look at the next picture which shows how a maze with two routes is coloured.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDfC2FXL3dH2cEmt9UHe5rJAQKYasO4T5hUZsoD6gHJ8fk9_TA2lJM1k-Ea182gmzgxM5rjSlKVxT_U6fPIMQKrpYEypeCfWYVL8WxeOiZmoql2ZDePXzq-50Zgdo6z8u7zAKVhFpVXfY0/s1600/rl_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="607" data-original-width="1000" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDfC2FXL3dH2cEmt9UHe5rJAQKYasO4T5hUZsoD6gHJ8fk9_TA2lJM1k-Ea182gmzgxM5rjSlKVxT_U6fPIMQKrpYEypeCfWYVL8WxeOiZmoql2ZDePXzq-50Zgdo6z8u7zAKVhFpVXfY0/s400/rl_4.png" width="400" /></a></div>
<br />
If the robot follows the longer non-optimal path then we can see hotness values become colder the further back we are from the target. At the starting point, the robot sees that going right moves it to a warmer cell than the current one. Going upwards moves it to a much colder cell than the current one. So the robot should choose moving right,<br />
<br />
This example shows two things relevant to RL:<br />
<br />
<ul>
<li>how a robot makes a choice between multiple options, choosing the path that gets hottest quickest</li>
<li>how working back from the target leaves longer paths with colder cells</li>
</ul>
<br />
<br />
<br />
<h3>
Some Terminology</h3>
The field of reinforcement learning has a fair bit of its own terminology and it helps to know the key terms.<br />
<br />
The following links this new terminology to the robot example to help us understand it better:<br />
<ul>
<li>the robot is an <b>agent</b>, it is the agent that is doing the learning</li>
<li>the maze is an <b>environment</b>, the agent interacts with the environment</li>
<li>the information that describes where the robot is in the maze is called the <b>state</b></li>
<li>deciding what the agent does next is called a <b>policy</b> - with our robot, it was random movement or following the higher value cells</li>
<li>what the agent does is called an <b>action</b>, and this results in a change of state</li>
<li>the information we use to learn from is called a <b>reward</b>, and usually comes from a <b>goal state</b></li>
<li>the benefit of being in a state is called a <b>value</b>, and this is like the hotness number we used for each cell</li>
</ul>
<br />
<br />
<h3>
Reinforcement Learning Worked Example</h3>
Let's use the simple robot example again, but this time, let's start to use numbers and do the calculations so we can see how they work.<br />
<br />
The following picture shows the robot at state <b>L3</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA2oB_t9LpjUSqlFu3SEGJuCRF0FGKRAIvzq_SL53iId6sR32BjLFdt11FPyeLMUNGjWg-JmJVHjDXM4VzmVjEnp4CBHWspHb2DdJ0FiTxN1fyWnT87J_8CWv2A8YoM43o5Js4j89mWhcR/s1600/rl_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="385" data-original-width="1000" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA2oB_t9LpjUSqlFu3SEGJuCRF0FGKRAIvzq_SL53iId6sR32BjLFdt11FPyeLMUNGjWg-JmJVHjDXM4VzmVjEnp4CBHWspHb2DdJ0FiTxN1fyWnT87J_8CWv2A8YoM43o5Js4j89mWhcR/s400/rl_5.png" width="400" /></a></div>
<br />
Because we have no information at all yet, we start with state values all set to zero.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGmbfKD66wpwkJK6FbT8Awxc7fTTs9YOxRH00htz37c71I1yUr9SVf-Xt3lmwiAaKj0EDmVK0LBlBWXkngU9rgbR0viYgNf3tbgDd6oo-jLdzoQofotuWGTuGar9jS3nRli-STyb1TAcYM/s1600/Screenshot+2019-09-03+at+00.22.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="239" data-original-width="872" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGmbfKD66wpwkJK6FbT8Awxc7fTTs9YOxRH00htz37c71I1yUr9SVf-Xt3lmwiAaKj0EDmVK0LBlBWXkngU9rgbR0viYgNf3tbgDd6oo-jLdzoQofotuWGTuGar9jS3nRli-STyb1TAcYM/s400/Screenshot+2019-09-03+at+00.22.17.png" width="400" /></a></div>
<br />
If the robot looks to the right it sees <b>L4</b> as having zero value. That is, there is no reward. So the value of <b>L3</b> remains unchanged. If the robot looks to the left, to <b>L2</b>, it has zero value, so again, the value of <b>L3</b> is unchanged.<br />
<br />
If the robot moves to the right to <b>L4</b>, again we have no new information. Looking at <b>L3</b> and <b>L5</b> we see both are zero. So our <b>L4</b> value remains zero.<br />
<br />
So far, all the state values are zero:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiodSdeCMuLncbHOKrDhU-tlEwwOmstChHsSFR0gW7sXaGTsdBAxnoKfkukitDyz4yRHulpvVnJ_CZE-nfADIBoZS0pmki81PacyEkPRL3_AlcfuBfVWvpM0w5NXTxtsbop-G37OyYCVVqQ/s1600/Screenshot+2019-09-03+at+00.22.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="239" data-original-width="872" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiodSdeCMuLncbHOKrDhU-tlEwwOmstChHsSFR0gW7sXaGTsdBAxnoKfkukitDyz4yRHulpvVnJ_CZE-nfADIBoZS0pmki81PacyEkPRL3_AlcfuBfVWvpM0w5NXTxtsbop-G37OyYCVVqQ/s400/Screenshot+2019-09-03+at+00.22.17.png" width="400" /></a></div>
<br />
If we then move right again to<b> L5</b>, things change. Looking left to <b>L4</b> we see it has zero value. But if we look right at <b>L6</b> we see that it's a target state and has a reward of <b>1.0</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiio7IS9abkpF6Jm2WldMG464rY7TtOPwOLciGUfBCqO7wg8vzdEu74mmEdlZ2Dq9Sak03SBjl41Wci6MHC2rxUxeCFk1uW22MBzKaKxvxTNbidwYyA0O1CF9bXi7czI7t9_hNt-xZaQ3J5/s1600/rl_6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="385" data-original-width="1000" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiio7IS9abkpF6Jm2WldMG464rY7TtOPwOLciGUfBCqO7wg8vzdEu74mmEdlZ2Dq9Sak03SBjl41Wci6MHC2rxUxeCFk1uW22MBzKaKxvxTNbidwYyA0O1CF9bXi7czI7t9_hNt-xZaQ3J5/s400/rl_6.png" width="400" /></a></div>
<br />
Let's update the value of state <b>L5</b>:<br />
<br />
$$<br />
\begin{align}<br />
V(s) & \leftarrow \underset{s'} {max} \left ( R(s') + \gamma \cdot V(s') \right ) \\<br />
V(s) & \leftarrow 1.0 + 0.9 \cdot 0 \\<br />
V(s) & \leftarrow 1.0 \\<br />
\end{align}<br />
$$<br />
<br />
The $R(s')$ is the reward for getting to the next state $s'$. The $V(s')$ is the value of the state $s'$.<br />
<br />
We've used a discount $\gamma = 0.9$, but it hasn't made a difference here because the value of <b>L6</b> is <b>0</b>, even though it is a target state.<br />
<br />
Note that the equation asks us to use the next state $s'$ that maximises the update.<br />
<br />
Let's look at the value of the states now.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBVxQqo3-RmRpSZaIGf7oeK0wGJNQifAf6CxkK2YHMmj6qcWCe7UrnLXK4Dq84vE1QKVmfi9GDlhzqqJXdChm8t8AsG3F1XEiBADq_iF9fOIZGvsec6-jqotCw5mOUcqe2J538No5S8ylE/s1600/Screenshot+2019-09-03+at+00.58.39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="263" data-original-width="900" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBVxQqo3-RmRpSZaIGf7oeK0wGJNQifAf6CxkK2YHMmj6qcWCe7UrnLXK4Dq84vE1QKVmfi9GDlhzqqJXdChm8t8AsG3F1XEiBADq_iF9fOIZGvsec6-jqotCw5mOUcqe2J538No5S8ylE/s400/Screenshot+2019-09-03+at+00.58.39.png" width="400" /></a></div>
<br />
Great - we can see that being in <b>L5</b> is a good thing!<br />
<br />
Let's run another journey.<br />
<br />
If we start again in <b>L3</b>, looking to the left and right at <b>L2</b> and <b>L4</b> we see they have values of <b>0</b>, so there are no useful updates.<br />
<br />
Let's see the maths doing the right thing:<br />
<br />
$$<br />
\begin{align}<br />
V(s) & \leftarrow \underset{s'} {max} \left ( R(s') + \gamma \cdot V(s') \right ) \\<br />
V(s) & \leftarrow 0 + 0.9 \cdot 0 \\<br />
V(s) & \leftarrow 0 \\<br />
\end{align}<br />
$$<br />
<br />
Let's move to state <b>L4</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSdnPTpCWaZuDHf5jJ-OfMkPomg46wDCpOb7YbC4hDx75O8Cz4exy7elHbTGjplCErcv8UxY8UwxIOEnGzMt_klc5VgGyluIsa4hKE2Yj2GD1VozlDPB6Vv_s2ML20Z4xuRq24ZiiDXNO_/s1600/rl_7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="385" data-original-width="1000" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSdnPTpCWaZuDHf5jJ-OfMkPomg46wDCpOb7YbC4hDx75O8Cz4exy7elHbTGjplCErcv8UxY8UwxIOEnGzMt_klc5VgGyluIsa4hKE2Yj2GD1VozlDPB6Vv_s2ML20Z4xuRq24ZiiDXNO_/s400/rl_7.png" width="400" /></a></div>
<br />
This time we look right and see that <b>L5</b> has a value, which it picked up from the previous journey. This means <b>L4</b> will get a new value.<br />
<br />
$$<br />
\begin{align}<br />
V(s) & \leftarrow \underset{s'} {max} \left ( R(s') + \gamma \cdot V(s') \right ) \\<br />
V(s) & \leftarrow 0 + 0.9 \cdot 1.0 \\<br />
V(s) & \leftarrow 0.9 \\<br />
\end{align}<br />
$$<br />
<br />
So the value of <b>L4</b> becomes <b>0.9</b>, which <b>1.0</b> discounted by <b>0.9</b>.<br />
<br />
Here's the table of state values so far.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV6VDwP0g9XncA_Pz2DKdTlAZ7RDRNHE4OpwZLnWNs3uyO3WUo8pJYWwCgwC_Q3BRmpwbEJPAcxQyh7-qepz6kGte1twfRvxMnx6k0OXS4thXOzyCabQphGKYuHNihxpkN9oESse49S9bW/s1600/Screenshot+2019-09-03+at+01.09.51.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="255" data-original-width="919" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV6VDwP0g9XncA_Pz2DKdTlAZ7RDRNHE4OpwZLnWNs3uyO3WUo8pJYWwCgwC_Q3BRmpwbEJPAcxQyh7-qepz6kGte1twfRvxMnx6k0OXS4thXOzyCabQphGKYuHNihxpkN9oESse49S9bW/s400/Screenshot+2019-09-03+at+01.09.51.png" width="400" /></a></div>
<br />
You can see how repeating the journeys will result in the table converging to the following:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRG-Lq_-P0IS0oHXfQguQ8qSKr-92PFE9q9tyVGyONOLlsF8_ZBoNae-2u1zAjw7e2jvfiE3iSvy_74diBTHT3NNRxaSfBboieHF1_3MaL8vMTOSZ9OlRZogNQNY9RnYL2TeBC3XLF1GLR/s1600/Screenshot+2019-09-03+at+01.16.28.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="281" data-original-width="909" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRG-Lq_-P0IS0oHXfQguQ8qSKr-92PFE9q9tyVGyONOLlsF8_ZBoNae-2u1zAjw7e2jvfiE3iSvy_74diBTHT3NNRxaSfBboieHF1_3MaL8vMTOSZ9OlRZogNQNY9RnYL2TeBC3XLF1GLR/s400/Screenshot+2019-09-03+at+01.16.28.png" width="400" /></a></div>
<br />
This map of state values guides our robot towards the target.<br />
<br />
You might be concerned that revisiting a state might change the value. If we look again at <b>L4</b>, we can see that the value from the left would be $0.9 * 0.81$, and from the right it would be $0.9 * 1$. Taking the maximum gives us <b>0.9</b> again.<br />
<br />
<br />
<h3>
Good States, Good Actions</h3>
What we've just done above is calculate how good each position in the maze is using actual numbers, and it mirrors what we did earlier with the intuitive example of hotness and coldness.<br />
<br />
A more common approach in RL is to work out which <b>actions</b> are good, rather than focus on which <b>states</b> are good. That is, which moves are good rather than which locations.<br />
<br />
The two are obviously related as <b>actions</b> are what take the agent from one <b>state</b> to another <b>state</b>.<br />
<br />
The terminology uses what's called a <b>Q-value</b> for quality value, which takes into account both <b>state</b> and <b>action</b>.<br />
<br />
Have a look at this picture which shows the agent one step away from the reward.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUiC6EtITUIuxzeDmoEinHfb0bsGobHC9GzckldcbpAlabLaYzd9kXQtI8fddc6UOTPSOokdqTyfDuMarrjPNg7TVjNKb-H6Zws0muWgGnaXBzdtYZCxKaHswxwCSo8L5s1UtE9l_a6F2I/s1600/rl_8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="411" data-original-width="1000" height="163" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUiC6EtITUIuxzeDmoEinHfb0bsGobHC9GzckldcbpAlabLaYzd9kXQtI8fddc6UOTPSOokdqTyfDuMarrjPNg7TVjNKb-H6Zws0muWgGnaXBzdtYZCxKaHswxwCSo8L5s1UtE9l_a6F2I/s400/rl_8.png" width="400" /></a></div>
<br />
<br />
Whats the value of moving to the right? It's clearly a good move as it takes us to the target, which gives us a reward of <b>1.0</b>. It makes sense that the value of moving right from <b>L5</b> has the maximum value, we can call it <b>1.0</b>.<br />
<br />
What if the agent is in <b>L4</b>, two steps away from the reward?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0d0OvoFGsjpHRvWL08qT6q9HXNyiM63aiZFCfwo6v0_ZS-pPtUvDVvFTZaFBElZh_Fn3klt8aw1l1LS0eFpyhu1HWQn5_ku18-GrsuZ-VQhmu6bI8WfdYziUs9Ns5y0Itq_iUmy5a5IiX/s1600/rl_9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="411" data-original-width="1000" height="163" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0d0OvoFGsjpHRvWL08qT6q9HXNyiM63aiZFCfwo6v0_ZS-pPtUvDVvFTZaFBElZh_Fn3klt8aw1l1LS0eFpyhu1HWQn5_ku18-GrsuZ-VQhmu6bI8WfdYziUs9Ns5y0Itq_iUmy5a5IiX/s400/rl_9.png" width="400" /></a></div>
<br />
We can use the same idea of using a discount for a future reward. If our discount is $\gamma = 0.9$, then the value of moving right from <b>L4</b> is <b>0.9</b>. We are assuming that the step after this one is optimal.<br />
<br />
Let's now look at the value of a move in what looks like the wrong direction.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtWcJmYEOXMOTn_GvNgY3g0EhBJM2bzeMM2D7GSiUKMJOnMOtP8F4qzDvGkn15W2k1DkqRSuc5ygS30MiNkc4iOMaNiRs1VLxsjnczyDrk38kw1VdCwuGBhFeq5Qae-CjGMvPKwo06ZckW/s1600/rl_10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="411" data-original-width="1000" height="163" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtWcJmYEOXMOTn_GvNgY3g0EhBJM2bzeMM2D7GSiUKMJOnMOtP8F4qzDvGkn15W2k1DkqRSuc5ygS30MiNkc4iOMaNiRs1VLxsjnczyDrk38kw1VdCwuGBhFeq5Qae-CjGMvPKwo06ZckW/s400/rl_10.png" width="400" /></a></div>
<br />
What's the value of a move left from <b>L5</b>?<br />
<br />
If we follow our previous logic, it is the discounted value if we followed the optimal path. So the Q-value is 0.9 * the maximum Q-value out of <b>L4</b> (which is moving right).<br />
<br />
Let's write the general update rule:<br />
<br />
$$<br />
Q(s, a) \leftarrow \underset{a'} {max} \left ( R(s') + \gamma \cdot Q(s', a') \right )<br />
$$<br />
<br />
For the agent in <b>L5</b>, the value of moving right is, $Q(L5, right)$:<br />
<br />
$$<br />
\begin{align}<br />
Q(L5, right) & \leftarrow \underset{a'} {max} \left ( R(s') + \gamma \cdot Q(s', a') \right ) \\<br />
V(s) & \leftarrow 1.0 + 0.9 \cdot 0 \\<br />
V(s) & \leftarrow 1.0 \\<br />
\end{align}<br />
$$<br />
<br />
So $Q(L5, right) = 1.0$. This comes entirely from the immediate reward from <b>L6</b>.<br />
<br />
And moving left from <b>L5</b>, $Q(L5, left)$:<br />
<br />
$$<br />
\begin{align}<br />
Q(L5, left) & \leftarrow \underset{a'} {max} \left ( R(s') + \gamma \cdot Q(s', a') \right ) \\<br />
V(s) & \leftarrow 0 + 0.9 \cdot 0.0 \\<br />
V(s) & \leftarrow 0 \\<br />
\end{align}<br />
$$<br />
<br />
There is no immediate reward from <b>L4</b>. From <b>L4</b>, the maximum Q-value out of it is currently <b>0 </b>because we've not done enough journey's to raise it.<br />
<br />
So for now, $Q(L5, left) = 0$,<br />
<br />
If we were to consider $Q(L4, right)$ it would't have a zero value because to the right, there are non-zero Q-values out of <b>L5</b>. In this way, <b>L4</b> gains Q-values.<br />
<br />
This illustrates why it is important to run many journeys to improve the estimates of Q-values.<br />
<br />
<br />
<h3>
Maze Example With Python</h3>
Writing code to demonstrate reinforcement learning really helps us understand it. Let's start with a very simple 1-dimensional maze, just like the one we thought about above.<br />
<br />
Let's start by importing useful libraries:<br />
<br />
<pre class="language-python"><code>
import numpy
import pandas
import random
</code></pre>
<br />
We create a table of Q-values, initialised to zero. It's two dimensional because one dimension represents the state (position) and the other the action (left, right).<br />
<br />
<pre class="language-python"><code>
# Q state-action table, initialised with zeros
Q = pandas.DataFrame(numpy.zeros((2,6)), index=[-1, 1])
# print initial Q (state, action) table
Q
</code></pre>
<br />
This creates a <b>2</b> by <b>6</b> table, with the horizontal rows labelled <b>-1</b> and <b>1</b>, for the <b>left</b> and <b>right</b> actions. The columns are the positions <b>0-5</b> in the very simple maze.<br />
<br />
Printing the table, makes this structure clear.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwVCByjBCb5MoC_mJs3OBDVqpAKOj-ABnHujtPjMdvogjfAf2wq0Rjhp0iL25rKT77FSJFI32-vCYLRuEHHGVnfWPyaKdADXMZBK19jCY43zlzKxTc9h88MKTMNSxHIIOL0xUDhWjeZgLM/s1600/Screenshot+2019-09-04+at+16.19.15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="412" data-original-width="1508" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwVCByjBCb5MoC_mJs3OBDVqpAKOj-ABnHujtPjMdvogjfAf2wq0Rjhp0iL25rKT77FSJFI32-vCYLRuEHHGVnfWPyaKdADXMZBK19jCY43zlzKxTc9h88MKTMNSxHIIOL0xUDhWjeZgLM/s400/Screenshot+2019-09-04+at+16.19.15.png" width="400" /></a></div>
<br />
To estimate Q, our agent moves around the environment. For simplicity, we can use a random walk, that is, move left and right randomly. Using the terminology, this is called a <b>stochastic policy</b>.<br />
<br />
Let's write the code that does this random walk, before we dive into updating the Q values.<br />
<br />
<pre class="language-python"><code>
# run several iterations to iteratively estimate Q-values
# number of iterations (actions)
iterations = 20
# initial position
xpos = 3
for i in range(iterations):
print("xpos = ",xpos)
# set new position position according to random walk policy
xpos_new = xpos + random.choice([-1, 1])
# check new position doesn't fall outside maze bounds
xpos_new = numpy.clip(xpos_new, 0, 5)
# also check it doesn't hit target location
if xpos_new in [5]:
xpos_new = xpos
pass
# update position
xpos = xpos_new
pass
</code></pre>
<br />
We've set the number of moves to <b>20</b>, and the initial agent position to be <b>3</b>, but it could have been any valid position.<br />
<br />
You can see we that for every iteration, we create a new position which is randomly to the left or right of the current position. We then test this new position to ensure it remains within the bounds of the maze. In fact, the code simply clips position values to remain within the range <b>0</b> to <b>5</b>.<br />
<br />
We also check the new position ins't the target location <b>5</b> as we don't want to move into it.<br />
<br />
Finally we update the position with this new position.<br />
<br />
Printing out the position values confirm the agent moves according to a random walk in the maze, and doesn't fall outside or hit the target cell.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2pdPF1mbfDQTzfdOCAAPdaS4Y8N6OfvtLuFNXCmy7ugjNpg_tGb_gVM23cQtkm27LW3de1dg6k_EE82CJapkpwjBCHuCjkZ7r7MhbZY2ucLNgLvC7ohoYck9ttkp3rt3GR5bE30bwJvt2/s1600/Screenshot+2019-09-04+at+17.47.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="706" data-original-width="1488" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2pdPF1mbfDQTzfdOCAAPdaS4Y8N6OfvtLuFNXCmy7ugjNpg_tGb_gVM23cQtkm27LW3de1dg6k_EE82CJapkpwjBCHuCjkZ7r7MhbZY2ucLNgLvC7ohoYck9ttkp3rt3GR5bE30bwJvt2/s400/Screenshot+2019-09-04+at+17.47.42.png" width="400" /></a></div>
<br />
Great - the agent is moving around the maze.<br />
<br />
Now we just need to use each position it lands on to estimate the Q values for actions from that position.<br />
<br />
The following code is inside the loop, before the position of the agent is updated.<br />
<br />
<pre class="language-python"><code>
# consider all actions
for action in [-1,1]:
xpos2 = xpos+action
# if xpos2 is outside maze, continue
if ((xpos2 < 0) or (xpos2 > 5)):
continue
# reward is at position 5
reward = 0
if (xpos2 == 5):
reward = 1
pass
# max Q from next state
maxQ2 = max(Q[xpos2])
# update Q-table
Q.loc[action,xpos] = reward + 0.9 * maxQ2
pass
</code></pre>
<br />
From the current position <b>xpos</b>, we look at the positions to the left and right <b>xpos2</b>. If the position <b>xpos2</b> being considered is outside the maze, then skip the rest of the code and and look at the other direction if we haven't, and if we have, try another move.<br />
<br />
We set a default <b>reward</b> to <b>0</b>, and only change it to one if the position being looked at is the target at location <b>5</b>.<br />
<br />
Remember the update rule for Q-values is the immediate reward and the maximum of the Q-values of the actions out of the position being considered. This is easy to code in Python. <b>Q[xpos2]</b> gives us a column of both Q-values from <b>xpos2</b>, and calling <b>max()</b> around thus gives us the maximum of those values.<br />
<br />
We finally set the current location's <b>Q</b> value to the reward added to the discounted <b>maxQ2</b>. You can see the discount is <b>0.9</b>.<br />
<br />
Let's see what the Q-value table looks like after a few iterations:<br />
<br />
<pre class="language-python"><code>
xpos = 3
0 1 2 3 4 5
-1 0.0 0.0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0 0.0 0.0
xpos = 4
0 1 2 3 4 5
-1 0.0 0.0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0 1.0 0.0
xpos = 4
0 1 2 3 4 5
-1 0.0 0.0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0 1.0 0.0
...
xpos = 1
0 1 2 3 4 5
-1 0.0000 0.59049 0.00 0.0 0.0 0.0
1 0.6561 0.72900 0.81 0.9 1.0 0.0
xpos = 2
0 1 2 3 4 5
-1 0.0000 0.59049 0.6561 0.0 0.0 0.0
1 0.6561 0.72900 0.8100 0.9 1.0 0.0
xpos = 3
0 1 2 3 4 5
-1 0.0000 0.59049 0.6561 0.729 0.0 0.0
1 0.6561 0.72900 0.8100 0.900 1.0 0.0
xpos = 4
0 1 2 3 4 5
-1 0.0000 0.59049 0.6561 0.729 0.81 0.0
1 0.6561 0.72900 0.8100 0.900 1.00 0.0
</code></pre>
<br />
We can see that initially the table's values are mostly zero. After some iterations, the Q-values grow as a result of the random walk being next to the target location, and then being diffused along the maze using the discount.<br />
<br />
Let's look at the Q-values table after <b>20</b> iterations.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwko3ADyWkmGjmotkeJV5_4Wy0qcIekS0FV-48azvdGx8HvEnbvmCtx3xZSCX5Rb5zRzp6vB1uNzllk0ye_ms9jMwWsE3uxzpsMrN-MOzmuQdvzPu2cLNL1IeUo7HApQPlbQsTqNkk3C-J/s1600/Screenshot+2019-09-04+at+18.07.54.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="505" data-original-width="1463" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwko3ADyWkmGjmotkeJV5_4Wy0qcIekS0FV-48azvdGx8HvEnbvmCtx3xZSCX5Rb5zRzp6vB1uNzllk0ye_ms9jMwWsE3uxzpsMrN-MOzmuQdvzPu2cLNL1IeUo7HApQPlbQsTqNkk3C-J/s400/Screenshot+2019-09-04+at+18.07.54.png" width="400" /></a></div>
<br />
There are some key features of this table:<br />
<br />
<ul>
<li>The Q-values get higher as we move to the right along the table. This makes sense as the target is on the right.</li>
<li>At any location, actions to the right should have higher Q-values than to the left. We can see this by looking vertically along a column. The values along the bottom row are higher than the corresponding values along the top row.</li>
<li>When in position <b>0</b>, moving left isn't possible as that's the end of the maze. This is why the left action remains <b>0</b> here.</li>
</ul>
<br />
<br />
We can visualise the Q-values table.<br />
<br />
<pre class="language-python"><code>
# visualise the Q-value table
import seaborn as sns
sns.heatmap(Q, cmap='coolwarm', annot=True)
</code></pre>
<br />
The resulting image is much easier to interpet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKlEzjNXFxN82dvJDtfh6ogNTrfK8imC_LAS1Mb2VRiKDNAndMYGcVDHTpYVKr21J9eJrRRFUA5QQk2PawuhzD-cQULynA0XoPQOKw5UKr2ywNDZZ4axozZPhXucu3lS286V6VrGOkz252/s1600/Unknown.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="252" data-original-width="349" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKlEzjNXFxN82dvJDtfh6ogNTrfK8imC_LAS1Mb2VRiKDNAndMYGcVDHTpYVKr21J9eJrRRFUA5QQk2PawuhzD-cQULynA0XoPQOKw5UKr2ywNDZZ4axozZPhXucu3lS286V6VrGOkz252/s320/Unknown.png" width="320" /></a></div>
<br />
The Python code for this simple example is online:<br />
<ul>
<li><a href="https://github.com/algorithmicart/reinforcement_learning/blob/master/Reinforcement_Learning_1.ipynb">https://github.com/algorithmicart/reinforcement_learning/blob/master/Reinforcement_Learning_1.ipynb</a></li>
</ul>
<br />
Extending the code to a 2-dimensional maze doesn't need any new RL ideas. We'll use the following 2-d map:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsSwtW9sbo_57F9elNLDQxsG84wV2mO6VbC4y-A0VmDPl2fRkQfuda7A7wjAjKsES53gM_30ZTwkruEUd40hmBmZoXZIpHCyF9KOXZ6zRkrW6e8Iel7qjTXNHazy22cGLvzQnu3zYeUBG8/s1600/made_a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="850" data-original-width="1200" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsSwtW9sbo_57F9elNLDQxsG84wV2mO6VbC4y-A0VmDPl2fRkQfuda7A7wjAjKsES53gM_30ZTwkruEUd40hmBmZoXZIpHCyF9KOXZ6zRkrW6e8Iel7qjTXNHazy22cGLvzQnu3zYeUBG8/s400/made_a.png" width="400" /></a></div>
<br />
The robot starts at the top left and need to find the target goal at the bottom left. The maze itself has barriers, marked in red above.<br />
<br />
The code itself is only slightly more complicated than the 1-d example as we now need to deal with four directions for the random walk. The Q-values table will have 4 rows for each of the 4 actions, <b>right</b>, <b>down</b>, <b>left</b>, <b>up</b>.<br />
<br />
<ul>
<li><a href="https://github.com/algorithmicart/reinforcement_learning/blob/master/Reinforcement_Learning_2.ipynb">https://github.com/algorithmicart/reinforcement_learning/blob/master/Reinforcement_Learning_2.ipynb</a></li>
</ul>
<br />
<br />
The following shows an example of the Q-values table after <b>1000</b> iterations.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPQ29W2zuSvSJYnqPjIVAs_2tc8xoBpdxOQlsxZZlMA_4cnhzQphUzwxiKjvVKLZTNRxrIAYdgWFa9pRumzXxJcN4IbOFNQ-dhfjhrmOC5u6kLbONALEWLxCGhyphenhyphenygB_Y-1_Jh3Ndc2zfex/s1600/Screenshot+2019-09-05+at+15.23.59.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="1600" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPQ29W2zuSvSJYnqPjIVAs_2tc8xoBpdxOQlsxZZlMA_4cnhzQphUzwxiKjvVKLZTNRxrIAYdgWFa9pRumzXxJcN4IbOFNQ-dhfjhrmOC5u6kLbONALEWLxCGhyphenhyphenygB_Y-1_Jh3Ndc2zfex/s400/Screenshot+2019-09-05+at+15.23.59.png" width="400" /></a></div>
<br />
Yours will might be different as the path chosen is random, but after many iterations, the numercial values should be converging.<br />
<br />
We can see that the value of moving right from the starting cell is <b>0</b>, because there is a barrier in the way!In fact the only valuable action is to move down.<br />
<br />
You might be wondering how we encode 2-dimensional positions $(x,y)$ to states along the table? We simply map them like this $(x + 5 \cdot y)$.<br />
<br />
Visualising the Q-values table meaningfully isn't easy unwell focus on one chosen direction. We can combine all the Q-values from a cell, that is, combining all the possible actions. If we chose the maximum instead of the sum or average, we get back the V "hotness" value we were thinking about right at the top of this article!<br />
<br />
The python notebook shows how this visualisation is done. The result is interesting:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGKdoBuUhDj1Gh7P9xJt4q5EOzRWL5iQ4C2Ki1uBlkXD7WqLE87EON4xWNWVZCXvDU6CHnafLtVgHjEXclxY3n7o6iM8d8XZMQ6LGS0NnKT1S-mLjMh8MI6os0asX2HkRT8bt8YqZzVJsp/s1600/made_b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="850" data-original-width="1200" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGKdoBuUhDj1Gh7P9xJt4q5EOzRWL5iQ4C2Ki1uBlkXD7WqLE87EON4xWNWVZCXvDU6CHnafLtVgHjEXclxY3n7o6iM8d8XZMQ6LGS0NnKT1S-mLjMh8MI6os0asX2HkRT8bt8YqZzVJsp/s400/made_b.png" width="400" /></a></div>
<br />
We can see that the hotness values direct the robot along the optimal path to the target. The heat map also shows a sub-optimal path which goes the long way around to the target.<br />
<br />
Great!<br />
<br />
Let's try an experiment to see what happens if we have an additional reward at the bottom right.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsEYo6ylJftyr3SfcEJ6XBP4nvcEO10XV5lECQ_3d1_yb2CV6YUl6cQdQkvmLAj437aSvRN0_jOXRHqL9sidYe8ZrlrUGi9AUv0FqBCHHA86sd7kLtQwgUZKDx72Cw9rvxUHbwmtEAzvWQ/s1600/made_a2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="850" data-original-width="1200" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsEYo6ylJftyr3SfcEJ6XBP4nvcEO10XV5lECQ_3d1_yb2CV6YUl6cQdQkvmLAj437aSvRN0_jOXRHqL9sidYe8ZrlrUGi9AUv0FqBCHHA86sd7kLtQwgUZKDx72Cw9rvxUHbwmtEAzvWQ/s400/made_a2.png" width="400" /></a></div>
<br />
The resulting heat map looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjksJC4DNkW-sillGSdhcvX8RZEblLVhRQKC7975iAC2gmChY3uGiJiHH57TOKA900l-mtvDen9pctbnBIt7Gp3nodJUPDSZzUeUb5m0zI6HK23CRMZglDtyKUfQ5eDLAZwtXyjk1CzVlbf/s1600/made_b2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="850" data-original-width="1200" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjksJC4DNkW-sillGSdhcvX8RZEblLVhRQKC7975iAC2gmChY3uGiJiHH57TOKA900l-mtvDen9pctbnBIt7Gp3nodJUPDSZzUeUb5m0zI6HK23CRMZglDtyKUfQ5eDLAZwtXyjk1CzVlbf/s400/made_b2.png" width="400" /></a></div>
<br />
We can see the two targets have paths that are of equal effort. When the robot reaches $(2,2)$ the choice to go right has an Q value equal to going doing. In a practical scenario the robot would choose randomly between two equal paths.<br />
<br />
Let's move the second target to $(2,0)$ where we know it is harder to get to.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZYISO1hM8UhVqhtKlmKv3huBdYq5jA2IDPoCeU8MoT1U_CdLi97GQkmleE9LxeGItu9uYQ8qUon3EOZz-9Pj5C2zTHkTpgvRNXeHelLQHIQ6M3sBBao-y7qyYT33F2zhc9IP6hEgTi9Rb/s1600/made_a3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="850" data-original-width="1200" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZYISO1hM8UhVqhtKlmKv3huBdYq5jA2IDPoCeU8MoT1U_CdLi97GQkmleE9LxeGItu9uYQ8qUon3EOZz-9Pj5C2zTHkTpgvRNXeHelLQHIQ6M3sBBao-y7qyYT33F2zhc9IP6hEgTi9Rb/s400/made_a3.png" width="400" /></a></div>
<br />
This is the resulting heat map:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvRJVP2EVwZtxLm8JJvneHgO5IgkBl96nVENOMTyBLD_7gWjMlIokzkY4QNNc0DUv6KzZQ5KaQ-sFNwYzeFOgDacRAwvoplnpdk1QOgmTB_ukhTO-aMRk1KQG80wXi1WHeZjhTNnGmhO9J/s1600/made_b3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="850" data-original-width="1200" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvRJVP2EVwZtxLm8JJvneHgO5IgkBl96nVENOMTyBLD_7gWjMlIokzkY4QNNc0DUv6KzZQ5KaQ-sFNwYzeFOgDacRAwvoplnpdk1QOgmTB_ukhTO-aMRk1KQG80wXi1WHeZjhTNnGmhO9J/s400/made_b3.png" width="400" /></a></div>
<br />
We can see the optimal path is to the first target and not the longer journey to the second target. At the location $(2,2)$ the Q-value to the right is 3.8, and the value down is the higher 4.3<br />
<br />
<br />
<h3>
More Sophisticated RL</h3>
Ali gave us an insight into more sophisticated RL concepts that are necessary for more realistic problems.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivJcpXdjJUTu_jqQVPt2MCLD9Oto6xEbgkBITkLST1Zu4BaLU3P1iiKCPOLjya4MOwKUVWLJ7n5ljypBRoaOpqAJC6ZleOLBfk-TWhNdOMcyvTsCQ5g7A1gGDKvBdwF76qCS3gcGdFxVzi/s1600/IMG_20190829_191447-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1018" data-original-width="1600" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivJcpXdjJUTu_jqQVPt2MCLD9Oto6xEbgkBITkLST1Zu4BaLU3P1iiKCPOLjya4MOwKUVWLJ7n5ljypBRoaOpqAJC6ZleOLBfk-TWhNdOMcyvTsCQ5g7A1gGDKvBdwF76qCS3gcGdFxVzi/s400/IMG_20190829_191447-01.jpg" width="400" /></a></div>
<br />
<br />
In larger environments, it can be inefficient to spend lots of computation power exploring it with random or other walks. There can be a balance between an <b>explore</b> and <b>exploit</b> mode, where exploring is useful for finding new targets or better paths, and exploit takes advantage of known good paths.<br />
<br />
In many real world scenarios, the environment isn't static. That means an action can lead to a different state when undertaken at a later time, because the environment has changed. Further more, the feedback to the learning agent can also change. This needs a probabilistic approach to learning where we think in terms of <b>expected</b> reward rather than a <b>deterministic</b> reward.<br />
<br />
It can be useful to think a little more deeply about the relationship between an agent's policy and the Q-values that it learns. So far we've stuck with a random-walk policy, but we don't have to.<br />
<br />
At a simple level, a bad policy will mean poor exploration of the environment, which may lead to a suboptimal solution, or non at all. In non-trivial examples, different policies will lead to different maps of Q being learned. This opens up a different area of policy learning where the aim is to learn which kinds of policy lead to optimal Q-value learning.<br />
<br />
Ali also introduced a variant of RL called <a href="https://en.wikipedia.org/wiki/Temporal_difference_learning" target="_blank">temporal difference learning</a>, or <b>TD learning</b>, which can be usefully applied to scenarios which don't have an obvious target state, and also scenarios with continuous rather than discrete states.<br />
<br />
It may seem counterintuitive that we can learn before we reach a target state. The following quote referenced by the <a href="https://en.wikipedia.org/wiki/Temporal_difference_learning" target="_blank">TD learning wikipedia</a> page provides a good example of a continuous scenario where guesses about a reward can make sense:<br />
<br />
<blockquote class="tr_bq">
"Suppose you wish to predict the weather for Saturday, and you have some model that predicts Saturday's weather, given the weather of each day in the week. In the standard case, you would wait until Saturday and then adjust all your models. However, when it is, for example, Friday, you should have a pretty good idea of what the weather would be on Saturday – and thus be able to change, say, Saturday's model before Saturday arrives."</blockquote>
<br />
<br />
<h3>
Deep RL with Neural Networks</h3>
A key development in machine learning has been the combination of neural networks and reinforcement learning.<br />
<br />
For larger and more complex scenarios, the number of states can be huge. Multiplied by the number of possible actions, the problem is even bigger.<br />
<br />
With our simple <b>5x5</b> maze, there a <b>25</b> states, each with 4 actions, so we have <b>100</b> state-action pairs, if we avoid the fact that a small subset are not possible due to barriers. This is a small number for modern computing.<br />
<br />
Ali presented similar numbers for chess and Go. Chess has <b>10<sup>111</sup></b> (<b>1</b> with <b>111</b> zeros after it) state-action pairs, and go has a humongous <b>10<sup>360</sup>,</b> which is larger than the number of atoms in the universe!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvFhAKn34GYF_AQyKKoYeXSRRe31xsA9B1pmnn8Nk974v5-dKWbKsNT6m4qvsR8p5eX7tVjhhhGuk7kqbvuFwG8RLne7SPehQJVQ4G7urcBmkCFrI2VXhY8cDwURIaR15r-5KdmNjSLLSa/s1600/Screenshot+2019-09-05+at+17.45.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="829" data-original-width="1600" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvFhAKn34GYF_AQyKKoYeXSRRe31xsA9B1pmnn8Nk974v5-dKWbKsNT6m4qvsR8p5eX7tVjhhhGuk7kqbvuFwG8RLne7SPehQJVQ4G7urcBmkCFrI2VXhY8cDwURIaR15r-5KdmNjSLLSa/s400/Screenshot+2019-09-05+at+17.45.02.png" width="400" /></a></div>
<br />
Neural networks provide a clever solution because they can take state and learn to approximate Q values in a way that is feasible, albeit approximate.<br />
<br />
Instead of a very large Q-values table, we use a neural network which more compactly maps state and action to a Q-value. A common configuration is for a neural network to take state as input and output Q values for multiple actions.<br />
<br />
What a neural network does that a table doesn't is discard less useful information, learning only those features and correlations which are actually useful to approximating the Q-values.<br />
<br />
The downside is that the neural network output is even more of an approximation than the tabular approach, and can suffer the usual issues of non-global minima and even poor convergence.<br />
<br />
Despite these issues, the advantage of making larger problems feasible are worth the effort of applying "tricks" such as experience replay to make the approach work.<br />
<br />
And this is how achievements like an RL agent learning to play classic Atari games using the raw screen bitmaps as input have happened.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidmw0CmGhKMw8lnpGJr9rYFKMvIMgC-5ns03wD_EoKfIHGKgCRWQS0oe1PBmKJGT4a3df7kklPJ-mDRzACJaqeK4Deu-Nz3SkTv9nYjV0pPgIkD19wx5aTakGsw4JQGWycrsunRLqoQcBk/s1600/rl_atari.gif" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="880" data-original-width="880" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidmw0CmGhKMw8lnpGJr9rYFKMvIMgC-5ns03wD_EoKfIHGKgCRWQS0oe1PBmKJGT4a3df7kklPJ-mDRzACJaqeK4Deu-Nz3SkTv9nYjV0pPgIkD19wx5aTakGsw4JQGWycrsunRLqoQcBk/s400/rl_atari.gif" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">DeepMind RL agent trained to play classic Atari games<br />
<a href="https://deepmind.com/research/publications/playing-atari-deep-reinforcement-learning">https://deepmind.com/research/publications/playing-atari-deep-reinforcement-learning</a></td></tr>
</tbody></table>
<br />
<br />
<h3>
Creative Applications</h3>
RL is primarily applied to industrial applications, because it is about an agent interactively in an environment which provides feedback towards a set of goals. This is why the robot analogy reflects RL concepts very well. Ali's example of Facebook using RL to decide on the timing of notifications to optimise user interaction also matches the RL framework very well.<br />
<br />
In terms of generative design, Ali discussed how RL is employed in drug design.<br />
<br />
As a contrast to industrial applications, Ali did present some creative applications. One that caught the audience's attention was teaching an agent to drive off-the-shelf graphics creation software to draw portraits.<br />
<br />
The following shows faces being drawn by an agent trained using RL with a reward based on its ability to fool a discriminator in the context of a <a href="http://algorithmicartmeetup.blogspot.com/2019/06/generative-adversarial-networks-with.html" target="_blank">GAN</a> architecture.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3LuQqeu_31cozZo_qER_iYG6UiWZDjLQNa9jDX8Uo6tGDJwBxrHXgVMYNbnPV85h0KflxlMqfuJGiKbia6OWWcPUk1GBtDodDo1aDHUy4BYhGi8eb_e0GG-45e-vkM2oTwVRGzAQ-QLN/s1600/default_wgangp_celebahq64_gen_19steps.gif" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="240" data-original-width="480" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3LuQqeu_31cozZo_qER_iYG6UiWZDjLQNa9jDX8Uo6tGDJwBxrHXgVMYNbnPV85h0KflxlMqfuJGiKbia6OWWcPUk1GBtDodDo1aDHUy4BYhGi8eb_e0GG-45e-vkM2oTwVRGzAQ-QLN/s400/default_wgangp_celebahq64_gen_19steps.gif" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">DeepMind SPIRAL: <a href="https://github.com/deepmind/spiral">https://github.com/deepmind/spiral</a></td></tr>
</tbody></table>
<br />
<br />
<h3>
Thoughts </h3>
There was an hour of Q&A after Ali's talk which shows how much interest there is in the subject, and how well he inspired the group.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivJcpXdjJUTu_jqQVPt2MCLD9Oto6xEbgkBITkLST1Zu4BaLU3P1iiKCPOLjya4MOwKUVWLJ7n5ljypBRoaOpqAJC6ZleOLBfk-TWhNdOMcyvTsCQ5g7A1gGDKvBdwF76qCS3gcGdFxVzi/s1600/IMG_20190829_191447-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1018" data-original-width="1600" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivJcpXdjJUTu_jqQVPt2MCLD9Oto6xEbgkBITkLST1Zu4BaLU3P1iiKCPOLjya4MOwKUVWLJ7n5ljypBRoaOpqAJC6ZleOLBfk-TWhNdOMcyvTsCQ5g7A1gGDKvBdwF76qCS3gcGdFxVzi/s400/IMG_20190829_191447-01.jpg" width="400" /></a></div>
<br />
During the discussion Ali made a very interesting point that the latest neuroscience research suggests that the human brain makes many predictions before acting, and then uses feedback to reinforce its understanding of the world.<br />
<br />
This underlines the importance of predict, trial, reward and update mechanism as a learning framework towards a potential <b>general intelligence</b>.<br />
<br />
Another very interesting question was about the equivalence between genetic algorithms and reinforcement learning. This provoked a lot of thought and discussion after the meetup itself.<br />
<br />
At one level, all machine learning is equivalent in that a model is updated based on observation. More useful are the higher level abstractions. Both GA and RL learn solutions to a problem, with fitness based on feedback from the environment. A key difference is that standard RL takes feedback more directly from an achieved goal or target, whereas GA takes feedback from a more continuous measure of success, fitness. A RL method is more amenable to exploring an unknown environment whereas a GAs require some domain or model knowledge.<br />
<br />
And this is the key advantage of RL - very little domain or model knowledge is required.<br />
<br />
A very important point that emerged after the talk is the comparison between the energy efficiency of RL algorithms and that of the human brain. The human brain appears to do far more with very little energy consumption compared to the energy needs of modern machine learning methods including RL.<br />
<br />
<br />
<h3>
More Reading</h3>
<ul>
<li>Dictionary of RL terminology: <a href="https://towardsdatascience.com/the-complete-reinforcement-learning-dictionary-e16230b7d24e" target="_blank">https://towardsdatascience.com/the-complete-reinforcement-learning-dictionary-e16230b7d24e</a></li>
<li>An excellent book on machine learning, with one of the clearest explanation of RL in chapter 13 (pdf): <a href="http://profsite.um.ac.ir/~monsefi/machine-learning/pdf/Machine-Learning-Tom-Mitchell.pdf" target="_blank">http://profsite.um.ac.ir/~monsefi/machine-learning/pdf/Machine-Learning-Tom-Mitchell.pdf</a></li>
<li>UCL RL Course Slides: <a href="http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html" target="_blank">http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html</a></li>
<li>History of RL by Prof AG Barto: <a href="https://www.youtube.com/watch?v=ul6B2oFPNDM" target="_blank">https://www.youtube.com/watch?v=ul6B2oFPNDM</a></li>
<li>MIT Intro Lecture on RL video: <a href="https://www.youtube.com/watch?v=zR11FLZ-O9M" target="_blank">https://www.youtube.com/watch?v=zR11FLZ-O9M</a></li>
<li>Google Depmind's AlphaGo Zero beats world-leading human Go player: <a href="https://deepmind.com/blog/article/alphago-zero-starting-scratch">https://deepmind.com/blog/article/alphago-zero-starting-scratch</a>, <a href="https://www.nature.com/articles/550336a.epdf">https://www.nature.com/articles/550336a.epdf</a></li>
<li>SPIRAL for painting faces: <a href="https://github.com/deepmind/spiral">https://github.com/deepmind/spiral</a></li>
<li>Good overview of RL: <a href="https://neuro.cs.ut.ee/demystifying-deep-reinforcement-learning/">https://neuro.cs.ut.ee/demystifying-deep-reinforcement-learning/</a></li>
</ul>
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-59094931058058285962019-07-19T08:07:00.002-07:002019-07-19T08:07:51.931-07:00Art Hackathon: Ghost In The MachineWe periodically have art hackathons as a change to the usual talk or tutorial format. This <a href="https://www.meetup.com/Algorithmic-Art/events/262257060/" target="_blank">month</a> we held our first hackathon in Cornwall.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyXEtjVNScF22qcWVuhiz9RTFqi5OI0dqhySmbU6_cVSdnyt2NHqvyEMn9whM_ZYk8XPZXVMbPgjQiQC8SFIryDNbjz89GcJuQ2yL1a8h7Hpa3MuK0ZI2AqypI4c4MXRWB0ojjs7y43FIg/s1600/ghost_in_the_machine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="902" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyXEtjVNScF22qcWVuhiz9RTFqi5OI0dqhySmbU6_cVSdnyt2NHqvyEMn9whM_ZYk8XPZXVMbPgjQiQC8SFIryDNbjz89GcJuQ2yL1a8h7Hpa3MuK0ZI2AqypI4c4MXRWB0ojjs7y43FIg/s400/ghost_in_the_machine.png" width="400" /></a></div>
<br />
The theme for this hackathon was "Ghost In the Machine".<br />
<br />
<br />
<h3>
Hackathon?</h3>
In a hackathon we are free to create anything we want. The theme is there to inspire us, and can be interpreted in any way we wish.<br />
<br />
Constraints, chosen carefully, provide a sense of common working but without feeling like your creativity is being clipped. For us the key constrain is to use <b><a href="https://www.openprocessing.org/" target="_blank">openprocessing.org</a></b> which is an online environment for using <b><a href="https://p5js.org/" target="_blank">p5js</a></b>.<br />
<br />
In our group there was a range of experiences and also a range of ages - luckily <b>openprocessing</b> is both beginner friendly as well as a tool for more advanced creative coders.<br />
<br />
In larger groups, people tend to self-organise into individuals and those working together. We also identify those who are able to help others, and those who want technical help.<br />
<br />
For complete beginners I I usually refer to the creative coding for kids course, which although designed for children, has been successful with adults too:<br />
<br />
<ul>
<li><a href="https://sites.google.com/view/creative-coding-for-kids" target="_blank">https://sites.google.com/view/creative-coding-for-kids</a></li>
</ul>
<br />
<br />
<br />
<h3>
Ghost In The Machine?</h3>
Someone asked about the theme, so I explained that all of our themes for this and previous hackathons are chosen to resonate with a theme without being too prescriptive. There is often a reference behind the theme but it is not intended that everyone will know this. In short, a playful theme.<br />
<br />
For me the phrase Ghost In The Machine refers to the philosophy of <a href="https://en.wikipedia.org/wiki/Ghost_in_the_machine" target="_blank">mind-body dualism</a>, but my intention was to invoke the classic Japanese animation <b><a href="https://en.wikipedia.org/wiki/Ghost_in_the_Shell" target="_blank">Ghost In The Shell</a></b>, a beautifully crafted exploration of consciousness, synthetic bodies and machines, artificial intelligence, their co-existence and conflict.<br />
<br />
<div style="text-align: center;">
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="288" src="https://www.youtube.com/embed/WB-ik-Bpl0c" width="512"></iframe></div>
<br />
Watching Ghost In The Machine in the 90s was a key moment for me - it set me on a lifelong journey into artificial intelligence, machine learning and algorithmic art.<br />
<br />
<br />
<h3>
Example Works</h3>
In the fixed timeframe of a hackathon most people find they don't finish wha they had planned. This is ok. Showing a work in progress, and talking about your inspiration and journey, what worked and what didn't, is often more interesting than a finished work in isolation.<br />
<br />
The following are some examples from the group.<br />
<br />
Jonathan worked, not with openprocessing, but <b><a href="https://www.blender.org/" target="_blank">blender</a></b> to create the following beautiful mandala-like designs.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGnkI0csje0QEaEH8FljVf-GZwVvIdkNSvuPx41apgF0xtkJqqmMKe3YLQXKciwsYDMfoj_ujPBfWFpP6wQBKm7gijxW5Uv-p04MtoIqu7YE1LdJMd8inthLwC_fUUEuBXUhnHk1-tJCEe/s1600/550pxPlaneRadialArray1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="550" data-original-width="550" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGnkI0csje0QEaEH8FljVf-GZwVvIdkNSvuPx41apgF0xtkJqqmMKe3YLQXKciwsYDMfoj_ujPBfWFpP6wQBKm7gijxW5Uv-p04MtoIqu7YE1LdJMd8inthLwC_fUUEuBXUhnHk1-tJCEe/s400/550pxPlaneRadialArray1.png" width="400" /></a></div>
<br />
The following playful image of ghosts has an underlying mathematical structure as the number increases along the fibonacci sequence with each ring layer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiByFRAG7uLTNIVRX3jHLm3D_4ViDeYgBeY1Y46NiXQD4s5K475zf0qODTGaJeraR3RvKa5I_RUUpUOctvnriBcCgxB5dbdKTCwaX2U7fCcQNBimTItroIneAMfBFJcJI5B9Xbw6R3nvY9J/s1600/GhostRadialArray1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1600" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiByFRAG7uLTNIVRX3jHLm3D_4ViDeYgBeY1Y46NiXQD4s5K475zf0qODTGaJeraR3RvKa5I_RUUpUOctvnriBcCgxB5dbdKTCwaX2U7fCcQNBimTItroIneAMfBFJcJI5B9Xbw6R3nvY9J/s400/GhostRadialArray1.png" width="400" /></a></div>
<br />
The following cute ghost was created by a young member who only learned to code very recently - lovely!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/738304" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2QWhBwuoRICCv0yfrgYIR3kHCD9DeMFY42sYTHjwbiCGWUt-Poypo_IxCtVhaEXpLZnPOqL1dgGE2fRwMy0axRIND7V3xjPTU0_wK8d_jp_U2HXBAXFfb-BzfvoX1anb7jD6m5cdef_NT/s400/ghost1.png" width="400" /></a></div>
<br />
The following animated work was started as an interaction between two machines, with polygons of varying facets, to see if the combined motion had any interesting emergent or optical effects. Click the image to see it in motion.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/738313" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjslNzshzeB3vp5oDbBGk74FLvboCztzCFrEfg3c19oeXRP8fcZ8c1V5LczJTztNKj1SUz5nO6I9ZlHG_xMB6odBOm5bLJRz3O86ut-hO1a_TEN8ZlUhBvKfQ6p3ifRxQUJxtPgzZlnR674/s400/ghost2.png" width="400" /></a></div>
<br />
The next animation was intended to show a rigid grid of dots - the machine - with other dots moving away from this rigid structure in an organic natural movement.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/738303" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="524" data-original-width="600" height="349" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzHcrSxsxzfTsKWHHEc8e7tOIyOzjCH5tbIbIPVr7q1lYUe8z87zpCk0OuBv0tAqKZls5IYGyZkOId3eWjF0xx6VWqLM4AP7CSigMUhudHIkIJBbcekIZj37CpmvPg2cHHl9EeZvT0v4hB/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<br />
The next work was created in collaboration between two friends, one with more experience as an artist and the other with more experience as a developer.<br />
<br />
It starts with the concept of <a href="https://www.youtube.com/watch?v=QbUPfMXXQIY" target="_blank">boids</a>, individual objects which move according to simple rules, but as an interacting collection, we see emergent behaviour such as flocking.<br />
<br />
They wanted the red objects to turn on and off, and when on they were intended to repel the boids. Click the image to see the full animation and code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/738311" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="344" data-original-width="600" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSeAiHKQ-xMrCGRJpkQxqmEydnkbrw7JdeyKCeOVGCLBovyv5aPkUefC43hevSZZIqL9zk4UxbsYvfKQMdsjJ8MFgd-u3VBOC5nvdz7AG_hA-_OPPZQUvlztNLlfzLjJYcLHBLyNPCsyv6/s400/ezgif.com-video-to-gif.gif" width="400" /></a></div>
<br />
<br />
<h3>
Thoughts</h3>
I think initially the idea of hackathon without somone leading a talk or tutorial might have felt a little uncertain but once underway, with soothing visuals and clasical music, the room was soon a hive of activity!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtZScbHFOG_aHYuqXGTv_Drps6oNB0FS0cRIIToblhtupnBV4Fh7CElWp75wJHt4eRTyjiJHJFMJkBHlRmSVRxCifCDvwxNKLXejxYuKabxXi7j4jaQhAJpR7UePhVn8CKRciNebCRbq7Q/s1600/IMG_20190718_182056-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="935" data-original-width="1600" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtZScbHFOG_aHYuqXGTv_Drps6oNB0FS0cRIIToblhtupnBV4Fh7CElWp75wJHt4eRTyjiJHJFMJkBHlRmSVRxCifCDvwxNKLXejxYuKabxXi7j4jaQhAJpR7UePhVn8CKRciNebCRbq7Q/s400/IMG_20190718_182056-01.jpg" width="400" /></a></div>
<br />
Typically the show-n-tell, where we see each others work and hear the artists ideas and journey, is really interesting and inspiring - and this session was no different!<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-20130503776069982332019-06-13T18:44:00.002-07:002019-06-13T18:44:26.290-07:00How Simple Maths Makes Beautiful Mandelbrot FractalsThis month's <a href="https://www.meetup.com/Algorithmic-Art/events/259974871/" target="_blank">meetup</a> in Cornwall aimed to demystify how the famous Mandelbrot and Julia fractals are created.<br />
<br />
We were also lucky to have Brod Ross, an artist from Falmouth, who shared his work and process creating stunning 3d scenes based on fractal constructions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcPWSRWz6Jm9HLvDj5Qt6E3cMpXuke0PFQY_EXJXxuprJ1BUamPzE7Tl47IzuUxCjPCKP_27GF5tBt-yrF1N72_NkQPno1BlrLqj5mA_wJxJ6lnR0N0REH__g_TdcLFJ8w0V7qmoHJ476G/s1600/SeaPea2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcPWSRWz6Jm9HLvDj5Qt6E3cMpXuke0PFQY_EXJXxuprJ1BUamPzE7Tl47IzuUxCjPCKP_27GF5tBt-yrF1N72_NkQPno1BlrLqj5mA_wJxJ6lnR0N0REH__g_TdcLFJ8w0V7qmoHJ476G/s400/SeaPea2.jpg" width="400" /></a></div>
<br />
The slides are online: <a href="https://tinyurl.com/y5gbbngn" target="_blank">pdf</a>.<br />
<br />
<br />
<h3>
Organic Patterns</h3>
We started by taking a look at examples of patterns that looked organic and natural but were in fact created by a mathematical process.<br />
<br />
Here is an example that has very fine filament-like details, combining a feeling of detailed thread work or the growth of an exotic plant.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF2rl2Zvc2lmgzmQv0hmOMMzZNT9d5IaKinpKY07WdxxYLCRfu9ejqqGyXEypnFt52Fo5mBStLTEdptzn2FgQO84QwArRlFQ3gGuqzBbvJvqQ8R-XL0IyposrrBJXu1dvaHm0Fq-R1AP_a/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF2rl2Zvc2lmgzmQv0hmOMMzZNT9d5IaKinpKY07WdxxYLCRfu9ejqqGyXEypnFt52Fo5mBStLTEdptzn2FgQO84QwArRlFQ3gGuqzBbvJvqQ8R-XL0IyposrrBJXu1dvaHm0Fq-R1AP_a/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" width="400" /></a></div>
<br />
The following is another example that looks like an underwater scene of seahorse-like creatures.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_H1-IRyqYzX9olls5vzccIiB0fiKv1DjDWf1I3ZqdrqRHBykJohlx54S0ReniWWZJ9Y6HH0JbvymOsaooNDxsSvI_gasg4lrryQVB0MNVmfjeGXvl3CKHXYiQZPCZBTrTWnc8oPmdtHEG/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_H1-IRyqYzX9olls5vzccIiB0fiKv1DjDWf1I3ZqdrqRHBykJohlx54S0ReniWWZJ9Y6HH0JbvymOsaooNDxsSvI_gasg4lrryQVB0MNVmfjeGXvl3CKHXYiQZPCZBTrTWnc8oPmdtHEG/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" width="400" /></a></div>
<br />
These patterns are entirely generated by a mathematical process. This surprises many as they're very organic and natural in form.<br />
<br />
The previous two patterns are details from the famous <b>Mandelbrot</b> fractal. The following are examples of a related mathematical pattern called a <b>Julia</b> fractal.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7bv2PaO7c_qjUJ9HOANzz-HWM9-gOkLSmrlHkr7_VmK0JGC6myrNHE7XnjRvJfer-HG4mGaPcs59Ku3XUHpk-wEpFSZmPLjPxCXIvFOi2D6y56xntOTXM9NfAjjZ3-0snrimUEiuKCb4H/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7bv2PaO7c_qjUJ9HOANzz-HWM9-gOkLSmrlHkr7_VmK0JGC6myrNHE7XnjRvJfer-HG4mGaPcs59Ku3XUHpk-wEpFSZmPLjPxCXIvFOi2D6y56xntOTXM9NfAjjZ3-0snrimUEiuKCb4H/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" width="400" /></a></div>
<br />
These are more self-contained and a higher degree of symmetry.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBgCs-g7DA5yQBSx5wI_CWpPUl9y8eI4msjQmqFfvjhm2iSnSPTZ_UUW4stMiCD8ZwmR17bN8ihP4nksX6BnbxSHmGfNsCCiGWGeYx7lYBnOXT6NaLFReJGWWi2T6WZwMz5W4LURN3srDm/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBgCs-g7DA5yQBSx5wI_CWpPUl9y8eI4msjQmqFfvjhm2iSnSPTZ_UUW4stMiCD8ZwmR17bN8ihP4nksX6BnbxSHmGfNsCCiGWGeYx7lYBnOXT6NaLFReJGWWi2T6WZwMz5W4LURN3srDm/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" width="400" /></a></div>
<br />
These patterns are <b><a href="https://en.wikipedia.org/wiki/Fractal" target="_blank">fractals</a></b> - they are self-similar at different scales.<br />
<br />
These fractals are named after the key characters who either discovered them, or did much of the ground-breaking work in the mathematical processes that create them - <a href="https://en.wikipedia.org/wiki/Benoit_Mandelbrot" target="_blank">Benoit Mandelbrot</a> and <a href="https://en.wikipedia.org/wiki/Gaston_Julia" target="_blank">Gaston Julia</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTlPqN_X9EVPqk5Zk0par3MQmYnGKiUODcTxHJre4tLE_aIH_kE0aeKCwUfbFLPHQpKfsjbkhRGe0BqKE9qdRk6e7wKKtpjdNNohvdzXeGE-aiiQnlfy8buqdGbDAC3piqrqz3AjjsTEB2/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTlPqN_X9EVPqk5Zk0par3MQmYnGKiUODcTxHJre4tLE_aIH_kE0aeKCwUfbFLPHQpKfsjbkhRGe0BqKE9qdRk6e7wKKtpjdNNohvdzXeGE-aiiQnlfy8buqdGbDAC3piqrqz3AjjsTEB2/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25284%2529.png" width="400" /></a></div>
<br />
<br />
<h3>
Simple Maths</h3>
We then took our first gentle steps into mathematics to prepare ourselves for the ideas that lie behind these fractals.<br />
<br />
The following expression <b>x<sup>2</sup> + c</b> is rather simple. All it says is "square a number and add another number to it". Square means "multiply by itself".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg19bgK3i6Qpb7WExjruvPS7UVNLBTNUBtuvpKHu7YDOHm4hQ98vr0PVf-O8ZlrZ7YWc-r1VHq2WBqY9E7H-sbHCqyW8WdLHUanwbo_hLR6bR2hOAr1OTjZ-MwK7EIJn1O442plhct2cBPl/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25285%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg19bgK3i6Qpb7WExjruvPS7UVNLBTNUBtuvpKHu7YDOHm4hQ98vr0PVf-O8ZlrZ7YWc-r1VHq2WBqY9E7H-sbHCqyW8WdLHUanwbo_hLR6bR2hOAr1OTjZ-MwK7EIJn1O442plhct2cBPl/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25285%2529.png" width="400" /></a></div>
<br />
For example, if <b>x</b> is <b>2</b> and <b>c</b> is <b>3</b>, then<b> x<sup>2</sup>+ c</b> is <b>4 + 3 = 7</b>.<br />
<br />
Easy enough.<br />
<br />
Yet surprisingly, this is the formula at the heart of the Mandelbrot and Julia fractals.<br />
<br />
The stark contrast between the simplicity of this formula and the extremely detailed organic fractals we've seen is a perfect example of how mathematics has a beauty, hidden not too far under its surface!<br />
<br />
Let's take another step.<br />
<br />
The way this simple formula is used, is to take the answers it gives us and feed them back in again. The following picture explains this idea better.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzY7Tvcr_KO7f-Xfp6UV64dgq8pxS7GjR6hR3kQMrtTZj7PNatMukZTW29N8ihGq6KKUvXNSWWP4zLWkUx8K0YVKjHuRT3JilDkeMtHKs93MTCd3Xx9i0FSDLRWdlrLTSZSLZQUUOTwDzb/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzY7Tvcr_KO7f-Xfp6UV64dgq8pxS7GjR6hR3kQMrtTZj7PNatMukZTW29N8ihGq6KKUvXNSWWP4zLWkUx8K0YVKjHuRT3JilDkeMtHKs93MTCd3Xx9i0FSDLRWdlrLTSZSLZQUUOTwDzb/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25286%2529.png" width="400" /></a></div>
<br />
So if <b>x</b> started at <b>2</b>, and <b>c</b> is <b>3</b>, we've seen the result is <b>7</b>. Let's put that back in. So <b>7<sup>2</sup> + 3 = 52</b>.<br />
<br />
We can think of <b>x<sup>2</sup> + c</b> as a machine that we feed, and that spits out an answer.<br />
<br />
Let's look at a simpler example using a simpler machine:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLsv1TG18rW_cKeAvudNNuKiZizJ_odj7UG8BYzCEJcpDE_hvK5ee44SQnTvYjGky5saRKPre08Ic7LSvkcU3eCB1R42hXGGICLmTHUgRHwDrNZNXW2nSW6k9dueKaNAQLVu3tETLkorc4/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25288%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLsv1TG18rW_cKeAvudNNuKiZizJ_odj7UG8BYzCEJcpDE_hvK5ee44SQnTvYjGky5saRKPre08Ic7LSvkcU3eCB1R42hXGGICLmTHUgRHwDrNZNXW2nSW6k9dueKaNAQLVu3tETLkorc4/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25288%2529.png" width="400" /></a></div>
<br />
This machine is simply <b>x<sup>2</sup></b>. If we start feeding it <b>2</b>, it spits out <b>4</b>. If we feed that <b>4</b> back in again, it spits out <b>16</b>. The sequence of numbers being spat out grows larger and larger through <b>256</b>, <b>65536</b>, and <b>4294967296</b> and upwards.<br />
<br />
What happens if we start with not <b>2</b> but <b>0.5</b>. The numbers seem to get smaller and smaller.<br />
<br />
The starting number seems to decide whether the numbers get bigger or smaller.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbSFe_jnSETlVThKf8PZVafwBOncP5PaWDQOK6OoB34F8GZ-B9YWvl_jSYjxemUtXpOaJAICtyDO-HRrL33N7Yrcz6C_QErIrcbDC7FBrExz2Hw5d22HadgygxQVvcezTHlxo92WE69BX3/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbSFe_jnSETlVThKf8PZVafwBOncP5PaWDQOK6OoB34F8GZ-B9YWvl_jSYjxemUtXpOaJAICtyDO-HRrL33N7Yrcz6C_QErIrcbDC7FBrExz2Hw5d22HadgygxQVvcezTHlxo92WE69BX3/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" width="400" /></a></div>
<br />
Let's make a <b>map</b> of how numbers behave - a map showing whether numbers get bigger and bigger, or smaller and smaller.<br />
<br />
The following shows the number <b>2</b> coloured green, because <b>iterated</b> through the x<sup>2</sup> machine it gets bigger and bigger.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtqc3RGkx5LLtv5I1BEzMqCjYpnm4k7gUQKeBjworeb0vU3wh_Zm4UK9gzvMIcoVDv7fEFBo1nv8WeaWso8bnYAOZVYXU-64JrdXz5Egm2M_1rYdnG4YLowlxq73Vzrit0tVXujXx9CHi0/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtqc3RGkx5LLtv5I1BEzMqCjYpnm4k7gUQKeBjworeb0vU3wh_Zm4UK9gzvMIcoVDv7fEFBo1nv8WeaWso8bnYAOZVYXU-64JrdXz5Egm2M_1rYdnG4YLowlxq73Vzrit0tVXujXx9CHi0/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" width="400" /></a></div>
<br />
The next picture shows the number <b>0.5</b> coloured red, because iterated through the machine the numbers get smaller and smaller.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm5cPh3lQyAyUfkvgXyJ3hWgVli09gzsw6tiBjV0BjOCuRCWZAJW4Z0i19TTyGxRAR36ujs6mkVheFkVzt59zHkU5gUBk_DAJ63aSbgZ_No4hFTPPeP6CDfCWMj2I6DdeXq7jUgIl2LxA0/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm5cPh3lQyAyUfkvgXyJ3hWgVli09gzsw6tiBjV0BjOCuRCWZAJW4Z0i19TTyGxRAR36ujs6mkVheFkVzt59zHkU5gUBk_DAJ63aSbgZ_No4hFTPPeP6CDfCWMj2I6DdeXq7jUgIl2LxA0/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" width="400" /></a></div>
<br />
If we continue to test lots of numbers on the number line, including negative numbers we get a map that looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRIxCIDpoIm8rU578ZcqJ94wGfu2DwI-9F71pVtMqVbmyDR6VBpIg7sGWWji3jCqj3plNeYvjXBpA1j_M5r2hoDr1hDcB4PHS-KPrRlI466Usqrs55MgSyPWW9t-piF2RLmxuODuFMDs6u/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRIxCIDpoIm8rU578ZcqJ94wGfu2DwI-9F71pVtMqVbmyDR6VBpIg7sGWWji3jCqj3plNeYvjXBpA1j_M5r2hoDr1hDcB4PHS-KPrRlI466Usqrs55MgSyPWW9t-piF2RLmxuODuFMDs6u/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" width="400" /></a></div>
<br />
The negative numbers smaller than <b>-1</b> are green because they do get bigger and bigger. Negative numbers squared become positive. The red region is around 0 and that makes sense because fractions less than 1 get smaller and smaller.<br />
<br />
The map also shows <b>1</b> and <b>-1</b> coloured blue because those numbers, when iterated through <b>x<sup>2</sup></b>, don't get bigger or smaller, they stay at <b>1</b>. The blue dots mark the boundary between the red and green territories.<br />
<br />
So far, the maths has been easy. Let's take one more step.<br />
<br />
Let's keep the idea of feeding a machine like we have before. Let's keep the idea of drawing a map to show how starting numbers behave.<br />
<br />
But let's change the numbers to another kind of number called a <b>complex number</b>, even though they aren't complex at all!<br />
<br />
<br />
<h3>
Complex Numbers</h3>
Complex numbers aren't complex. They are just a composite number made of two normal numbers.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Wy6o5ZuZ6uaHWAoQbNXBpdBYrRPZuyfenrU1Om9YZ8cCpncG2e6FKARADCXqruhk1JZy9ntuVBReF4jj9Q14TcxQHx3RlF5973DkD2_npO5I-sLhc0_mdVCg4VaytVwgcfp7svITvaLT/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25287%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Wy6o5ZuZ6uaHWAoQbNXBpdBYrRPZuyfenrU1Om9YZ8cCpncG2e6FKARADCXqruhk1JZy9ntuVBReF4jj9Q14TcxQHx3RlF5973DkD2_npO5I-sLhc0_mdVCg4VaytVwgcfp7svITvaLT/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25287%2529.png" width="400" /></a></div>
<br />
One part is called the <b>real</b> part, and the other is called the <b>imaginary</b> part. We mustn't let this surreal naming scare us away!<br />
<br />
Things made of <b>2</b> parts or <b>2</b> numbers aren't unfamiliar. We're used to latitude and longitude on geographical maps, chess board positions or cells in a spreadsheet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLBBXXmBUmXFeu8Z9p4uml9hrarPLFzkxUZg4orVudWXMq0d1lpIgVz4ixJYxDrXg4JtCYNCSxrfBEKua7iRbRHmB1czV902WRgYvZvd7k3AzMg8i5PAcWI8CEDjj9fpJVqfu2Liqc91c/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLBBXXmBUmXFeu8Z9p4uml9hrarPLFzkxUZg4orVudWXMq0d1lpIgVz4ixJYxDrXg4JtCYNCSxrfBEKua7iRbRHmB1czV902WRgYvZvd7k3AzMg8i5PAcWI8CEDjj9fpJVqfu2Liqc91c/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25286%2529.png" width="400" /></a></div>
<br />
Because complex numbers have <b>2 parts</b>, we can visualise them on a 2d surface like a grid or a map. It is normal for the real part to be along the horizontal direction, and the imaginary part along the vertical direction.<br />
<br />
If we want to push these numbers through our machine, we need to know how to add and multiply them.<br />
<br />
Adding complex numbers is easy - we just combine real parts with real parts, and imaginary parts with imaginary parts:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZqKRLMW50ZhVBK2Qb5Wb0ntg3JQNpmMYOnJNbHX70VGaQZ_g0Hv93AHlYpOzxniV9-wTEWITw1bN1IE7fyS3g8ZDzyp3tYGni6_1S_0412DukQ5XXTi_hJPXA02FtLNPzyGara4ligq_/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25288%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZqKRLMW50ZhVBK2Qb5Wb0ntg3JQNpmMYOnJNbHX70VGaQZ_g0Hv93AHlYpOzxniV9-wTEWITw1bN1IE7fyS3g8ZDzyp3tYGni6_1S_0412DukQ5XXTi_hJPXA02FtLNPzyGara4ligq_/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25288%2529.png" width="400" /></a></div>
<br />
Multiplying is also simple in principle. We combine all the elements just like we might multiply out brackets at school algebra:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfIzXho1LWqhNIDCwF9SYzY0I0oFhPY4nCR9n915SogvclVBQ5UltnvmnxEMsdScK3bUf4q11BFtpOolznY_-AhNnVITY1X-cM3PuhHY2BZVb5sO42PU24WnAA1YP_KnrjAF68XpMWXo39/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25289%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfIzXho1LWqhNIDCwF9SYzY0I0oFhPY4nCR9n915SogvclVBQ5UltnvmnxEMsdScK3bUf4q11BFtpOolznY_-AhNnVITY1X-cM3PuhHY2BZVb5sO42PU24WnAA1YP_KnrjAF68XpMWXo39/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25289%2529.png" width="400" /></a></div>
<br />
We can sweep together real parts and imaginary parts but we're left with an element with <b>i<sup>2</sup></b>. In the above example it is <b>3i * 5i = 15i<sup>2</sup></b>.<br />
<br />
What is <b>i<sup>2</sup></b>? Let's look at the following picture showing what happens when <b>1</b> is multiplied by <b>i</b>. The result is a rotation of 90 degrees anticlockwise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjthd5QbJir9QECJB6zLkW2iPci9w_unTVDxFX0O7umi7pKB8FgYnvDj4RagKDrA79ZeZehFTaKTEFaaDLQnR5wWq_Aky-eYjNGRu6XAVwo9o9MzCPa0_ZEr_M8nSLMRhtmIHaEXGie_Ve8/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252811%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjthd5QbJir9QECJB6zLkW2iPci9w_unTVDxFX0O7umi7pKB8FgYnvDj4RagKDrA79ZeZehFTaKTEFaaDLQnR5wWq_Aky-eYjNGRu6XAVwo9o9MzCPa0_ZEr_M8nSLMRhtmIHaEXGie_Ve8/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252811%2529.png" width="400" /></a></div>
<br />
Another multiplication by <b>i</b> means another similar rotation which leads to <b>-1</b>.<br />
<br />
So <b>i<sup>2</sup> = -1</b>.<br />
<br />
We can now finish our multiplication:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeVwBbwgEpIuy7dQIOMXvvRbveSW_bkyeTRgUtUzSjnD08QaKaNKHzNMp78v3NFS16-Y_-pdtGbUDIU9dz6Oyi9QwUcJLZEj-MUvOtBdauV9fwbknxGiQi8LA05-qeQSHtD-F2n9xfQ0uX/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252812%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeVwBbwgEpIuy7dQIOMXvvRbveSW_bkyeTRgUtUzSjnD08QaKaNKHzNMp78v3NFS16-Y_-pdtGbUDIU9dz6Oyi9QwUcJLZEj-MUvOtBdauV9fwbknxGiQi8LA05-qeQSHtD-F2n9xfQ0uX/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252812%2529.png" width="400" /></a></div>
<br />
So now we know how to add and multiply complex numbers, we're ready to feed these numbers to a machine again.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz0d4nAxNphwNTOy3YhBU9V0DRBJHNbiTya0AJqLaVcegNWZMn3e4MsGqeDEsDfzt-Dae7h0ihAaRSdBmzaHIeuxK9dI8jh4B2Lhhyyv1dUt6SEiYTOVGcekmCn1lVnVkiXf0uez1ZKUbE/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252813%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz0d4nAxNphwNTOy3YhBU9V0DRBJHNbiTya0AJqLaVcegNWZMn3e4MsGqeDEsDfzt-Dae7h0ihAaRSdBmzaHIeuxK9dI8jh4B2Lhhyyv1dUt6SEiYTOVGcekmCn1lVnVkiXf0uez1ZKUbE/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252813%2529.png" width="400" /></a></div>
<br />
We'll start <b>x</b> at <b>0 + 0i</b> which is the complex number for <b>0</b>. We can choose a complex number for <b>c</b>, we just need to stick with it consistently through all the calculations.<br />
<br />
Because complex numbers are <b>2</b> dimensional, the map we draw to show how they behave as we iterate them through the <b>x<sup>2</sup> + c</b> function will be <b>2</b> dimensional too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC31oJ6gRzOuNjIHZaAV1G0_OpOqIBxDWtgYEzMqknSug-BXlxPWrMP4y4xvFgIyKCIlR5cRRUSqhpCHPoNUmRs7_W0LKosIR6FxrFbF9U4-CcHS6Iws3b2KTdXqd_nW3kjmBm9MMDtKny/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252814%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC31oJ6gRzOuNjIHZaAV1G0_OpOqIBxDWtgYEzMqknSug-BXlxPWrMP4y4xvFgIyKCIlR5cRRUSqhpCHPoNUmRs7_W0LKosIR6FxrFbF9U4-CcHS6Iws3b2KTdXqd_nW3kjmBm9MMDtKny/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%252814%2529.png" width="400" /></a></div>
<br />
<br />
<h3>
Surprising Behaviour of Complex Numbers</h3>
Let's see what happens is we start with <b>x = 0 + 0i</b> and <b>c = 2 + 2i</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo6kxmmcN2zf7-Yf9TE4rvVfkRi_ww3-G4ElNY-XS6kgJ2jkPYq-GoKcNgmv5PNfnrr9K22RJU2qDjlZB7unHRHqLEj45AFPMPGrya6pF4hyNPdQIVsVth0BiLnJ6a5pW9bobyxUHqvCH5/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo6kxmmcN2zf7-Yf9TE4rvVfkRi_ww3-G4ElNY-XS6kgJ2jkPYq-GoKcNgmv5PNfnrr9K22RJU2qDjlZB7unHRHqLEj45AFPMPGrya6pF4hyNPdQIVsVth0BiLnJ6a5pW9bobyxUHqvCH5/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" width="400" /></a></div>
<br />
We can see the complex numbers get bigger rand bigger. The second value is <b>2 + 2i</b>, the third is <b>2 + 10i</b>, and the fourth is <b>-94 + 42i</b>. On the graph we can see the numbers are spiralling outwards.<br />
<br />
The following picture shows this spiralling out, and also the direct distance to the point - the magnitude of the complex number. We can see the magnitude gets bigger quickly.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoTRCcAdYxQVYuG5NBIasTCUDSNIMJvi4tTmgul5TivEhEYtLJlO4FlkzH8wGUWXtUP74hMAaeTOi-yMa50xU-FKgghNK7MGkoQKZxHkxBaCMNpX2BHTxw0Y6SgqVJLpK6L6Hvly25MdaO/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoTRCcAdYxQVYuG5NBIasTCUDSNIMJvi4tTmgul5TivEhEYtLJlO4FlkzH8wGUWXtUP74hMAaeTOi-yMa50xU-FKgghNK7MGkoQKZxHkxBaCMNpX2BHTxw0Y6SgqVJLpK6L6Hvly25MdaO/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" width="400" /></a></div>
<br />
Let's try <b>c = 0.4 + 0.4i</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC3GAEQlcIDaDSr97p5H_Ag-OedOHieaWuftg38Y50Xgths7fevh5MQ3GThHt2hCQLD1unMWKkKd-GxAQCTx_e1D3M4-IsK_09erl5oA2oqGvg4bVnaQvNa7k9UminPkHgJvRwUiZRMdIu/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC3GAEQlcIDaDSr97p5H_Ag-OedOHieaWuftg38Y50Xgths7fevh5MQ3GThHt2hCQLD1unMWKkKd-GxAQCTx_e1D3M4-IsK_09erl5oA2oqGvg4bVnaQvNa7k9UminPkHgJvRwUiZRMdIu/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" width="400" /></a></div>
<br />
This time we can see the numbers spiralling around before finally escaping. The magnitude chart shows this eventual explosion. This is interesting behaviour given how simple the function <b>x<sup>2</sup> + c</b> is.<br />
<br />
Let's try <b>c = -0.3 + 0.4i</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmaj_WwkeMWYmOMcMwRcjztH5lVNVWNGLLxWBjWRJvpGgildFpOAgCqAiPOg1ssYU1_epUPY1kfAZxmYDOHbJzTfbEE6dowEE4lewJwFkmmBHs0oJMEqQ4nnzrcZH_wm6IoxHA4ZjGoZhG/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmaj_WwkeMWYmOMcMwRcjztH5lVNVWNGLLxWBjWRJvpGgildFpOAgCqAiPOg1ssYU1_epUPY1kfAZxmYDOHbJzTfbEE6dowEE4lewJwFkmmBHs0oJMEqQ4nnzrcZH_wm6IoxHA4ZjGoZhG/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" width="400" /></a></div>
<br />
The numbers seem to be getting sucked into an orbit around a specific point, and getting sucked inwards to that point - like a black hole. That point, in mathematical terms, is called an <b>attractor</b>.<br />
<br />
More interesting behaviour!<br />
<br />
Let's try <b>c = 0.3 + 0.5i</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_5-rF7lU_m7_mZicCtM4AMtHWNvzihPbcE34O1pizOuXlzpZwcHpD9pO1DiwOBEZ58S7GTKx_y_vRY2IUCpfpPlk6nM3oDKhp5xiEo3QyeXrQZ7bQB4NO1TEc4vhPULBSzn_EI-J9q0Rk/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_5-rF7lU_m7_mZicCtM4AMtHWNvzihPbcE34O1pizOuXlzpZwcHpD9pO1DiwOBEZ58S7GTKx_y_vRY2IUCpfpPlk6nM3oDKhp5xiEo3QyeXrQZ7bQB4NO1TEc4vhPULBSzn_EI-J9q0Rk/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25284%2529.png" width="400" /></a></div>
<br />
This time the orbit is more sustained and has a larger shape. Another kind of behaviour - all from the innocent looking <b>x<sup>2</sup> + c</b>.<br />
<br />
What could a map of this behaviour look like?<br />
<br />
The following shows an early plot created in <b>1978</b>!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnbTOVMudILBhCAS5eXvO3ICnKp7uuq2aIyOlIl7Xjjlwkw6xZMlX4IyPDFqR077hqSRTihTBKCKo8K3BwhTC6If2NJUyuCHYz6Lx9TP4jhTVfj8zsjXjzJIsb37zbmWCSQHQ3JSJVNQOc/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25285%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnbTOVMudILBhCAS5eXvO3ICnKp7uuq2aIyOlIl7Xjjlwkw6xZMlX4IyPDFqR077hqSRTihTBKCKo8K3BwhTC6If2NJUyuCHYz6Lx9TP4jhTVfj8zsjXjzJIsb37zbmWCSQHQ3JSJVNQOc/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25285%2529.png" width="400" /></a></div>
<br />
The map isn't a circle or a square, an oval or a diamond. It is a strange beetle shape!<br />
<br />
Again - this strangeness from the innocent <b>x<sup>2</sup> + c</b> function!<br />
<br />
Here is a higher-resolution plot of the map, showing which numbers explode and which fall towards zero.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib8y2DamLBDha4x-eahZcAVw2uk1uPRpEGCWHvmoUbLMXXDACdnJYlsQJVXVNDZ8XzVzaPkDJllPud9QsxJu6OqbmxGByXltL9YihRwf43NruAopiWLAPhqMsezzmQramwFaoeG3JtBHvI/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib8y2DamLBDha4x-eahZcAVw2uk1uPRpEGCWHvmoUbLMXXDACdnJYlsQJVXVNDZ8XzVzaPkDJllPud9QsxJu6OqbmxGByXltL9YihRwf43NruAopiWLAPhqMsezzmQramwFaoeG3JtBHvI/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25286%2529.png" width="400" /></a></div>
<br />
Finally ... the famous <b>Mandelbrot Set</b>.<br />
<br />
We can see self-similarity in the pattern. There are smaller bulbs on the main bulbs, and each one of those has smaller bulbs too.<br />
<br />
Let's remind ourselves how the image is created:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDxLNxVz_SsHOLanfY6gx4Qfbw6IK1xjAVIq01oJw4J0Fhmq4GP6xDpiyTzRG9dFgQcVFj9PPoEJ3LaOhKqYoZCV4DQk0MFs32_r-r8TXARgZclRefbxAP1hYFN9lliQr9HCu5AGb9JJwt/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25287%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDxLNxVz_SsHOLanfY6gx4Qfbw6IK1xjAVIq01oJw4J0Fhmq4GP6xDpiyTzRG9dFgQcVFj9PPoEJ3LaOhKqYoZCV4DQk0MFs32_r-r8TXARgZclRefbxAP1hYFN9lliQr9HCu5AGb9JJwt/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25287%2529.png" width="400" /></a></div>
<br />
We pick a point on the 2-d map to test. We push that number as c through the function <b>x<sup>2</sup> + c</b>, repeatedly feeding the answer back into the function. If the numbers get larger and larger we colour the point white. If the numbers fall towards zero, we colour them black.<br />
<br />
We saw earlier that sometimes the numbers seem to orbit around a point, not exploding or diminishing. These are at the boundary of that beetle, dividing the two kinds of regions.<br />
<br />
The most popular renditions of the Mandelbrot fractal are coloured. There are many options for choosing how to colour the fractal, but the following is a popular option:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjENg5YnIvmfXu1gCfUmzSUONMK4oULlf9qg-KxL5p-5krhZCIttBNmdXJPQ1FYXwrRn6bhcxRHk05tw038pGDkH8ajp70NAXOwJHitJQJvyXzn7U-C8TL7Aj-affvTotqeXMEvTgscXOpt/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25288%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjENg5YnIvmfXu1gCfUmzSUONMK4oULlf9qg-KxL5p-5krhZCIttBNmdXJPQ1FYXwrRn6bhcxRHk05tw038pGDkH8ajp70NAXOwJHitJQJvyXzn7U-C8TL7Aj-affvTotqeXMEvTgscXOpt/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25288%2529.png" width="400" /></a></div>
<br />
We still colour black the regions that fall towards zero. For the regions that explode, we identify how fast the numbers grow and use this rate to choose a colour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfE-9YUiTMrp8FCWCtNF7ae3l0D2CGkmLKEyLHwKzVgHELfqhAZFQWhvnp36pe1i3u4jZIKR3tdEXmc7ul3IyFqL_vd6EWl6Tl3grPVgf9IClTc69rnfH6KMHD9Hdp5ZWeCVb3_EEE8KPl/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25289%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfE-9YUiTMrp8FCWCtNF7ae3l0D2CGkmLKEyLHwKzVgHELfqhAZFQWhvnp36pe1i3u4jZIKR3tdEXmc7ul3IyFqL_vd6EWl6Tl3grPVgf9IClTc69rnfH6KMHD9Hdp5ZWeCVb3_EEE8KPl/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25289%2529.png" width="400" /></a></div>
<br />
When calculating the numbers, we can stop if the magnitude get's larger than <b>2</b>. There is a mathematical <a href="http://makeyourownalgorithmicart.blogspot.com/2017/12/escape-conditions-for-julia-and.html" target="_blank">proof</a> that shows that if a number get's larger than <b>2</b>, then it will escape.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn7Nw8PbOqL739K-pWhH7ov580xHtAP5AyRDJvHZKxG_h-mZnXDkwvtK3Dki_ZD03a7N2yi8AMvq4LbCZTDac9pE-t0Wq4OeQzXJBKniUfJGXS0IfbxfH2jiGUvAuX8UDOgvth2SzIIZ7c/s1600/escape.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="960" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn7Nw8PbOqL739K-pWhH7ov580xHtAP5AyRDJvHZKxG_h-mZnXDkwvtK3Dki_ZD03a7N2yi8AMvq4LbCZTDac9pE-t0Wq4OeQzXJBKniUfJGXS0IfbxfH2jiGUvAuX8UDOgvth2SzIIZ7c/s400/escape.png" width="400" /></a></div>
<br />
We also set a maximum for the number of times we iterate the function because we don't have all the time in the world to see if a point <b>diverges</b> or <b>converges</b>. If the size reaches 2 before this maximum is reached, we can use the actual iteration count as a measure of how fast the number escapes, which we can use for the colouring.<br />
<br />
The fractal is infinitely detailed, and we can set the "window" size to see the detail more closely.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqrqapvKVDaq0o3lAAN1bJ05NLVv9r4sSGYRu5sOmmn-ow9KkfrZEKl9Z__VCAB0u5upQUcmjH8cHoaX_yA4lkI3Pb9OtU0u83blOULvUO8d77APYAyTc-zK0hKUuW_H67FCOQBD1qFdZx/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqrqapvKVDaq0o3lAAN1bJ05NLVv9r4sSGYRu5sOmmn-ow9KkfrZEKl9Z__VCAB0u5upQUcmjH8cHoaX_yA4lkI3Pb9OtU0u83blOULvUO8d77APYAyTc-zK0hKUuW_H67FCOQBD1qFdZx/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals.png" width="400" /></a></div>
<br />
That simple zooming-in reveals an incredible amount of beautiful detail - all from that very simple function!<br />
<br />
The following youtube video shows an animated zooming into the Mandelbrot fractal ... the level of detail is breathtaking!<br />
<br />
<div style="text-align: center;">
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="288" src="https://www.youtube.com/embed/PD2XgQOyCCk" width="512"></iframe>
</div>
<br />
<br />
You can find commented Python code to draw a Mandelbrot set here:<br />
<ul>
<li><a href="https://github.com/algorithmicart/mandelbrot/blob/master/mandelbrot.ipynb">https://github.com/algorithmicart/mandelbrot/blob/master/mandelbrot.ipynb</a></li>
</ul>
<br />
<br />
<br />
<h3>
Julia Sets</h3>
The Julia fractals are created in an almost identical manner. There is only one change:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEPf2-gPLDKSssc2TXkZzdepCtYiGNMn1YIhYipWMoezjgfYqUFku52fG9yGhN0r8hlqJKDtC6xYaP50O4aSD0Ofo_qPDFSTeppvzMJpSjNyedb09Bg6qdw-XjbzB_cbecS0e4apkzZ1FA/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEPf2-gPLDKSssc2TXkZzdepCtYiGNMn1YIhYipWMoezjgfYqUFku52fG9yGhN0r8hlqJKDtC6xYaP50O4aSD0Ofo_qPDFSTeppvzMJpSjNyedb09Bg6qdw-XjbzB_cbecS0e4apkzZ1FA/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25281%2529.png" width="400" /></a></div>
<br />
With the Mandelbrot fractal, we start <b>z</b> as <b>0 + 0i</b> and <b>c</b> as the point being tested.<br />
<br />
With the Julia fractal we set <b>z</b> to start as the point being tested, but set <b>c</b> to a constant all over the map.<br />
<br />
In effect, the roles of <b>z</b> and <b>c</b> are swapped.<br />
<br />
Here is another nice example of a Julia set.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFaReNb-jzDSXIwWsb5B-OiYqYSSluzrokWzjjMEKkPyCsL7xBKwOWvHehME5yd61P9YSLak-vMxyFDD5YcTCEZDSkkyx41OvCHmtRyIRMlqzRmsOfknGOjf4n_E9v8iEUgoimhE8MmBEN/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFaReNb-jzDSXIwWsb5B-OiYqYSSluzrokWzjjMEKkPyCsL7xBKwOWvHehME5yd61P9YSLak-vMxyFDD5YcTCEZDSkkyx41OvCHmtRyIRMlqzRmsOfknGOjf4n_E9v8iEUgoimhE8MmBEN/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25282%2529.png" width="400" /></a></div>
<br />
<br />
Sample Python code for creating a Julia set is here:<br />
<ul>
<li><a href="https://github.com/algorithmicart/mandelbrot/blob/master/julia.ipynb">https://github.com/algorithmicart/mandelbrot/blob/master/julia.ipynb</a></li>
</ul>
<br />
<br />
<br />
<h3>
3D Landscapes</h3>
We previously used the rate of escape to choose a colour. We can also use this rate as a height of a point on a 3d landscape.<br />
<br />
Here is the simple Mandelbrot fractal transformed into a 3d landscape surface.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfZQxvl1QZVmqDvMeAYQ9vWAhD4t-RU-H0thNIewTUHfrVVt4_z_Ri5leJf_N1J7c4HUO6MeKmAsOydb3GawvH5mxQ_Ee5Qa2ia6TN_cKjUYDLG6xr7fv5aKk_y3qMBSj6vJF6Q7s-DZok/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfZQxvl1QZVmqDvMeAYQ9vWAhD4t-RU-H0thNIewTUHfrVVt4_z_Ri5leJf_N1J7c4HUO6MeKmAsOydb3GawvH5mxQ_Ee5Qa2ia6TN_cKjUYDLG6xr7fv5aKk_y3qMBSj6vJF6Q7s-DZok/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25283%2529.png" width="400" /></a></div>
<br />
A closer zoom into a Julia fractal creates a more interesting landscape:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiQNV6SLWcessPZkZeRcb-OmQrjxzDOkEUyCLHARDNNrVs0C2qnrhZtiyBbZ1vKx_Tq1eGYFbn7qI2f8cS9s9HGqq2wexTLivIozefoikU7wJqhOiaJr-STcx5bu0LYlvhhOr0j0ZuFD9T/s1600/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiQNV6SLWcessPZkZeRcb-OmQrjxzDOkEUyCLHARDNNrVs0C2qnrhZtiyBbZ1vKx_Tq1eGYFbn7qI2f8cS9s9HGqq2wexTLivIozefoikU7wJqhOiaJr-STcx5bu0LYlvhhOr0j0ZuFD9T/s400/How+Simple+Maths+Makes+Beautiful+Mandelbrot+Fractals+%25284%2529.png" width="400" /></a></div>
<br />
Being able to interactively move around and explorable a landscape is an interesting experience:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio2YDQ98GDZnXJZkJz2pWlUxghq6Ek2I6n3YOjcqje9WCS3G5a_YKMsGu5nhVGDJQhF7tJwnxeWCevD-fl7CES1WnUIlStBq9OYC9-wxahy7O0EJUaPlYk8RnPq4rqn8Kz77Z8DPS4WvlK/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="489" data-original-width="600" height="325" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio2YDQ98GDZnXJZkJz2pWlUxghq6Ek2I6n3YOjcqje9WCS3G5a_YKMsGu5nhVGDJQhF7tJwnxeWCevD-fl7CES1WnUIlStBq9OYC9-wxahy7O0EJUaPlYk8RnPq4rqn8Kz77Z8DPS4WvlK/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<br />
The code for creating and exploring landscapes like this is online too:<br />
<br />
<ul>
<li><a href="https://github.com/algorithmicart/mandelbrot/blob/master/mandelbrot_height_field.ipynb">https://github.com/algorithmicart/mandelbrot/blob/master/mandelbrot_height_field.ipynb</a></li>
</ul>
<br />
<br />
<br />
<h3>
Mandelbulb Worlds</h3>
We were lucky to have Brod Ross show some of the worlds he creates using tools which create an almost photorealistic rendering of scenes containing objects that are fractals creates in basically the same way as the Mandelbrot and Julia sets.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirSCtP9EUDPrTnbolN6C-XShy6hxNiVWcw8wHw-i7VQsdV9yoiXhUYuggpqooQgnGSA1DpjO_qywHqeE1rili35pB6kJOEhqOQL0Jn1Pi9MAlmF2BzRgRW1je0JRHRrQ8WmmzxCNzwE6dd/s1600/IMG_20190611_181237-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1217" data-original-width="1600" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirSCtP9EUDPrTnbolN6C-XShy6hxNiVWcw8wHw-i7VQsdV9yoiXhUYuggpqooQgnGSA1DpjO_qywHqeE1rili35pB6kJOEhqOQL0Jn1Pi9MAlmF2BzRgRW1je0JRHRrQ8WmmzxCNzwE6dd/s400/IMG_20190611_181237-01.jpg" width="400" /></a></div>
<br />
Here are some of his works:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIzdp-593tdcPhUsppvutFuLcmaF2WKlrM_br3ifTjdhrRQgT40b_92TrWbqHs9wQHJoGhPeNiIa1SVrXE1qgkHBkMzBuGn3s4PQaal8QgD_7K9k-j6h_LvtMcmUginPGwXPWC8R4_5U9n/s1600/Orbital+dock1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="961" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIzdp-593tdcPhUsppvutFuLcmaF2WKlrM_br3ifTjdhrRQgT40b_92TrWbqHs9wQHJoGhPeNiIa1SVrXE1qgkHBkMzBuGn3s4PQaal8QgD_7K9k-j6h_LvtMcmUginPGwXPWC8R4_5U9n/s400/Orbital+dock1.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhviWZy3o6EmoN6COpU8Q7hyZyYbTwsSAQVqKUK1lBolUJR4effpSHpGPaZ5yb2_p4hqxc5lryE3q5GpNmLBX6RXgQ1DMN3V2v97i2yLuaP7eRxMZI0fqPLBzpZagCFSvICZAHwcUZ0KAi/s1600/Uneasey+lies+the+Crown2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhviWZy3o6EmoN6COpU8Q7hyZyYbTwsSAQVqKUK1lBolUJR4effpSHpGPaZ5yb2_p4hqxc5lryE3q5GpNmLBX6RXgQ1DMN3V2v97i2yLuaP7eRxMZI0fqPLBzpZagCFSvICZAHwcUZ0KAi/s400/Uneasey+lies+the+Crown2.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zOGIWiQyn-GYGWy4l5OxrcoO7ZAK8XWBtRTWz-dvPKAySZQR3f-zoCvWdH_TxELw4smY1j8auOT33_6CPhHAhaYISjtqaktxP7AG2ZKbqfhhD6qoGiXHFq6_OCqXb1qIj5Zyk7SVi1dN/s1600/ugley.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zOGIWiQyn-GYGWy4l5OxrcoO7ZAK8XWBtRTWz-dvPKAySZQR3f-zoCvWdH_TxELw4smY1j8auOT33_6CPhHAhaYISjtqaktxP7AG2ZKbqfhhD6qoGiXHFq6_OCqXb1qIj5Zyk7SVi1dN/s400/ugley.jpg" width="400" /></a></div>
<br />
If you look closely, you can see the fractal nature of the structures.<br />
<br />
<br />
<h3>
Tools</h3>
If you want to use tools to explore these fractals, the following are good starting points:<br />
<br />
<ul>
<li>A web-only Mandelbrot explorer, no need to install any software: <a href="http://www.mandelbulb.com/2014/mandelbulb-3d-mb3d-fractal-rendering-software/">http://www.mandelbulb.com/2014/mandelbulb-3d-mb3d-fractal-rendering-software/</a></li>
<li>A fast open source renderer, so fast it can animate a zoom in real time: <a href="http://matek.hu/xaos/doku.php">http://matek.hu/xaos/doku.php</a></li>
<li>MandelBulb 3D for creating scenes similar to Brod's work above: <a href="http://www.mandelbulb.com/">http://www.mandelbulb.com/</a></li>
</ul>
<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-27178714644875024012019-06-06T10:17:00.001-07:002019-06-06T10:22:52.847-07:00Generative Adversarial Networks with PyTorchThis month's London <a href="https://www.meetup.com/Algorithmic-Art/events/260708327/" target="_blank">meetup</a> was an introduction to Generative Adversarial Networks, or <b><a href="https://en.wikipedia.org/wiki/Generative_adversarial_network" target="_blank">GANs</a></b>, currently a hot topic in machine learning and data mining.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-wK4n_FOWL9xvJOYaf__9s0H9pAyLFY9hZr6xeOuOV5X38c0J7oUmouEqOubNQ7AjhkZoPP7B2r6vCOKasVJpDBkMCMABsrikodIz-bTIoHssulPdZiOBucxBAeavovF3mo7v05f-vnm/s1600/simple_e20_faces.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="218" data-original-width="178" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-wK4n_FOWL9xvJOYaf__9s0H9pAyLFY9hZr6xeOuOV5X38c0J7oUmouEqOubNQ7AjhkZoPP7B2r6vCOKasVJpDBkMCMABsrikodIz-bTIoHssulPdZiOBucxBAeavovF3mo7v05f-vnm/s320/simple_e20_faces.gif" width="260" /></a></div>
<br />
The aim of the talk was to:<br />
<ul>
<li>provide a <b>beginner-friendly</b> introductory overview of GANs</li>
<li><b>demystify</b> how they work, avoiding unnecessary maths and jargon</li>
<li>explain the basic of <b>PyTorch</b>, a python machine learning framework</li>
<li>provide <b>practical tutorial code</b> to explore</li>
<li>share some of the current <b>heuristics</b> used to make GANs work</li>
</ul>
<br />
The slides for the talk are here: (<a href="https://tinyurl.com/y3n55acf" target="_blank">pdf</a>).<br />
<br />
A video recording of the talk is here: (<a href="https://skillsmatter.com/skillscasts/13999-algorithmic-art-june-meetup" target="_blank">link</a>).<br />
<br />
<br />
<h3>
Four-Part Blog</h3>
The journey of learning about GANS and writing simple examples is detailed in this 4-part series published on my other blog. This talk is the result of much of the learning and content created during that journey.<br />
<ul>
<li><a href="https://makeyourownalgorithmicart.blogspot.com/2019/04/generative-adversarial-networks-part-i.html" target="_blank"><b>Part 1</b></a> introduces the idea of adversarial learning and starts to build the machinery of a GAN implementation.</li>
</ul>
<ul>
<li><a href="https://makeyourownalgorithmicart.blogspot.com/2019/04/generative-adversarial-networks-part-ii.html" target="_blank"><b>Part 2</b></a> extends the code to learn a simple 1-dimensional pattern <b>1010</b>.</li>
</ul>
<ul>
<li><b><a href="https://makeyourownalgorithmicart.blogspot.com/2019/05/generative-adversarial-networks-part-iii.html" target="_blank">Part 3</a></b> develops our code to learn to generate 2-dimensional grey-scale images that look like handwritten digits</li>
</ul>
<ul>
<li><b><a href="http://makeyourownalgorithmicart.blogspot.com/2019/06/generative-adversarial-networks-part-iv.html" target="_blank">Part 4</a></b> further develops our code to generate 2-dimensional full-colour images of faces, and also develops a GAN based on convolution layers to learn localised features.</li>
</ul>
<br />
I won't repeat the content of those blogs here - you should read those for a fuller yet gentle journey from preparatory basics through to a working convolutional GAN.<br />
<br />
Here I'll set out the key steps taken in the talk.<br />
<br />
<br />
<h3>
GANs? Adversarial Learning?</h3>
We started by playing a game which challenges us to see if we can tell real photos from computer generated faces apart.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioSF6YKrFvjaQrS4FltpIR15TFIm2bOM1xutksbXIXEw_uFV5DtlirRAK_GxgUYfr5L-49qYWGJ9df7IRG3uHCeLm6Q6q_aLTGcoMY1qIClFn0Kyqig38Xd6j_8_9VO2k5t2dVwbz7I7zB/s1600/Generative+Adversarial+Networks+with+PyTorch+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioSF6YKrFvjaQrS4FltpIR15TFIm2bOM1xutksbXIXEw_uFV5DtlirRAK_GxgUYfr5L-49qYWGJ9df7IRG3uHCeLm6Q6q_aLTGcoMY1qIClFn0Kyqig38Xd6j_8_9VO2k5t2dVwbz7I7zB/s400/Generative+Adversarial+Networks+with+PyTorch+%25281%2529.png" width="400" /></a></div>
<br />
The computer generated images are surprisingly realistic and it was genuinely difficult to tell them apart. See for your self at <a href="http://www.whichfaceisreal.com/">http://www.whichfaceisreal.com/</a><br />
<br />
These images are generated by GANs, and the game demonstrates their effectiveness.<br />
<br />
We also talked about the growing interest in creating art with GANs. A key milestone in the history of art is the sale of a <a href="https://www.christies.com/features/A-collaboration-between-two-artists-one-human-one-a-machine-9332-1.aspx" target="_blank">Portrait of Edmond Belamy</a> at Christies for $432,500 in October 2018.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1xnMxOem2Il_Nm9-hN2WSXEhZ8yZW-TLy4U_N5SMqYusAaS6BUJqkXI_7mzsoC2SYrxQL9ivNM4q-zq9EtjbpAK3VQLpfxmo5xWt3tU3cXZZCWNMRmJnUaQK4DCsQ03brSnbAx_mp57dB/s1600/Generative+Adversarial+Networks+with+PyTorch+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1xnMxOem2Il_Nm9-hN2WSXEhZ8yZW-TLy4U_N5SMqYusAaS6BUJqkXI_7mzsoC2SYrxQL9ivNM4q-zq9EtjbpAK3VQLpfxmo5xWt3tU3cXZZCWNMRmJnUaQK4DCsQ03brSnbAx_mp57dB/s400/Generative+Adversarial+Networks+with+PyTorch+%25282%2529.png" width="400" /></a></div>
<br />
That portrait was generated entirely by computer, using a GAN.<br />
<br />
<a href="https://robbiebarrat.github.io/" target="_blank">Robbie Barrat</a>, who created the code behind that portrait, himself has some stunning images created by GANs. This is one notable example:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFMGvCFtaUaJeW_rDCOnDJNxz2WuxCmLeyGGLmhvMixaklukii1UZ9v66oTd7_x2r3Fsqdhp9tQdRdBV_fs-M3iQFoYZWObwWdqEa5d3M08h7SaiELWElQef_SmOgkEYiw_UiFO0vMGLh6/s1600/Generative+Adversarial+Networks+with+PyTorch+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFMGvCFtaUaJeW_rDCOnDJNxz2WuxCmLeyGGLmhvMixaklukii1UZ9v66oTd7_x2r3Fsqdhp9tQdRdBV_fs-M3iQFoYZWObwWdqEa5d3M08h7SaiELWElQef_SmOgkEYiw_UiFO0vMGLh6/s400/Generative+Adversarial+Networks+with+PyTorch+%25283%2529.png" width="400" /></a></div>
<br />
Before diving into GANs, we refreshed our understanding of basic machine learning and how neural networks work.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtuTfY7jCcKjl1iXFYa4rdbARQ9_juPx1baRo4KYh2QYx15bGa9GzIef2-VD7Z36ntAwo_ieDpOkvSr9MKHHZa7ipf9sH0ugjyWIchGu-Nl6uPYAEe02HiAFzyAW-JKYutQhv0ZVJlS_sv/s1600/Generative+Adversarial+Networks+with+PyTorch+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtuTfY7jCcKjl1iXFYa4rdbARQ9_juPx1baRo4KYh2QYx15bGa9GzIef2-VD7Z36ntAwo_ieDpOkvSr9MKHHZa7ipf9sH0ugjyWIchGu-Nl6uPYAEe02HiAFzyAW-JKYutQhv0ZVJlS_sv/s400/Generative+Adversarial+Networks+with+PyTorch+%25284%2529.png" width="400" /></a></div>
<br />
In essence, neural networks are trained by feeding them data, images for example, and comparing their actual output to the known-good output. This difference, the error, is used to adjust the link weights inside the network with the aim of producing a slightly better output.<br />
<br />
Neural networks can be trained to perform tasks like classifying images - and a common tutorial example is to learn to classify images of human handwritten digits, known as the MNIST dataset.<br />
<br />
<a href="https://www.amazon.com/Make-Your-Own-Neural-Network-ebook/dp/B01EER4Z4G/" target="_blank">Make Your Own Neural Network</a> is an accessible introduction to neural networks designed for beginners which starts from scratch and builds a simple neural network to classify these digits.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCCEQDcQWG4npr1wI2wU1nNeVMuRHWpM9QHo4IB1ahZ75uavG6TTQDGksEJJXZaI8hNJAJMlRsq-bft_DnZgqTlzLiYFJ1E3j2oRGbG_youVBo1Z_FtAVsX-FLYdNMBzDgLkvQmlbthveK/s1600/Generative+Adversarial+Networks+with+PyTorch+%25285%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCCEQDcQWG4npr1wI2wU1nNeVMuRHWpM9QHo4IB1ahZ75uavG6TTQDGksEJJXZaI8hNJAJMlRsq-bft_DnZgqTlzLiYFJ1E3j2oRGbG_youVBo1Z_FtAVsX-FLYdNMBzDgLkvQmlbthveK/s400/Generative+Adversarial+Networks+with+PyTorch+%25285%2529.png" width="400" /></a></div>
<br />
We proceeded to learn about <b>PyTorch</b>, a python framework which makes doing machine learning easier. In particular it provides automatic gradient calculation, which is a critical part of updating a neural network. Previously the algebra and calculus had to be done by hand, but today toolkits like PyTorch can do this automatically for many kinds of networks we might want to build.<br />
<br />
A working notebook showing this capability was demonstrated, using Google's colab service:<br />
<br />
<ul>
<li><a href="https://colab.research.google.com/drive/1PFJcz3KSJ0j0ECm2LgNGMXY3QZZBo6iZ">https://colab.research.google.com/drive/1PFJcz3KSJ0j0ECm2LgNGMXY3QZZBo6iZ</a></li>
</ul>
<br />
<br />
PyTorch also makes using a GPU to accelerate machine learning very easy. Again a simple live notebook was demonstrated to show the key code elements:<br />
<br />
<ul>
<li><a href="https://colab.research.google.com/drive/1PFJcz3KSJ0j0ECm2LgNGMXY3QZZBo6iZ">https://colab.research.google.com/drive/1PFJcz3KSJ0j0ECm2LgNGMXY3QZZBo6iZ</a></li>
</ul>
<br />
<br />
Using the GPU does have some overhead which means for small tasks the benefit isn't there, but as the following graph shows, the benefits emerge as we scale the data or size of neural network we're training:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheGHfHDOoIB4X4z_dCwjAsdiG8LGPOL0GnZL1fNmYjomFk4pEwHL-XZF30FsgiE-2sOhh8lIj8f2-gmVRC9PXgV8EURs1dY2UjM6xjFjV5dWrnRLoMyd1Ilbo6VK2DRY05FlimwbNXhQY-/s1600/Generative+Adversarial+Networks+with+PyTorch+%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheGHfHDOoIB4X4z_dCwjAsdiG8LGPOL0GnZL1fNmYjomFk4pEwHL-XZF30FsgiE-2sOhh8lIj8f2-gmVRC9PXgV8EURs1dY2UjM6xjFjV5dWrnRLoMyd1Ilbo6VK2DRY05FlimwbNXhQY-/s400/Generative+Adversarial+Networks+with+PyTorch+%25286%2529.png" width="400" /></a></div>
<br />
A simple example of PyTorch code to classify the MNIST images was explored.<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/02_mnist_pytorch.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/02_mnist_pytorch.ipynb</a></li>
</ul>
<br />
<br />
Using this simple example, we focussed on the machinery of PyTorch code - subclassing from the <b>nn.Module</b> class, building up network layers, choosing a loss function and an optimiser for performing the network updates.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXRKCTlDGyZ6wCiVVvbjfYV7CwAshPmE50nI9_bghlM0fHgkaBI__hD00C7mt0bRbOulllErEjJY3aQrWPCRhdcOc0_WpMFQMnW6uJFrfwQOJTgseXQnwWUlo0iSF7Re-0onM-cgxBHx3z/s1600/Generative+Adversarial+Networks+with+PyTorch+%25288%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXRKCTlDGyZ6wCiVVvbjfYV7CwAshPmE50nI9_bghlM0fHgkaBI__hD00C7mt0bRbOulllErEjJY3aQrWPCRhdcOc0_WpMFQMnW6uJFrfwQOJTgseXQnwWUlo0iSF7Re-0onM-cgxBHx3z/s400/Generative+Adversarial+Networks+with+PyTorch+%25288%2529.png" width="400" /></a></div>
<br />
This code pattern will remain pretty much the same as our code grows, so is a good educational example.<br />
<br />
We finally asked what a GAN was.<br />
<br />
We started by looking at the architecture of simple machine learning. A machine learning model, which can be a neural network but doesn't have to be, has its internal parameters adjusted in response to the error it produces:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu2ifI1nbnXbCJusFtdmi9E7aXeCvBqFsx6sbNSEd1XtgUlpoxkuGop5h2V-rxgpnqJP_hRSmiua35Z5yE-DecfSZ8CBYaiEgG7cOBEKqn0QIA-9hNoSbb9Sox6qRcMIPvqlsLB38CtiST/s1600/Generative+Adversarial+Networks+with+PyTorch+%25289%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu2ifI1nbnXbCJusFtdmi9E7aXeCvBqFsx6sbNSEd1XtgUlpoxkuGop5h2V-rxgpnqJP_hRSmiua35Z5yE-DecfSZ8CBYaiEgG7cOBEKqn0QIA-9hNoSbb9Sox6qRcMIPvqlsLB38CtiST/s400/Generative+Adversarial+Networks+with+PyTorch+%25289%2529.png" width="400" /></a></div>
<br />
We then looked at the GAN architecture:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmZW4joefD-U-C0QgbYzpFQH3rJy4LCqjKejIb_cLYYtcxnW4mmDoo4TVi-euqSEIran13LTJuJ3tTbCLrFWB2s_1YzRApWmuEiOWfvoS8IoQOwoWS-pwmfLl7puSTa5cS1JKUFV_CDwg_/s1600/Generative+Adversarial+Networks+with+PyTorch+%252810%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmZW4joefD-U-C0QgbYzpFQH3rJy4LCqjKejIb_cLYYtcxnW4mmDoo4TVi-euqSEIran13LTJuJ3tTbCLrFWB2s_1YzRApWmuEiOWfvoS8IoQOwoWS-pwmfLl7puSTa5cS1JKUFV_CDwg_/s400/Generative+Adversarial+Networks+with+PyTorch+%252810%2529.png" width="400" /></a></div>
<br />
We have a learning model, a <b>discriminator</b>, which it is trained to separate real data from fake data. On its own that's just like a typical machine learning system. We also have a second machine learning model, a <b>generator</b>, which learns to generate data with the aim of getting it past the <b>discriminator</b>.<br />
<br />
If this architecture works well, the <b>discriminator</b> and the <b>generator</b> compete to out-do each other.<br />
<br />
As the <b>discriminator</b> gets better and better at telling real from fake data apart, the <b>generator</b> also gets better and better at <b>generated</b> fake data that can pass as real.<br />
<br />
A common analogy is of a forger learning to get better at fooling a policeman or detective:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSQHpsdSvnFDKLC8vsCpr1hvSwexjUxxDj643t-OLoatpEvWU60Sd-reujXUhhr8Htl2QvXbjkt2D_fOz51ADlKYxIY63I3x7dA6yYEOtAU8bmfDvwfdWtKNAr-O66MItnnXo2wuRdK9q/s1600/Generative+Adversarial+Networks+with+PyTorch+%252811%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSQHpsdSvnFDKLC8vsCpr1hvSwexjUxxDj643t-OLoatpEvWU60Sd-reujXUhhr8Htl2QvXbjkt2D_fOz51ADlKYxIY63I3x7dA6yYEOtAU8bmfDvwfdWtKNAr-O66MItnnXo2wuRdK9q/s400/Generative+Adversarial+Networks+with+PyTorch+%252811%2529.png" width="400" /></a></div>
<br />
This <b>adversarial</b> dynamic is quite unique and in fact a relatively recent invention (<a href="https://arxiv.org/abs/1406.2661" target="_blank">Ian Goodfellow, 2014</a>), and is the reason the architecture is called a <b>generative adversarial network</b>.<br />
<br />
We then proceeded in steps to develop our GAN code. We started first with a simple example learning a 1-dimensional <b>1010</b> pattern:<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/01_simple_gan.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/01_simple_gan.ipynb</a></li>
</ul>
<br />
<br />
The simplicity of the task allowed us to focus on the machinery again, especially the collection and display of the error, often called the loss.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj93Y7j5zsrjqQaQltbQsSmbQpuZsWKSDgXwvrXwGd61NuL7TvUt6AmnrJR0Jp43sSB0DGirLtO06AgbtQTYGBVa0eccKYmKO4owiAfgl1zuAWpBF4Tf95jES_tv6TTeL2HJN-hsw-CFR5K/s1600/Generative+Adversarial+Networks+with+PyTorch+%252812%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj93Y7j5zsrjqQaQltbQsSmbQpuZsWKSDgXwvrXwGd61NuL7TvUt6AmnrJR0Jp43sSB0DGirLtO06AgbtQTYGBVa0eccKYmKO4owiAfgl1zuAWpBF4Tf95jES_tv6TTeL2HJN-hsw-CFR5K/s400/Generative+Adversarial+Networks+with+PyTorch+%252812%2529.png" width="400" /></a></div>
<br />
Normally the loss is expected to fall to zero in a normal network, but with a GAN the <b>discriminator</b> should find it harder and harder to tell apart the real data from the generated data - and so the error should approach <b>1/2</b> (or <b>1/4</b> if we're using mean squared error as in the picture above).<br />
<br />
The following shows visually how the output of the generator improves as training progresses. You can clearly see the <b>1010</b> pattern emerge.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnwco8hF-TFsclRr7xXceOmtiDHog24uZjBDRWkyMRHGz2qfw_6c8j8EoKbIblMvtd1PNbz44Xeh7b0MsSKrHUJVrrPxi8BWvsiM7g4bpMPHFY3HSyOD8HcBzO_Bjgsy_sqPGOyxxYfIOF/s1600/Generative+Adversarial+Networks+with+PyTorch+%252813%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnwco8hF-TFsclRr7xXceOmtiDHog24uZjBDRWkyMRHGz2qfw_6c8j8EoKbIblMvtd1PNbz44Xeh7b0MsSKrHUJVrrPxi8BWvsiM7g4bpMPHFY3HSyOD8HcBzO_Bjgsy_sqPGOyxxYfIOF/s400/Generative+Adversarial+Networks+with+PyTorch+%252813%2529.png" width="400" /></a></div>
<br />
The next step was to learn 2-dimensional data, images, and the monochrome MNIST dataset is ideal:<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/03_image_gan_first_attempt.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/03_image_gan_first_attempt.ipynb</a></li>
</ul>
<br />
<br />
The shape and nature of the <b>discriminator</b> followed the simple classifier we developed earlier - a simple network with one middle layer. The input size is fixed at <b>784</b> because the images are <b>28x28</b>. The output size is <b>10</b> to match the <b>10</b> digits.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXDqxf_mByM_9n-etN0xTHZRg38jv6s6cpICBq-zvs1hDBEcWJfZBZLn1qt8AgwIz7AeHqCOmvNYS4pbLX7K8yX7WZytqYLyrquEFdxmDQh7KSjgwcKA6tyiu853xsvKE0Hy85dthl-2Y/s1600/Generative+Adversarial+Networks+with+PyTorch+%252816%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXDqxf_mByM_9n-etN0xTHZRg38jv6s6cpICBq-zvs1hDBEcWJfZBZLn1qt8AgwIz7AeHqCOmvNYS4pbLX7K8yX7WZytqYLyrquEFdxmDQh7KSjgwcKA6tyiu853xsvKE0Hy85dthl-2Y/s400/Generative+Adversarial+Networks+with+PyTorch+%252816%2529.png" width="400" /></a></div>
<br />
The <b>generator</b> is often designed first as a mirror of the discriminator, and then adjusted as required.<br />
<br />
The results looked disappointing:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid7mPOEfXyY5EpMiP05TfplXRV0Q25Bb30gHCtuavB7o399_3BB3UXbZEMUzPyGbpq67dV6aK7TlPDw2YB73YAFopu_AYV3dsNzLsE-hj6xbVNygDB5WUrLOk5udEEAviDQecQz88bfqRw/s1600/Generative+Adversarial+Networks+with+PyTorch+%252815%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid7mPOEfXyY5EpMiP05TfplXRV0Q25Bb30gHCtuavB7o399_3BB3UXbZEMUzPyGbpq67dV6aK7TlPDw2YB73YAFopu_AYV3dsNzLsE-hj6xbVNygDB5WUrLOk5udEEAviDQecQz88bfqRw/s400/Generative+Adversarial+Networks+with+PyTorch+%252815%2529.png" width="400" /></a></div>
<br />
The generator has failed to learn to draw digits, and all the images look very similar.<br />
<br />
We discussed how, in general, GANs are hard to train, with common pitfalls like <b>mode collapse</b> where only one of many possible solutions is found by the <b>generator</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxn2AK1YakYlEoDx5F2KjWImRlXs6ITQyaZQk-dByp4X0OtDadii_nyzxcp9zL0o3TKUO4fEi7bwtCnL0bAZZrEfQYF6mg_tWhR46oICqIGp1oBsbEJYq66rY6cyGhTtlt85N02eIAzVWX/s1600/Generative+Adversarial+Networks+with+PyTorch+%252817%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxn2AK1YakYlEoDx5F2KjWImRlXs6ITQyaZQk-dByp4X0OtDadii_nyzxcp9zL0o3TKUO4fEi7bwtCnL0bAZZrEfQYF6mg_tWhR46oICqIGp1oBsbEJYq66rY6cyGhTtlt85N02eIAzVWX/s400/Generative+Adversarial+Networks+with+PyTorch+%252817%2529.png" width="400" /></a></div>
<br />
It is worth remembering that a successful GAN is a fine equilibrium between the <b>generator</b> and the <b>discriminator</b>.<br />
<br />
The next version of the code implemented some common improvements - using a leakyRELU activation instead of the vanilla sigmoid because it doesn't suffer from vanishing gradients, layer normalisation to rescale network signals to the sweet spot for the activation functions, and a stronger <a href="http://ruder.io/optimizing-gradient-descent/" target="_blank">Adam optimiser </a>which works per-learning parameter.<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/03_image_gan.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/03_image_gan.ipynb</a></li>
</ul>
<br />
<br />
The results looked much better:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl3uaosLdERnTDhTLIsSY82u4RC7CpT_Qev9v09CxdTtOxJ5eICCk0RqHs_R2WlVdCqR2Oag84UhEu-MMBvogBPVA0wMzch7cCsnOdTBrJUHy_Mx3zA0EB9aHolYz8OeEdUiU8d-myWGJN/s1600/Generative+Adversarial+Networks+with+PyTorch+%252818%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl3uaosLdERnTDhTLIsSY82u4RC7CpT_Qev9v09CxdTtOxJ5eICCk0RqHs_R2WlVdCqR2Oag84UhEu-MMBvogBPVA0wMzch7cCsnOdTBrJUHy_Mx3zA0EB9aHolYz8OeEdUiU8d-myWGJN/s400/Generative+Adversarial+Networks+with+PyTorch+%252818%2529.png" width="400" /></a></div>
<br />
Those generated images are impressive if we remember that the generator has not seen the real images from the data set at all. We've also avoided mode collapse too.<br />
<br />
We then moved beyond the monochrome images to full-colour photos of celebrity faces, using a popular <a href="http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html" target="_blank">CelebA</a> dataset of <b>200,000</b> images. For our experiments, we used only <b>20,000</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQkp5fafF-w6JlkI58E3pdTed46cnHaArEUzn3R2X-v-kIWIhykVVSDcAutQ_YFp3pg5DykxTiLMs8sBCgK0T7PNfCu9mjH3s5LojKdbt0hKDnVnWbLqUAbFQ4Qh3vN_PTNjKF1xfcqg_7/s1600/Generative+Adversarial+Networks+with+PyTorch+%252819%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQkp5fafF-w6JlkI58E3pdTed46cnHaArEUzn3R2X-v-kIWIhykVVSDcAutQ_YFp3pg5DykxTiLMs8sBCgK0T7PNfCu9mjH3s5LojKdbt0hKDnVnWbLqUAbFQ4Qh3vN_PTNjKF1xfcqg_7/s400/Generative+Adversarial+Networks+with+PyTorch+%252819%2529.png" width="400" /></a></div>
<br />
The code itself didn't need any structural changes, only needed to adapt to the new 3-channel images and larger but still simple neural networks:<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/04_celeba_gan.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/04_celeba_gan.ipynb</a></li>
</ul>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIE_P1fZiLRQS8XKs-jujmCYfszNd6d93uhFAh6LvRyVZcPQ5EYJMKyl_k8rmOTA1pYLjJB-_DaQ2wjUV_ojy2ASKUXzrZKZ7rLFMtoQYDesP-n-wQDlgVIclMpCK1VuknoCdWP6GadxdM/s1600/Generative+Adversarial+Networks+with+PyTorch+%252820%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIE_P1fZiLRQS8XKs-jujmCYfszNd6d93uhFAh6LvRyVZcPQ5EYJMKyl_k8rmOTA1pYLjJB-_DaQ2wjUV_ojy2ASKUXzrZKZ7rLFMtoQYDesP-n-wQDlgVIclMpCK1VuknoCdWP6GadxdM/s400/Generative+Adversarial+Networks+with+PyTorch+%252820%2529.png" width="400" /></a></div>
<br />
The results were impressive in that a diverse set of faces were indeed generated:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOREPDWkodnEOoHIFaeMWXPTA8mS-VW6aA8wrCOxb4gxpMgkLSdG9dBXvymoXjUIVv9fzGdXaWL4aIWvuGFOEhQRghJpkz6khv5y-10f4smDuOl0FDy-g_kCWpMPRugxN-n4cnNJHPyadz/s1600/Generative+Adversarial+Networks+with+PyTorch+%252821%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOREPDWkodnEOoHIFaeMWXPTA8mS-VW6aA8wrCOxb4gxpMgkLSdG9dBXvymoXjUIVv9fzGdXaWL4aIWvuGFOEhQRghJpkz6khv5y-10f4smDuOl0FDy-g_kCWpMPRugxN-n4cnNJHPyadz/s400/Generative+Adversarial+Networks+with+PyTorch+%252821%2529.png" width="400" /></a></div>
<br />
There are faces with different skin colour, different hair styles, and even different pose orientations too.<br />
<br />
It is wort noting that the GAN approach doesn't learn <b>"average faces"</b>. What is learned is a probability distribution from which samples can pass the <b>discriminator</b>. This is why the generated images are nicely diverse.<br />
<br />
A second round, epoch, of training improves the images:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7IksCtaV5PejC6FjteUHeNYyv5whMMQD4yB6T9AiY1UCZPZyTMfItQXHBFdNo0eH7N7VXwMJQXKsajtcRiCoRyaBfKjqS-BQaMeVM6rOYz_RQtJe0_LMvhFEpOZ_TCt5FsZAc3fxi7ITx/s1600/Generative+Adversarial+Networks+with+PyTorch+%252822%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7IksCtaV5PejC6FjteUHeNYyv5whMMQD4yB6T9AiY1UCZPZyTMfItQXHBFdNo0eH7N7VXwMJQXKsajtcRiCoRyaBfKjqS-BQaMeVM6rOYz_RQtJe0_LMvhFEpOZ_TCt5FsZAc3fxi7ITx/s400/Generative+Adversarial+Networks+with+PyTorch+%252822%2529.png" width="400" /></a></div>
<br />
And more training improves the images again:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRL2IPd9i5WkulcbUM9LJyUp58PLxoyJns0g-jYtHf73iSg6htK7H6Kec7zdGCHDhm3v1PEDOsWz9YPFPlFpKfwHtetPKDTxsvS-bCjw9NyWsV-qScItGG40IgDBZMBK0m1ZwnEVzwzSo/s1600/Generative+Adversarial+Networks+with+PyTorch+%252823%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRL2IPd9i5WkulcbUM9LJyUp58PLxoyJns0g-jYtHf73iSg6htK7H6Kec7zdGCHDhm3v1PEDOsWz9YPFPlFpKfwHtetPKDTxsvS-bCjw9NyWsV-qScItGG40IgDBZMBK0m1ZwnEVzwzSo/s400/Generative+Adversarial+Networks+with+PyTorch+%252823%2529.png" width="400" /></a></div>
<br />
Much further training led to a degradation of image quality, which suggests we've reached the limits of our intentionally simple architecture.<br />
<br />
The animated image at the top of this post shows several generated images being interpolated smoothly. They are generated by moving a consecutive sequence of <b>1</b>'s across the <b>100</b>-long input array.<br />
<br />
We next looked at <b><a href="https://en.wikipedia.org/wiki/Convolutional_neural_network" target="_blank">convolutional neural networks</a></b>. The reason for this is that <b>convolution</b> layers learn localised image features, and are well suited to image classification tasks.<br />
<br />
The following diagram shows how a convolution kernel pick out diagonal patterns in the source image and builds a feature map.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7XdcH-uBoMYJuFjvG0yGG7sa8Ws3Y_6nXGGYeI6XrOVcSvw3p1SsGup3WKF7oVwbPm3mgaxKXUkKH6hHpdRhGcPf5l0uQLeHBWEhdcQW8kCzF2nUxZytVPmSEHAamqEwRFntZUY7knn2t/s1600/Generative+Adversarial+Networks+with+PyTorch+%252824%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7XdcH-uBoMYJuFjvG0yGG7sa8Ws3Y_6nXGGYeI6XrOVcSvw3p1SsGup3WKF7oVwbPm3mgaxKXUkKH6hHpdRhGcPf5l0uQLeHBWEhdcQW8kCzF2nUxZytVPmSEHAamqEwRFntZUY7knn2t/s400/Generative+Adversarial+Networks+with+PyTorch+%252824%2529.png" width="400" /></a></div>
<br />
We can set a neural network to learn these kernels by itself instead of predefining them. Here is a simple example of an MNIST classifier that uses convolution layers:<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/02_mnist_pytorch_cnn.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/02_mnist_pytorch_cnn.ipynb</a></li>
</ul>
<br />
<br />
For a GAN, we hope that a convolution layers in the generator will learn to build an image from features, perhaps elements like eyes, noses, lips etc.<br />
<br />
<br />
At first the results from the generator were not as expected, reflecting the difficulty of designing and training a GAN:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9-nADmDUMjQKdRqgkF0tSJEmWR5RujUR06o5EvM3L0Z1fXlWD_n4OcuCNJhX9hen6Fh2HzvbqZikyagXvrCGgHXUkMiU7O5xqalzGCwKcapIFOoHFtM8IB9LFBhOByVTToB4AvXuOJOtT/s1600/Generative+Adversarial+Networks+with+PyTorch+%252826%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9-nADmDUMjQKdRqgkF0tSJEmWR5RujUR06o5EvM3L0Z1fXlWD_n4OcuCNJhX9hen6Fh2HzvbqZikyagXvrCGgHXUkMiU7O5xqalzGCwKcapIFOoHFtM8IB9LFBhOByVTToB4AvXuOJOtT/s400/Generative+Adversarial+Networks+with+PyTorch+%252826%2529.png" width="400" /></a></div>
<br />
That GAN was rather good at generating horror characters!<br />
<br />
After some trial and error, a successful and still simple GAN was found:<br />
<br />
<ul>
<li><span style="color: #0000ee; text-decoration-line: underline;">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/generative-adversarial-network/04_celeba_gan_conv.ipynb</span></li>
</ul>
<br />
<br />
The results were impressive. The following from one training epoch shows how the faces are indeed being patched together from learned features.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijKkr2s-fG6yg7anJ5IG-Vx-mQDj4uwz_xpAj4K4CcbnUM0muZft-20AZOhANHUDTVzDCsBjzYXUihF-ewKFKqisolqIbm8q3j-mAgYGcJ5lGWfw3RPOYY3OA_yRO7-psWuriMagZuRsa6/s1600/Generative+Adversarial+Networks+with+PyTorch+%252827%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijKkr2s-fG6yg7anJ5IG-Vx-mQDj4uwz_xpAj4K4CcbnUM0muZft-20AZOhANHUDTVzDCsBjzYXUihF-ewKFKqisolqIbm8q3j-mAgYGcJ5lGWfw3RPOYY3OA_yRO7-psWuriMagZuRsa6/s400/Generative+Adversarial+Networks+with+PyTorch+%252827%2529.png" width="400" /></a></div>
<br />
A second epoch improves how the faces are constructed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxXOjfcresINpKvM_1nOwyR8CJGJudaPjWTfKmNeStGATSj_f4ekMmZEp0dOwR2JIhDfMuVamACxgTwe7i8DqkrnEIz7Nsa0iBteWW53bGEBZZ-YvbRrbVGUXegVicdBvBcrnt9r4iysaa/s1600/Generative+Adversarial+Networks+with+PyTorch+%252828%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxXOjfcresINpKvM_1nOwyR8CJGJudaPjWTfKmNeStGATSj_f4ekMmZEp0dOwR2JIhDfMuVamACxgTwe7i8DqkrnEIz7Nsa0iBteWW53bGEBZZ-YvbRrbVGUXegVicdBvBcrnt9r4iysaa/s400/Generative+Adversarial+Networks+with+PyTorch+%252828%2529.png" width="400" /></a></div>
<br />
Six epochs again shows some improvement.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvWgIdkrEFzjCBCriVbCVRWXbDAdhW6GFm9O5E72EDLeG5Um1ae_Y0sQblul8brZS58w1CiUg41Q1Pg0LcG4lsAgtvAO7jy8nlYB8qgvs-XbICopQYhKtMCYYgOaLVpQV2zfSgHu_PRJcp/s1600/Generative+Adversarial+Networks+with+PyTorch+%252829%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvWgIdkrEFzjCBCriVbCVRWXbDAdhW6GFm9O5E72EDLeG5Um1ae_Y0sQblul8brZS58w1CiUg41Q1Pg0LcG4lsAgtvAO7jy8nlYB8qgvs-XbICopQYhKtMCYYgOaLVpQV2zfSgHu_PRJcp/s320/Generative+Adversarial+Networks+with+PyTorch+%252829%2529.png" width="320" /></a></div>
<br />
Eight epochs results in faces that are starting to be constructed more smoothy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUx9bZ6iq9zEpn_pjZGIx7qS3h0J12th7HqTTBGS64eIvTHSvwBgzhXyXRZwhwvmtRMD2EAnCbpqRJ4suLPvUaz_gyhf-cE3w-ZkPz5jixMze9Oa9ghp-Skt4cEVsZ9zxss5yWi6mWmrlS/s1600/Generative+Adversarial+Networks+with+PyTorch+%252830%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUx9bZ6iq9zEpn_pjZGIx7qS3h0J12th7HqTTBGS64eIvTHSvwBgzhXyXRZwhwvmtRMD2EAnCbpqRJ4suLPvUaz_gyhf-cE3w-ZkPz5jixMze9Oa9ghp-Skt4cEVsZ9zxss5yWi6mWmrlS/s400/Generative+Adversarial+Networks+with+PyTorch+%252830%2529.png" width="400" /></a></div>
<br />
The following is an animation of several generated faces smoothly transitioned just for effect.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxP4J3rlIbGcVL7a3KEbOAM8tIWjh2ndn3QlmnJ4pIVynr8iniCvblkYE_oQu-LztgqYu1qvFbyPlWFidMaFIxayAAM3OAC_GHhbUVbpbTbiooRgchzPn0MWAUQsdLGjAB5_z1JMFytuPs/s1600/dcgan_anim.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="128" data-original-width="128" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxP4J3rlIbGcVL7a3KEbOAM8tIWjh2ndn3QlmnJ4pIVynr8iniCvblkYE_oQu-LztgqYu1qvFbyPlWFidMaFIxayAAM3OAC_GHhbUVbpbTbiooRgchzPn0MWAUQsdLGjAB5_z1JMFytuPs/s400/dcgan_anim.gif" width="400" /></a></div>
<br />
Although these images might not win awards for fidelity, they do show that even a very simple network using only a few lines of code can still create fascinating images.<br />
<br />
They're fascinating because the <b>generator</b> has never seen the real images, and has still learned to construct faces from features it has also learned indirectly via the <b>discriminator</b>.<br />
<br />
<br />
<h3>
Conclusion</h3>
I was really pleased the talk matched the audience's expectations of an introductory talk that demystified GANs, and also provided simple tutorial code and summarised a few of the heuristics currently used to make them work.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH5xo1pc_tt3q7AfpkxXhV_8ViLJeAmeJXuClQxTgpPKN022_OfbQW-6IGTipqOW249gD5XkMC9AwK68hxqvzqGHMmKptuM8Jpj1hclTQ2S-qEjlxbBzw_K8N0vb6-83eA-3JugKap0ij6/s1600/IMG_20190603_185528-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1062" data-original-width="1600" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH5xo1pc_tt3q7AfpkxXhV_8ViLJeAmeJXuClQxTgpPKN022_OfbQW-6IGTipqOW249gD5XkMC9AwK68hxqvzqGHMmKptuM8Jpj1hclTQ2S-qEjlxbBzw_K8N0vb6-83eA-3JugKap0ij6/s400/IMG_20190603_185528-01.jpg" width="400" /></a></div>
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-78815638287897698912019-04-23T15:04:00.000-07:002019-11-24T15:49:12.058-08:00Automata, Chaos and Emergent BehaviourWe were lucky to have Peter Marks visiting Cornwall to lead this <a href="https://www.meetup.com/Algorithmic-Art/events/259360284/" target="_blank">meetup</a> on <b>Automata, Chaos and Emergent Behaviour.</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBUrdBVQfHcbOH1nM7cjHLCYNUdSGir_ZGK16hBOBy1GA8XZBqU_lIwxGaamPbDubY_dervE5K2_Bgi5EHgpjxAVt2ww_tOgcZ9dSW89k9MmCEyR0nj-iZkHtaQE19SX3nI1K8X2UNAGtO/s1600/IMG_20190418_183038-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBUrdBVQfHcbOH1nM7cjHLCYNUdSGir_ZGK16hBOBy1GA8XZBqU_lIwxGaamPbDubY_dervE5K2_Bgi5EHgpjxAVt2ww_tOgcZ9dSW89k9MmCEyR0nj-iZkHtaQE19SX3nI1K8X2UNAGtO/s400/IMG_20190418_183038-01.jpg" width="400" /></a></div>
<br />
Working examples, including code, are online: <a href="https://codepen.io/spluko/">https://codepen.io/spluko/</a>.<br />
<br />
<br />
A similar session was already run in London previously, and was <a href="https://algorithmicartmeetup.blogspot.com/2018/10/automata-chaos-and-emergent-behaviour.html" target="_blank">written up</a>, so I won't repeat the content but focus on just the key points and differences to that session.<br />
<br />
<br />
<h3>
Automata</h3>
Mathematicians, scientists and indeed philosophers, often consider whether the natural world and its behaviour can be modelled as a collection of abstract objects following simple rules. Indeed, the justification of modelling real world behaviour isn't even necessary, we can be interested in objects following simple rules just because it is interesting.<br />
<br />
Although there are very precise and formal definitions of <a href="https://en.wikipedia.org/wiki/Automata_theory" target="_blank"><b>automata</b></a>, an informal definition is more understandable. Automata are abstract things - which take input, and follow simple rules to decide their next state, from where they can continue to take more input and continue to evolve.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0xxiiLBJCQnxbxrFhBAccHg2L9H7RaFm6Abw3EXjMgc8jsh19ohNdVw-JFsjAl3U_RK3qG4Egdj5vLPLkrA5IAAsHws3fAiw-qxb4uxQESlPBDDtiLo5Gfzj7wbv0Y6BipcSsyTyjtYDW/s1600/automata_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="400" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0xxiiLBJCQnxbxrFhBAccHg2L9H7RaFm6Abw3EXjMgc8jsh19ohNdVw-JFsjAl3U_RK3qG4Egdj5vLPLkrA5IAAsHws3fAiw-qxb4uxQESlPBDDtiLo5Gfzj7wbv0Y6BipcSsyTyjtYDW/s400/automata_0.png" width="400" /></a></div>
<br />
The word <b>state</b> is just a technical term for the configuration of, and information in, an automaton.<br />
<br />
It might be difficult to picture an "abstract" thing. It just means that many kinds of things can be automata - from small robot ants to pixels moving around a screen.<br />
<br />
The reason they can be interesting is that from the simple rules can emerge interesting, and sometimes surprisingly sophisticated, behaviour.<br />
<br />
<br />
<h3>
Key Principles</h3>
Peter structured his talk by progressively exploring the key principles at play when modelling automata - <b>iteration</b>, <b>multiplicity</b> and <b>interaction</b>:<br />
<br />
<ul>
<li><b>Iteration</b> - the repeated application of rules, often mathematical rules.</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBhK_hJihUf0KkM0_8vr-nyR3kXEAD6SRietNcRvSe9lsqJSqFJBRj1Z6kLphU2SOun_uH9GZk1krSHd_H5EouYFVt1TEzZdDmzt9V8qWyTzUczsJ2v6i25QuyltjNkD274MXfj5TiO-4C/s1600/automata_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="400" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBhK_hJihUf0KkM0_8vr-nyR3kXEAD6SRietNcRvSe9lsqJSqFJBRj1Z6kLphU2SOun_uH9GZk1krSHd_H5EouYFVt1TEzZdDmzt9V8qWyTzUczsJ2v6i25QuyltjNkD274MXfj5TiO-4C/s400/automata_1.png" width="400" /></a></div>
<br />
<br />
<ul>
<li><b>Multiplicity</b> - Creating and evolving many automata.</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8qx3d91kW4cMN3wZMLG-d5lKaaNwodFn5GaV4Kw_D8jCRhXPqJjHKGk8r8X8_siWoQRwd1JJPqkYODplMWKnK6hyphenhyphen5GcE9mYUVlnr_-siLIixsBQeieLHFpubvUadfiRpRto_TWR8yuDvP/s1600/automata_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="400" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8qx3d91kW4cMN3wZMLG-d5lKaaNwodFn5GaV4Kw_D8jCRhXPqJjHKGk8r8X8_siWoQRwd1JJPqkYODplMWKnK6hyphenhyphen5GcE9mYUVlnr_-siLIixsBQeieLHFpubvUadfiRpRto_TWR8yuDvP/s400/automata_2.png" width="400" /></a></div>
<br />
<br />
<ul>
<li><b>Interaction</b> - Allowing the evolution of automata to depend on other automata, encoded again as the simple rules that define their next state.</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUXn3WVCg7lkaVXq6zc9fAtF8njeQ2eaEEtKIAxE0JKxPt7xGMrzsI4ixByOaKLhsyRCHw3-N3ZPRFXNEdsPn56zbuW8A0Q8Us1URzcdGCT99d2yyH-ZnUY9lXMP9SQjw-gIRMkIeic-Sx/s1600/automata_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="400" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUXn3WVCg7lkaVXq6zc9fAtF8njeQ2eaEEtKIAxE0JKxPt7xGMrzsI4ixByOaKLhsyRCHw3-N3ZPRFXNEdsPn56zbuW8A0Q8Us1URzcdGCT99d2yyH-ZnUY9lXMP9SQjw-gIRMkIeic-Sx/s400/automata_3.png" width="400" /></a></div>
<br />
Peter illustrated the principle of <b>iteration</b> with an object that just happened to be a circle. The rules that are applied to it increase its size. The <b>state</b> of the object changes over time - the circle grows. Although this example sounds a little laboured, it illustrates the concepts.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFrnPQqEIYqlvlK40UYOBdvcvTkAYg2FoOn41PGXVW9zxXlF2_wb8R5LppsAQRvmI8Wf7OBBJ2G1bX028JAObbfgYfc4OOKTv-yMVGyCpUhOnefbz5dehKc1Dk1b0umhqsvclpNkiym4KV/s1600/a_circles.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="228" data-original-width="400" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFrnPQqEIYqlvlK40UYOBdvcvTkAYg2FoOn41PGXVW9zxXlF2_wb8R5LppsAQRvmI8Wf7OBBJ2G1bX028JAObbfgYfc4OOKTv-yMVGyCpUhOnefbz5dehKc1Dk1b0umhqsvclpNkiym4KV/s400/a_circles.gif" width="400" /></a></div>
<br />
Peter proceeded to demonstrate the principle of <b>multiplicity</b>, creating many objects and allowing them to evolve according to the same simple rules.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMhOFr681SE20rf83Il1IgAD2mvpBn1d9EN5AdpyXlJB4dQq9kyKmkqAJ3DHL0N3pmwEIwf0EpQnOQA6dJuIxn88DMVadf7bWYQ1lPGwllilWWj9cwArocJ_J-8ljnH5VUyAXlDODVt1o6/s1600/a_particles.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="186" data-original-width="400" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMhOFr681SE20rf83Il1IgAD2mvpBn1d9EN5AdpyXlJB4dQq9kyKmkqAJ3DHL0N3pmwEIwf0EpQnOQA6dJuIxn88DMVadf7bWYQ1lPGwllilWWj9cwArocJ_J-8ljnH5VUyAXlDODVt1o6/s400/a_particles.gif" width="400" /></a></div>
<br />
<br />
These <b>particles</b> appear to move along different paths. The rules that apply to them are still the same, the different paths are due to their different initial starting states - they all have different initial speeds and directions (velocity).<br />
<br />
Peter the proceeded to the interesting idea of <b><a href="https://en.wikipedia.org/wiki/Chaos_theory" target="_blank">chaos</a> </b> - the apparent breakdown of a system into randomness. He explained that actually the chaotic systems we were looking at were not random, just so varied in their behaviour that it was had to predict their future state. Chaotic systems are very sensitive to their initial conditions, which contributes ti their difficult predictability.<br />
<br />
A good example of a <b>chaotic system</b> is an ink drop falling into a glass of water. The ink molecules are start off in a relatively well defined small space, but then move around the glass in a very unpredictable way, and also along paths very different to molecules they started off as neighbours with.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidH4iwuNxghafjH-5HRS-jgota3LUi36zD0g3viILo0zoVXYKhCIIfoFgBJmiThfWCikULofRuXm_TGMIBdB-Ux9UxH2fPtoWDlYJO1iEmoCXS4ueneW9bMfEqdrO9vRPW2_xuBSp3DhPL/s1600/ink.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="904" data-original-width="1400" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidH4iwuNxghafjH-5HRS-jgota3LUi36zD0g3viILo0zoVXYKhCIIfoFgBJmiThfWCikULofRuXm_TGMIBdB-Ux9UxH2fPtoWDlYJO1iEmoCXS4ueneW9bMfEqdrO9vRPW2_xuBSp3DhPL/s400/ink.png" width="400" /></a></div>
<br />
The following curves are drawn according to positions which evolve in a chaotic manner.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDS3xDlFxe9PkxtCGs9TQZgaiPx5PZlIVZxkDgIFISDO3xPgKu1zrarKljWjyl6fd3YwxummGhXkJ8yF3g_JfP024QC3ckaZT3f7gBLdPx9WxpaWMdAv93wgu50uyy6BwlaHhhW4F-5JZA/s1600/a_scribble.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="183" data-original-width="400" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDS3xDlFxe9PkxtCGs9TQZgaiPx5PZlIVZxkDgIFISDO3xPgKu1zrarKljWjyl6fd3YwxummGhXkJ8yF3g_JfP024QC3ckaZT3f7gBLdPx9WxpaWMdAv93wgu50uyy6BwlaHhhW4F-5JZA/s320/a_scribble.gif" width="320" /></a></div>
<br />
Peter then proceeded to demonstrate the opposite effect - <b>order out of chaos</b>. Particles are created and moved according to the following fairly simple mathematical rules:<br />
<blockquote class="tr_bq">
<span style="color: blue;"><b>xt+1 = sin(a * yt) - cos(b * xt)</b><b><br /></b><b>yt+1 = sin(c * xt) - cos(d * yt)</b></span></blockquote>
The initial impression is that the particles seem to follow a chaotic path with no order or pattern. However, creating many particles and following theirs allows a pattern to emerge.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1UXIg8OjNJYXYrkGyHZ31NkiTudxubdEZeS7P0lROWeYXRhE46POJmUfPbR6xVRjO7K0id3C2RNq6Win9O9vUpGEe3dRFP97-MQ9o7r8gbdFLLRZ6NS8dhJanOfBrpmV8_V95UTDb9kKP/s1600/attractor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="280" data-original-width="400" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1UXIg8OjNJYXYrkGyHZ31NkiTudxubdEZeS7P0lROWeYXRhE46POJmUfPbR6xVRjO7K0id3C2RNq6Win9O9vUpGEe3dRFP97-MQ9o7r8gbdFLLRZ6NS8dhJanOfBrpmV8_V95UTDb9kKP/s400/attractor.png" width="400" /></a></div>
<br />
You can find many more example of these beautiful forms online, here for example: <a href="http://paulbourke.net/fractals/peterdejong/">http://paulbourke.net/fractals/peterdejong/</a>, which includes:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilM-Vp7k5G41knY79kdh0z9RhQve_CTC5Wo8lhaqtYOEfkjhEhY8MIh8KdpzA5iv5QSV5muzlI5FhzJk3chg9-ULjxtOScNBDChM59863gVKWFeFLwfVVm0SyvEwL8WmzJcZRJ75AynTj2/s1600/8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilM-Vp7k5G41knY79kdh0z9RhQve_CTC5Wo8lhaqtYOEfkjhEhY8MIh8KdpzA5iv5QSV5muzlI5FhzJk3chg9-ULjxtOScNBDChM59863gVKWFeFLwfVVm0SyvEwL8WmzJcZRJ75AynTj2/s400/8.jpg" width="400" /></a></div>
<br />
Finally, Peter demonstrated automata whose behaviour depended on the state of other automata - <b>interaction</b>. Simple examples include balls that bounce off each other, transferring momentum to each other.<br />
<br />
Peter showed how even simple rules can lead to <b>emergent behaviour</b>, for example the <b>self-organising </b>of objects according to their colour.<br />
<br />
Before:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSRKuKdKl_8YPt9n6na2XTH8a9h7YKWrREoS7N7eXZww3wDxPqjgFms04L1M_oOWpz0VwVqVJIO-igCTDzBUNfaMl4p1rRo1YqR_nFTHe-DgK60kgP8EJcvbiU2keV0JgTKsw7tjDHNdIs/s1600/IMG_20190418_192006-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSRKuKdKl_8YPt9n6na2XTH8a9h7YKWrREoS7N7eXZww3wDxPqjgFms04L1M_oOWpz0VwVqVJIO-igCTDzBUNfaMl4p1rRo1YqR_nFTHe-DgK60kgP8EJcvbiU2keV0JgTKsw7tjDHNdIs/s400/IMG_20190418_192006-01.jpg" width="400" /></a></div>
<br />
After:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqqpGyCuQK_HetHtcTeECs84AsBtq7Sl79BQcGfuzxKXfG7Vaw8mvPPkJsMn_u_fXHTzLDINof18tJKY5JLaiQfEJGQ3DI1VgUr9uVxqQ6PdjbM2aI1PMir3nEuoGNnMjZMZtNmzmsSChD/s1600/IMG_20190418_192236.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqqpGyCuQK_HetHtcTeECs84AsBtq7Sl79BQcGfuzxKXfG7Vaw8mvPPkJsMn_u_fXHTzLDINof18tJKY5JLaiQfEJGQ3DI1VgUr9uVxqQ6PdjbM2aI1PMir3nEuoGNnMjZMZtNmzmsSChD/s400/IMG_20190418_192236.jpg" width="400" /></a></div>
<br />
More sophisticated example is of <b><a href="https://www.red3d.com/cwr/boids/" target="_blank">boids</a></b>, where bird-like automata follow rules that encourage them to follow each other by matching velocities, but also not allowing them to get too close, whilst aiming to cohere towards a group or cluster. The resulting behaviour is very similar to birds <b>flocking</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk7FyV0CkXR4PBNJ1ywtR3O745QLmAC4E8S7wTaSh7yThDkvaKg8iA_uhP_7LVPg20T99eFn4xNTWq5FjzQWZMmQplhBuD2zwew-0_Lz2X1I8ffmgZvChIGoRwxyUs_yv7ZKO0yvXBjq9N/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk7FyV0CkXR4PBNJ1ywtR3O745QLmAC4E8S7wTaSh7yThDkvaKg8iA_uhP_7LVPg20T99eFn4xNTWq5FjzQWZMmQplhBuD2zwew-0_Lz2X1I8ffmgZvChIGoRwxyUs_yv7ZKO0yvXBjq9N/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<br />
<br />
Here is another example showing the <b>boids</b> more clearly, from the processing <a href="https://processing.org/examples/flocking.html" target="_blank">website</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf_pReU_GLypsObfD3o8if28-KAoIaSuBTUdKxijtz84kgR6lmVJSeNHyBhdM8Hh670eVZcj5D7H8IuUsjPK7s6f6PRgrZet13jeIfiX1cFBxMW2fqHRLVKVSR1TDcc9pzq-KfIq9TTsVi/s1600/flocking.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="336" data-original-width="600" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf_pReU_GLypsObfD3o8if28-KAoIaSuBTUdKxijtz84kgR6lmVJSeNHyBhdM8Hh670eVZcj5D7H8IuUsjPK7s6f6PRgrZet13jeIfiX1cFBxMW2fqHRLVKVSR1TDcc9pzq-KfIq9TTsVi/s400/flocking.gif" width="400" /></a></div>
<br />
<br />
<h3>
Conclusion</h3>
Peter took us through a well structured tour of automata, starting with very simple and easy to understand examples, and working through the principles of <b>iteration</b>, <b>multiplicity</b> and <b>interaction</b>.<br />
<br />
For many, including myself, there is still the sense of excitement, surprise and wonder at how simple rules can lead to both <b>chaos</b>, and also <b>emergent behaviour</b>.<br />
<br />
Peter's talk inspired some of the conversation after the session, which broadened out to how nature itself works and the role of simple laws of physics, chemistry and biology governing the emergence of the world we observe!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgJS1ZJgHWvvvlvGOiOqfTBBxDXUFsOQ2Y-aG-GPTJ92p3avT6RLUd78vKJIEc0tSk-Xexun4HDO9b31uWZFic8zfq1k7x2-Z3oNtbq0DcGb27tRkYnzO-tHNRpW7jEydnlV8wHGE_oO1g/s1600/IMG_20190418_191522-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgJS1ZJgHWvvvlvGOiOqfTBBxDXUFsOQ2Y-aG-GPTJ92p3avT6RLUd78vKJIEc0tSk-Xexun4HDO9b31uWZFic8zfq1k7x2-Z3oNtbq0DcGb27tRkYnzO-tHNRpW7jEydnlV8wHGE_oO1g/s400/IMG_20190418_191522-01.jpg" width="400" /></a></div>
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-55739950607701939502019-04-16T15:26:00.000-07:002019-04-17T14:47:42.147-07:00Art Hackathon - "Artificial Emotional Intelligence"This month's London <a href="https://www.meetup.com/Algorithmic-Art/events/259362246/">meetup</a> was not a talk or tutorial but a <a href="https://en.wikipedia.org/wiki/Hackathon">hackathon</a>.<br />
<br />
The theme, to be interpreted freely, was <b>"Artificial Emotional Intelligence"</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfXB3ndWOXO8ARGtIYLellAIjHD5DCQAY45LsVHGwD_we6knLWufDu65L8CPnBul-D5LYF_pjlVHfztGtvxDir7et-D8Ea8yStm8M7ej_anmtAKxLTmLoreVVtqEjGY3duV3bd8-klxAGO/s1600/francis_bacon_hackathon_out.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1117" data-original-width="1600" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfXB3ndWOXO8ARGtIYLellAIjHD5DCQAY45LsVHGwD_we6knLWufDu65L8CPnBul-D5LYF_pjlVHfztGtvxDir7et-D8Ea8yStm8M7ej_anmtAKxLTmLoreVVtqEjGY3duV3bd8-klxAGO/s400/francis_bacon_hackathon_out.png" width="400" /></a></div>
<br />
In setting the theme I had hoped some would consider that, although AI has made huge leaps forward, they have been in the ability to repeat a task, rather than in the ability to interact with humans at an emotional level.<br />
<br />
<br />
<h3>
Art Hackathons</h3>
The normal format for our meetups is a talk or a hands-on tutorial, but there has always been demand for a session where members just code to create.<br />
<br />
I'm not particularly experienced in organising hackathons (- should we use post-its? -) but we've run three before:<br />
<br />
<ul>
<li><b>"Future Pangs"</b> - [<a href="https://algorithmicartmeetup.blogspot.com/2017/09/art-hackathon-future-pangs.html" target="_blank">blog</a>]</li>
<li><b>"I Want To Believe"</b> - [<a href="https://algorithmicartmeetup.blogspot.com/2018/03/art-hackathon-i-want-to-believe.html" target="_blank">blog</a>]</li>
<li><b>"In The News"</b> - [<a href="https://algorithmicartmeetup.blogspot.com/2018/04/art-from-pydata-art-hackathon.html" target="_blank">blog</a>]</li>
</ul>
<br />
<br />
They seem to be fairly well received.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR6L33A7A4fURBbriuhob3eKtqwEBoqOjKrGf2aKwDdzYXl_Hv6hzyK9xvJSCG4BvcMX0uA6J61DG2rrSSsQWSU4b0g8f0sIg-NkzPInxcYgxtPqat8TwUw0B_dm8BcMF_Yptn2TXIDigM/s1600/IMG_20190415_194852-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="780" data-original-width="1600" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR6L33A7A4fURBbriuhob3eKtqwEBoqOjKrGf2aKwDdzYXl_Hv6hzyK9xvJSCG4BvcMX0uA6J61DG2rrSSsQWSU4b0g8f0sIg-NkzPInxcYgxtPqat8TwUw0B_dm8BcMF_Yptn2TXIDigM/s400/IMG_20190415_194852-01.jpg" width="400" /></a></div>
<br />
The key features are they everyone works on <b><a href="https://openprocessing.org/" target="_blank">openprocessing.org</a></b> so there is a common programming language (javascript and p5js) and an easy ability to share their art and code through a simple we URL.<br />
<br />
Some people want to work together with others, some along, and depending on the night, there are a number of more experienced creative coders willing to help others. This is one area I need to organse better.<br />
<br />
There are always newcomers and first-time coders. In addition to in-person help, onlien tutorials are helpful too. I'm pleased my own guide has been well received - ignore that it is labelled "for kids":<br />
<br />
<ul>
<li><a href="https://sites.google.com/view/creative-coding-for-kids">https://sites.google.com/view/creative-coding-for-kids</a></li>
</ul>
<br />
<br />
A unique feature of our art hackathons is setting the mood! We turn down the lights and project a nice ambient nature video with the beautiful but unobtrusive classical music - <a href="https://www.youtube.com/watch?v=Uk7OhwxD88w" target="_blank">Gymnopedies 3, Satie</a>.<br />
<br />
Creative bliss!<br />
<br />
<br />
<h3>
Selected Works</h3>
I was again really taken by the broad diversity of interpretations and approaches to the theme. The following are selected works.<br />
<br />
<br />
<b>Peepl</b><br />
In the work, the artist has the idea of small bodies moving around the space driven by their own speed and direction. However, when two such "people" come close to each other, they pause from their high speed dash and remain close to each other for a short while - as if having a conversation.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/699525" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="419" data-original-width="600" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxFb0TS5enT2aL773jAc9FucG4yCcSGw8zY8BxevoU_eTx_eijb8TqBtGELIl9VbNKFWYo4Qq0ijs9JnKag1mgTu_b1fHPwNJ-y5xU9pRACQeQxFOS3oDxzg0uvtiXql8AfFRUlpUMJQle/s400/peepl.gif" width="400" /></a></div>
<br />
This is an interesting take on particle systems, one I've not seen before.<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/699525" target="_blank">https://www.openprocessing.org/sketch/699525</a></li>
</ul>
<br />
<br />
<b>Colour Mind</b><br />
In this work, the artists working as a team, developed the idea of taking a canonical list of emotions and using a hash function to convert them into colours.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJSlhJks7K3P2iAw5-T8dwhhaKuaxm5bwbCQfdzlulMHt-0lSE9O8Scega3x-NYT6Jy4xK-2pwPT4P0GPTVgsoa0HX799d6brZVkuCUpPOVuTM99nVVRdlADOzBEZVOiFfQu0Iy2XM6YTJ/s1600/IMG_20190415_203055-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1229" data-original-width="1600" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJSlhJks7K3P2iAw5-T8dwhhaKuaxm5bwbCQfdzlulMHt-0lSE9O8Scega3x-NYT6Jy4xK-2pwPT4P0GPTVgsoa0HX799d6brZVkuCUpPOVuTM99nVVRdlADOzBEZVOiFfQu0Iy2XM6YTJ/s400/IMG_20190415_203055-01.jpg" width="400" /></a></div>
<br />
The work itself presents itself as three buttons which the viewer is impelled to click, resulting in a series of circles, coloured and labelled with one the emotions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKcsu8lFrqrWF2b-ZAVUUhzfQH5hTiTbYhHX_-LeUflzQv89R48cw16fzyBlZLcsCZzdZfgPunqX8krb_k9_ETDanin8pik9UKlgKr3tMCB5d7EVvAli_CzBPwjRvMkhmNhI4W6yqeNnfn/s1600/IMG_20190415_202906-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKcsu8lFrqrWF2b-ZAVUUhzfQH5hTiTbYhHX_-LeUflzQv89R48cw16fzyBlZLcsCZzdZfgPunqX8krb_k9_ETDanin8pik9UKlgKr3tMCB5d7EVvAli_CzBPwjRvMkhmNhI4W6yqeNnfn/s400/IMG_20190415_202906-01.jpg" width="400" /></a></div>
<br />
The artists insisted that there was no intended correlation between the colour chosen by the hash function and the meaning of the chosen emotion word. The reason was to place meaning, interpretation, and reaction firmly in the space of the viewer, not the code.<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/699517" target="_blank">https://www.openprocessing.org/sketch/699517</a></li>
</ul>
<br />
<br />
<b>Hamlet's Emotions</b><br />
In this unique work, the artist has taken the text of Shakespeare's Hamlet and as his code reads it line by line, it picks out key emotive words, and visualises them. The words fall into three categories, broadly strong negative, intermediate, and strong positive.<br />
<br />
It is interesting to see this chart grow as the code reads the text.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiezLQLotQsmuB-qba5Dy2k9IQDzkwpuqJp174w5ZqtmnHe_4hoGlVeoqMvtV1a3Gxom_hiUDsjYpwhRx5-JIsdmzw6uVqRCLw2wNKffcw6JUfwFO6dfnnZf5o7jSEJluOdtvFLIWb6WMF1/s1600/hamlet.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiezLQLotQsmuB-qba5Dy2k9IQDzkwpuqJp174w5ZqtmnHe_4hoGlVeoqMvtV1a3Gxom_hiUDsjYpwhRx5-JIsdmzw6uVqRCLw2wNKffcw6JUfwFO6dfnnZf5o7jSEJluOdtvFLIWb6WMF1/s400/hamlet.png" width="400" /></a></div>
<br />
I particularly liked the graphs at the bottom, which looks like cpu or load monitors, evoking the feeling of a monitor, perhaps a medical monitor, keeping an eye on the emotions in Hamlet as the tale proceeds.<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/699448" target="_blank">https://www.openprocessing.org/sketch/699448</a></li>
</ul>
<br />
<br />
<b>Dots</b><br />
In this work, the artist started from the particles theme which looks fairly basic but as the particles interact they change and flash.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDSA60R330Gh3RtCAcOX-VpuMnEC8uSeVTQmcAW1vDP_xfripBlAyumD7Eoo-NfxBIljX3R806RUrDlYtNGnbImQd_WkFSZVC1JCIWgOTwz5t_2-Zoq5a9rI6JFcVLVRBp7qL-hPY3Xxf7/s1600/dots.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="600" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDSA60R330Gh3RtCAcOX-VpuMnEC8uSeVTQmcAW1vDP_xfripBlAyumD7Eoo-NfxBIljX3R806RUrDlYtNGnbImQd_WkFSZVC1JCIWgOTwz5t_2-Zoq5a9rI6JFcVLVRBp7qL-hPY3Xxf7/s400/dots.gif" width="400" /></a></div>
<br />
The code is online, but to run it effectively you should delete the debugging print statement first. I hope the artist continues to work on this code because the ideas are interesting and I think the fruits could be even more interesting.<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/699519#code" target="_blank">https://www.openprocessing.org/sketch/699519#code</a></li>
</ul>
<br />
<br />
<b>Cellular Growth</b><br />
This work is quite striking in how it is presented, growing out from the centre of the canvas.<br />
<br />
The patterns formed by the colours seem natural, not entirely random, with a definite organic structure.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGzeszN4Zb9ft5p2147WD7QfFFJdsZ0i3FAYil-v8ocAvCSUrG5u-r5NBeiqJ4he93YkugrdTiL_6qmxKV3LyeEQUy7UY6zBG5H7Kk99SwCf2OD9i20doXDvXd6VCpdLlhibE2dQmBCFIR/s1600/diamond.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="419" data-original-width="600" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGzeszN4Zb9ft5p2147WD7QfFFJdsZ0i3FAYil-v8ocAvCSUrG5u-r5NBeiqJ4he93YkugrdTiL_6qmxKV3LyeEQUy7UY6zBG5H7Kk99SwCf2OD9i20doXDvXd6VCpdLlhibE2dQmBCFIR/s400/diamond.gif" width="400" /></a></div>
<br />
Looking through the code, I think I'm right that the pattern grows based on cell creation determined by its neighbours. It reminds me of code I first saw in the 1980s (!) which seemed to magically create detail based on a matrix of neighbouring cells, but following a formula that was sufficiently organic and not-so-random to make it feel natural.<br />
<br />
Ben later explained that he wanted to show generations learning how best to communicate with their neighbours. He got as far as cells reproducing and their children taking traits from the parent(s). A cell's traits represent their emotional disposition, shown here by the red/blue colour. His intention was to use a genetic algorithm that learns an optimal way for cells to communicate, and the visualisation to show this learning over generations.<br />
<br />
I can see echoes of the artist's previously presented work on grids and game theory!<br />
<br />
You can try the code yourself:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/699470" target="_blank">https://www.openprocessing.org/sketch/699470</a></li>
</ul>
<br />
<br />
<br />
<b>(Miro-Like) Shapes</b><br />
This work I is particularly effective. One one level it simply draws some simple shapes - circles and triangles, and some curling curves.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtORfM76eExYslcGrm4cdW3yxhHMYsrefTR3BD9RNlVzpX4htG9TaqhWInE3y5zjUWFE27D1saWE-xr1Fs9p7USGiwV69fL-m3RDiQvXaSeKdRa7AnwNpAQT19cyZhyphenhyphenBK0Ee42sJ72jJrk/s1600/miros1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1510" data-original-width="1600" height="377" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtORfM76eExYslcGrm4cdW3yxhHMYsrefTR3BD9RNlVzpX4htG9TaqhWInE3y5zjUWFE27D1saWE-xr1Fs9p7USGiwV69fL-m3RDiQvXaSeKdRa7AnwNpAQT19cyZhyphenhyphenBK0Ee42sJ72jJrk/s400/miros1.png" width="400" /></a></div>
<br />
But the artists careful and thoughtful constraints on the colour palette, on the sizes and orientation of the shapes, the amount of curl and varying thickness of the wavy lines - all combines to create a powerful composition, very reminiscent of the works of <a href="https://www.moma.org/artists/4016?locale=en" target="_blank">Joan Miro</a>.<br />
<br />
The code produces different compositions every time it is run - and almost all of them seem to work.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi20FV1SP4ChaIKpVb_NnybQRwoIX7vcSk0x-7JOX5CQ2UANfh3icR4dYeIyj1UYJ8oh3-UV_Br1fR2oRlKi_2lqIgz_yN3M2qKsF2UxEU28aMXDCNJTn8vT7og3QeazbP32P9jiPSRJwIa/s1600/miros4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1538" data-original-width="1600" height="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi20FV1SP4ChaIKpVb_NnybQRwoIX7vcSk0x-7JOX5CQ2UANfh3icR4dYeIyj1UYJ8oh3-UV_Br1fR2oRlKi_2lqIgz_yN3M2qKsF2UxEU28aMXDCNJTn8vT7og3QeazbP32P9jiPSRJwIa/s400/miros4.png" width="400" /></a></div>
<br class="Apple-interchange-newline" />
Simple - yet sophisticated!<br />
<br />
For me, I the algorithm that draws the swirls is particularly effective and I can't wait to explore the code to see how it works...<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/699516" target="_blank">https://www.openprocessing.org/sketch/699516</a></li>
</ul>
<br />
<br />
<br />
<h3>
Thoughts</h3>
The art hackathons are always popular, and the show-n-tells at the end are, in my experience, the best part of the evening. It is inspiring and exciting to see the ideas that others have come up with, even if they haven't managed to finish them in the session itself.<br />
<br />
I still feel I need to organise the hackathons better, and would love suggestions. At times they can feel like nobody knows what supposed to be happening. Maybe I can project a schedule of what's happening, and also make very clear that finished work is far from expected.<br />
<br />
A useful feedback was to extend the coding time - one hour isn't enough!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3DVa-QjJao_RBc1IREWjvlS3-xmCf5ROSt-x31ZVDz-CCVxP6WssIKt-gIZoXkPwo72T_1UwWXS2X5GscMzGFmBVprio1s3-U2I6MWad3edny6U4QSvYVyPN0unksjXVWwYvbna573bqu/s1600/IMG_20190415_191651-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1202" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3DVa-QjJao_RBc1IREWjvlS3-xmCf5ROSt-x31ZVDz-CCVxP6WssIKt-gIZoXkPwo72T_1UwWXS2X5GscMzGFmBVprio1s3-U2I6MWad3edny6U4QSvYVyPN0unksjXVWwYvbna573bqu/s400/IMG_20190415_191651-01.jpg" width="400" /></a></div>
<br />
<br />
I haven't run a creative coding hackathon in Cornwall yet, so that will happen at the next available date.<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-60887002774692773422019-03-22T14:10:00.002-07:002019-03-22T14:10:21.194-07:00Animation and Creative Uses of MathsThis month's <a href="https://www.meetup.com/Algorithmic-Art/events/259341581/" target="_blank">meetup</a> in Cornwall continued the introductory series of sessions by introducing animation and seeing how mathematical functions can be used creatively.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwHEL-U1ti-HhePxOW3_tDw3r15SfcHCdJgK7hKOwbbm0fK2R91ko5y552qRl7WSYwTgGPpyy5H-9LZT9daNFXGTzl2UP3_S2fzgs6_WkkbE-zQVK9ZAxnqCBxFwM9NwOHd3Ykmn6HtK5U/s1600/ezgif.com-video-to-gif.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="276" data-original-width="600" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwHEL-U1ti-HhePxOW3_tDw3r15SfcHCdJgK7hKOwbbm0fK2R91ko5y552qRl7WSYwTgGPpyy5H-9LZT9daNFXGTzl2UP3_S2fzgs6_WkkbE-zQVK9ZAxnqCBxFwM9NwOHd3Ykmn6HtK5U/s400/ezgif.com-video-to-gif.gif" width="400" /></a></div>
<br />
The slides are here: [<a href="https://goo.gl/ooRQnT" target="_blank">PDF</a>].<br />
<br />
<br />
<h3>
Flip-books and Animation</h3>
Being able to move, animate, design elements adds a powerful and engaging new dimension works we create.<br />
<br />
We started by looking at how animation is made without a computer or code - using pen and paper.<br />
<br />
We briefly looked at this video demonstrating flip-books work.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/Un-BdBSOGKY/0.jpg" frameborder="0" height="333" src="https://www.youtube.com/embed/Un-BdBSOGKY?feature=player_embedded" width="400"></iframe></div>
<br />
Each page of the flip-book has an image that is slightly different from the image on the previous page. When viewed in quick succession, an illusion of movement is created.<br />
<br />
That idea is exactly the same for digital animation. We still create animation frames, each differing from the previous one by a small change.<br />
<br />
The following shows three frames, each with a red circle which we can think of as a ball. On the first frame the ball is near the top of the frame. In the next frame the ball is slightly lower, and in the third frame it further down.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga_aU8t9GjU8ifnIUEA4Brtzi0yOAasaeUQTVFY4Cp9VvI4FynKGunP9emBwPGyjXzWPLfaZgxmjI3JjxxPUAraHM86mRQVWiGhOMVzQt_C-RR8U2nl0Cxov_jbhX6nEkMHbRYag5N02rX/s1600/anim_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="192" data-original-width="640" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga_aU8t9GjU8ifnIUEA4Brtzi0yOAasaeUQTVFY4Cp9VvI4FynKGunP9emBwPGyjXzWPLfaZgxmjI3JjxxPUAraHM86mRQVWiGhOMVzQt_C-RR8U2nl0Cxov_jbhX6nEkMHbRYag5N02rX/s400/anim_0.png" width="400" /></a></div>
<br />
We want to draw these frames, which could easily be from a flip-book, using code. That means thinking about the ball as a <b>circle()</b> shape, and its location in terms of vertical coordinates.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSa2oUOA5_RtnCFRZQCUKgFQ2qRPtfyArXb7JQ6-CsoRHY0s26MmEXsIF5tr2-w71S5RzGHExkjacTHjQhURsuao1H7VKEC3x61sRYnOkCrOMexeSGH-rByqgNl_aGhhmbY5jQYHcVQLVD/s1600/anim_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="206" data-original-width="640" height="128" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSa2oUOA5_RtnCFRZQCUKgFQ2qRPtfyArXb7JQ6-CsoRHY0s26MmEXsIF5tr2-w71S5RzGHExkjacTHjQhURsuao1H7VKEC3x61sRYnOkCrOMexeSGH-rByqgNl_aGhhmbY5jQYHcVQLVD/s400/anim_2.png" width="400" /></a></div>
<br />
The picture shows the ball at <b>y=50</b>, <b>y=100</b> and then at <b>y=150</b>. Although these are actually big jumps, the key idea is that the coordinates of the ball change with each frame.<br />
<br />
With a flip-book, we flip each page so we seem then in quick succession. How can we do the same in code? How can we rapidly draw each frame?<br />
<br />
We could do it manually, but <b>p5js</b> supports animation by providing an easy way to repeatedly call the main <b>draw()</b> function - the one which contains our instructions for drawing shapes and colours.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwrF3ZdAcHk5N4XxAjFzg6ZyBtOFP_-tw8VGRsXNrgWDl50iHYEKsN_ahJs4dJ8G_4EVYlfg6lMPM1kwHvgVKMRlxCGnI8-Rzi8-nkFrb-Q_gZXVbN_vJMcH6bcR8irLf8iPgjjDZwFiu9/s1600/anim_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="248" data-original-width="640" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwrF3ZdAcHk5N4XxAjFzg6ZyBtOFP_-tw8VGRsXNrgWDl50iHYEKsN_ahJs4dJ8G_4EVYlfg6lMPM1kwHvgVKMRlxCGnI8-Rzi8-nkFrb-Q_gZXVbN_vJMcH6bcR8irLf8iPgjjDZwFiu9/s400/anim_3.png" width="400" /></a></div>
<br />
Have a look at the following simple code. We have the familiar <b>setup()</b> and <b>draw()</b> functions, with the <b><a href="https://github.com/makeyourownalgorithmicart/simple.js/wiki">simple.js</a></b> library being initialised in <b>setup()</b>, and a very familiar circle() instruction in <b>draw()</b>.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisXwK_qU-Xh0yMq82ZeZMxHjIRsECc4rpKRAPlqobkIc2aku-sXbftJDS4AUpeU3sAJ5gRDTOqnq4zPMzdWj_RlpW2jB9OK2-YhiwIq9bRRxQJgw-hL6WJuHOj3dSF6mZO8hxG-vlUudJc/s1600/Animation+and+Creative+Use+of+Maths.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisXwK_qU-Xh0yMq82ZeZMxHjIRsECc4rpKRAPlqobkIc2aku-sXbftJDS4AUpeU3sAJ5gRDTOqnq4zPMzdWj_RlpW2jB9OK2-YhiwIq9bRRxQJgw-hL6WJuHOj3dSF6mZO8hxG-vlUudJc/s400/Animation+and+Creative+Use+of+Maths.png" width="400" /></a></div>
<br />
There are some new things in that code too. The <b>loop()</b> instruction in the setup section causes the <b>draw()</b> function to be called repeatedly. That's just what we need to repeatedly draw each animation frame. The <b>background()</b> instruction simply wipes the canvas clean with a background colour, which is just like starting a fresh new page of a flip-book.<br />
<br />
We then turned our attention to actually drawing each frame of the animation. The following code draws a circle at <b>(x, 300)</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjctFu-swMOy4PBRkfX-F9S8pFm1Vz3E0ZMrhCcdeBX07y6_c4g0o-ChFf8tNGUvNz9ZKO3mjlGV9iT6hAQTSVcQz9yMHtkizF1cv7uJtfSKZj5b3DDqiosw-f_5H5G-DAw3Aiiw5FmZb5o/s1600/Animation+and+Creative+Use+of+Maths+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjctFu-swMOy4PBRkfX-F9S8pFm1Vz3E0ZMrhCcdeBX07y6_c4g0o-ChFf8tNGUvNz9ZKO3mjlGV9iT6hAQTSVcQz9yMHtkizF1cv7uJtfSKZj5b3DDqiosw-f_5H5G-DAw3Aiiw5FmZb5o/s400/Animation+and+Creative+Use+of+Maths+%25282%2529.png" width="400" /></a></div>
<br />
The important point is that <b>x</b> changes at every frame because it is increase by <b>5</b> inside the <b>draw()</b> function. Remember that <b>draw()</b> is called repeatedly, so <b>x</b> keeps increasing.<br />
<br />
That <b>x</b> is initialised to <b>0</b> outside the <b>draw()</b> function. That means it is set before <b>draw()</b> is run, and is visible from <b>draw()</b>.<br />
<br />
Here are the results.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ1vHv10ojD2LNBjmbV-2PIWPmlVDHkjFC7_tlf1J-QZMScZN9vmJ-d3F8qK1CGSeUtPNowvllEdAIhSxSaB64lS3N9lAu3WALiu2Bu09Kvh1OTOf5WQkroGGhWvVl-MqNSpz6m74BOoxI/s1600/ezgif.com-video-to-gif+%25281%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="446" data-original-width="600" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ1vHv10ojD2LNBjmbV-2PIWPmlVDHkjFC7_tlf1J-QZMScZN9vmJ-d3F8qK1CGSeUtPNowvllEdAIhSxSaB64lS3N9lAu3WALiu2Bu09Kvh1OTOf5WQkroGGhWvVl-MqNSpz6m74BOoxI/s400/ezgif.com-video-to-gif+%25281%2529.gif" width="400" /></a></div>
<br />
That worked!<br />
<br />
Although the code, and the resulting animation, is simple - it contains all the key points fundamental to all animation:<br />
<br />
<ul>
<li>each frame is drawn in quick succession</li>
<li>the drawing on each frame differs by a small amount</li>
<li>viewed in quick succession, the frames give the illusion of movement</li>
<li>incrementing/changing variables can be used to control the changing position of an object</li>
<li>each new frame must be blank</li>
</ul>
<br />
<br />
We then saw how the speed of the ball could be controlled by changing the amount by which the <b>x</b> coordinate was incremented. Increasing it by <b>1</b> caused the ball to move slowly, and increasing it by <b>20</b> caused the ball to zoom by!<br />
<br />
That concluded the introduction to creating animation with code.<br />
<br />
Next we looked at mathematical function and how they can help with animation.<br />
<br />
<br />
<h3>
The Shape of Mathematical Functions</h3>
Mathematical functions are not something that everyone gets excited about, and some even view them with fear or impending boredom!<br />
<br />
Our treatment of mathematical functions wasn't about doing algebra or exploring mathematical proofs. We focussed only on their "shape".<br />
<br />
We started with a very very simple function <b>y = x+3</b>. We looked at what <b>y</b> is when <b>x</b> is <b>0, 1, 2</b> and <b>3</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpDftepYgZRrMfrLy3fTiK5ktNpfuDqX2SDH6TDFBhl6umRqqLcm1bkF9K-KOStJ0906Jj4azmhwoX7-BWFDtdofCDrhL7yT252PecasDPVdIyhkqihSQz_gjDLtnDHp8nOMpQ-rZbRmXa/s1600/Animation+and+Creative+Use+of+Maths+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpDftepYgZRrMfrLy3fTiK5ktNpfuDqX2SDH6TDFBhl6umRqqLcm1bkF9K-KOStJ0906Jj4azmhwoX7-BWFDtdofCDrhL7yT252PecasDPVdIyhkqihSQz_gjDLtnDHp8nOMpQ-rZbRmXa/s400/Animation+and+Creative+Use+of+Maths+%25283%2529.png" width="400" /></a></div>
<br />
We saw that <b>y</b> takes on the values <b>3, 4, 5</b> and <b>6</b>. For example, when <b>x</b> is <b>2</b>, <b>y = x+3</b> which is <b>2+3</b>, or <b>5</b>.<br />
<br />
That was easy enough.<br />
<br />
We wrote some code to draw a small circle at each of these points. We continued with the same code skeleton which used <b>loop()</b> to repeatedly call <b>draw()</b>, and commented out the <b>background()</b> instruction so we could see all the drawn circles.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvSEOAQwKZStR9k55rMQS22vFpFTafc-PfJDBZl9ylmDN9fcbIKZIlsZY8OL4BtlZeUYExUo2NGtiITbgQHrOs9Ft-WSVCaDg4HLxDJbgyxGCSv4O-nKl_ER2B3xAItouAUDhY2lqpzOVR/s1600/Animation+and+Creative+Use+of+Maths+%25285%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvSEOAQwKZStR9k55rMQS22vFpFTafc-PfJDBZl9ylmDN9fcbIKZIlsZY8OL4BtlZeUYExUo2NGtiITbgQHrOs9Ft-WSVCaDg4HLxDJbgyxGCSv4O-nKl_ER2B3xAItouAUDhY2lqpzOVR/s400/Animation+and+Creative+Use+of+Maths+%25285%2529.png" width="400" /></a></div>
<br />
The code simply draws a circle at every <b>(x,y)</b> where <b>x</b> starts at <b>0</b> and increased in steps of <b>5</b>, and where <b>y</b> is calculated using the function <b>y = x+3</b>.<br />
<br />
Here's the result.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1Y94cgUoY1xnFBO9hkx7usck0OK8VNjKIomwjnC7QV_s_OldhnX_sk7Qk_N190kIE9jhxroDSV3PXqwnZziYwv4MY8xGZ50SIfqLmQtRnhk3bORGtIazeldJtRxgMiWqZU0xuhShIwnaQ/s1600/g1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1Y94cgUoY1xnFBO9hkx7usck0OK8VNjKIomwjnC7QV_s_OldhnX_sk7Qk_N190kIE9jhxroDSV3PXqwnZziYwv4MY8xGZ50SIfqLmQtRnhk3bORGtIazeldJtRxgMiWqZU0xuhShIwnaQ/s400/g1.png" width="400" /></a></div>
<br />
The result is a straight line. If you're familiar with some maths, you won't be surprised that the <b>linear</b> function had a straight line shape.<br />
<br />
We then looked at <b>y = x<sup>2</sup></b>. A table of <b>x</b> and <b>y</b> values shows that <b>y</b> grows big rather quickly.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOUiWz6sTmb73_PMmJvOrgJlS734ZQ2hq3tnBfXtpgBNVb7apaB7YKj0g_dxcO9WnO0fmBhwAlGkOjen0-dSWM9D56O5Jklh-0fqj7c6kr_9bQDMtO0wGXDfp1wM72NtU8BVXm1fDPkh8H/s1600/Animation+and+Creative+Use+of+Maths+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOUiWz6sTmb73_PMmJvOrgJlS734ZQ2hq3tnBfXtpgBNVb7apaB7YKj0g_dxcO9WnO0fmBhwAlGkOjen0-dSWM9D56O5Jklh-0fqj7c6kr_9bQDMtO0wGXDfp1wM72NtU8BVXm1fDPkh8H/s400/Animation+and+Creative+Use+of+Maths+%25284%2529.png" width="400" /></a></div>
<br />
Here's the result.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqIFc8k30iE_Okl4gxbEjeQnMk5w-0eUnxuIJZ-wjuvbni8TvTeORecw8XsHY7gVK8HMJ9CE5i7dlNPRzC2OHu_bT_AAd_-rV30e0c9d6NY1CLSvnPLGLe_Cf-P7TI6T9lEZCkiUcHDMRY/s1600/g2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqIFc8k30iE_Okl4gxbEjeQnMk5w-0eUnxuIJZ-wjuvbni8TvTeORecw8XsHY7gVK8HMJ9CE5i7dlNPRzC2OHu_bT_AAd_-rV30e0c9d6NY1CLSvnPLGLe_Cf-P7TI6T9lEZCkiUcHDMRY/s320/g2.png" width="320" /></a></div>
<br />
The circles fall off the canvas very quickly - because the <b>y</b> values grow large every quickly. When <b>x</b> is <b>10</b>, <b>y</b> is <b>100</b>. When <b>x</b> is <b>100</b>, <b>y</b> is <b>10,00</b>!<br />
<br />
We need a way to slow it down. A very common technique is to scale <b>x</b> by dividing it. We tried dividing it by <b>20</b>.<br />
<br />
The following shows <b>y=(x/20)<sup>2</sup></b>. The <b>y</b> values are much smaller.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBierzy30COV2iWnQrQz1KSYsH_d25HbUSthgzCXQEkTzE96fG1_tdghtZS9Otn7zOSyjZe65FGMgB3AC0DuYkef04Rt1npSR2eNtbbBdSjxeLLtTlx-AeNEKiJio4ZBNFbB6uDGM8P76G/s1600/Animation+and+Creative+Use+of+Maths+%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBierzy30COV2iWnQrQz1KSYsH_d25HbUSthgzCXQEkTzE96fG1_tdghtZS9Otn7zOSyjZe65FGMgB3AC0DuYkef04Rt1npSR2eNtbbBdSjxeLLtTlx-AeNEKiJio4ZBNFbB6uDGM8P76G/s400/Animation+and+Creative+Use+of+Maths+%25286%2529.png" width="400" /></a></div>
<br />
The results are interesting.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBIfgUzjzVzoxPPAW_h6DQZ-YXBkBQq4Z2yyJvcribvPd6LCwCy4sIqrH1WCkc5MgNMyrHE07v6GxpyQPim2L8vw_8je94RVvKqog_SnWxVagIvemfAkz2gDsSNaLBXVW_ty_Y4-Imuedo/s1600/g3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBIfgUzjzVzoxPPAW_h6DQZ-YXBkBQq4Z2yyJvcribvPd6LCwCy4sIqrH1WCkc5MgNMyrHE07v6GxpyQPim2L8vw_8je94RVvKqog_SnWxVagIvemfAkz2gDsSNaLBXVW_ty_Y4-Imuedo/s400/g3.png" width="400" /></a></div>
<br />
This function has a shape that isn't a straight line, but is a curve that seems to speed up after a slow start. That shape is actually a <b>parabola</b> and the function is of a type called a <b>quadtratic</b> function.<br />
<br />
Even with this simple example, we can see the possibilities for modelling a ball falling down, or a colour gradient that changes rapidly after a slow change.<br />
<br />
We then looked at another function, called a <b>sine</b> function.<br />
<br />
We also used a website that makes drawing the shapes of mathematical functions really easy. This link shows the <b>sin()</b> function being drawn: <a href="https://www.desmos.com/calculator/seoidaqekt">https://www.desmos.com/calculator/seoidaqekt</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEB8gjXbiirGir9P8I5fb0jzoItwB7mrWPMz0AbfsqrC2pUHLclKCGcIChzbr3LaBgOooolpxjl6UjIgtdo04Q9mn6L74hZSycNTSK-63tlyT0hzK2KxxtgNEIwvQbppDvC_vdMBj3WNmy/s1600/Animation+and+Creative+Use+of+Maths+%25287%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEB8gjXbiirGir9P8I5fb0jzoItwB7mrWPMz0AbfsqrC2pUHLclKCGcIChzbr3LaBgOooolpxjl6UjIgtdo04Q9mn6L74hZSycNTSK-63tlyT0hzK2KxxtgNEIwvQbppDvC_vdMBj3WNmy/s400/Animation+and+Creative+Use+of+Maths+%25287%2529.png" width="400" /></a></div>
<br />
We don't need to talk about trigonometry or angles or do any algebra. All we need to do is appreciate the shape - which is a nice up and down wave! That should be really useful.<br />
<br />
Changing our code to draw circles at every <b>y=sin(x)</b> gave an unexpected result. This was because the <b>sin()</b> function varies from <b>-1</b> to <b>+1</b>, so not very tall at all. We can scale it by multiplying by <b>100</b>. We also shift the coordinates to the middle of the canvas.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNej5ANDEFsBDKeJhZGGSc0anLzr4za2jTkLZNta95OPLc65OyMYAofOUKbN7lrxTXeFbbYfdr1j-4row5dijDedLVaUV7XsCHJX2aLvI7r85B8BI-Gsu_tlMcl46vfN-yItVJnhYFSszP/s1600/Animation+and+Creative+Use+of+Maths+%25289%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNej5ANDEFsBDKeJhZGGSc0anLzr4za2jTkLZNta95OPLc65OyMYAofOUKbN7lrxTXeFbbYfdr1j-4row5dijDedLVaUV7XsCHJX2aLvI7r85B8BI-Gsu_tlMcl46vfN-yItVJnhYFSszP/s400/Animation+and+Creative+Use+of+Maths+%25289%2529.png" width="400" /></a></div>
<br />
<br />
The result confirmed the wavy shape.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqFFVt7ah6vdfmIm3OtNrcumCDHhyphenhyphenkg-ZTBqvI6fKB6WSPVFpcZyO3HsKbBn54SZxwsR2jD_yCBLqjAMLMFl3dm4wYMHJo9RwITCUEJbMrphvfPMwow3KL-Uz8ULEbi5rhd-XMaj0_hS0i/s1600/g4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqFFVt7ah6vdfmIm3OtNrcumCDHhyphenhyphenkg-ZTBqvI6fKB6WSPVFpcZyO3HsKbBn54SZxwsR2jD_yCBLqjAMLMFl3dm4wYMHJo9RwITCUEJbMrphvfPMwow3KL-Uz8ULEbi5rhd-XMaj0_hS0i/s400/g4.png" width="400" /></a></div>
<br />
By blanking the canvas again, we can create an undulating motion.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrSYXCG-DrgOKDSP8rpAMDLpupxDmQjg8EW_PIxLlnxEz-JWAnejoOn6LffRRhSXOOPIeB-SgjThrEQuISrAtyfeK1ecQz8waackYPcfhFgHrLkIz8Cv4_dZdvb-IJLqHQ9W9TYOWAb4Q0/s1600/ezgif.com-video-to-gif+%25282%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="446" data-original-width="600" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrSYXCG-DrgOKDSP8rpAMDLpupxDmQjg8EW_PIxLlnxEz-JWAnejoOn6LffRRhSXOOPIeB-SgjThrEQuISrAtyfeK1ecQz8waackYPcfhFgHrLkIz8Cv4_dZdvb-IJLqHQ9W9TYOWAb4Q0/s400/ezgif.com-video-to-gif+%25282%2529.gif" width="400" /></a></div>
<br />
This shows how we can use mathematical function to control the motion of objects in an animaition - without needing to be an expert in doing algebra or analysis - we just need to apreciate the shape of the function, and tools like the desmos website make this really easy.<br />
<br />
We looked at a few more mathematical functions because they have useful shapes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNW7FRGtsRDHT4skGvQ4FSXZfssmK-xzsrz7VMeeB0pPeTnbSfbASDX_SlP3Cf1ZWRwnUX9h8W25_l2q9VKnYjEfdNKOSNw9H0HoXKRR3eqVT_Vxr5c5caU3oxQe_s49Hz95QsfvW08c3W/s1600/Animation+and+Creative+Use+of+Maths+%252810%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNW7FRGtsRDHT4skGvQ4FSXZfssmK-xzsrz7VMeeB0pPeTnbSfbASDX_SlP3Cf1ZWRwnUX9h8W25_l2q9VKnYjEfdNKOSNw9H0HoXKRR3eqVT_Vxr5c5caU3oxQe_s49Hz95QsfvW08c3W/s400/Animation+and+Creative+Use+of+Maths+%252810%2529.png" width="400" /></a></div>
<br />
The following shows the <b>tanh()</b> function, which starts at <b>0</b> and rises towards <b>1</b> but never gets there. That can come in handy, especially when dealing with values that can grow indefinitely.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS9qjZSzpSkpZgdHvN0NkENL4bIVsHEJfLj1b4LWoSosNvpDGwTLXnN84wILqnlpKFfQvZ9TDiC_TKW6RGxUU0FZX7HmExqnQKc0vn757C-dZKTwqZi2Q9NUvkZbV0mHCB9h4VMVsAafSJ/s1600/desmos-graph+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS9qjZSzpSkpZgdHvN0NkENL4bIVsHEJfLj1b4LWoSosNvpDGwTLXnN84wILqnlpKFfQvZ9TDiC_TKW6RGxUU0FZX7HmExqnQKc0vn757C-dZKTwqZi2Q9NUvkZbV0mHCB9h4VMVsAafSJ/s400/desmos-graph+%25281%2529.png" width="400" /></a></div>
<br />
The following is an exponential decay <b>exp(-x<sup>2</sup>)</b>. It's the perfect shape for a smooth rolling off.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNqbI8evOUJLTMRQiF-CX906dLy0oPiuHEwsoiXzFkW-s4ITZh6Y-AHjjAZJgOvWKqNo1Kt_kHMHpwO6ZhAohipk2CO20vQBDQwVhEBbrgxcQb4HdvpMRodihG3Ge7s_zWDLORf_0T2yGE/s1600/desmos-graph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNqbI8evOUJLTMRQiF-CX906dLy0oPiuHEwsoiXzFkW-s4ITZh6Y-AHjjAZJgOvWKqNo1Kt_kHMHpwO6ZhAohipk2CO20vQBDQwVhEBbrgxcQb4HdvpMRodihG3Ge7s_zWDLORf_0T2yGE/s320/desmos-graph.png" width="320" /></a></div>
<br />
We can combine these function to combine their shapes. The following combines the waves of a sine function and the roll off of an exponential decay <b>exp(-x<sup>2</sup>)*sin(10x)</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQPQIa7xpU1b3Cy0Izs5NFB8JnWFDX1oQgSN0ayInPttJ2ctNvHPefIo_J3RB5SqbojeSmPpTUj0ubn8mA1TxRa-tKYDRepgi1U0Hw5qMVM6To-7D1smw7lHfCNDj6hH75yARgp8xAYnIS/s1600/desmos-graph+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQPQIa7xpU1b3Cy0Izs5NFB8JnWFDX1oQgSN0ayInPttJ2ctNvHPefIo_J3RB5SqbojeSmPpTUj0ubn8mA1TxRa-tKYDRepgi1U0Hw5qMVM6To-7D1smw7lHfCNDj6hH75yARgp8xAYnIS/s400/desmos-graph+%25282%2529.png" width="400" /></a></div>
<br />
We can even create a train of pulses which themselves contain pulses. You can explore it here: <a href="https://www.desmos.com/calculator/9lsgxqfxau">https://www.desmos.com/calculator/9lsgxqfxau</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6XuFUMOnnWVpNPxXjde6Q4Yj7W5Nx5sMre81VsbAj4lJd0KncX6AYs3Mvfs2kXjYVwVIHPGbWP49ZBcNSzOLcXt8m9fAJsknbY8axSiSa_9OaSHZ-j43SbFtim7VSaReeNMfaR0IFW6Q5/s1600/desmos-graph+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6XuFUMOnnWVpNPxXjde6Q4Yj7W5Nx5sMre81VsbAj4lJd0KncX6AYs3Mvfs2kXjYVwVIHPGbWP49ZBcNSzOLcXt8m9fAJsknbY8axSiSa_9OaSHZ-j43SbFtim7VSaReeNMfaR0IFW6Q5/s400/desmos-graph+%25283%2529.png" width="400" /></a></div>
<br />
As an example of using these functions, the following shows a colour field creates by mixing amounts of red, green and blue that follow the values of a sine wave.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDPu38gBrF27t4oeTbvqJQccuK5J_j81p20ocg5ClOHDC6wtLOsTYUmozBDX94CFwXZ5J4GMZzFLlqhXARl7epmX6BbgQ455oHAS74Ya25zlz3wsejuFz2CFH-RHffueP9ZnElQe_9FDSq/s1600/26_out_sin_rgb_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDPu38gBrF27t4oeTbvqJQccuK5J_j81p20ocg5ClOHDC6wtLOsTYUmozBDX94CFwXZ5J4GMZzFLlqhXARl7epmX6BbgQ455oHAS74Ya25zlz3wsejuFz2CFH-RHffueP9ZnElQe_9FDSq/s400/26_out_sin_rgb_0.png" width="400" /></a></div>
<br />
We looked at a more interesting example. The size of the randomly placed circles increases and decreases as we move out and away from the centre of the canvas. In fact the circle size is determined by a sine wave!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhQUqBZzDPjxIuXEUuJ_j695HKLulJXrUzQhAJcIi4TpjBdC9JfpujKxm0pnwNDotR9QULZ6wJRzWk8OA22OfXohUspF9kxtAFs8peEjFA_IPWm9a1aPlnEGBGBlwbp3QpEJNFmLZ6HqAw/s1600/26_out_sin_particles.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhQUqBZzDPjxIuXEUuJ_j695HKLulJXrUzQhAJcIi4TpjBdC9JfpujKxm0pnwNDotR9QULZ6wJRzWk8OA22OfXohUspF9kxtAFs8peEjFA_IPWm9a1aPlnEGBGBlwbp3QpEJNFmLZ6HqAw/s400/26_out_sin_particles.png" width="400" /></a></div>
<br />
You can explore the fairly simple code yourself: <a href="https://www.openprocessing.org/sketch/677344">https://www.openprocessing.org/sketch/677344</a><br />
<br />
<br />
<h3>
More Examples</h3>
We looked at more examples of animation where the motion of key elements is determined by a mathematical function.<br />
<br />
This is a simple example which follows on from the code we wrote in the session.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2XdabF9d4_BTimIU4B5rAGkNBKVPWVEr3qNhNPwv5_Kke5XsE_Iva4lzE3TvP1eWiNLWndxMC1R0o39WMroCwFHeZsh_cIzTVDFaqTTBhl5iFXD_XqjvXEPbLfku__G8ZZcHsfYpOXKYT/s1600/ezgif.com-video-to-gif+%25283%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="306" data-original-width="600" height="203" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2XdabF9d4_BTimIU4B5rAGkNBKVPWVEr3qNhNPwv5_Kke5XsE_Iva4lzE3TvP1eWiNLWndxMC1R0o39WMroCwFHeZsh_cIzTVDFaqTTBhl5iFXD_XqjvXEPbLfku__G8ZZcHsfYpOXKYT/s400/ezgif.com-video-to-gif+%25283%2529.gif" width="400" /></a></div>
<br />
The animation seems to show the motion of a ball as it bounces up and down, losing momentum and then rolling along the floor. The motion is actually a sin wave combined with an exponential decay. That's it - nothing more complicated than that. Yet the result is fairly realistic. The bounce is achieved by taking the absolute (positive) values of the damped wave, so the ball never falls before the green floor.<br />
s<br />
<br />
We noted that a more realistic physics simulation would use a slightly different approach using speed and gravity which results in a parabola rather than a sine wave.<br />
<br />
The next example follows the motion of many small particles, which start with a random initial velocity and move according to this velocity as well as the influence of gravity. The overall results look like fireworks.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA5B1L2LMMHpb6vjXTGhDDVJcyW0uD56rdt6GcYuZ46hkLO98_oRykqkRW7d1Nbi-6HNETMSRltCx6xjESHGJqNrbooWZFHmnKGiEodqlJl58d8mINmkUoAkqq3-ieLkUO330GPpZwT-zi/s1600/simple_anim_fireworks.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="446" data-original-width="600" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA5B1L2LMMHpb6vjXTGhDDVJcyW0uD56rdt6GcYuZ46hkLO98_oRykqkRW7d1Nbi-6HNETMSRltCx6xjESHGJqNrbooWZFHmnKGiEodqlJl58d8mINmkUoAkqq3-ieLkUO330GPpZwT-zi/s400/simple_anim_fireworks.gif" width="400" /></a></div>
<br />
Although the motion is parabolic, the maths we use to follow the motion is simply adding speed to a location, which is very simple but sufficiently valid Newtonian physics. You can read more about this particular simulation here [<a href="https://goo.gl/BiV8m5">PDF</a>], and see the code here: <a href="https://www.openprocessing.org/sketch/682243">https://www.openprocessing.org/sketch/682243</a>.<br />
<br />
A more involved example uses a different kind of mathematical function, <a href="https://algorithmicartmeetup.blogspot.com/2018/08/creative-uses-for-not-quite-random-noise.html">Perlin noise</a>, which is a smoother form of randomness. In this animation we follow the path of ants which move according to this not-so-random noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnr6x6g3KLpvdfITSuultEuA3XpykxOkywV-i8m4psx-VHj2SwGtwsYITU0SuHNuI92gIa0gO1P8MlCgFDIbpNAlLDgxySvzmVbytVQv9U8FVz6r6f0_5mqgM8GBP7RizcokkhRXGa6AnE/s1600/noise_ants.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="414" data-original-width="600" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnr6x6g3KLpvdfITSuultEuA3XpykxOkywV-i8m4psx-VHj2SwGtwsYITU0SuHNuI92gIa0gO1P8MlCgFDIbpNAlLDgxySvzmVbytVQv9U8FVz6r6f0_5mqgM8GBP7RizcokkhRXGa6AnE/s400/noise_ants.gif" width="400" /></a></div>
<br />
You can explore this slightly more involved code here <a href="https://www.openprocessing.org/sketch/687126">https://www.openprocessing.org/sketch/687126</a>.<br />
<br />
Finally we looked at an example where the motion is based on noise, but repeats smoothly because the underlying parameters that feed the noise function are taken from a looped path on the parameter space.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHKfjd5kTGXvdA_9sAjUjdFPlRjACiZ1ye2rsLrvqrVDX0Q63aVnZXrUEnPDhe6N46E9vUmxB-CEQJdgXNkcRwwSz7A9y4SLNVrSVcoeBMKCz_eR2keapu8fpqUrRFvtQ6Nt8WK1JP28EK/s1600/wobby_tree.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="397" data-original-width="600" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHKfjd5kTGXvdA_9sAjUjdFPlRjACiZ1ye2rsLrvqrVDX0Q63aVnZXrUEnPDhe6N46E9vUmxB-CEQJdgXNkcRwwSz7A9y4SLNVrSVcoeBMKCz_eR2keapu8fpqUrRFvtQ6Nt8WK1JP28EK/s400/wobby_tree.gif" width="400" /></a></div>
<br />
In this example the noise parameters move around a unit circle so the noise itself does repeat smoothly, and this leads to the tree moving smoothly too. The gif above doesn't show that, but the actual animation does: <a href="https://www.openprocessing.org/sketch/687189">https://www.openprocessing.org/sketch/687189</a>.<br />
<br />
<br />
<h3>
Conclusion</h3>
Most of the members attending were fairly confident coders so the beginner-focussed introduction to coding was likely something that was already understood.<br />
<br />
The later themes combining mathematical functions, and in particular using noise seemed to be of interest.<br />
<br />
We've now held a few beginner-focussed sessions in Cornwall now, and I feel going forward we'll proceed to explore more sophisticated topics, whilst still keeping them accessible so that newcomers always have something they can take away.<br />
<br />
<br />
<h3>
References</h3>
<ul>
<li>Another blog I wrote on animation: <a href="http://makeyourownalgorithmicart.blogspot.com/2018/05/introduction-to-animation-with-p5js.html">http://makeyourownalgorithmicart.blogspot.com/2018/05/introduction-to-animation-with-p5js.html</a></li>
<li>Previous meetup exploring creative uses of Perlin noise: <a href="https://algorithmicartmeetup.blogspot.com/2018/08/creative-uses-for-not-quite-random-noise.html">https://algorithmicartmeetup.blogspot.com/2018/08/creative-uses-for-not-quite-random-noise.html</a></li>
<li>How Perlin noise is actually calculated: <a href="http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html">http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html</a></li>
</ul>
Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-29287166815688068602019-02-22T15:32:00.001-08:002019-03-22T09:52:14.259-07:00Working With ColourThis month's <a href="https://www.meetup.com/Algorithmic-Art/events/258369820/" target="_blank">meetup</a> in Cornwall was on working with colour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA7tQQ9Hvpy3WNBfTx8jex1th7J0gpby0nI4yX4MIjCojxyR1W_2xTqOZQ4WV82hBMzMlam50Uq_nJCOnjId_lr82HlU-lBgnctsCqF_HAzLLUlbATJDXUGHisror8du31YyOF984wsoAO/s1600/IMG_20190221_182039-01.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA7tQQ9Hvpy3WNBfTx8jex1th7J0gpby0nI4yX4MIjCojxyR1W_2xTqOZQ4WV82hBMzMlam50Uq_nJCOnjId_lr82HlU-lBgnctsCqF_HAzLLUlbATJDXUGHisror8du31YyOF984wsoAO/s400/IMG_20190221_182039-01.jpeg" width="400" /></a></div>
<br />
The slides, including links to code and sketches, are online [<a href="https://goo.gl/3GkTHf" target="_blank">pdf</a>].<br />
<br />
<br />
<h3>
Mixing Your Own Colours</h3>
In this group, we've been learning to code using <b><a href="https://p5js.org/" target="_blank">p5js</a></b> on <b><a href="https://www.openprocessing.org/" target="_blank">openprocessing.org</a></b> and the <b><a href="https://github.com/makeyourownalgorithmicart/simple.js/wiki" target="_blank">simple.js</a></b> library to further simplify learning.<br />
<br />
Up to this point we've been able to choose colours for filling shapes or drawing shape outlines using colour names. The list of named colours can be found <a href="https://www.w3schools.com/cssref/css_colors.asp" target="_blank">here</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizQAMp5QQZY6CH-SAUNZBawggGxOCoj_ZNgiy3Sg2PORjA8fhIW-DAs9TgQfrQzuJ0zhn3ufmHWJ6RTLJ04XIIQnspB6Uo_Rr7xDEd8bM9EynBFXh6gzJueLsxUQ4sKmwpy9hgpXsKuKWX/s1600/Screenshot+2019-02-22+at+19.02.11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="899" data-original-width="1600" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizQAMp5QQZY6CH-SAUNZBawggGxOCoj_ZNgiy3Sg2PORjA8fhIW-DAs9TgQfrQzuJ0zhn3ufmHWJ6RTLJ04XIIQnspB6Uo_Rr7xDEd8bM9EynBFXh6gzJueLsxUQ4sKmwpy9hgpXsKuKWX/s400/Screenshot+2019-02-22+at+19.02.11.png" width="400" /></a></div>
<br />
There are quite a few colours there to choose from, <b>140</b> in fact, with examples as specific as <b>BlanchedAlmond</b> and <b>PapayaWhip</b>.<br />
<br />
This works well for many scenarios but has two disadvantages:<br />
<br />
<ul>
<li>That list of <b>140</b> colours might not have the exact colour we want.</li>
<li>We can't use code to calculate related colours if we only have a list of names.</li>
</ul>
<br />
<br />
Luckily there are different ways to choose colours which solve these two problems.<br />
<br />
<br />
<h3>
Red Green Blue</h3>
The most prevalent method for mixing colours is the <b>RGB colour model</b>, which mixes <b>red</b>, <b>green</b> and <b>blue</b> light to create the desired colour.<br />
<br />
Pretty much every electronic display - your smartphone, tablet, laptop, and TV - creates colours using an array of many tiny red, green and blue lights.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7__60HqXhhujpjRZZLoSvfb-eYqh5qLavD1QmRUaSsiHJvDK7ufv4nHSOnEa_1J7NSmfR5KDaj6M0BtG2TaXxHGShcqEoOcPjXvotxZCWfoQ1FKKWGNhtjZEmrFCw606JDF5DQiMAaeJq/s1600/additive_colour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="961" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7__60HqXhhujpjRZZLoSvfb-eYqh5qLavD1QmRUaSsiHJvDK7ufv4nHSOnEa_1J7NSmfR5KDaj6M0BtG2TaXxHGShcqEoOcPjXvotxZCWfoQ1FKKWGNhtjZEmrFCw606JDF5DQiMAaeJq/s400/additive_colour.png" width="400" /></a></div>
<br />
You can see that as we mix the red, green and blue lights, the resulting colour is lighter, and mixing all three seems to give us white light. We can think of this as reversing what a prism or raindrop does when it splits sunlight into a rainbow of colours.<br />
<br />
If you're a painter, you might be puzzled by this colour mixing because mixing paints results in darker muddier colours.<br />
<br />
The following shows the mixing of cyan, magenta and yellow pigments, used in many paper printing processes, which does result in darker colours.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1paLJNoAbtKf6KJUj9YhZ-7nIMKy2Yr7xaLtHYXmTHDKTTAbFnt9PyU8N0XXNiQeqiLdNG6Qyb-POBagd9xLImuUXj9dmchLGd8p9RY-EoH5i3OjrP04sxXE7uUmlngiYavKo6BNriowu/s1600/subtractive_colour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="961" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1paLJNoAbtKf6KJUj9YhZ-7nIMKy2Yr7xaLtHYXmTHDKTTAbFnt9PyU8N0XXNiQeqiLdNG6Qyb-POBagd9xLImuUXj9dmchLGd8p9RY-EoH5i3OjrP04sxXE7uUmlngiYavKo6BNriowu/s400/subtractive_colour.png" width="400" /></a></div>
<br />
The reason mixing paint or pigments results in darker colours is that pigments absorb some light frequencies (colours) and reflect others. So when the sun's white light, made of all the rainbow colours, hits a pigmented surface but some of those rainbow colours are absorbed and not reflected. The smaller selection of rainbow colours that are reflected are what give the pigmented surface its colour appearance.<br />
<br />
You might have seen RGB colour mixers in your favourite image editing application. Many people simply pick a colour from a palette but some then refine it by tweaking the levels of red, green and blue light.<br />
<br />
A good online RGB colour mixer is here: <a href="https://www.w3schools.com/colors/colors_rgb.asp">https://www.w3schools.com/colors/colors_rgb.asp</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0G8K_CC-wppkq7R7s0or6ooZOwpGOhlOeSqWlRXNCPEeRDekgsZKjG8jMlJyLKFtmlm0y__c74OMWEH6RhfMaM-hVj6S0G263LZXUdm7aMKYBVL5jQBd5diNVbjQ33PqUqqZ2qz6V0R3H/s1600/rgb_colour_picker.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="757" data-original-width="1600" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0G8K_CC-wppkq7R7s0or6ooZOwpGOhlOeSqWlRXNCPEeRDekgsZKjG8jMlJyLKFtmlm0y__c74OMWEH6RhfMaM-hVj6S0G263LZXUdm7aMKYBVL5jQBd5diNVbjQ33PqUqqZ2qz6V0R3H/s400/rgb_colour_picker.png" width="400" /></a></div>
<br />
Here you can see a <b>yellow</b> colour mixed by turning the red and green lights up full, and turning the blue light down to zero.<br />
<br />
If you look closely when experimenting, you'll notice the red, green and blue levels go from <b>0</b> to <b>255</b>. Typically we use maximum values of <b>100</b> or <b>1.0</b>, but the maximum for RGB levels is often set to <b>255</b>. The reason is historic, where the unit of memory, a byte, could hold a maximum value of of <b>255</b>.<br />
<br />
The number of colours possible using RGB is <b>256*256*256</b> or <b>16,777,216</b>. That's almost <b>17</b> million colours, far more than the <b>140</b> named colours we used before. You do of course need a suitable display to show all these colours, and many consumer displays can't.<br />
<br />
In the session, we experimented with this mixer to create our own colours. We noted that although we have far more control over the colour being mixed, the relationship between the RGB levels and the resulting colour isn't very intuitive.<br />
<br />
Using our mixed colours in code is easy. We still use the <b>fill() </b>instruction but instead of the colour name, we now provide three numbers, separated by commas. These are the red, green and blue levels.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlf9-LYEUBkNKWw8DqqC2LneuwUKkNSIHs9iU_To_hgo3AHPAKL3pF7bBJSTi7pBsKp2qsLUt8U-e0-Kl436PclXkOk486XU594wu3LfLueGxvpjxdslxSwErpgV0HoGBy8jqX4fVPBwIa/s1600/Working+With+Colour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlf9-LYEUBkNKWw8DqqC2LneuwUKkNSIHs9iU_To_hgo3AHPAKL3pF7bBJSTi7pBsKp2qsLUt8U-e0-Kl436PclXkOk486XU594wu3LfLueGxvpjxdslxSwErpgV0HoGBy8jqX4fVPBwIa/s400/Working+With+Colour.png" width="400" /></a></div>
<br />
<br />
<h3>
Calculating Colours</h3>
As soon as we can use numbers in code, we can use all kinds of ideas to come up with those numbers. This is actually a powerful thing, being able to move away from specific values to being able to calculate values in any way we want.<br />
<br />
A simple idea is to use randomly chosen numbers, in the range <b>0</b> to <b>255</b>, for each of the red, green and blue levels to mix a colour. The following shows lots of circles whose colour is mixed by random levels of red, green and blue.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdiuUnV5tp4uL66pKoYshyphenhyphend6vWpD41lYgVSMJl4ZJhyh6VK0AOGD2DmxFtx94Qm3iXL0Lo8xcjpxPMuX1WlLIdWOW6PcKyS7ITgYEL0Qw88mpH_BiwsPrXibgLBU7hTr9Ah8iXXTQDalHk/s1600/24_many_circles.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdiuUnV5tp4uL66pKoYshyphenhyphend6vWpD41lYgVSMJl4ZJhyh6VK0AOGD2DmxFtx94Qm3iXL0Lo8xcjpxPMuX1WlLIdWOW6PcKyS7ITgYEL0Qw88mpH_BiwsPrXibgLBU7hTr9Ah8iXXTQDalHk/s400/24_many_circles.png" width="400" /></a></div>
<br />
As many artists know, applying constraints often results in more powerful visual designs. This is like consciously choosing a limited palette, or using only a few pens from a set.<br />
<br />
Let's apply that idea here. Instead of choosing the red, green and blue levels from the full range, let's limit the ranges. The following shows the resulting colours when red is pinned to <b>0</b>, and green and blue are limited to the range <b>100</b> to <b>255</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIxmCqubvwi2tJmFqsIDg4eD4W8yVUf9SWfni9toH43kHJwfJr8JP31f8O39r1p4VPTOyKD3QO6BvVxfKGkVcmAanMdM3GpifjXkisRTSqn_Pr7N9tMgHHgVM4gCW8PkJ3rHHcqxJnX47F/s1600/24_greenyblue_rgb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIxmCqubvwi2tJmFqsIDg4eD4W8yVUf9SWfni9toH43kHJwfJr8JP31f8O39r1p4VPTOyKD3QO6BvVxfKGkVcmAanMdM3GpifjXkisRTSqn_Pr7N9tMgHHgVM4gCW8PkJ3rHHcqxJnX47F/s400/24_greenyblue_rgb.png" width="400" /></a></div>
<br />
That creates a more coherent palette. Other constraints will result in different palettes.<br />
<br />
This is an important point worth repeating. Constrained colour mixing can provide more powerful palettes.<br />
<br />
The code that sketch is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/600092" target="_blank">https://www.openprocessing.org/sketch/600092</a></li>
</ul>
<br />
<br />
We looked at an other example of calculating colours where we used the vertical height of a circle to calculate the red, green and blue levels.<br />
<br />
The following code shows the blue level being a random number between <b>100</b> and <b>255</b>, but the red and green levels being the vertical position <b>y</b> divided by <b>2</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO_QMti0u3mXEI11P4g-10IrLCQIAiSBNkfXvQxpxSWU951EuOn44DaxzfL7PG9qkWFB-Bc2SHT41hTTVJIgKzdj_EBhA9Qp3WaSyfgqxIfd9YcGG4IMmVcbnznnQS9WxFYimsThAeUg29/s1600/Working+With+Colour+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO_QMti0u3mXEI11P4g-10IrLCQIAiSBNkfXvQxpxSWU951EuOn44DaxzfL7PG9qkWFB-Bc2SHT41hTTVJIgKzdj_EBhA9Qp3WaSyfgqxIfd9YcGG4IMmVcbnznnQS9WxFYimsThAeUg29/s400/Working+With+Colour+%25282%2529.png" width="400" /></a></div>
<br />
That should result in colours that change up and down the canvas.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdfKhUsME1cbZILXtnVGnbcGS-SfLTJX2qaWG2Lyb1DiWr9IdJQL7DSp6CFALeNTJWB6Y-IPFRkTn1i11WDbsH5LOcEoYoXdScFLr9-xTwPsHPyW75jcmlX12iDr5LpcDwofcs10uGuqeE/s1600/24_calculating_rgb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdfKhUsME1cbZILXtnVGnbcGS-SfLTJX2qaWG2Lyb1DiWr9IdJQL7DSp6CFALeNTJWB6Y-IPFRkTn1i11WDbsH5LOcEoYoXdScFLr9-xTwPsHPyW75jcmlX12iDr5LpcDwofcs10uGuqeE/s400/24_calculating_rgb.png" width="400" /></a></div>
<br />
This example, although simple, does show that we can calculate colours using a wide range of range of ideas.<br />
<br />
The code for this sketch is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/601678" target="_blank">https://www.openprocessing.org/sketch/601678</a></li>
</ul>
<br />
<br />
<br />
<h3>
RGB Is Not Intuitive</h3>
Even though the RGB colour model is everywhere, it isn't very intuitive. Without looking it up, can you work out in your head the red, green and blue levels that make <b>yellow</b>? It's not trivial.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7bgqDhlcDaIG-cSaTouDB12ucJjYp-DGDcPxX2qbUeG4t_H8v5VYLtem9kKFlJ1afBeolSR6IIFXBY-N7-8oy2TgCc080osSKRhsA0BoqSoqKqtcRfhGoAVUaEGBZWOeexnI3vixE0g2e/s1600/p5_hsb_puzzle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="952" data-original-width="1600" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7bgqDhlcDaIG-cSaTouDB12ucJjYp-DGDcPxX2qbUeG4t_H8v5VYLtem9kKFlJ1afBeolSR6IIFXBY-N7-8oy2TgCc080osSKRhsA0BoqSoqKqtcRfhGoAVUaEGBZWOeexnI3vixE0g2e/s400/p5_hsb_puzzle.png" width="400" /></a></div>
<br />
And even if you happened to get it right, how do you calculate a lighter or darker shade of that colour? Again, not easy.<br />
<br />
Luckily, there are alternative colour models, each with its own strengths. A popular one amongst algorithmic artists is the <b>HSB colour model</b>.<br />
<br />
<br />
<br />
<h3>
Hue Saturation Brightness</h3>
The HSB colour model is based on a simple colour wheel.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiore-eFkE-HuciYNGY_KDSjKdTiF303laADS276MbpeixQwqBVIR121V7wuXxVvjwA_wDxwyyymiM2ETJk4HOJBmySZaqtCKOa9EQnCK_fWh-m3ajumTwRecJM_e0fBtLqkF4-d4OH9yn5/s1600/Working+With+Colour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiore-eFkE-HuciYNGY_KDSjKdTiF303laADS276MbpeixQwqBVIR121V7wuXxVvjwA_wDxwyyymiM2ETJk4HOJBmySZaqtCKOa9EQnCK_fWh-m3ajumTwRecJM_e0fBtLqkF4-d4OH9yn5/s400/Working+With+Colour.png" width="400" /></a></div>
<br />
Going around the colour wheel are the full range of rainbow colours. The term <b>hue</b> is used to describe these colours.<br />
<br />
Each hue is referred to by the angle around the circle, with red being at <b>0</b> degrees, and yellow being at <b>60</b> degrees.<br />
<br />
The following shows some of these hues with <b>saturation</b> and <b>brightness</b> turned up full. All the colours are pretty intense.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ba4eEdGFOlZ4UQQT3UGtVgReF18eWbAbSpWYrvziOssCkjV5VVyZgeop8F5B-IJMWDueFTXwOrAuKtC3CX5UDpMtMVDOLnmLncE0pNPFBQLN2-KwpChe5lgkbZTIXph4IhiQGHdsZRG1/s1600/p5_hsb_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ba4eEdGFOlZ4UQQT3UGtVgReF18eWbAbSpWYrvziOssCkjV5VVyZgeop8F5B-IJMWDueFTXwOrAuKtC3CX5UDpMtMVDOLnmLncE0pNPFBQLN2-KwpChe5lgkbZTIXph4IhiQGHdsZRG1/s400/p5_hsb_0.png" width="400" /></a></div>
<br />
The following shows the same hues but with <b>saturation</b> turned down to <b>50%</b>. The colours look dilated, closer to white.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSkjLt01baXY8kgJ3bej2h9QD_cGe0uZcfv3mSYWHJWLr6ehrEHZokD0CS-XYOdieLwxnJfpdds-cq46lzPesjwaESiS7dvw4xD-Dsz1toVnKx_3LW7GQ5-ivcIHoViQloUEObEs6JKUtf/s1600/p5_hsb_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSkjLt01baXY8kgJ3bej2h9QD_cGe0uZcfv3mSYWHJWLr6ehrEHZokD0CS-XYOdieLwxnJfpdds-cq46lzPesjwaESiS7dvw4xD-Dsz1toVnKx_3LW7GQ5-ivcIHoViQloUEObEs6JKUtf/s400/p5_hsb_1.png" width="400" /></a></div>
<br />
The next picture shows the same hues again, but wit the <b>brightness</b> turned down to <b>70%</b>. The colours are darker, closer to black.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioBtL-VGpH3saF8H71zxoFguuzRHeFgOmGnkcWFdPqff6aKGSbuxJYHdSNlksYTZ320uqu3clTkRcShuYwhngLYvqq2sloNOIve-2JaV0a-Rnmur7XY9HyZUQusH0lgt3byeNCoHh3ENzv/s1600/p5_hsb_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioBtL-VGpH3saF8H71zxoFguuzRHeFgOmGnkcWFdPqff6aKGSbuxJYHdSNlksYTZ320uqu3clTkRcShuYwhngLYvqq2sloNOIve-2JaV0a-Rnmur7XY9HyZUQusH0lgt3byeNCoHh3ENzv/s400/p5_hsb_2.png" width="400" /></a></div>
<br />
What we've see is several things that make calculating colours easier:<br />
<br />
<ul>
<li>a lighter version of a colour is easy to calculate, we just reduce the saturation.</li>
<li>a darker version of a colour is easy to calculate, we simply lower the brightness.</li>
</ul>
<br />
<br />
To use the HSB colour model, we need to set it in the <b>setup()</b> section. The <b>fill()</b> instruction is the same but this time the three numbers are the <b>hue</b>, <b>saturation</b> and <b>value</b>, with ranges <b>0-360</b>, <b>0-100</b>, and <b>0-100</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKyvQiLaG3wIGsxGSHWHIaH436f-WOY4NdBm9wHSGQr6o3ggFvJ8IUU2kAk4plt2aVk2SCIfCnJUFX-i23Ay9x8MBvF0nAgTUfYS0z6hbZhLdmO0Y03buYIPK0vw_4XYY42_IWx_9FjP6f/s1600/Working+With+Colour+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKyvQiLaG3wIGsxGSHWHIaH436f-WOY4NdBm9wHSGQr6o3ggFvJ8IUU2kAk4plt2aVk2SCIfCnJUFX-i23Ay9x8MBvF0nAgTUfYS0z6hbZhLdmO0Y03buYIPK0vw_4XYY42_IWx_9FjP6f/s400/Working+With+Colour+%25281%2529.png" width="400" /></a></div>
<br />
<br />
The code above draws three circles with progressively lower <b>saturation</b> <b>100</b>, <b>60</b> and <b>20</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxKZ8thnB3__k82i6GSbmducVFaBzkElfciMgWxsKp4a9zThrUUFoGPxypMVQOya0ufjXQitjaimTlGLVxAhdbZ1K97jjDOD_th8egpkejhSfwG5z4N2sI665dEPV5lSebctrkk2Ap-yti/s1600/27_out_3circles_hsb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxKZ8thnB3__k82i6GSbmducVFaBzkElfciMgWxsKp4a9zThrUUFoGPxypMVQOya0ufjXQitjaimTlGLVxAhdbZ1K97jjDOD_th8egpkejhSfwG5z4N2sI665dEPV5lSebctrkk2Ap-yti/s400/27_out_3circles_hsb.png" width="400" /></a></div>
<br />
The code to mix these colours these circles is very simple and would not have been so easy using the RGB colour model.<br />
<br />
The code is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/628462">https://www.openprocessing.org/sketch/628462</a></li>
</ul>
<br />
<br />
<br />
<h3>
A Little Colour Theory</h3>
When calculating colour, it is sometimes useful to find a colour's opposite, the <b><a href="https://en.wikipedia.org/wiki/Complementary_colors" target="_blank">complementary colour</a></b>.<br />
<br />
The HSB colour model makes this really easy. The following diagram shows that complementary colours are opposite each other on the colour wheel.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnStmMSaE-HvNia54lbPrpS7PEceE04LT0U_o_38qA_Gwjdc2vdhRO0KpSt2wGwXBLDkGZO0fcpuURenQDjELnG5dMj7dhp3HrucWtlczQYAN6xxEPsigUA_FklkxIg-BzcuyJEFwMsm-A/s1600/p5_hsb_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnStmMSaE-HvNia54lbPrpS7PEceE04LT0U_o_38qA_Gwjdc2vdhRO0KpSt2wGwXBLDkGZO0fcpuURenQDjELnG5dMj7dhp3HrucWtlczQYAN6xxEPsigUA_FklkxIg-BzcuyJEFwMsm-A/s400/p5_hsb_3.png" width="400" /></a></div>
<br />
That means we simply add <b>180 degrees</b> to a hue to find its opposite. If the sum grows larger than <b>360</b>, we simply wrap back around from <b>0 degrees</b>.<br />
<br />
The following sketch shows a row of circles with random hues. Inside each circle is a smaller circle with the opposite hue calculating by adding <b>180 degrees</b> to the outer hue.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ66k_5WdhNbjRF-rhlYcQYcgWR2dXJSL-fPO59lDizJEtY3kw_i97-eZWaCFg6oWBAayoA7HdvYrpfqzh-fuaF7ssLkPEmnRkpHRhbujqoAklUzNMS1dbYe_4Eys6BX7W54V8jPF-FdUT/s1600/27_out_opposite_hues.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ66k_5WdhNbjRF-rhlYcQYcgWR2dXJSL-fPO59lDizJEtY3kw_i97-eZWaCFg6oWBAayoA7HdvYrpfqzh-fuaF7ssLkPEmnRkpHRhbujqoAklUzNMS1dbYe_4Eys6BX7W54V8jPF-FdUT/s400/27_out_opposite_hues.png" width="400" /></a></div>
<br />
The resulting colour pairs do clash strongly, as we expect from complementary pairs.<br />
<br />
The code for this sketch is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/628741" target="_blank">https://www.openprocessing.org/sketch/628741</a></li>
</ul>
<br />
<br />
We can do more with HSB. The following shows that similar, or <b><a href="https://www.thespruce.com/understanding-analogous-colors-1973820" target="_blank">analogous</a></b>, colours are close together on the colour wheel. That is, their angles are similar.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEies1e2DhX1xb088d6XwRqQuzY7Q9vmaIIslWeof_zWZJaguY3JcXt2dk69RpWDarNFAtJsB1A4eDvzs5wFvcikDlYQlL4bhQ9YDYLjuu2-uoXxDY4_U0sUZQEVtyh93ZA4Ofnd3wC4n-Of/s1600/p5_hsb_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEies1e2DhX1xb088d6XwRqQuzY7Q9vmaIIslWeof_zWZJaguY3JcXt2dk69RpWDarNFAtJsB1A4eDvzs5wFvcikDlYQlL4bhQ9YDYLjuu2-uoXxDY4_U0sUZQEVtyh93ZA4Ofnd3wC4n-Of/s400/p5_hsb_4.png" width="400" /></a></div>
<br />
We can easily write code to pick a hue and calculate analogous colours by adding and subtracting a small angle to its hue.<br />
<br />
The following sketch shows a series of rectangles with random hues. Either side of each rectangle are analogues colours calculated by adding and subtracting <b>15 degrees</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3jr_0EPADZ4NtHKO8djQOIZwiTtuzeYXVj_1UqAlAMEFKVK6mb-4e9s_6Pj1GmjWnEhiiC36mP_rPB7OcJ3BjjDcwHi3KUgSyN-2XqpPYH-8nopzNBKUKPcvTXqvi9rK5YP24ez8_TrzB/s1600/27_out_similar_hues.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3jr_0EPADZ4NtHKO8djQOIZwiTtuzeYXVj_1UqAlAMEFKVK6mb-4e9s_6Pj1GmjWnEhiiC36mP_rPB7OcJ3BjjDcwHi3KUgSyN-2XqpPYH-8nopzNBKUKPcvTXqvi9rK5YP24ez8_TrzB/s400/27_out_similar_hues.png" width="400" /></a></div>
<br />
The effect is very calm and pleasing, again as we expect from a palette of analogous colours.<br />
<br />
The code for this sketch is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/628710" target="_blank">https://www.openprocessing.org/sketch/628710</a></li>
</ul>
<br />
<br />
We also mentioned <b><a href="http://www.tigercolor.com/color-lab/color-theory/color-harmonies.htm" target="_blank">split complementaries</a> </b>for creating vibrant combinations, and left it as an exercise to try at home.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE8FTeEjTMnU9zdwir-8QlEd6pHnjGdg0ThhRY2pBWffH7lx4rQurjfoB4paNR-cQOdoTBdwELSsLoQE0D0X4mnK8euBQWeoN4IIEwZAUSEzD1wTVhZ_k7gINYV67quvqtNZGtfvqwSfDR/s1600/p5_hsb_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE8FTeEjTMnU9zdwir-8QlEd6pHnjGdg0ThhRY2pBWffH7lx4rQurjfoB4paNR-cQOdoTBdwELSsLoQE0D0X4mnK8euBQWeoN4IIEwZAUSEzD1wTVhZ_k7gINYV67quvqtNZGtfvqwSfDR/s400/p5_hsb_5.png" width="400" /></a></div>
<br />
<br />
<h3>
Translucency</h3>
We looked at one final aspect of working with colour - <b>translucency</b>. The following chart shows how colours can be progressively more and more see-through.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitZa_ZulV_BXWqnKltHQD_dBdVz_2nvKnXpU0Fm3lLT5TuJapX3NtXOg502WJmaPKKi-eYVWLslZu8BsVEY8KeJG3t7aGlpgHXGMrMA1Vc2eCyrWGwtM8m3Axho3KDMAymc40k2hB7abnW/s1600/alpha_scale.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="530" data-original-width="1600" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitZa_ZulV_BXWqnKltHQD_dBdVz_2nvKnXpU0Fm3lLT5TuJapX3NtXOg502WJmaPKKi-eYVWLslZu8BsVEY8KeJG3t7aGlpgHXGMrMA1Vc2eCyrWGwtM8m3Axho3KDMAymc40k2hB7abnW/s400/alpha_scale.png" width="400" /></a></div>
<br />
Technically, <b>transparent</b> means no colour at all, but translucency can include an amount of colour. So only the circle on the left is <b>transparent</b>, but the first four are <b>translucent</b>.<br />
<br />
The number which controls how see-through a colour is often called an <b>alpha value</b>, and both RGB and HSB colour modes support it as an extra number after the usual three. In RGB the alpha value ranges from <b>0 </b>to<b> 255</b>, but in HSB it ranges from <b>0</b> to <b>1</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitslveDJ3Rns6V4d9U8rsFvEhdx8t80foIIdFLJzns2BoKoZ0hHbZrJ1AfOqr4_X_Rm1quiRkuzxIrjNOnD-s0Plks3VZ7raOUNWcbwari4AjdEgFxs-2l-tywGEq2F2AAZJkOjo029MoO/s1600/Working+With+Colour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitslveDJ3Rns6V4d9U8rsFvEhdx8t80foIIdFLJzns2BoKoZ0hHbZrJ1AfOqr4_X_Rm1quiRkuzxIrjNOnD-s0Plks3VZ7raOUNWcbwari4AjdEgFxs-2l-tywGEq2F2AAZJkOjo029MoO/s400/Working+With+Colour.png" width="400" /></a></div>
<br />
One of the key advantages of translucency is making busy designs with lots of detail possible without becoming overly saturated.<br />
<br />
Here's a busy design without translucency.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf-W_F1PWuHjlxxyaq9QALbpDA8jkl2-BfXldqqgpgRiEsyjVWHnDwZThwoz1vH11bi3ktPhKAmpsNl0dcAtQ56TGd0x72u4JW2U2pB2tu7Qs_6eLNV_TCfEpm_QdedlXxiYS-XFzHmqV2/s1600/29_out_blobs1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf-W_F1PWuHjlxxyaq9QALbpDA8jkl2-BfXldqqgpgRiEsyjVWHnDwZThwoz1vH11bi3ktPhKAmpsNl0dcAtQ56TGd0x72u4JW2U2pB2tu7Qs_6eLNV_TCfEpm_QdedlXxiYS-XFzHmqV2/s400/29_out_blobs1.png" width="400" /></a></div>
<br />
Here's a similar design with translucent circles.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxk6Ork17i34MibojGs7BtwKfL3CZZCuBeaF4c5pA_OBuNaMb7qpOrpq0CBXCJi-cm8EFXq9VUm7OqF1X1uIyTDibzbZlRlIp1GVx92FyBidECfG7v_xp6Km096CyPm-d1d7PAgLFh_gOl/s1600/29_out_blobs2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxk6Ork17i34MibojGs7BtwKfL3CZZCuBeaF4c5pA_OBuNaMb7qpOrpq0CBXCJi-cm8EFXq9VUm7OqF1X1uIyTDibzbZlRlIp1GVx92FyBidECfG7v_xp6Km096CyPm-d1d7PAgLFh_gOl/s400/29_out_blobs2.png" width="400" /></a></div>
<br />
Although a simple example, it is clear that much more detail becomes visible with translucency.<br />
<br />
We looked at several other designs that make key use of translucency, using it to create detail too. The following design is made of lots of circles moving up and down along a sine wave, where each circle is empty but has a translucent outline. When they move more slowly, the overlaying becomes closer and the rendered colour darker.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrXZ18_fd5o-hDNGdwfkxX_65D4vqHi-N2j9rT_k7unUx4qnYAzdKTNmHQxjGyO4UP3agLENR6WunMZ2DykxItc8kKNljGzX-2ZWPL1haiMaZwuPsi0QtGBboixQEV8AwbqJdiVdDCdP7n/s1600/29_out_alpha_sine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrXZ18_fd5o-hDNGdwfkxX_65D4vqHi-N2j9rT_k7unUx4qnYAzdKTNmHQxjGyO4UP3agLENR6WunMZ2DykxItc8kKNljGzX-2ZWPL1haiMaZwuPsi0QtGBboixQEV8AwbqJdiVdDCdP7n/s400/29_out_alpha_sine.png" width="400" /></a></div>
<br />
The code for this design is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/635212" target="_blank">https://www.openprocessing.org/sketch/635212</a></li>
</ul>
<br />
<br />
To demonstrate the advantage of translucency, here's the same sketch using circles without translucency, and showing fewer circles to make them visible.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLf3fW6QZx_uDKBmIX16_H0ORbAN0xam72wIsln3U2oAfmK4wGIZj_7iW-zeu8T5EBjHVbASDn8mivkcY5qiiTtQKJnn-c4auzse3D2o7WlNxJhVCzwJyaD6cv5JqMShsqHsLYsTqP88mJ/s1600/Screenshot+2019-02-22+at+23.21.23.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLf3fW6QZx_uDKBmIX16_H0ORbAN0xam72wIsln3U2oAfmK4wGIZj_7iW-zeu8T5EBjHVbASDn8mivkcY5qiiTtQKJnn-c4auzse3D2o7WlNxJhVCzwJyaD6cv5JqMShsqHsLYsTqP88mJ/s400/Screenshot+2019-02-22+at+23.21.23.png" width="400" /></a></div>
<br />
<br />
<h3>
Group Ideas</h3>
The group tried several of these ideas themselves which was good to see.<br />
<br />
One member recommended an online colour picker which is particularly good at selecting combinations such as analogous and split complementaries:<br />
<br />
<ul>
<li><a href="http://paletton.com/" target="_blank">http://paletton.com/</a></li>
</ul>
<br />
<br />
He also demonstrated a sketch we has been working on in his own time, which makes excellent use of colour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUsL9Ah1gBF_RBoScrtjl4vj5Ry0z7mXZyi77YmDxs3iAOrGpuTns35KZl_NiYHCf5TYQvRmFelVSkxGVv9tmr24K4gJHhTvC2eSjIiu6_fiTCvFf0kdrmSV0Hq7sJ_6RU7hjXsZE9HKp7/s1600/Screenshot+2019-02-22+at+23.29.12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1094" data-original-width="1493" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUsL9Ah1gBF_RBoScrtjl4vj5Ry0z7mXZyi77YmDxs3iAOrGpuTns35KZl_NiYHCf5TYQvRmFelVSkxGVv9tmr24K4gJHhTvC2eSjIiu6_fiTCvFf0kdrmSV0Hq7sJ_6RU7hjXsZE9HKp7/s400/Screenshot+2019-02-22+at+23.29.12.png" width="400" /></a></div>
<br />
The code is online:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/666708">https://www.openprocessing.org/sketch/666708</a></li>
</ul>
<br />
<br />
The matrix-style typography is created very cleverly using rectangles which overlay each other - great work!<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com1tag:blogger.com,1999:blog-2044972050276999466.post-53299264204255696082019-02-21T19:32:00.002-08:002019-02-22T10:40:50.037-08:00Three.js Overview, and Visualising Games ad FractalsThis month's London <a href="https://www.meetup.com/Algorithmic-Art/events/254417464/">meetup</a> had two interesting themes - an interesting way of visualising how games play out which results in fractal images, and an introduction to three.js, a leading javascript 3d library.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBILGZbvk96M2zcxr2UBQ5zN5PlVEVkgEQe5IHERIk-x10BWj5Umx1nmBmXmhx1a1GTrZOW6rz3yWMYwVD278MjVHZ59frNhm4PWXJajmD-YQizFE92EM-Vy-2RRGQX0SU1AIlE4IbnPJj/s1600/ezgif.com-optimize-4.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="362" data-original-width="600" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBILGZbvk96M2zcxr2UBQ5zN5PlVEVkgEQe5IHERIk-x10BWj5Umx1nmBmXmhx1a1GTrZOW6rz3yWMYwVD278MjVHZ59frNhm4PWXJajmD-YQizFE92EM-Vy-2RRGQX0SU1AIlE4IbnPJj/s400/ezgif.com-optimize-4.gif" width="400" /></a></div>
<br />
Ben's slides for visualising games is here: [<a href="https://goo.gl/Z8Jbp3">PDF</a>].<br />
<br />
Carl's guide for threejs. is here: [<a href="https://goo.gl/DXWK8T">PDF</a>].<br />
Carl's code and working demos are online: [<a href="https://glitch.com/@CarlBateman/algorithmic-art">glitch</a>].<br />
<br />
<br />
<h3>
Visualising How Games Play Out</h3>
Algorithms and AI techniques for game play is one of Ben's interests. He's previously demonstrated his work and given a very brief talk but I wanted to give him more time to fully explain his work because I think it really deserves a fuller hearing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTIQf0WQreKX2hyTzUDDq_ESildzVeBECaYtQ4VDU9FMJS807c1hcaU46K2twXjb8pJUMw3-Er_9WXd852egtFCg2bdAbFq1iXypUQrWrPEZq_FhlYK4gybhVbfFpiQI5vndWe3ynFQmzO/s1600/IMG_20190218_190828-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTIQf0WQreKX2hyTzUDDq_ESildzVeBECaYtQ4VDU9FMJS807c1hcaU46K2twXjb8pJUMw3-Er_9WXd852egtFCg2bdAbFq1iXypUQrWrPEZq_FhlYK4gybhVbfFpiQI5vndWe3ynFQmzO/s400/IMG_20190218_190828-01.jpg" width="400" /></a></div>
<br />
Ben started by discussing the simple game of naughts and crosses. At the start of the game there is an empty <b>3x3</b> grid. We can label the cells <b>1-9</b>, or <b>0-8</b> which is equivalent.<br />
<br />
If the first player chooses to place a mark in the top left we can define the move as <b>0</b>, because the cell filled is labelled <b>0</b>. If the next player chooses to fill in the top middle cell labelled <b>1</b>, the game sequence so far is <b>01</b>. If the first player then chooses to fill the central cell labelled <b>4</b>, the game sequence is <b>014</b>.<br />
<br />
Ben's slide illustrates this idea well.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv6AehAHrtlR_05d2tOBwYVvKiB9MhSNb0Brj73wrDVoMdY__eUnekWzMcQ05ML1Oh_TLsBrJRlJ9CN_TmqIW6NKC-FBS0smIpTA7K_YWeWuAiGmOzsT-jqBAgCMRAD-gwnJxsbfHa55jt/s1600/Screenshot+2019-02-21+at+23.07.49.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="901" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv6AehAHrtlR_05d2tOBwYVvKiB9MhSNb0Brj73wrDVoMdY__eUnekWzMcQ05ML1Oh_TLsBrJRlJ9CN_TmqIW6NKC-FBS0smIpTA7K_YWeWuAiGmOzsT-jqBAgCMRAD-gwnJxsbfHa55jt/s400/Screenshot+2019-02-21+at+23.07.49.png" width="400" /></a></div>
<br />
If we wanted to visualise the game after one move, we could simply use a <b>3x3</b> grid. After the second move we can use a <b>9x9</b> grid because each cell in the <b>3x3</b> grid becomes a <b>3x3</b> grid itself for the next move. For simplicity we can ignore the fact that some cells will be excluded as they are already filled.<br />
<br />
This provides the basis for visualising a game as it proceeds. If we use game data, or simulate games to completion, we can use the likelihood of winning from a position to colour a cell. The following shows that the chances of winning are highest if a player starts from the central cell. The corner cells are also advantageous, but not as much as the central cell.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE3TTu2ACpMBKjDLIEktQvCI3r_XtCaerD6dmP9XaNnNhyiqmef9NExBr6NJdDmUYROGt6WNlqyciQcYKNZiog71nkeEb2NwONUyRGv6Vta_Ubqb_sPcALA9e3D9h-VBJY7YzUy1ZDq3Fa/s1600/figure-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="219" data-original-width="500" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE3TTu2ACpMBKjDLIEktQvCI3r_XtCaerD6dmP9XaNnNhyiqmef9NExBr6NJdDmUYROGt6WNlqyciQcYKNZiog71nkeEb2NwONUyRGv6Vta_Ubqb_sPcALA9e3D9h-VBJY7YzUy1ZDq3Fa/s400/figure-1.png" width="400" /></a></div>
<br />
If we start from the second move, the grid will be <b>9x9</b> as we've already seen. The colouring indicating likelihood of winning starts to show a fractal pattern.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4TtcCuDKUd87R3DjUk1upx5QhpwAlkSK_sqTttAbf3fhm5zhAh7EAS7KHygZ3HTdO_M4slpNSslfdN5vJhLUpySX2wOZmVWQPf_dBbrPgGAE-1_5XU9qIY5Mjj-DxZk9PesLKG1EqOPbz/s1600/figure-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="219" data-original-width="500" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4TtcCuDKUd87R3DjUk1upx5QhpwAlkSK_sqTttAbf3fhm5zhAh7EAS7KHygZ3HTdO_M4slpNSslfdN5vJhLUpySX2wOZmVWQPf_dBbrPgGAE-1_5XU9qIY5Mjj-DxZk9PesLKG1EqOPbz/s400/figure-2.png" width="400" /></a></div>
<br />
Ben's blog shows how the pattern develops as the starting point progresses from <b>1</b> to <b>5</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUi_nmBlNbRRD6CjGhM19tDfP6qqkzHnHUJ0-OMCZENPcn4Pv0ocoOfVEwKCbMC5fRdsK-Ak73h-Vr8uUfVPtv0xpTJa-8j3thyphenhyphen54tomsiS4QHVT9WaBRIvPRxAI3VISu7XRqS5_oknBPA/s1600/repeat.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="100" data-original-width="500" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUi_nmBlNbRRD6CjGhM19tDfP6qqkzHnHUJ0-OMCZENPcn4Pv0ocoOfVEwKCbMC5fRdsK-Ak73h-Vr8uUfVPtv0xpTJa-8j3thyphenhyphen54tomsiS4QHVT9WaBRIvPRxAI3VISu7XRqS5_oknBPA/s400/repeat.png" width="400" /></a></div>
<br />
Ben then talked about applying these ideas to other games such as <a href="https://en.wikipedia.org/wiki/Quarto_(board_game)">Quarto</a> and chess. In particular he looked at the <a href="https://en.wikipedia.org/wiki/Eight_queens_puzzle">8 queens challenge</a>, which is to see if a chess board can be set up with 8 queens that aren't attacking any other. He used simulation to see which starting positions led to solutions, and which led far but didn't succeed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizoLTWZKLvmLtLlhB8lKzCZNaXGeLgYfE4H1vME-RuaBR1ZyqYqAuRXLsa5zBDN6yFk5GXDrJBAcXjCmGLGVesSc1dDclsXgH36rSKu87kuACOboIXWGuvgJU7VWqDQpqT9KPoJN-H04VE/s1600/Screenshot+2019-02-21+at+23.59.56.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="899" data-original-width="1600" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizoLTWZKLvmLtLlhB8lKzCZNaXGeLgYfE4H1vME-RuaBR1ZyqYqAuRXLsa5zBDN6yFk5GXDrJBAcXjCmGLGVesSc1dDclsXgH36rSKu87kuACOboIXWGuvgJU7VWqDQpqT9KPoJN-H04VE/s400/Screenshot+2019-02-21+at+23.59.56.png" width="400" /></a></div>
<br />
I find Ben's approach provides an insight into the dynamics of games and puzzles, revealing structure which itself reflects on either biases or advantageous positions in the game.<br />
<br />
During the Q&A Ben mentioned that many games explode exponentially in terms of possible next states, and so a sampling is used to reduce the computational load.<br />
<br />
Ben also pointed to a <a href="https://www.youtube.com/watch?v=1MtEUErz7Gg">numberphile</a> and a <a href="https://www.youtube.com/watch?v=diGjw5tghYU">coding train</a> video for wider applications of these ideas.<br />
<div>
<br /></div>
You can read more on Ben's blog posts:<br />
<br />
<ul>
<li><a href="https://www.purplecrane.com/blog/posts/2018/11/02/visualising-games-as-fractals">https://www.purplecrane.com/blog/posts/2018/11/02/visualising-games-as-fractals</a></li>
<li><a href="https://www.purplecrane.com/blog/posts/2018/12/11/visualising-games-as-fractals-showing-player-choice">https://www.purplecrane.com/blog/posts/2018/12/11/visualising-games-as-fractals-showing-player-choice</a></li>
</ul>
<br />
<br />
<br />
<h3>
Three.js Introduction</h3>
Carl developed a thorough <a href="https://goo.gl/DXWK8T">tutorial</a> introducing <b>three.js</b>, a popular javascript library for creating 3d scenes. <b>Three.js</b> itself works on top of the low level <a href="https://en.wikipedia.org/wiki/WebGL">WebGL</a>.<br />
<br />
Instead of repeating the tutorial exactly, I will try to use his guide to develop a simple scene, step by step.<br />
<br />
<b>Three.js</b> is a javascript library that can be included in a normal web page using the standard <script> tags, after which it can be used in subsequent javascript code.<br />
<br />
We'll avoid messing about with source code files, and work on the web, using a site called <a href="https://glitch.com/">glitch</a>. After sign up for an account, we can create a new web page project. This creates a skeleton set of html, css and javascript files. The following shows the <b>index.html</b> file, which we will edit.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiW4Vbbz6Hvavv882Aac7KLXT-vGT4iTgOP7RS7E3mMEISyyMOhslZJgkDMpwN2rlZCnL3ZowXj5f5s7r8XzjBlDiQc4ZK1j-GH6C8u1z0XajHx20zd0Jp_pcRYiNQUHWixRzGBOcC4Fl86/s1600/Screenshot+2019-02-22+at+00.31.20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="944" data-original-width="1600" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiW4Vbbz6Hvavv882Aac7KLXT-vGT4iTgOP7RS7E3mMEISyyMOhslZJgkDMpwN2rlZCnL3ZowXj5f5s7r8XzjBlDiQc4ZK1j-GH6C8u1z0XajHx20zd0Jp_pcRYiNQUHWixRzGBOcC4Fl86/s400/Screenshot+2019-02-22+at+00.31.20.png" width="400" /></a></div>
<br />
We add our reference to <b>three.js</b> using the standard <script> tags:<br />
<br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace;"><b><!-- import three.js --></b></span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace;"><b><script src="https://threejs.org/build/three.js"></script></b></span><br />
<br />
The resulting <b>index.html</b> file now looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixlRYOatK_GOXfvBoeKTfS2YW8rmdm-hMLh1aJU1mB0wLzqHmZFgoC47bmB0tABvB8gK-9jZiW4acVu-XRD1owF4MDQdQE_l9h6lSC8quSWceRCiEAFNpOOLs04FTN9O3dtj5dRP-lgM75/s1600/Screenshot+2019-02-22+at+00.46.50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="832" data-original-width="1600" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixlRYOatK_GOXfvBoeKTfS2YW8rmdm-hMLh1aJU1mB0wLzqHmZFgoC47bmB0tABvB8gK-9jZiW4acVu-XRD1owF4MDQdQE_l9h6lSC8quSWceRCiEAFNpOOLs04FTN9O3dtj5dRP-lgM75/s400/Screenshot+2019-02-22+at+00.46.50.png" width="400" /></a></div>
<br />
I've also removed the content of the <body> tags leaving it empty.<br />
<br />
Glitch auto-saves changes, and the resulting web page can be viewed in a separate window or tab, updated live.<br />
<br />
The <b>style.css</b> file, linked from <b>index.html</b>, is also adjusted to ensure the canvas fills the tab or window, and removes the scrollbar which can sometimes appear.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>body { margin: 0; overflow: hidden; }</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>canvas { width: 100%; height: 100% }</b></span></span><br />
<br />
The resulting <b>style.css</b> now looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgckF8-ZjE-Jd20pahB6B_bpNnP-zeiMj5ZeqVvP_dna2jks3jq-FY3fNkuX7p6aFrUnUp-a0tQpUfE2K14IpEewgMlAOkGokyglxs1C9HcKdGq0gHCj9bDAqbVmZvx9Ff39Rkg8qC7ms9a/s1600/Screenshot+2019-02-22+at+00.38.39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="736" data-original-width="1600" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgckF8-ZjE-Jd20pahB6B_bpNnP-zeiMj5ZeqVvP_dna2jks3jq-FY3fNkuX7p6aFrUnUp-a0tQpUfE2K14IpEewgMlAOkGokyglxs1C9HcKdGq0gHCj9bDAqbVmZvx9Ff39Rkg8qC7ms9a/s400/Screenshot+2019-02-22+at+00.38.39.png" width="400" /></a></div>
<br />
This is a good point to open the live view of the web page which is rendered using these <b>index.html</b>, <b>style.css</b> and <b>script.js</b> files. Click the show live icon at the top, which has the spectacles logo attached.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvLRv8GH0FpPEjJPMTagKIrpcpfFAnzJnHrcRLX7U5Ui2oBnhtDO8Mmv3jMZC46CsO1XkvLfh6rNjH4HEokkA-mWPVkeqYtyzfhqHeKRlWhCcDSKo1Yo1K0X3e0rrs_jDJeYI_rIA9U_0M/s1600/Screenshot+2019-02-22+at+00.48.39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="866" data-original-width="1600" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvLRv8GH0FpPEjJPMTagKIrpcpfFAnzJnHrcRLX7U5Ui2oBnhtDO8Mmv3jMZC46CsO1XkvLfh6rNjH4HEokkA-mWPVkeqYtyzfhqHeKRlWhCcDSKo1Yo1K0X3e0rrs_jDJeYI_rIA9U_0M/s400/Screenshot+2019-02-22+at+00.48.39.png" width="400" /></a></div>
<br />
You should see a new tab open. The page itself should look empty.<br />
<br />
We can now start using <b>three.js</b> in the <b>script.js</b> file, also linked from <b>index.html</b>.<br />
<br />
The first thing we need to set up is a scene, a camera and a renderer object.<br />
<br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var scene = new THREE.Scene();</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"><br /></b></span>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var renderer = new THREE.WebGLRenderer();</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">renderer.setSize( window.innerWidth, window.innerHeight );</b></span><br />
<br />
A scene is needed for all three.js scenes, there isn't a choice about it.<br />
<br />
There are different kinds of camera, here we've chosen a simple PerspectiveCamera. The options are, in order:<br />
<br />
<ul>
<li>the field of view (FOV) which is 75 degrees here</li>
<li>the aspect ratio of the camera, here calculated from the size of the window</li>
<li>the near and far clipping points outside which scene objects are not shown</li>
</ul>
<br />
<br />
The renderer is the hardware accelerated WebGL renderer. Other options are available, but usually not used, and are there as fallbacks if the browser is old and doesn't have WebGL.<br />
<br />
So far so good. We now need to attach something to the web pages's body so that it has a html element showing us something. In this case we attached the renderer to the body element.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>document.body.appendChild( renderer.domElement );</b></span></span><br />
<div>
<br /></div>
Although not obvious, this actually adds a <canvas> element to the page, which you can check by using the "inspect element" or page source viewing tools in most browsers.<br />
<br />
Now let's create an actual 3d object for our scene. Let's start with a cube.<br />
<br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var geometry = new THREE.BoxGeometry( 1, 1, 1 );</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var cube = new THREE.Mesh( geometry, material );</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">scene.add( cube );</b></span><br />
<br />
The term geometry is a little misleading. In the world of <b>three.js</b> geometries can be thought of as 3d objects of certain type - like a box, or a sphere, or a cone, or a pipe, and so on. Here we create a box geometry, which is given a width, height and depth of <b>1</b>. because all the sides are the same this box is a cube.<br />
<br />
We also create a material, which is given a green colour. The MeshBasicMaterial is the simplest, and doesn't interact with light, which means it has no reflections and doesn't show shadows.<br />
<br />
We then combine the geometry and material into a Mesh object and it to the scene.<br />
<br />
Because our cube is located at the origin, we need to move out camera back so we can see a wider view of the scene.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>camera.position.z = 5;</b></span></span><br />
<br />
If we look at the live view of this scene, we don't see anything. That's because we need a render or animate loop, as they're often called.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>function animate() {</b></span></span><br />
<span class="Apple-tab-span" style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-weight: bold; white-space: pre;"> </span><span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-weight: bold;">renderer.render( scene, camera );</span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>requestAnimationFrame( animate );</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>}</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>animate();</b></span></span><br />
<br />
This looks a bit ugly! We call a function called <b>animate()</b> which we've defined just beforehand. That function uses <b>requestAnimatonFrame</b> with <b>animate()</b> as the callback which is called whenever the browser is ready to draw the next frame of an animated scene. Not that clean looking but it's apparently better than what came before. You can read more <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">here</a>, and <a href="https://stackoverflow.com/questions/23979309/endless-animations-requestanimationframe-and-call-stack-limits?rq=1">here</a>.<br />
<br />
Finally we can see the cube.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwE9RzgrO_zMMTr6MfFDZwwlZPFH3uahqlIbWYTPEYNQBhlAOEHQyIxxUExP5SwHXYABq6PoWa9RP6vLfi_vit_LG1Bq6EYH582dPCHqhRLcsDWs9eU3K1fpAYojCRHpEiRJkJ_heJdv-F/s1600/Screenshot+2019-02-22+at+01.53.31.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwE9RzgrO_zMMTr6MfFDZwwlZPFH3uahqlIbWYTPEYNQBhlAOEHQyIxxUExP5SwHXYABq6PoWa9RP6vLfi_vit_LG1Bq6EYH582dPCHqhRLcsDWs9eU3K1fpAYojCRHpEiRJkJ_heJdv-F/s400/Screenshot+2019-02-22+at+01.53.31.png" width="400" /></a></div>
<br />
The cube doesn't do anything because we've not told it to yet. Let's now rotate it with ever animation render frame. We simple adjust the <b>x</b> and <b>y</b> rotations by a small amount with every frame.<br />
<br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">function animate() {</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"> cube.rotation.x += 0.01;</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"> cube.rotation.y += 0.01;</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"> </b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"> renderer.render( scene, camera );</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"> </b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;"><span class="Apple-tab-span" style="white-space: pre;"> </span>requestAnimationFrame( animate );</b></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">};</b></span><br />
<br />
Every time the <b>animate()</b> function is called to draw a new frame, the cube's orientation will be changed a bit.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSwrIJrqCScJAs3D6ZLhxtm1TURuX2Gzm62Mej2NHS3QB-G-1ErLGW_U-LjuowYuFBvToS9WKkGrJvt9BJh6Vi1cqaS2qWaRe0ehLYh1UjrhTDM_OEroeADaCSyhXUuKUn2mY8nGKftd_f/s1600/ezgif.com-video-to-gif.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="422" data-original-width="600" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSwrIJrqCScJAs3D6ZLhxtm1TURuX2Gzm62Mej2NHS3QB-G-1ErLGW_U-LjuowYuFBvToS9WKkGrJvt9BJh6Vi1cqaS2qWaRe0ehLYh1UjrhTDM_OEroeADaCSyhXUuKUn2mY8nGKftd_f/s400/ezgif.com-video-to-gif.gif" width="400" /></a></div>
<br />
That worked - we can see an actual 3d rotating cube.<br />
<br />
This didn't work in Safari, which is known to have WebGL issues, but did work in Chrome and Firefox.<br />
<br />
Let's change the material to better show the 3-d nature of the cube.<br />
<br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b style="background-color: #fff2cc;">var material = new THREE.MeshNormalMaterial();</b></span><br />
<div>
<br /></div>
This material uses the <a href="https://en.wikipedia.org/wiki/Normal_(geometry)">normals</a> of the surface to decide the local colour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBOWQVX9o-4RH_01E1nSLbGPGT3PdbUTR3aukxKTeYeCmjeF_Z56ZS1VSiXmXBs0RuwdODd7ykeJPW-xK_yXr_iI3EJTd_N8numHvv3eDmlcf2ZzcpAnQFOPypEIQVBnymPVkJe4vqZ371/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBOWQVX9o-4RH_01E1nSLbGPGT3PdbUTR3aukxKTeYeCmjeF_Z56ZS1VSiXmXBs0RuwdODd7ykeJPW-xK_yXr_iI3EJTd_N8numHvv3eDmlcf2ZzcpAnQFOPypEIQVBnymPVkJe4vqZ371/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<br />
That's a much clearer rendering of a 3d object.<br />
<br />
Carl then introduced the idea of manual controls to orient the object. We include another library from <b>three.js</b> called <b>OrbitControls.js</b>.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b><script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script></b></span></span><br />
<br />
In our javascript we add the controls linked to the camera:<br />
<br />
<b style="background-color: #fff2cc; color: blue; font-family: "Courier New", Courier, monospace;">var controls = new THREE.OrbitControls(camera);</b><br />
<br />
We remove the cube rotation from the animate loop and instead set the orientation using these control library.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>controls.update();</b></span></span><br />
<br />
We can now control how we view the scene by effectively moving the camera.<br />
<br />
Now let's use the power of code to create lots of objects.<br />
<br />
Let's replace the code that creates a single material and cube with a loop that creates many, padding each to an initially empty list.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>var boxes = [];</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>var numBoxes = 9;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>for (let x = -numBoxes; x <= numBoxes; x++) {</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> for (let y = -numBoxes; y <= numBoxes; y++) {</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> var material = new THREE.MeshNormalMaterial( );</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> var cube = new THREE.Mesh( geometry, material );</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> cube.position.x = x * 1.1;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> cube.position.y = y * 1.1;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> boxes.push(cube);</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> scene.add(cube);</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> }</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>}</b></span></span><br />
<br />
To keep each cube independent, each needs a new instance of a material. The loop counters x and y are used to set the location of each individual cube.<br />
<br />
The following shows the array of boxes this loop creates.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0q9-1Umjyi2y5OSs_N8PHnvDqc1X4y1NZycMJff1mnLFwfiSAn0D1NTWfbSICYxQWZH9-iapwMlkAVEhHn7oRod7y9Yl2VoYA_KwjQS48tPTpnxQW906kNd47JWaFDAqcpVqFPpuLHZ1D/s1600/Screenshot+2019-02-22+at+02.58.34.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1285" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0q9-1Umjyi2y5OSs_N8PHnvDqc1X4y1NZycMJff1mnLFwfiSAn0D1NTWfbSICYxQWZH9-iapwMlkAVEhHn7oRod7y9Yl2VoYA_KwjQS48tPTpnxQW906kNd47JWaFDAqcpVqFPpuLHZ1D/s400/Screenshot+2019-02-22+at+02.58.34.png" width="400" /></a></div>
<br />
Let's now modify these. Inside the animate function we can adjust the positions and rotations of each of these cubes individually.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: #666666; font-family: "courier new" , "courier" , monospace;"><b>// work through each box</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>for (var box of boxes) {</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> </b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> var x = box.position.x;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> var y = box.position.y;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> </b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> box.position.z = Math.abs(x) + Math.abs(y);</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> </b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>}</b></span></span><br />
<br />
Here we've pulled out the x and y position of each cube and used it to set the z position. The calculation uses the Manhattan distance, which results in an arrangement that looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBAwP0leZRm55NdzKTdyDXjRQvFUi-tPCohBzZfVX61Yyjp2LuIaGWy_ZMqaxR8hFoJplzwbG7YvIS3klN-HzbXgKc3ljz2AYG1nvY5vQRWtxvPbG4phcrJ8ZM12MtOF6Kqgl1wJK1QOgC/s1600/ezgif.com-optimize-2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="600" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBAwP0leZRm55NdzKTdyDXjRQvFUi-tPCohBzZfVX61Yyjp2LuIaGWy_ZMqaxR8hFoJplzwbG7YvIS3klN-HzbXgKc3ljz2AYG1nvY5vQRWtxvPbG4phcrJ8ZM12MtOF6Kqgl1wJK1QOgC/s400/ezgif.com-optimize-2.gif" width="400" /></a></div>
<br />
That's pretty effective!<br />
<br />
Carl demonstrated other kinds of manipulation such as offsetting each cube using wavy trigonometric functions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_TJFTY_-jhD6k0o0avdLxOgLzhyphenhyphenfNX-q5XY1e1MfCWxpHZ-JunSWO79b_qSIgu8j-K1lDrqHNdc0eRlmJSPfCS-d6XtuwLTEBQk0fKL6s83drMX7QQDE0u95kk4LXIUPbm2jzie-8yoD0/s1600/IMG_20190218_200303-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1201" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_TJFTY_-jhD6k0o0avdLxOgLzhyphenhyphenfNX-q5XY1e1MfCWxpHZ-JunSWO79b_qSIgu8j-K1lDrqHNdc0eRlmJSPfCS-d6XtuwLTEBQk0fKL6s83drMX7QQDE0u95kk4LXIUPbm2jzie-8yoD0/s400/IMG_20190218_200303-01.jpg" width="400" /></a></div>
<br />
A key idea he did introduce was the use of a pseudo-timer to calculate box positions. The pseudo-timer variable, which we can call step, is created in the main javascript code.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>var step = 0;</b></span></span><br />
<br />
It is updated inside the animate loop, incrementing it by <b>0.0001</b> with each call to <b>animate()</b>.<br />
<br />
<span style="background-color: #fff2cc;"><span style="color: #666666; font-family: "courier new" , "courier" , monospace;"><b>// work through each box</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>for (var box of boxes) {</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> step += 0.0001;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> </b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> var x = box.position.x;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> var y = box.position.y;</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> </b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> box.position.z = Math.sin(step + Math.sqrt(x*x + y*y));</b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b> </b></span></span><br />
<span style="background-color: #fff2cc;"><span style="color: blue; font-family: "courier new" , "courier" , monospace;"><b>}</b></span></span><br />
<br />
Here we set the z position of each box using a sine function that depends on the distance of the box from the origin, and also the <b>step</b> pseudo-timer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-fCxTLOMhDwk5R0ugXMlw63pV3UiU7cm669WYmc4lUs1QGMY-uhBrNxuR9ToQJ_nJkgzVn2vwMXN7pMBc6ezglCZTpWU9Ir-DbNBuicIpXxMKyfcxa_zycFkWgznLpwsJim8ZHrojtjRa/s1600/ezgif.com-optimize-3.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="412" data-original-width="600" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-fCxTLOMhDwk5R0ugXMlw63pV3UiU7cm669WYmc4lUs1QGMY-uhBrNxuR9ToQJ_nJkgzVn2vwMXN7pMBc6ezglCZTpWU9Ir-DbNBuicIpXxMKyfcxa_zycFkWgznLpwsJim8ZHrojtjRa/s400/ezgif.com-optimize-3.gif" width="400" /></a></div>
<br />
That's a rather pleasing effect! The key point is the use of the pseudo-timer to adjust the positions of the boxes in the animate loop.<br />
<br />
You can explore the code on glitch:<br />
<br />
<ul>
<li><a href="https://glitch.com/~algorithmicartmeetup">https://glitch.com/~algorithmicartmeetup</a></li>
</ul>
<br />
<br />
Carl proceeded to look at more advanced ideas such as setting colours dynamically, adding additional lighting, and also <a href="https://glitch.com/~algoart-feb19-g" target="_blank">grouping</a> objects so they could be rotated together, or even adjusting the <a href="https://glitch.com/~algoart-feb19-k" target="_blank">vertices</a> of each object. Do look through his tutorial to explore these ideas in more detail.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzI9iS2yQ5GqUNN0nbMNKKxUsyyTfw4jSXdeq5K_DmvSTGP7ENX3Uqnq5xt3Svauj9w4w4OcTFDZdBANO3U8-grsnmgiVFOyPGy0tKHUGLcTJs2ZjV6S47tdhJZZ3Or-F-fbZvuHM-7S4g/s1600/IMG_20190218_200811-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzI9iS2yQ5GqUNN0nbMNKKxUsyyTfw4jSXdeq5K_DmvSTGP7ENX3Uqnq5xt3Svauj9w4w4OcTFDZdBANO3U8-grsnmgiVFOyPGy0tKHUGLcTJs2ZjV6S47tdhJZZ3Or-F-fbZvuHM-7S4g/s400/IMG_20190218_200811-01.jpg" width="400" /></a></div>
<br />
The group enjoyed Carl's tutorial and we reflected that his introduction took away most of the initial barriers to trying a new technology. Several said they'd go home and continue to explore <b>three.js</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc7tf_eUcwwFRVMaGV_L0zcR4fs6I3X1LKwzTXK60J9_3Nmc9UfgwqkkGSxaTbbwEkPEh21CAhJtUPLfS5wHX076KLad3T5AooYDKaiuTSlkZVS_iMUifUdEImYhIbXB6YTJaESdd6-5pB/s1600/IMG_20190218_193535-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1076" data-original-width="1600" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc7tf_eUcwwFRVMaGV_L0zcR4fs6I3X1LKwzTXK60J9_3Nmc9UfgwqkkGSxaTbbwEkPEh21CAhJtUPLfS5wHX076KLad3T5AooYDKaiuTSlkZVS_iMUifUdEImYhIbXB6YTJaESdd6-5pB/s400/IMG_20190218_193535-01.jpg" width="400" /></a></div>
<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-71603212354442714192019-01-25T09:20:00.001-08:002019-01-25T09:29:22.428-08:00Introduction To Creative Coding With RecursionThis month we held the <a href="https://www.meetup.com/Algorithmic-Art/events/256648516/" target="_blank"><b>second</b></a> Cornwall meetup, following on from the <a href="https://algorithmicartmeetup.blogspot.com/2018/11/first-meetup-in-cornwall-beginners.html" target="_blank"><b>first</b></a> one which started introducing creative coding with <b>p5js</b>.<br />
<br />
This time we continued our learning to code and focussed on <b>recursion</b> - a powerful concept that can elegantly create intricate patterns, but one which some people find difficult to get started with.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipvP4qxdPMT7ZRmw3R23bfrSv0L0FjAaRxXPSb6AicewlQ2cngEDmjNFMwLLltmQ8vZWo3BNa2iASTfMPItN8Silznc3PZeMPNtbP5VJZldto3kWEfbXYfuH5v3FjPuFNXGgLQY3ArUdBr/s1600/IMG_20190124_194456-01-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1146" data-original-width="1600" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipvP4qxdPMT7ZRmw3R23bfrSv0L0FjAaRxXPSb6AicewlQ2cngEDmjNFMwLLltmQ8vZWo3BNa2iASTfMPItN8Silznc3PZeMPNtbP5VJZldto3kWEfbXYfuH5v3FjPuFNXGgLQY3ArUdBr/s400/IMG_20190124_194456-01-01.jpg" width="400" /></a></div>
<br />
<br />
The slides are here: <a href="https://goo.gl/kqXpFB">[link]</a>.<br />
<br />
Because we've covered recursion <b><a href="https://algorithmicartmeetup.blogspot.com/2018/04/recursion-for-beginners.html" target="_blank">before</a></b> in London, this post will focus on the keys points and improvements over the previous session.<br />
<br />
<br />
<h3>
Examples Of Recursive Patterns</h3>
We started by looking at a few examples of patterns and discussed the common thread between them - that of <b>self-similarity</b>.<br />
<br />
We looked at geometric patterns as well as natural forms, such as this fern leaf.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixYf5q1yXmY2gI3ERM8TixQy68hYFhcW5hbx0W-xCQucuMvlWRuVJZ8VvYRiAuu4KLo_Kc-zBeKaAGT80Ed9sN0bujdUuGmjZlwIqK1GXSzvwPUAj1LpeyG9XB2zIhXaI8_eaZuVWSSxGc/s1600/Cornwall+-+Recursion+for+Beginners+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixYf5q1yXmY2gI3ERM8TixQy68hYFhcW5hbx0W-xCQucuMvlWRuVJZ8VvYRiAuu4KLo_Kc-zBeKaAGT80Ed9sN0bujdUuGmjZlwIqK1GXSzvwPUAj1LpeyG9XB2zIhXaI8_eaZuVWSSxGc/s400/Cornwall+-+Recursion+for+Beginners+%25281%2529.png" width="400" /></a></div>
<br />
We briefly touched on the idea that self-similarity at different scales is one design strategy for beauty, and nature is a bounty of such <a href="https://en.wikipedia.org/wiki/Fractal"><b>fractals</b></a>.<br />
<br />
Pure mathematics itself, far from being predictable and boring, has within it's structures beautiful organic self-similar forms, such as this <b><a href="https://en.wikipedia.org/wiki/Julia_set">Julia set</a></b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRoyG0FwZOEpkBv_Sds5dQFZmbfuBpw_BLeJPkEXmf8-PlqwV_4K0PRUBX5KSlftoxpI_8lCbnBQeqg2ux8IXElyA_qxpc85snybdqBVzayxwK0wp0iqtsuf5fe8t-D-DGyAwxEd0Gri6O/s1600/Cornwall+-+Recursion+for+Beginners+%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRoyG0FwZOEpkBv_Sds5dQFZmbfuBpw_BLeJPkEXmf8-PlqwV_4K0PRUBX5KSlftoxpI_8lCbnBQeqg2ux8IXElyA_qxpc85snybdqBVzayxwK0wp0iqtsuf5fe8t-D-DGyAwxEd0Gri6O/s400/Cornwall+-+Recursion+for+Beginners+%25283%2529.png" width="400" /></a></div>
<br />
We also noted the use of self-similarity in art, with the Droste example from 1904, and another example of Christian art going back to about 1320.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmoKOTHRxCGCHqHe9HA1v4wtmBUV-ZVUgDDyaPY2-yDnVUbXEAbqMcyV5imLoj3nGUSFA-S1i0kge2-Ac-4tOjpdQUOXAVHjMYDmaSqZdjxzEy44XGjAueL6V0eRomjMzfeH3e433-KxRp/s1600/Droste_Cacao.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="769" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmoKOTHRxCGCHqHe9HA1v4wtmBUV-ZVUgDDyaPY2-yDnVUbXEAbqMcyV5imLoj3nGUSFA-S1i0kge2-Ac-4tOjpdQUOXAVHjMYDmaSqZdjxzEy44XGjAueL6V0eRomjMzfeH3e433-KxRp/s320/Droste_Cacao.jpg" width="240" /></a></div>
<br />
<br />
<h3>
An Apparently Unhelpful Conversation</h3>
We then discussed a conversation happening amongst Victorian ladies in the evocative setting of a rose garden.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYSCbYvXWTfLqKDrFNlQfQ7Kl5BgUXTJASTHsvI_tMCnfi0uiXnUYO7NuMt7ofXXOk86BYOefwRt_ws8guMVD0__Sky8cT7VVt0Yb6xSmrKHx6H9IFJlSJ9DH0BdHKwFMhz-NYQLAUukZ0/s1600/Cornwall+-+Recursion+for+Beginners+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYSCbYvXWTfLqKDrFNlQfQ7Kl5BgUXTJASTHsvI_tMCnfi0uiXnUYO7NuMt7ofXXOk86BYOefwRt_ws8guMVD0__Sky8cT7VVt0Yb6xSmrKHx6H9IFJlSJ9DH0BdHKwFMhz-NYQLAUukZ0/s400/Cornwall+-+Recursion+for+Beginners+%25282%2529.png" width="400" /></a></div>
<br />
The first lady is asking <i>"what is 3"</i>, to which the reply is <i>"1 more than 2"</i>. The first lady then asks <i>"what is 2"</i>, to which the reply is <i>"1 more than 1"</i>. Again, the first lady asks <i>"what is 1"</i> to which there is finally a concrete answer.<br />
<br />
The second lady looks like she's being particularly unhelpful but she's actually being rather clever. She is using only two phrases:<br />
<br />
<ul>
<li><b><i>"1 more than .."</i></b></li>
<li><b><i>"that's how many noses you have"</i></b></li>
</ul>
<br />
<br />
With just these two definitions she is able to reply to any question from the first lady about any number.<br />
<br />
Although this is a contrived example, the key point is that a small number of definitions can describe many more things - a concept key to using recursion.<br />
<br />
<br />
<h3>
Coding A Self-Similar Pattern</h3>
We then looked a simple, but still self-similar pattern, and asked ourselves how we could write code to draw it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoIBXO-lWKEGPCLobScUwAGYn8zRWSCAJv5WHcbM-fLCN5fXXSOdeaUuXAnMCVkkh7b9nM4Jy1ob6XX1VfKlAV8HNxxYX6YMJetJ2e20lyv2sFOwfKu3qu1NkMekNsZQWXLLIjrUUj_7fu/s1600/Cornwall+-+Recursion+for+Beginners+%25284%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoIBXO-lWKEGPCLobScUwAGYn8zRWSCAJv5WHcbM-fLCN5fXXSOdeaUuXAnMCVkkh7b9nM4Jy1ob6XX1VfKlAV8HNxxYX6YMJetJ2e20lyv2sFOwfKu3qu1NkMekNsZQWXLLIjrUUj_7fu/s400/Cornwall+-+Recursion+for+Beginners+%25284%2529.png" width="400" /></a></div>
<br />
We noticed that the main pattern has two smaller versions of itself to the left and to the right.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib5Kows8ClVcILZfvIyJeBzgPWYef9WCVI_Uvefj9JcXFY3u84tSDxC-C8Z9rYAgYdh6ILLuxEpoRUZditbfQWtdHUfa8fmUv_KgIcFEH4Q_bv5Vaxs-ATLXut3OcCuM5ZY4UWL8olrK25/s1600/Cornwall+-+Recursion+for+Beginners+%25285%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib5Kows8ClVcILZfvIyJeBzgPWYef9WCVI_Uvefj9JcXFY3u84tSDxC-C8Z9rYAgYdh6ILLuxEpoRUZditbfQWtdHUfa8fmUv_KgIcFEH4Q_bv5Vaxs-ATLXut3OcCuM5ZY4UWL8olrK25/s400/Cornwall+-+Recursion+for+Beginners+%25285%2529.png" width="400" /></a></div>
<br />
And that means each of those has an even smaller version attached.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUnWAEGFBhuyEa1ibJCrAyDVpD3oym5h7qX5AQXZFez3r_pix5RX-dz81KIi3rZSLJykeKTk4HrXWG7NDZ9UBy77yhpUkMaHY-yvhs8dvo9okrplzMx1s3d5uCtG5ktH96A0AJ4Qd4Dls7/s1600/Cornwall+-+Recursion+for+Beginners+%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUnWAEGFBhuyEa1ibJCrAyDVpD3oym5h7qX5AQXZFez3r_pix5RX-dz81KIi3rZSLJykeKTk4HrXWG7NDZ9UBy77yhpUkMaHY-yvhs8dvo9okrplzMx1s3d5uCtG5ktH96A0AJ4Qd4Dls7/s400/Cornwall+-+Recursion+for+Beginners+%25286%2529.png" width="400" /></a></div>
<br />
This description of the pattern is <b>recursive</b> - it is defined in terms of itself.<br />
<br />
We then started to think about how to code, not an easy task when trying it for the first time. We started by taking small steps, and coding the big central circle.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFXeUK-CFFuWM1gGpraJyewba0unyaQCwIDTeXxRhbRUaexTForcg8rewBE6GsU7pGDsNuW_bk7oLcOjkyMjX9U-IxxZRJ6ULHWz-5NY-_PpbC_lV4HA44YhA8HDg7lbS8dX9SAzkXViiv/s1600/Cornwall+-+Recursion+for+Beginners+%25287%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFXeUK-CFFuWM1gGpraJyewba0unyaQCwIDTeXxRhbRUaexTForcg8rewBE6GsU7pGDsNuW_bk7oLcOjkyMjX9U-IxxZRJ6ULHWz-5NY-_PpbC_lV4HA44YhA8HDg7lbS8dX9SAzkXViiv/s400/Cornwall+-+Recursion+for+Beginners+%25287%2529.png" width="400" /></a></div>
<br />
That's easy enough but only draws a single yellow circle. Now we need more code to draw the other circles. There are lots of them .. does that suggest lots of <b>circle()</b> code instructions?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWKr8SwmGWY546rmV3XIvLUgS6u7VqGYG2BpyYisp7RcrYBZHaMeU9NaRHo9QJTIAUTGA-jBhtoUhoC9LJAMSXpqByqIfM9cl1CcmcnDJGJYtqP2x5CkIRvG4of_Msq6WW7vNHoQRMIZ7Y/s1600/Cornwall+-+Recursion+for+Beginners+%25288%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWKr8SwmGWY546rmV3XIvLUgS6u7VqGYG2BpyYisp7RcrYBZHaMeU9NaRHo9QJTIAUTGA-jBhtoUhoC9LJAMSXpqByqIfM9cl1CcmcnDJGJYtqP2x5CkIRvG4of_Msq6WW7vNHoQRMIZ7Y/s400/Cornwall+-+Recursion+for+Beginners+%25288%2529.png" width="400" /></a></div>
<br />
That goes against the key idea of using a small number of rules to describe something more complex.<br />
<br />
Instead, let's try to write code which expressed the idea that the main pattern is a circle with two smaller versions of the same pattern.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfM1JgaX9TSyuOPLIrYwqGMe_-H05vhsBTlASNvWCp5uTemwEBK1QmVmTw87jpnTf78fipLBji7amdR4vLl7inHwmFegGyCwDPUxmYkSlBjmd2z9_V3v_Pnk-Q3k6TD22zORCFxD1YXADT/s1600/Cornwall+-+Recursion+for+Beginners+%25289%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfM1JgaX9TSyuOPLIrYwqGMe_-H05vhsBTlASNvWCp5uTemwEBK1QmVmTw87jpnTf78fipLBji7amdR4vLl7inHwmFegGyCwDPUxmYkSlBjmd2z9_V3v_Pnk-Q3k6TD22zORCFxD1YXADT/s400/Cornwall+-+Recursion+for+Beginners+%25289%2529.png" width="400" /></a></div>
<br />
This looks like it shouldn't work. How can we describe something in terms of itself. Surely we haven't really defined it? Isn't this a logical error?<br />
<br />
Turns out that many programming languages do allow you to create such definitions - <b>recursive</b> definitions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUG_m-1lquDx6pAP52C7MlEd5Vbm41pnO3sUiqtLIKAei4T2qN2r8Rj9Sw4137xsyDVWAuZ-QIyopLqeeXFg43WbqfIeCddHzVvJcOCaMUopAAHCCZUIk7CsmfqzQCLwavjRqsHENRbYAA/s1600/mindblown.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="233" data-original-width="350" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUG_m-1lquDx6pAP52C7MlEd5Vbm41pnO3sUiqtLIKAei4T2qN2r8Rj9Sw4137xsyDVWAuZ-QIyopLqeeXFg43WbqfIeCddHzVvJcOCaMUopAAHCCZUIk7CsmfqzQCLwavjRqsHENRbYAA/s320/mindblown.gif" width="320" /></a></div>
<br />
<br />
Mind blowing!<br />
<br />
<br />
<h3>
Make Sure To Stop!</h3>
Before running the code, I told the group there was one important problem with the code, and asked them to see if they could spot it.<br />
<br />
The code as we wrote it would never stop. The <b>my_pattern</b> function would call <b>my_pattern</b>, albeit with a smaller size, which would call <b>my_pattern</b> ... and so on .. until the code crashed.<br />
<br />
We need to establish a limit to how deep the recursion goes. There are many ways to do this, and a simple one is to stop when the size gets smaller than a threshold.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjgoCzK0Ht-J6EKVtnnj1m5ehnyoG3OtL7yPyceBeIRQ6AjDMoZ_yGajr1olIyxS01wkAoiM6-3hALrJp8LQ_hsQTkCtrrTrra1hOss_Dew3Z1s48r_XvvEFbrxG37JBg8D-Uzoa2qlU99/s1600/Cornwall+-+Recursion+for+Beginners+%252810%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjgoCzK0Ht-J6EKVtnnj1m5ehnyoG3OtL7yPyceBeIRQ6AjDMoZ_yGajr1olIyxS01wkAoiM6-3hALrJp8LQ_hsQTkCtrrTrra1hOss_Dew3Z1s48r_XvvEFbrxG37JBg8D-Uzoa2qlU99/s400/Cornwall+-+Recursion+for+Beginners+%252810%2529.png" width="400" /></a></div>
<br />
Finally we had code ready to run.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnRERrJZni8E2fDc535BCAwjSR54JsVgpQQNPpXcDIwQ8Vc9H0EtpHOfEGhjkZ7ywcYsSqUmj_kJeVHXz33f3hJMvweUc4I7gpex53gP-XRbbFkZ2xigqsog-t3WBU6fBsAcSRY2z3zOE0/s1600/Cornwall+-+Recursion+for+Beginners+%252812%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnRERrJZni8E2fDc535BCAwjSR54JsVgpQQNPpXcDIwQ8Vc9H0EtpHOfEGhjkZ7ywcYsSqUmj_kJeVHXz33f3hJMvweUc4I7gpex53gP-XRbbFkZ2xigqsog-t3WBU6fBsAcSRY2z3zOE0/s400/Cornwall+-+Recursion+for+Beginners+%252812%2529.png" width="400" /></a></div>
<br />
The result so far is a series of circles getting smaller to the right. That's because our code only defines the pattern as having a smaller version of itself to the right. We need to add the left side too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5PcdoXiNfZspX3zI-4jDWYsJB_phR1VKNXnwI0UXr6BYbwDNRSQVFE-vpZV2WdDnvER7Fs4593LpcHPoOleAErWXgaGsMNRWLmmhbtd7_7liNtKFGKy0aEXvWDfFjk4zpfGer4ZdjFYUs/s1600/Cornwall+-+Recursion+for+Beginners+%252813%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5PcdoXiNfZspX3zI-4jDWYsJB_phR1VKNXnwI0UXr6BYbwDNRSQVFE-vpZV2WdDnvER7Fs4593LpcHPoOleAErWXgaGsMNRWLmmhbtd7_7liNtKFGKy0aEXvWDfFjk4zpfGer4ZdjFYUs/s400/Cornwall+-+Recursion+for+Beginners+%252813%2529.png" width="400" /></a></div>
<br />
And finally we have the pattern we wanted.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiPzqkpABkSveWnYkHzlpcsQmvXtPhWIoEFn6PEPT9ivQi9ydmthsMaJErJlnBMRFg_azptQm5-CtJ-VW4XIsHAug6KcDvUok_-nedOEWgiqKCOvrVRhhHbe7lO3GmovAN0-XnBrdHcXL0/s1600/Cornwall+-+Recursion+for+Beginners+%252811%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiPzqkpABkSveWnYkHzlpcsQmvXtPhWIoEFn6PEPT9ivQi9ydmthsMaJErJlnBMRFg_azptQm5-CtJ-VW4XIsHAug6KcDvUok_-nedOEWgiqKCOvrVRhhHbe7lO3GmovAN0-XnBrdHcXL0/s400/Cornwall+-+Recursion+for+Beginners+%252811%2529.png" width="400" /></a></div>
<br />
The striking thing here is how a small change to the definition results in a drastic change in teh pattern.<br />
<br />
We look at other examples of patterns which were based on the very same simple code but with small variations. This next one defined a pattern as having smaller versions of itself not just to the left and right, but above and below too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYK-_6ups_gYHrw_avG-3rXZ-UFAFPL5JVp_LdHGW_HxXsCiUEPuM-e8n0FoXa1M5vzl8hX0QQzStauo1KKzDbWoPx9xeXy3pJtjtKEr3mUJeV2v27GN9hZLp_G81mTrQPCcTlXc011Rmy/s1600/33_out_recursion_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYK-_6ups_gYHrw_avG-3rXZ-UFAFPL5JVp_LdHGW_HxXsCiUEPuM-e8n0FoXa1M5vzl8hX0QQzStauo1KKzDbWoPx9xeXy3pJtjtKEr3mUJeV2v27GN9hZLp_G81mTrQPCcTlXc011Rmy/s400/33_out_recursion_5.png" width="400" /></a></div>
<br />
The code for this pattern is online and worth exploring:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/642059">https://www.openprocessing.org/sketch/642059</a></li>
</ul>
<br />
<br />
<br />
<h3>
A Framework for Recursion</h3>
We looked again at the code for the pattern made of circles and noted some key elements.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYp7Iub-vHSgrUP3vIxuWodjPJWTzU-w2Sb_2JjDuEBwyrkrpPnlIfVe80rOoczu3A7e6-_WvJkASBmMS_p0YQoan6_MNdp68nSqDckivxGIIs1HFR52-mwzAoqdK6ZQyptEknHY8XJeda/s1600/Cornwall+-+Recursion+for+Beginners+%252814%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYp7Iub-vHSgrUP3vIxuWodjPJWTzU-w2Sb_2JjDuEBwyrkrpPnlIfVe80rOoczu3A7e6-_WvJkASBmMS_p0YQoan6_MNdp68nSqDckivxGIIs1HFR52-mwzAoqdK6ZQyptEknHY8XJeda/s400/Cornwall+-+Recursion+for+Beginners+%252814%2529.png" width="400" /></a></div>
<br />
The code has a termination rule, a rule that decides when to stop going deeper into the recursion. There is also code which defines what the detail is at the current level of recursion. Finally there is a continuation rule which defines where the next next level of detail is.<br />
<br />
This is a general framework that is useful to planning your own code, or seeing if a problem can be solved elegantly in a recursive manner.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbEIc5q_c2icLHJj3KVcjhi-EgKbm_UcH05pAx-2cZK6ZNR6s2XXkX0Jqq6t-7XDZLXPOTf_SMihPR3DZHVqATRuH89oNelIS3ofuGPAbZrrEA81rXaM3nFGCKxNmsuXO59k_0uQ-ee8Z5/s1600/Cornwall+-+Recursion+for+Beginners+%252815%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbEIc5q_c2icLHJj3KVcjhi-EgKbm_UcH05pAx-2cZK6ZNR6s2XXkX0Jqq6t-7XDZLXPOTf_SMihPR3DZHVqATRuH89oNelIS3ofuGPAbZrrEA81rXaM3nFGCKxNmsuXO59k_0uQ-ee8Z5/s400/Cornwall+-+Recursion+for+Beginners+%252815%2529.png" width="400" /></a></div>
<br />
<br />
<h3>
Randomness and Recursion</h3>
There is no reason we can't combine different ideas with recursion, <b>randomness</b> for example.<br />
<br />
We looked at a pattern where the next level of detail could be one of two options, chosen at random when drawn.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3KP7HPOO9uNma-awN7XpGGOkD3tE1EN8kBPO3Py97C_W-k84312XJUiDed6cqDpKfFe91OpMVnKwcpg21zSa5ZMyXjfRPHEq4nXIfIr_QmRhxO2VJStPdqUmnvO16EHeq637omKjVNAwZ/s1600/Cornwall+-+Recursion+for+Beginners+%252816%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3KP7HPOO9uNma-awN7XpGGOkD3tE1EN8kBPO3Py97C_W-k84312XJUiDed6cqDpKfFe91OpMVnKwcpg21zSa5ZMyXjfRPHEq4nXIfIr_QmRhxO2VJStPdqUmnvO16EHeq637omKjVNAwZ/s400/Cornwall+-+Recursion+for+Beginners+%252816%2529.png" width="400" /></a></div>
<br />
You can see the main pattern is composed of squares, but the next level of detail has squares either top-left to bottom-right, or top-right to bottom-left.<br />
<br />
The results are different every time the code is run.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9e5fOWUTb7Qgi_Cbi_lkaET0x4CDNU9akXjlx94MHX1h3Zzdl2HlYXA6kq0OnFRkREPVbFTbkAV2H1k5GIUI-enODQYgbkqpNxHoeUVwjgy8Cq6aarEuNkw1X5ACzT2u8PGfz0FseoAFZ/s1600/Cornwall+-+Recursion+for+Beginners+%252817%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9e5fOWUTb7Qgi_Cbi_lkaET0x4CDNU9akXjlx94MHX1h3Zzdl2HlYXA6kq0OnFRkREPVbFTbkAV2H1k5GIUI-enODQYgbkqpNxHoeUVwjgy8Cq6aarEuNkw1X5ACzT2u8PGfz0FseoAFZ/s400/Cornwall+-+Recursion+for+Beginners+%252817%2529.png" width="400" /></a></div>
<br />
You can explore the simple code yourself ere:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/658450">https://www.openprocessing.org/sketch/658450</a></li>
</ul>
<br />
<br />
<br />
<h3>
Natural Forms</h3>
We then discussed recursive natural forms, taking inspiration from nature itself. We looked at a tree in winter, when its branches are more visible. We noticed that roughly speaking, a tree is made of smaller trees emerging from a branch - a <b>recursive</b> pattern.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixlCDmkCAJ09ewSofItFmFTWSxCBkORV7GRIpmZOQ96CJqHG2hFqKgJqLi9Dk-ijVsB8CQjguvWewbfMn2ztLsnpaAkUpfyUHkh06iueVKz6BsLpMk5x2_XXlF5m0H3mxMsxRKNkVKoDw9/s1600/Cornwall+-+Recursion+for+Beginners+%252818%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixlCDmkCAJ09ewSofItFmFTWSxCBkORV7GRIpmZOQ96CJqHG2hFqKgJqLi9Dk-ijVsB8CQjguvWewbfMn2ztLsnpaAkUpfyUHkh06iueVKz6BsLpMk5x2_XXlF5m0H3mxMsxRKNkVKoDw9/s400/Cornwall+-+Recursion+for+Beginners+%252818%2529.png" width="400" /></a></div>
<br />
We don't have to encode all the details of a real tree, often a simplification is interesting by itself. Here is the simple idea of a tree being defined a s branch with two smaller trees emerging form the end of it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkY7yZe05dmSazl1J4ORZ78EFa5sZoHa4L5DxjnYSm3nTaMjMkvYPsesRFeRxDBGDq2t2KCRTLtZlA1UJ7-1ErGQ6lMHFXVAwRY_7ZWKknUsAJFYaBUmCfl8aHUeQ0EwhNTL_e89gQcIPU/s1600/Cornwall+-+Recursion+for+Beginners+%252819%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkY7yZe05dmSazl1J4ORZ78EFa5sZoHa4L5DxjnYSm3nTaMjMkvYPsesRFeRxDBGDq2t2KCRTLtZlA1UJ7-1ErGQ6lMHFXVAwRY_7ZWKknUsAJFYaBUmCfl8aHUeQ0EwhNTL_e89gQcIPU/s400/Cornwall+-+Recursion+for+Beginners+%252819%2529.png" width="400" /></a></div>
<br />
And of course each of those smaller trees will have a branch with even smaller trees.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7xZxIWbFGiSAkyVmYLoTa2mvXbnwFw_q14GE6fLyfZAZv2ye84pYxlQo0vncyq99MfqHEV2PWppIsawg8naTsFkR0nXwYmlftKsDhE5PJfsTg9Jh0hL2ULqavpjB7hpu9ZK9RcgxUAQzg/s1600/Cornwall+-+Recursion+for+Beginners+%252820%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7xZxIWbFGiSAkyVmYLoTa2mvXbnwFw_q14GE6fLyfZAZv2ye84pYxlQo0vncyq99MfqHEV2PWppIsawg8naTsFkR0nXwYmlftKsDhE5PJfsTg9Jh0hL2ULqavpjB7hpu9ZK9RcgxUAQzg/s400/Cornwall+-+Recursion+for+Beginners+%252820%2529.png" width="400" /></a></div>
<br />
We can encode these ideas using the framework we discussed earlier.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqg47Pft9poJCx8cKLxFrxSyB3EEak1QzUg49PZ_qh4N8QQbJMzjMXSpiwi4sfp2birU6kAK_crqv9StQenHNqReHAwtjPmlt0PTYsd7aauRtNvgrzm4T1bOOy4LFL1zoYQYivCYHNJysx/s1600/Cornwall+-+Recursion+for+Beginners+%252821%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqg47Pft9poJCx8cKLxFrxSyB3EEak1QzUg49PZ_qh4N8QQbJMzjMXSpiwi4sfp2birU6kAK_crqv9StQenHNqReHAwtjPmlt0PTYsd7aauRtNvgrzm4T1bOOy4LFL1zoYQYivCYHNJysx/s400/Cornwall+-+Recursion+for+Beginners+%252821%2529.png" width="400" /></a></div>
<br />
And the results are really rather effective! This rendering does make two further refinements, it reduces the thickness of the branches deeper into the recursion, and also varies the green hue randomly too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI_73CnSlxW93s1xryfgq2PFLDDklZdNp_WKwiiFEiShFv8VCBZ6QGMdHpEr3xARBet6-TNMy8COGmSvReJTGPdmjJ9PjuJWEeYFfhQC4cXqXfbZgwBpYSK6sVeW55fgbjunW_9vSqeDxE/s1600/33_out_tree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI_73CnSlxW93s1xryfgq2PFLDDklZdNp_WKwiiFEiShFv8VCBZ6QGMdHpEr3xARBet6-TNMy8COGmSvReJTGPdmjJ9PjuJWEeYFfhQC4cXqXfbZgwBpYSK6sVeW55fgbjunW_9vSqeDxE/s400/33_out_tree.png" width="400" /></a></div>
<br />
You can explore the surprisingly simple code here:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/642756">https://www.openprocessing.org/sketch/642756</a></li>
</ul>
<br />
The code does use trigonometry because it deals with angles and directions for emerging branches. The maths for this is not that difficult, but too many people have a negative feeling about it from a poor experience at school.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9dlMoyduoehXuu_AqKDSZMVldm0OXNj1KY-fjg_txjXxow6bHn-lfHQOYBgxFdlL5cNZTYcQhcfVSZeamTcX0a6v3XkiH_8dzsN0ECo0LVk9btpp-gOLwuGqYucajVggFbdCdk9o-ETml/s1600/Cornwall+-+Recursion+for+Beginners+%252822%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9dlMoyduoehXuu_AqKDSZMVldm0OXNj1KY-fjg_txjXxow6bHn-lfHQOYBgxFdlL5cNZTYcQhcfVSZeamTcX0a6v3XkiH_8dzsN0ECo0LVk9btpp-gOLwuGqYucajVggFbdCdk9o-ETml/s400/Cornwall+-+Recursion+for+Beginners+%252822%2529.png" width="400" /></a></div>
<br />
I was really pleased that an artist in the group did want to explore trigonometry and we worked through a simple example at the end of the session.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLHgIB7zDNYfhx9QxAG5Z28tepF7xKDoRnPB3mhH3caquLdT2FNW3HzbOL-Avzu9j0mNG_OYZT3JGcZ0yH0iNn8GztgpLfbgEeFHj5EcY3majfVGEn9Aw5qElMvQ-8nYZr4jm5hCLJJOsd/s1600/IMG_20190125_172410-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLHgIB7zDNYfhx9QxAG5Z28tepF7xKDoRnPB3mhH3caquLdT2FNW3HzbOL-Avzu9j0mNG_OYZT3JGcZ0yH0iNn8GztgpLfbgEeFHj5EcY3majfVGEn9Aw5qElMvQ-8nYZr4jm5hCLJJOsd/s400/IMG_20190125_172410-01.jpg" width="400" /></a></div>
<br />
We finished that section by looking at a bubbly recursive pattern developed by a member of the group from the session in London, and discussed how angles and trigonometry were used to place three bubbles on the edge of a bubble, and then smaller ones on those, and so on...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinmpaWhglvsFBbIACZkj_uSBH6iJdegyjzA_rsUQiHHhkO-Lur3ERy0cx-lmADEShi-EJfh30I8TuI6ZBaE_gIKlBj_LByolBopFwmSVwbSpkdZlqNsou_MIk_Jap4p5OyK_ac2BMAXBta/s1600/Cornwall+-+Recursion+for+Beginners+%252823%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinmpaWhglvsFBbIACZkj_uSBH6iJdegyjzA_rsUQiHHhkO-Lur3ERy0cx-lmADEShi-EJfh30I8TuI6ZBaE_gIKlBj_LByolBopFwmSVwbSpkdZlqNsou_MIk_Jap4p5OyK_ac2BMAXBta/s400/Cornwall+-+Recursion+for+Beginners+%252823%2529.png" width="400" /></a></div>
<br />
You can explore the code yourself at:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/658493">https://www.openprocessing.org/sketch/658493</a></li>
</ul>
<br />
<br />
<br />
<h3>
Gallery</h3>
We took some time to have a go at developing recursive patterns ourselves. Here are some examples.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguU_EdygPiajVEYDd7AbKCe3zbdeeiBnu_h18vTtLZqY9z4H3NGbEcCxdO_0uVLNll67trSPg0aO-p2CQ-7LSiwwpFrc4BA0R6pRhMrX3elqvwXIdcAUKDI60xmDuiA4AMlA7zYriXigYX/s1600/Screenshot+2019-01-25+at+17.13.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1196" data-original-width="1596" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguU_EdygPiajVEYDd7AbKCe3zbdeeiBnu_h18vTtLZqY9z4H3NGbEcCxdO_0uVLNll67trSPg0aO-p2CQ-7LSiwwpFrc4BA0R6pRhMrX3elqvwXIdcAUKDI60xmDuiA4AMlA7zYriXigYX/s400/Screenshot+2019-01-25+at+17.13.17.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGo7pzKwLGojMug4wChiDPqW0JPyQV5ExDuyqY4oe7POncxOSP8CxbUQRbxwdKcS65Tnd2VIfm6Tle-58wFXEqRjGj-cwE_PfySVNbGohB-ZqeuEucxr5QLkp7jDDMeEbtfPHXiNSjd95l/s1600/Screenshot+2019-01-25+at+17.15.47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGo7pzKwLGojMug4wChiDPqW0JPyQV5ExDuyqY4oe7POncxOSP8CxbUQRbxwdKcS65Tnd2VIfm6Tle-58wFXEqRjGj-cwE_PfySVNbGohB-ZqeuEucxr5QLkp7jDDMeEbtfPHXiNSjd95l/s400/Screenshot+2019-01-25+at+17.15.47.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjneYVWxbVq0ziRtwNuH4KzgEH4gH0LSG0AdRNjftphCqUYPCM0YlUHas-BhNo0mpJdOwH-i8Clw6hjbnP7aXWDQlSbHyrkOMZJYtmPnYrt3yqA7HaClW1kzFFFRBvGFdWn6RD-0baM5RCB/s1600/Screenshot+2019-01-25+at+17.16.12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjneYVWxbVq0ziRtwNuH4KzgEH4gH0LSG0AdRNjftphCqUYPCM0YlUHas-BhNo0mpJdOwH-i8Clw6hjbnP7aXWDQlSbHyrkOMZJYtmPnYrt3yqA7HaClW1kzFFFRBvGFdWn6RD-0baM5RCB/s400/Screenshot+2019-01-25+at+17.16.12.png" width="400" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCQknrtUvYorUr0bYw7zgK2cCrRL7zZkPlQcavSO4pYuTQjFz0BumkxwqQetP1K8JiaIuStBbsyZ4ggIo1sQ0LLm4-hH6KezQkofEdw3UuCAoI-dCqiqbafB45EDwXC8B9dhvoDdz0MtPu/s1600/Screenshot+2019-01-25+at+17.15.58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1030" data-original-width="1600" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCQknrtUvYorUr0bYw7zgK2cCrRL7zZkPlQcavSO4pYuTQjFz0BumkxwqQetP1K8JiaIuStBbsyZ4ggIo1sQ0LLm4-hH6KezQkofEdw3UuCAoI-dCqiqbafB45EDwXC8B9dhvoDdz0MtPu/s400/Screenshot+2019-01-25+at+17.15.58.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqN9-tQj0PC-jwI5Q5CfBGLc9JWuWzK6g_9P7eNci4FPBdt9bt8RidO0K3zp2uAE2blSMjRzwH9GZUHezMM_JUp_tEE2wHG1kvCmOa_Jv2LWR-p5Unv5xzkNVsEl2gU2D2cWCrxi78fETG/s1600/Screenshot+2019-01-24+at+20.03.58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="676" data-original-width="1004" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqN9-tQj0PC-jwI5Q5CfBGLc9JWuWzK6g_9P7eNci4FPBdt9bt8RidO0K3zp2uAE2blSMjRzwH9GZUHezMM_JUp_tEE2wHG1kvCmOa_Jv2LWR-p5Unv5xzkNVsEl2gU2D2cWCrxi78fETG/s400/Screenshot+2019-01-24+at+20.03.58.png" width="400" /></a></div>
<br />
You can find links to these designs in the meetup <a href="https://www.meetup.com/Algorithmic-Art/events/256648516/">comments</a>. It is interesting how different ideas result in quite unique patterns.<br />
<br />
<br />
<h3>
Growing Code</h3>
As a bonus we looked briefly at using recursion not to grow a pattern, but to grow code that itself draws a pattern!<br />
<br />
We'll look at this idea properly at a future session, but this taster showed that there are no limits to how creative we can be in combining algorithmic ideas, not just combining colours and shapes.<br />
<br />
We looked at turtle code (<b>L</b>=left, <b>R</b>=right, <b>F</b>=forward, etc) which can be used to draw patterns. Some examples are show here. You can see how <b>FRFRFRF</b> draws a square.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlwObyBloa3Tx2aAUvTACVbu0kcEiSUplktWWv7RSLZ-dDdeMiEZAQ9SS-pSln6BaKjrOGJ5KrIrYXiyjWcDLfFEdApQv0Zq_CZRmFQJGYfZ2UdTWpz4ffRN5EP9vEcBSKKohzswYS63lE/s1600/Cornwall+-+Recursion+for+Beginners+%252824%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlwObyBloa3Tx2aAUvTACVbu0kcEiSUplktWWv7RSLZ-dDdeMiEZAQ9SS-pSln6BaKjrOGJ5KrIrYXiyjWcDLfFEdApQv0Zq_CZRmFQJGYfZ2UdTWpz4ffRN5EP9vEcBSKKohzswYS63lE/s400/Cornwall+-+Recursion+for+Beginners+%252824%2529.png" width="400" /></a></div>
<br />
We can use a recursive rule to relate the next generation of the code to a previous one through a simple growth rule. The next picture shows how turtle code <b>FRF</b> is turned into <b>RFLFRRFLF</b> using the rule <b>F>RFLF</b> which mean grow every <b>F</b> into <b>RFLF</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpAJZlpjOIhbzrdHlztME0Nd1yaTbXTRCZ62CTxkEwTalJfl2c42TNU5lKCX67-vsep6lnPPigZd7fBRvg_PxLQC142LVBTTQWrBbHoNzbY9BXKQe8umPMOZq-6yAD8SLn69AX6Sqkl4z2/s1600/Cornwall+-+Recursion+for+Beginners+%252826%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpAJZlpjOIhbzrdHlztME0Nd1yaTbXTRCZ62CTxkEwTalJfl2c42TNU5lKCX67-vsep6lnPPigZd7fBRvg_PxLQC142LVBTTQWrBbHoNzbY9BXKQe8umPMOZq-6yAD8SLn69AX6Sqkl4z2/s400/Cornwall+-+Recursion+for+Beginners+%252826%2529.png" width="400" /></a></div>
<br />
The <b>3</b> instructions of <b>FRF</b> are grown into <b>9</b> instructions. The pattern drawn is an upside down <b>T</b>.<br />
<br />
Growing the code to the next third generation creates <b>21</b> instructions, and an interesting looped pattern.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1wZrYTpPtPD-7zVUlfPcJ_20NED4sS9juHpLm6XBC_T53QvY_7vp1VfEL82zU_7wAdmmMXs9v9XquonYtJRzrVCSC8T_Kg8QQn2jW8EbO45CbAxWYjy1C9Hk9d985PTdT4ea-OO_bhVfP/s1600/Cornwall+-+Recursion+for+Beginners+%252825%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1wZrYTpPtPD-7zVUlfPcJ_20NED4sS9juHpLm6XBC_T53QvY_7vp1VfEL82zU_7wAdmmMXs9v9XquonYtJRzrVCSC8T_Kg8QQn2jW8EbO45CbAxWYjy1C9Hk9d985PTdT4ea-OO_bhVfP/s400/Cornwall+-+Recursion+for+Beginners+%252825%2529.png" width="400" /></a></div>
<br />
Generation <b>5</b> has <b>191</b> instructions, and the pattern is more intricate.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnej_Tm9HT218yhvw6Wj7oe7NmTX01QilIYvpoyQBUm59hXA1Lex7ta8AUic7y0OdC-Yd8iGB1rX5SFLc7zSFmaa7UAkeJE0KqqZiCDyxjNYnNkZJsRShOzOaWwG6jjBopKc4Vvu3hiaXD/s1600/Cornwall+-+Recursion+for+Beginners+%252827%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnej_Tm9HT218yhvw6Wj7oe7NmTX01QilIYvpoyQBUm59hXA1Lex7ta8AUic7y0OdC-Yd8iGB1rX5SFLc7zSFmaa7UAkeJE0KqqZiCDyxjNYnNkZJsRShOzOaWwG6jjBopKc4Vvu3hiaXD/s400/Cornwall+-+Recursion+for+Beginners+%252827%2529.png" width="400" /></a></div>
<br />
Generation <b>16</b> has <b>393,213</b> instructions - a third of a million! And the result is a very detailed design.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy4uklr6W8aH2Icz6Fw70-rigMqeXxdd29bmdLefB5QVeji7-v-ZUpNM7YxqGJ8dVB1XS4xcOy2xKuJXxXhiVMly_9ZUo2CK8yAOc82ouRjc3XijcbmHNC8ue6JkcQnghyphenhyphenTks66daxouTN/s1600/Cornwall+-+Recursion+for+Beginners+%252828%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy4uklr6W8aH2Icz6Fw70-rigMqeXxdd29bmdLefB5QVeji7-v-ZUpNM7YxqGJ8dVB1XS4xcOy2xKuJXxXhiVMly_9ZUo2CK8yAOc82ouRjc3XijcbmHNC8ue6JkcQnghyphenhyphenTks66daxouTN/s400/Cornwall+-+Recursion+for+Beginners+%252828%2529.png" width="400" /></a></div>
<br />
Changing the starting and growth rules results in a drastically diverse range of patterns.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdpWZ64y8hXVrtB89SjyGEW2gWW0TG2G-dqDP6-YLUtQfCJO-9AveMHBFjKp6MPsiiSzE4lLIbevao6NDRmPXxS_F6AKF3xTHzW5KKfF52tSL3Lv0kHFmhiooWye1G025Z8CBGdjhZDVEI/s1600/Cornwall+-+Recursion+for+Beginners+%252829%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdpWZ64y8hXVrtB89SjyGEW2gWW0TG2G-dqDP6-YLUtQfCJO-9AveMHBFjKp6MPsiiSzE4lLIbevao6NDRmPXxS_F6AKF3xTHzW5KKfF52tSL3Lv0kHFmhiooWye1G025Z8CBGdjhZDVEI/s400/Cornwall+-+Recursion+for+Beginners+%252829%2529.png" width="400" /></a></div>
<br />
Here is a recent design I did with the turtle code augmented wit instructions that change colour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_fTdeK2fz_VgR2RuNGNkY37kJu74G8EY1il6LmWVCS6wLjBz-HrmEj3341bc0p5BAENNXbIxaTME-wCaTosmAwxUmvPVRfYcBe5tcAac_AokzsC1tDPpFSivmkF-KlwZLqUDZtH-7RXqB/s1600/36_turtle_12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_fTdeK2fz_VgR2RuNGNkY37kJu74G8EY1il6LmWVCS6wLjBz-HrmEj3341bc0p5BAENNXbIxaTME-wCaTosmAwxUmvPVRfYcBe5tcAac_AokzsC1tDPpFSivmkF-KlwZLqUDZtH-7RXqB/s400/36_turtle_12.png" width="400" /></a></div>
<br />
You can explore the code yourself:<br />
<br />
<ul>
<li><a href="https://www.openprocessing.org/sketch/649660">https://www.openprocessing.org/sketch/649660</a></li>
</ul>
<br />
<br />
<br />
<h3>
Further Reading</h3>
<br />
<ul>
<li><b>Creative Coding Course</b> in easy bite-sized projects, ideal for new and young coders - <a href="https://sites.google.com/view/creative-coding-for-kids/">https://sites.google.com/view/creative-coding-for-kids/</a></li>
<li>Youtube channel introducing creative coding gently for beginners - <a href="https://www.youtube.com/channel/UCO6iBPzIvUdzxcf87BN24FQ/videos">https://www.youtube.com/channel/UCO6iBPzIvUdzxcf87BN24FQ/videos</a></li>
</ul>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOSeInx0sjvvYfmXcm3ZZl27fmZZCu_XAC6PgwsHnlRgjeujDtFLXc331aW6ZLnTAKzvfXZ_hJKGakChMuvwf-FfgKV94eAScJFK9BuXZD7VHogA8Drmn1VNWNhkDpht6FrRwXDeJDMjaB/s1600/IMG_20190124_195600-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1109" data-original-width="1600" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOSeInx0sjvvYfmXcm3ZZl27fmZZCu_XAC6PgwsHnlRgjeujDtFLXc331aW6ZLnTAKzvfXZ_hJKGakChMuvwf-FfgKV94eAScJFK9BuXZD7VHogA8Drmn1VNWNhkDpht6FrRwXDeJDMjaB/s400/IMG_20190124_195600-01.jpg" width="400" /></a></div>
<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-45717587073834639542018-12-17T18:12:00.002-08:002018-12-18T08:55:53.400-08:00Christmas Social - With Painting Robot, Lighting Effects, Pendulum Chaos, And Fractal Game TheoryEarlier we had our last meetup of 2018 and it was a <a href="https://www.meetup.com/Algorithmic-Art/events/253974275/">Christmas Social</a> - no talk or turorial, just a chance for us to just mingle, talk and appreciate a few demonstrations.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwFjX58BEOKSLfVSm5i9goz9Jizpt0E1qbbZQGZ7FX6q1DfJ2wmJYlfjHKQyaEY1FJlFkvV8jZFh3a7SlYq-arOybn0TQTzc8NG07AbF1G4s14ox3UDGyoyRYZpk6gWehKfWdwqhONWCS6/s1600/IMG_20181217_175954-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1025" data-original-width="1600" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwFjX58BEOKSLfVSm5i9goz9Jizpt0E1qbbZQGZ7FX6q1DfJ2wmJYlfjHKQyaEY1FJlFkvV8jZFh3a7SlYq-arOybn0TQTzc8NG07AbF1G4s14ox3UDGyoyRYZpk6gWehKfWdwqhONWCS6/s400/IMG_20181217_175954-01.jpg" width="400" /></a></div>
<br />
It's a reflective time of year and I wanted to thank everyone in our community who has made the success of this group possible, members and speakers, tutorial leaders and helpers, and of course <a href="https://skillsmatter.com/">SkillsMatter</a> too.<br />
<br />
<br />
<h3>
Painting Robot</h3>
We were very lucky to have Jose Salatino fly in from Spain with his robot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ofBloYeKzpOzFR_lcwTY3gwByJ3vFw9FhDt7S_zBRyU8dr67zmfLSqIdFJ9YRq1lJ3nvmBIglKguLgq7-zAXKsK6D4vw7B7mdpN7NC-oN-ijQms88kkp2Sl9bBrDJ1yHwrDR694Gigyl/s1600/IMG_20181217_173332-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1201" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ofBloYeKzpOzFR_lcwTY3gwByJ3vFw9FhDt7S_zBRyU8dr67zmfLSqIdFJ9YRq1lJ3nvmBIglKguLgq7-zAXKsK6D4vw7B7mdpN7NC-oN-ijQms88kkp2Sl9bBrDJ1yHwrDR694Gigyl/s400/IMG_20181217_173332-01.jpg" width="400" /></a></div>
<br />
Jose's robot is unique because it doesn't just draw shapes and fill them with colour like a pen plotter. Instead, it has learned to mix real wet pain, and even refresh the brush with water.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiupE-HJcei8dG7loTgTUfjA2Rsn4HIbB4B-k_oeG8cut6Yxv_k8zCkzJXyRCvoHIuiRKu5rJVU8NDxKOjHuKIBWFj57tAoyCAn6Kdk5PulcGtxC6qUVUaY5cLwu6v9Xg-djUNgnDIb8GsD/s1600/IMG_20181217_173320-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiupE-HJcei8dG7loTgTUfjA2Rsn4HIbB4B-k_oeG8cut6Yxv_k8zCkzJXyRCvoHIuiRKu5rJVU8NDxKOjHuKIBWFj57tAoyCAn6Kdk5PulcGtxC6qUVUaY5cLwu6v9Xg-djUNgnDIb8GsD/s400/IMG_20181217_173320-01.jpg" width="400" /></a></div>
<br />
During the session, the robot gradually built up layers of paint, until the image was almost complete. Jose and his robot attracted a lot of interest from our group, and even from the venue's own staff too!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji0QiYO8oXyGu8pnowVO4g774fDsszs9PqLloTV72DVWWHAJTub9Tx1RSse-jJaxo-6pZ3G42yxJG3iUODviavvhFpF9HfxKtWqTX5ZerG-LyqkbeCFwEsc4zvgp6-kuTjrlNSJjWTL_8K/s1600/IMG_20181217_201259-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1522" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji0QiYO8oXyGu8pnowVO4g774fDsszs9PqLloTV72DVWWHAJTub9Tx1RSse-jJaxo-6pZ3G42yxJG3iUODviavvhFpF9HfxKtWqTX5ZerG-LyqkbeCFwEsc4zvgp6-kuTjrlNSJjWTL_8K/s400/IMG_20181217_201259-01.jpg" width="380" /></a></div>
<br />
The sophistication required of an algorithm as it builds up an image from wet paint, which can mix if applied naively, is significant. The order of shapes and colours itself has to be considered carefully if one paint colour is not to overpower another. If you're a painter, you'll have your own method of applying paint, perhaps you'll apply darker colours first with highlights later. This empathy goes to show how much work has gone into making a painting robot which makes it look easy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsKEyOXqru1y-C1-SOgRbSToD042BRYZnbaJs3ZMKaL5EZkv-Wb2aNbwKCudtKTtWsWehKBRHt5F5AM7XNlPDquW66gx623knk5BZH6PlGqJLrxoSILe7UaVYyszJyo0fwMDjZwyTqCsoq/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsKEyOXqru1y-C1-SOgRbSToD042BRYZnbaJs3ZMKaL5EZkv-Wb2aNbwKCudtKTtWsWehKBRHt5F5AM7XNlPDquW66gx623knk5BZH6PlGqJLrxoSILe7UaVYyszJyo0fwMDjZwyTqCsoq/s400/ezgif.com-optimize.gif" width="400" /></a></div>
<br />
You can find out more about Jose's work here:<br />
<br />
<ul>
<li><a href="http://blog.florsalatino.com/index.php/2018/02/25/video-portrait-painter-robot-project/">http://blog.florsalatino.com/index.php/2018/02/25/video-portrait-painter-robot-project/</a></li>
</ul>
<br />
<br />
<br />
<h3>
Light Effects</h3>
Regular member, speaker and helper Peter has several other interests including building things with hardware and developing domain specific languages.<br />
<br />
He brought along an array of LED's which was built similar to a much larger "theatre-size" structure he made for another project.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsazgbdQQydvS-tii-AjoyDhyphenhyphenLdZSy3zadc2ByL78DHvEpI8OPFvtrFnH0cqoSnS12c6CMDnmUKP-iZXyILRfPEEYleAtC3CPMS2RV_67fdYZWHWeFZdqVbX-KC0-4QlsmeTgWD34uX4OJ/s1600/IMG_20181217_182232-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsazgbdQQydvS-tii-AjoyDhyphenhyphenLdZSy3zadc2ByL78DHvEpI8OPFvtrFnH0cqoSnS12c6CMDnmUKP-iZXyILRfPEEYleAtC3CPMS2RV_67fdYZWHWeFZdqVbX-KC0-4QlsmeTgWD34uX4OJ/s400/IMG_20181217_182232-01.jpg" width="400" /></a></div>
<br />
He demonstrated his domain specific language, controlling the lights to make engaging effects, and his work attracted a lot of interest and participation too!<br />
<br />
We had a short chat and it was clear that in the wider industry, the hardware for event and theatrical lighting is good but the software for controlling it not so good. His domain specific language certainly fills a gap that many others feel.<br />
<br />
<br />
<h3>
Double-Pendulum Chaos</h3>
Hector, a mathematician, is doing some work exploring visualisations of the range of behaviours that a <a href="https://en.wikipedia.org/wiki/Double_pendulum">double-pendulum</a> can have.<br />
<br />
A double pendulum is just a pendulum attached to another. A simple pendulum's motion is fairly simple - it moves from left to right with varying amplitude and speed. A double pendulum can move in this simple way too, but only for small perturbations from its resting hanging position. For staring positions that are further from this we start to see non-trivial behaviour, and mathematical <a href="https://www.youtube.com/watch?v=QXf95_EKS6E" target="_blank">chaos emerges</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7SwM9FgpNsr88XVwIEnQTyWikPyOopIJ1dHPiiZIST7Y7jDED620v5MZkNt4qiU7BcSzEtQCqUHvb7vh-4kC5mCpvigQiNrdHTyEkN9dV82Ab7RUQ3YIz-IlA4R8-sVaufmX2N5ZfZ0TG/s1600/IMG_20181217_203210-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7SwM9FgpNsr88XVwIEnQTyWikPyOopIJ1dHPiiZIST7Y7jDED620v5MZkNt4qiU7BcSzEtQCqUHvb7vh-4kC5mCpvigQiNrdHTyEkN9dV82Ab7RUQ3YIz-IlA4R8-sVaufmX2N5ZfZ0TG/s400/IMG_20181217_203210-01.jpg" width="400" /></a></div>
<br />
One of his works takes a starting position of a double pendulum, the angle of each pendulum, and calculates how it moves for a fixed period of time. It then starts the double pendulum again from the same starting position, but changed by a very small amount. The movement is calculated for the same amount of time. The final position could be very similar to where the first pendulum ended up .. or it could be wildly different .. or somewhere in between.<br />
<br />
This mathematical experiment measures the sensitivity of the double pendulum from that starting position. The starting position is two numbers, the two angles, and these can be mapped to a two dimensional surface.<br />
<br />
Here is a visualisation created in the same way for a similar dynamic system. The animation is jusst varying another parameter. The result is very mesmerising!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB5OTRSXY_m6xm1FA7lY3SLqoQjdZAA5YfNImK6-cAIg9h0OXEhQYZSfoJwYbwGQn7GPUbl4lpv_NQuPJceQyTIgYiqJC9OW6_7cyu-1IwUauNWi3W8bUx8Qd4G99Fps3CnVBhWywvtRyq/s1600/ezgif.com-optimize-2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="600" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB5OTRSXY_m6xm1FA7lY3SLqoQjdZAA5YfNImK6-cAIg9h0OXEhQYZSfoJwYbwGQn7GPUbl4lpv_NQuPJceQyTIgYiqJC9OW6_7cyu-1IwUauNWi3W8bUx8Qd4G99Fps3CnVBhWywvtRyq/s400/ezgif.com-optimize-2.gif" width="400" /></a></div>
<br />
I love this work because it focusses very much on a mathematical phenomenon, and without too many steps uncovers the hidden beauty of the laws which govern the motion of s simple system, a double pendulum that a child can make.<br />
<br />
<br />
<h3>
Game Theory and Fractals</h3>
Ben has also done some innovative work visualising how games play. He considers how simple, and not so simple, games can evolve as players take turns within the rules of the game.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3VvbJnTJg3ixYL9sW4xvu38ZSMR_yGtqU7KHnMA-KdxU0ARp3DOq4XCDm-3Qs1tXM1Z6oCCV3szsrnll5Z3hHN4GTQoBEzlRTER5PklQ4nXbgVT-sRlcKt3pYZTBnSP0gtOMEGXJho4cD/s1600/IMG_20181217_183752-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3VvbJnTJg3ixYL9sW4xvu38ZSMR_yGtqU7KHnMA-KdxU0ARp3DOq4XCDm-3Qs1tXM1Z6oCCV3szsrnll5Z3hHN4GTQoBEzlRTER5PklQ4nXbgVT-sRlcKt3pYZTBnSP0gtOMEGXJho4cD/s400/IMG_20181217_183752-01.jpg" width="400" /></a></div>
<br />
By considering all possible outcomes, for a given depth into the game, he is able to visualise maps of outcomes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcfpc7M9pCxYt25i1PITv_-R-0mGGVck7XPDXkTAtLn9ce5Vd4ujXAlcX9JluuHH17vHQ_OusIspvNRxzlVLw-vb278_u4l1Ix96AkdhOfAwcfwIQVSflajIiPw9wt-retRTOxdICKsdHD/s1600/oxnstate_getcolor-1-1-_38.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="500" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcfpc7M9pCxYt25i1PITv_-R-0mGGVck7XPDXkTAtLn9ce5Vd4ujXAlcX9JluuHH17vHQ_OusIspvNRxzlVLw-vb278_u4l1Ix96AkdhOfAwcfwIQVSflajIiPw9wt-retRTOxdICKsdHD/s320/oxnstate_getcolor-1-1-_38.png" width="320" /></a></div>
<br />
Not only do the visuals show hot-spots and black-spots, advantageous and disadvantageous positions, the visuals are often fractal in nature.<br />
<br />
You can read more about his work here:<br />
<br />
<ul>
<li>Part 1 - <a href="https://www.purplecrane.com/blog/posts/2018/11/02/visualising-games-as-fractals">https://www.purplecrane.com/blog/posts/2018/11/02/visualising-games-as-fractals</a></li>
<li>Part 2 - <a href="https://www.purplecrane.com/blog/posts/2018/12/11/visualising-games-as-fractals-showing-player-choice">https://www.purplecrane.com/blog/posts/2018/12/11/visualising-games-as-fractals-showing-player-choice</a></li>
</ul>
<br />
<br />
<br />
<h3>
Journal Of Mathematics And The Arts</h3>
Mara, editor of the <a href="https://www.tandfonline.com/toc/tmaa20/current" target="_blank">Journal of Mathematics and the Arts</a>, was kind enough to provide copies of their journal for members to have a look at, take a free copy, and hopefully subscribe to.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_F91iYGDnPagh7YFpfeBLzA9np1xBMIPTHkmcNfkmHX5XNFTiuo20oRt9FwDlnOVcjQE65FZTJ-67BfUbUqe-nVVJY7Gp_I-LUv6sz5mf1rRsuEWlKcboD1C6nDBZ7iDyqa0LLaCLmeNG/s1600/IMG_20181217_181136-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_F91iYGDnPagh7YFpfeBLzA9np1xBMIPTHkmcNfkmHX5XNFTiuo20oRt9FwDlnOVcjQE65FZTJ-67BfUbUqe-nVVJY7Gp_I-LUv6sz5mf1rRsuEWlKcboD1C6nDBZ7iDyqa0LLaCLmeNG/s400/IMG_20181217_181136-01.jpg" width="400" /></a></div>
<br />
We're particularly grateful as this gift is of not of small value.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYfZgb3ywEDbkJjE1y8zW-wOu9RWrZF_wRmGMKFWd8KbrC-QUXCIl-JTYuXLB33d8ehWbAdOnTjUKGdiKUi0fCBoJ9aAHSfTC2qKjajLwLV6gja4vIPykOdH-89Oem39xxYrJFHGIfGShS/s1600/IMG_20181217_202526-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYfZgb3ywEDbkJjE1y8zW-wOu9RWrZF_wRmGMKFWd8KbrC-QUXCIl-JTYuXLB33d8ehWbAdOnTjUKGdiKUi0fCBoJ9aAHSfTC2qKjajLwLV6gja4vIPykOdH-89Oem39xxYrJFHGIfGShS/s400/IMG_20181217_202526-01.jpg" width="300" /></a></div>
<br />
<br />
<h3>
Conclusion</h3>
In the almost 2 years we've been running, we've never had a session like this - without a talk or tutorial - so I wasn't sure if it was going to work. Even our hackathons were structured in some way.<br />
<br />
Luckily members seemed to really enjoy the opportunity to just mingle and talk - something we rarely get time to do during our normal events.<br />
<br />
I did discuss with a few people the low numbers of female members, which is is contrast to the normal events which I'm pleased to say welcome a good number of women. The best answer we came up with was that events promoted as socials might mean some people behaving inappropriately and put people off from coming. Something to think more about for me.<br />
<br />
I did take the opportunity to project a relaxing <a href="https://www.youtube.com/watch?v=Uk7OhwxD88w" target="_blank">video</a> of nature with classical piano music on the room's audio .. and it seemed to create a nice effect, just as it did during a previous hackathon.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEjtVy-xO7SnyZfqeO0UZQAZu-8zEj0QhxKKGxwkC2FcEd7IHqtyosSfoQJEhyphenhyphen00ta1ULPTVN39GwqGrm6kcLAJePqxLMBbej7nJZVWwO8oI9HdmZ0Z0VCzz-rvKNzFdlY1WN_iYCwGJBL/s1600/IMG_20181217_203114-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1201" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEjtVy-xO7SnyZfqeO0UZQAZu-8zEj0QhxKKGxwkC2FcEd7IHqtyosSfoQJEhyphenhyphen00ta1ULPTVN39GwqGrm6kcLAJePqxLMBbej7nJZVWwO8oI9HdmZ0Z0VCzz-rvKNzFdlY1WN_iYCwGJBL/s400/IMG_20181217_203114-01.jpg" width="400" /></a></div>
<br />
<b>Thanks for a great 2018 .. and happy coding for 2019!</b><br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com1tag:blogger.com,1999:blog-2044972050276999466.post-39863132768340952402018-11-23T08:13:00.000-08:002018-11-23T09:39:39.156-08:00First Meetup in Cornwall - Beginner's Intro To Creative CodingWith my move to Cornwall, Algorithmic Art will meet in both London and Cornwall on alternating months.<br />
<br />
This month was the first <a href="https://www.meetup.com/Algorithmic-Art/events/254711498/">meetup</a> in Cornwall, hosted by the <a href="https://www.royalcornwallmuseum.org.uk/">Royal Cornwall Museum</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWmRxqcD1ExW93t6D-kLLJeeUTrbfLz-JOIQFxQoqYQgOmGOmNLPAX7kp3jsZUeVRe6s5D3_aI3RQEEQR8WleYGof0NCaircYXpA5zK0lUxZDay5c-wGmP2ogwU0OueZs6QENHjTO6fGMZ/s1600/rcm_FotoSketcher.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="1170" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWmRxqcD1ExW93t6D-kLLJeeUTrbfLz-JOIQFxQoqYQgOmGOmNLPAX7kp3jsZUeVRe6s5D3_aI3RQEEQR8WleYGof0NCaircYXpA5zK0lUxZDay5c-wGmP2ogwU0OueZs6QENHjTO6fGMZ/s400/rcm_FotoSketcher.jpg" width="580" /></a></div>
<br />
Slides with examples of algorithmic art are here: <a href="https://goo.gl/RyjnVb" target="_blank">https://goo.gl/RyjnVb</a><br />
<br />
<br />
<h3>
Algorithmic Art?</h3>
We started with a brief overview of algorithmic art, looking at examples as broad as genetic algorithms creating music, to machine learning text to create verse performed by a robot, from infinitely detailed fractal forms to objects created in code and 3D printed.<br />
<br />
We discussed the central element of algorithmic art being a mathematical or logical recipe rtha is central to the design of the work. For some, the appreciation of algorithmic art is purely the result. For others, it is the, often surprising, beauty and intricacy, hidden in mathematics that's revealed by the artist.<br />
<br />
For some of us, we can't appreciate algorithmic art without appreciating the algorithm!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhayXbLHjdK5qcEZbvGfYlZHql2zt1hgnYFndvQ659DPpL5qKKIBaO3CK8s8azQfpX_qNRlaol_-p3qlLQgR0hjRemjLaL3tr6uJNcxk0YnTYt7gkjQG_P0Br8qYYe5m8M_tHGcoaEtzuFY/s1600/Dnzla2OW0AUULmQ.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1199" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhayXbLHjdK5qcEZbvGfYlZHql2zt1hgnYFndvQ659DPpL5qKKIBaO3CK8s8azQfpX_qNRlaol_-p3qlLQgR0hjRemjLaL3tr6uJNcxk0YnTYt7gkjQG_P0Br8qYYe5m8M_tHGcoaEtzuFY/s400/Dnzla2OW0AUULmQ.jpg" width="398" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://twitter.com/tylhobbs/status/1043961878282739712">https://twitter.com/tylhobbs/status/1043961878282739712</a></td></tr>
</tbody></table>
<br />
<br />
<h3>
Gentle Introduction to Creative Coding</h3>
This first session was intended for artists who may never have coded before.<br />
<br />
It was also a chance to meet local artist fir the first time and start to understand what people are interested in.<br />
<br />
We've previously run beginner's introductions to creative coding with <b>P5js</b> / <b>Processing</b>.<br />
<ul>
<li><a href="https://algorithmicartmeetup.blogspot.com/2017/05/a-gentle-introduction-to-processing.html">https://algorithmicartmeetup.blogspot.com/2017/05/a-gentle-introduction-to-processing.html</a></li>
<li><a href="https://algorithmicartmeetup.blogspot.com/2017/12/a-gentle-intro-to-processing-coding-for.html">https://algorithmicartmeetup.blogspot.com/2017/12/a-gentle-intro-to-processing-coding-for.html</a></li>
</ul>
<br />
<br />
This time we didn't use a set of slides to work through. Instead we set out a broad set of concepts we wanted to work through, and decided to work more closely with the group and only go as fast or slow as needed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiruvQE51rMREhYfG17LYimTJgPxbwhPQAl_DW9a1gubWYqwJdWzT_EGhuisUx7cWgc38kQMpTzar1Mk80zeSUdEau82r1f9DBqS2S2lz7iuqnqz_GX0uVYcxAP9rA5Fa32eSLRdikOznDx/s1600/A+Gentle+Introduction+to+Creative+Coding.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiruvQE51rMREhYfG17LYimTJgPxbwhPQAl_DW9a1gubWYqwJdWzT_EGhuisUx7cWgc38kQMpTzar1Mk80zeSUdEau82r1f9DBqS2S2lz7iuqnqz_GX0uVYcxAP9rA5Fa32eSLRdikOznDx/s400/A+Gentle+Introduction+to+Creative+Coding.png" width="400" /></a></div>
<br />
<br />
<h3>
OpenProcessing Makes Coding Really Easy</h3>
A question arose early about why we weren't using the locally installed Processing software.<br />
<br />
It became clear through the session that <a href="https://www.openprocessing.org/">openprocess.org</a> makes coding really easy for both beginners and non-beginners alike:<br />
<br />
<ul>
<li>there is no need to install any software - we can create code and see the resulting drawings all in a browser, any modern browser</li>
<li>we avoid the hassle of software conflicts and versions - all that's taken care of by <b>openprocessing</b></li>
<li>we don't need to worry about source code files, or html code to contain our <b>p5js</b> code .. we just type code into the web page and click run</li>
<li>sketches can be saved, and then shared by sharing the link, and anyone with a web browser on their computer, laptop, tablet or smartphone can see your work, including your code - that's powerful!</li>
</ul>
<br />
<br />
<h3>
Structure of a Sketch</h3>
We started by looking briefly at the structure of all <b>p5js</b> sketches.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5ojgIx2QYjvSHVGCrkH1m6NmGJMR4uP0Exr-wY3YOOhJjukmuWT_RMTWO6hEhoIA0gfqQLOUjUSBlYM8GngI-naEP-7sIr0ZeSDDyB14quvu-znhqgXGeSfnp-6k8x09lwjZgwmP7dGik/s1600/code_setup_draw_fns.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="783" data-original-width="1600" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5ojgIx2QYjvSHVGCrkH1m6NmGJMR4uP0Exr-wY3YOOhJjukmuWT_RMTWO6hEhoIA0gfqQLOUjUSBlYM8GngI-naEP-7sIr0ZeSDDyB14quvu-znhqgXGeSfnp-6k8x09lwjZgwmP7dGik/s400/code_setup_draw_fns.png" width="400" /></a></div>
<br />
We talked about how the <b>setup()</b> section contains instructions (<b>code</b>) which set up the drawing environment. That would be things like canvas background colour, canvas size, and so on.<br />
<br />
The other section <b>draw()</b> is where we write code that actually does the drawing.<br />
<br />
<br />
<h3>
Making Things Even Simpler With Simple.JS</h3>
As easy as <b>p5js</b> is, and as easy as <b>openprocessing</b> makes working with it .. my experience is that there are still some barriers to newcomers because the language itself isn't designed for young or new learners, and also some of the defaults aren't that friendly.<br />
<br />
So I wrote a library called <b><a href="https://github.com/makeyourownalgorithmicart/simple.js/wiki">simple.js</a></b> which tries to smooth off these hard edges. For example, it provides instructions like <b>circle()</b> and <b>square()</b> which are missing from <b>p5js</b>. It also provides a much much simpler way of doing loops using a <b>repeat()</b> command. Sensible defaults include a visible stroke, background colour, and a yellow fill, as well as turning of he automatic looping of <b>draw()</b> which is only useful for animation.<br />
<br />
We use <b>openprocessing</b> to "switch on" the library, and invoke it in <b>setup()</b> like this.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnnkdFoVfSJ-mpo_utCMgHVx3MVNVi7J9nT9eWKtMkDjJ8qAGh2zAdmYJ65V4xncdAUY2L_jCcABwpTunz3Z23nkSgdOq7vITjQRlYKBjSQvBaAQcXnVlJ9YuNhLj8HcvkY7-o_vHyuFjU/s1600/11_simple_code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1600" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnnkdFoVfSJ-mpo_utCMgHVx3MVNVi7J9nT9eWKtMkDjJ8qAGh2zAdmYJ65V4xncdAUY2L_jCcABwpTunz3Z23nkSgdOq7vITjQRlYKBjSQvBaAQcXnVlJ9YuNhLj8HcvkY7-o_vHyuFjU/s400/11_simple_code.png" width="400" /></a></div>
<br />
This minimal code above, is a good starting point for many projects.<br />
<br />
<br />
<h3>
Shapes, Colours</h3>
We started by asking what the computer code for drawing a circle would be if it was an intuitive language. Most people guessed <b>circle()</b> .. and we tried it. We didn't spend long going over the coordinate system other than to say it starts at the top left, not bottom left.<br />
<br />
Everyone write code to draw a circle, and then experimented with different locations and sizes.<br />
<br />
<b>This is the point at which everyone in the room was a coder!</b><br />
<br />
We then took on the challenge of drawing two different circles. Again the group successfully worked out how to use two <b>circle()</b> instructions.<br />
<br />
Someone asked why the circle was yellow. Rather a answering we progressed to using the <b>fill()</b> instruction to define which colour to use for filling subsequent shapes. We used the named colours, such as '<b>red</b>', '<b>green</b>', '<b>pink</b>', which is a great way to start using colours compared to the RGB method.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXEXsm_lDwqDspLi9C5Gz7StJiUMkIWah6k70Sz10Be7_lOpKGmVUNj6kpeS8nxy6HqWQA5k9jS37bTxLMXcDc_0PINiab2Nd0xfx2AYPRh-FR4ymzCRyCgBJYIV8-v-0ITMNQ_-xYK-Z/s1600/css_colref_table.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="633" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXEXsm_lDwqDspLi9C5Gz7StJiUMkIWah6k70Sz10Be7_lOpKGmVUNj6kpeS8nxy6HqWQA5k9jS37bTxLMXcDc_0PINiab2Nd0xfx2AYPRh-FR4ymzCRyCgBJYIV8-v-0ITMNQ_-xYK-Z/s400/css_colref_table.png" width="400" /></a></div>
<br />
The valid named colours are actually CSS colours used by web developers:<br />
<br />
<ul>
<li><a href="https://www.w3schools.com/cssref/css_colors.asp">https://www.w3schools.com/cssref/css_colors.asp</a></li>
</ul>
<div>
<br /></div>
<div>
I did explain that I had chosen yellow as a sane default in <b>simple.js</b> because the <b>p5js</b> default is a transparent no-colour.</div>
<div>
<br /></div>
<div>
We also tried using a <b>square()</b> instruction just to practise and start to see the comparative similarities between code - a useful skill even for advanced coders.</div>
<br />
<br />
<br />
<h3>
Variables, Randomness</h3>
Having used numbers for location and size, we introduced the idea of using <b>variable</b>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYGX40ZMj3X3uv_dktej2i3Qypl2EoYbNB8ayF2-oqA9Z5BoMWxjqxVyGnuOeK2Djp4NvOVfG6HTor2sXcxNd5aHi7RaAr_OAs7vreeNdH2194kbhReoRUxm13LSIfF4z4Pj0pp9ulZzuI/s1600/variables.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="450" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYGX40ZMj3X3uv_dktej2i3Qypl2EoYbNB8ayF2-oqA9Z5BoMWxjqxVyGnuOeK2Djp4NvOVfG6HTor2sXcxNd5aHi7RaAr_OAs7vreeNdH2194kbhReoRUxm13LSIfF4z4Pj0pp9ulZzuI/s400/variables.png" width="400" /></a></div>
<br />
The picture above illustrates a good way of thinking about variables. Instead of using the number <b>10</b>, we put it inside a box called <b>x</b>, and then use <b>x</b> instead of the number.<br />
<br />
This might not be useful for very simple code, but for more interesting code, we can generalise a problem by using variables instead of specific numbers. You can imagine a complex drawing of many parts, all of which depending on a <b>size</b> variable. We only need to change the <b>size</b> variable once and the while drawing is correctly rescaled. We could have used the name <b>banana</b> but <b>size</b> is more descriptive.<br />
<br />
We created variables <b>x</b> and <b>y</b> and used these in the circle instruction instead of actual numbers for location.<br />
<br />
We then introduced a big idea - <b>randomness</b>. Instead of setting <b>x</b> and <b>y</b> to specific numbers, we used <b>randomNumber()</b> to get our computers to randomly choose a number from a range. For example <b>var x = randomNumber(0, 800)</b> will choose a number between <b>0</b> and <b>800</b> and put that inside the variable <b>x</b>.<br />
<br />
We ran our code and found the circle was drawn at different place to someone else's code. Running the code again results in a different location again. The code is choosing a random number every time the code is run.<br />
<br />
As an exercise, the group tried to make the size of the circles random. Everyone got that working to great satisfaction!<br />
<br />
<br />
<h3>
Functions, Repetition</h3>
We the moved onto a more advanced topic - that of packaging useful code to it can be reused. These are called <b>functions</b>.<br />
<br />
We decided our code which draws a circle of random size at a random location was pretty neat. So we looked at how to package it so it could be used again and again. A fun part of doing that is giving the packaged code a name. I called mine <b>blob()</b>!<br />
<br />
We saw how we can call our code simply by using its name, in my case <b>blob()</b>. More importantly we saw how calling <b>blob()</b> twice, or even four times, calls the code four times. We started to see the benefits of functions - we didn't need to write the all the code that randomly chooses a location and size and draws the circle four times - we just called blob four times.<br />
<br />
I then set the challenge of drawing <b>400</b> circles!<br />
<br />
We talked about not writing all the code <b>400</b> times, and we also said it wouldn't be good to write <b>blob()</b> <b>400</b> times either!<br />
<br />
We know computers are good at repeating things, and they are fast, and don't get bored. And this is why many coding languages make it easy to repeat instructions.<br />
<br />
We used the <b>repeat()</b> instruction to repeatedly run code In my case it was <b>repeat(400, blob)</b> which calls <b>blob()</b> <b>400</b> times.<br />
<br />
The simplicity and power of <b>repetition</b> started to become very apparent! And the resulting 400 circles on the canvas were pretty cool too!<br />
<br />
Finally we introduced the ability to randomly pick a colour from a list, a colour palette, and use that to fill each circle.<br />
<br />
The results were impressive and a great conclusion to the session!<br />
<br />
Here's one example:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtAO6PaSHW9PrqPLGeabgJ-hvlwT7GWSyPMSq-10A7q5Tyq8-y-2O3jVrb9IQkR1NVB9dnGxbLPxP5OvLYtkxTf97nngCX-Ex2xBkAfyHMvrT-FDMFyE3saji3DQ2GprrpK-Kt1PK0vbxh/s1600/algoart_cornwall2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1209" data-original-width="1600" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtAO6PaSHW9PrqPLGeabgJ-hvlwT7GWSyPMSq-10A7q5Tyq8-y-2O3jVrb9IQkR1NVB9dnGxbLPxP5OvLYtkxTf97nngCX-Ex2xBkAfyHMvrT-FDMFyE3saji3DQ2GprrpK-Kt1PK0vbxh/s400/algoart_cornwall2.png" width="400" /></a></div>
<br />
And another:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxxA2bFWQpnhWFaaZLBPD5NorYioEpB6HFmh_GzfML5Zv0lC-3n5xLgtc59j_W-zGF6yPDPJMndP4vSoM7juEaXQixm4QlfCn7FlzYqS87gxQ_zWzdIxQn5Ej49I-K7XNQ66yFXTxws2XZ/s1600/algoart_cornwall.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1047" data-original-width="1455" height="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxxA2bFWQpnhWFaaZLBPD5NorYioEpB6HFmh_GzfML5Zv0lC-3n5xLgtc59j_W-zGF6yPDPJMndP4vSoM7juEaXQixm4QlfCn7FlzYqS87gxQ_zWzdIxQn5Ej49I-K7XNQ66yFXTxws2XZ/s400/algoart_cornwall.png" width="400" /></a></div>
<br />
<br />
<h3>
Conclusion</h3>
The class was quite full and everyone seem to enjoy the session. I was concerned that the already-coders might be bored but they said they weren't.<br />
<br />
Most importantly, the first time coders all seemed enthused and weren't daunted by the idea of coding.<br />
<br />
And best of all, some said they were inspired to continue!<br />
<br />
I did let the group know that even in this short session they had actually covered quite a few computer science and programming concepts - the idea of code structure, variables, functions, repetition, and generalisation.<br />
<br />
<br />
<h3>
Resources</h3>
<ul>
<li><b>Creative Coding for Kid</b>s - <a href="https://sites.google.com/view/creative-coding-for-kids/">https://sites.google.com/view/creative-coding-for-kids/</a></li>
<li><b>P5js Reference</b> - <a href="https://p5js.org/reference/">https://p5js.org/reference/</a></li>
</ul>
<br />
<ul>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiW4BvCI1O0ly6LGFeBf7LSLzLLfi0gLo04oPUQIxlXA0EWJsPG5WAaROF5CxpY970Nlv3DVO40NiCy4kvgfl-wjKZy7RH7SnKYk_Q4ruWZKI4X8_uaMfTqEmSBg8fAJUCUmApaOPU-NdBH/s1600/algorithm_and_art_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="952" data-original-width="1600" height="343" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiW4BvCI1O0ly6LGFeBf7LSLzLLfi0gLo04oPUQIxlXA0EWJsPG5WAaROF5CxpY970Nlv3DVO40NiCy4kvgfl-wjKZy7RH7SnKYk_Q4ruWZKI4X8_uaMfTqEmSBg8fAJUCUmApaOPU-NdBH/s640/algorithm_and_art_2.png" width="580" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-33537525341767252142018-10-24T07:39:00.001-07:002018-10-25T05:31:14.704-07:00Automata, Chaos and Emergent BehaviourThis month's <a href="https://www.meetup.com/Algorithmic-Art/events/253943298/">meetup</a> was an introduction and tutorial by <a href="https://skillsmatter.com/legacy_profile/peter-marks#overview">Peter Marks</a> on automata, chaos and emergent behaviour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz25ZvvdOkQYX_AzT3WiKkVacKxp2-GDii6Cqgr4vom1YlBVrqknoGTkZ1ARf_YVtC8bsJDQ4VV0jew-0LVPme3SMQm5HhtPI3x4LEEKJzP6Z7ew2qm6ZY9LXYOerEms5P2jhggIsfcXIl/s1600/attractor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1120" data-original-width="1600" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz25ZvvdOkQYX_AzT3WiKkVacKxp2-GDii6Cqgr4vom1YlBVrqknoGTkZ1ARf_YVtC8bsJDQ4VV0jew-0LVPme3SMQm5HhtPI3x4LEEKJzP6Z7ew2qm6ZY9LXYOerEms5P2jhggIsfcXIl/s400/attractor.png" width="400" /></a></div>
<br />
Tutorial code examples and reference links are at <a href="http://art.spluko.com/ace/">http://art.spluko.com/ace/</a>.<br />
<br />
<br />
<h3>
Key Themes</h3>
Rather than spend a long time trying to define the rather abstract idea of <b><a href="https://en.wikipedia.org/wiki/Automata_theory">automata</a></b>, Peter decided to briefly introduce it as <b>a thing which evolves by following simple rules</b>, and to develop the idea during the talk.<br />
<br />
The word <b>state</b> is used to describe the current state of these "things". Again, this is an abstract idea, and could mean one of many things - state could be location, or colour, or size, or how healthy a thing is feeling.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD6WNdgG9zwzlTOWqBvfqwF1WdyXyaJyH7fzu8pn-Fs55z6X6JKtWYExKMhqzH5oWAHmhF-fKPDjeMfPaV5sBwO5VpyhU-gfMCNKaTgW_BPfbGc7PWCFW3O8Kzq3YGY0gua16D5A-Y2eXs/s1600/automata_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="837" data-original-width="1600" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD6WNdgG9zwzlTOWqBvfqwF1WdyXyaJyH7fzu8pn-Fs55z6X6JKtWYExKMhqzH5oWAHmhF-fKPDjeMfPaV5sBwO5VpyhU-gfMCNKaTgW_BPfbGc7PWCFW3O8Kzq3YGY0gua16D5A-Y2eXs/s400/automata_0.png" width="400" /></a></div>
<br />
These "things" could be pretty much anything, which gives us a lot of creative opportunities, rather than a cause for discomfort.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDMAZLnWykVC-ZEvOmjgY636NJxq7fAG5Pg7Py9smctUIwIR6a0t6JWJ-eNrJszGCldum9j42Tu66ZuQg5yHb7ycczI_gOQAqgGieNyIiXZrkh4mgNKMBWbL3KFmem1tptS8YdV6tYMRv7/s1600/IMG_20181022_191935-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1198" data-original-width="1600" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDMAZLnWykVC-ZEvOmjgY636NJxq7fAG5Pg7Py9smctUIwIR6a0t6JWJ-eNrJszGCldum9j42Tu66ZuQg5yHb7ycczI_gOQAqgGieNyIiXZrkh4mgNKMBWbL3KFmem1tptS8YdV6tYMRv7/s400/IMG_20181022_191935-01.jpg" width="400" /></a></div>
<br />
Peter set out the key themes we would explore during this journey through automata and their behaviour.<br />
<div>
<br /></div>
<ul>
<li><b>Iteration</b> - the repeated application of rules, often mathematical rules</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMXX5P4VXyRHXGCU6pJUepj6gO4UuEWdlhQR2LBmozqqtsoeVqN11KIzAYN6h6_nI8ZcwN81f-q8_Z768TqKphp_J94DGUIvmieGJjqC7hkBUMe6QRUVL8N3j_2JLDcAvD22F3iOImljgv/s1600/automata_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="837" data-original-width="1600" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMXX5P4VXyRHXGCU6pJUepj6gO4UuEWdlhQR2LBmozqqtsoeVqN11KIzAYN6h6_nI8ZcwN81f-q8_Z768TqKphp_J94DGUIvmieGJjqC7hkBUMe6QRUVL8N3j_2JLDcAvD22F3iOImljgv/s400/automata_1.png" width="400" /></a></div>
<br />
<ul>
<li><b>Multiplicity</b> - Creating and evolving many automata. </li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmJD2h4oYrFMbroDkwl-RYGR6oy12RGCoXdtaiedOxegPvWorUFfan8FGG5pRK1DRofy0OzR2ewICDDMvMaTyubTtz8zdE5sBC35Q8NYsyUMnl2DAwrfVEsPumLeK6Md-EDirmroKHs62x/s1600/automata_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="837" data-original-width="1600" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmJD2h4oYrFMbroDkwl-RYGR6oy12RGCoXdtaiedOxegPvWorUFfan8FGG5pRK1DRofy0OzR2ewICDDMvMaTyubTtz8zdE5sBC35Q8NYsyUMnl2DAwrfVEsPumLeK6Md-EDirmroKHs62x/s400/automata_2.png" width="400" /></a></div>
<br />
<ul>
<li><b>Interaction</b> - Allowing the evolution of automata to depend on other automata, encoded again as the simple rules that define their next state.</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheDkufKyblhribMA1h84lQWRRrB2UmRFy_IOxm9_OtzqwUQH7OcyykMz4rA6zjCmHofwiV8OlXld9VaWq6XrbWnytgWDXgJpmYxjXeBMqZ03vpaXF1FRZi25NwQ6AQRKJACVsPh5w98Hgf/s1600/automata_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="837" data-original-width="1600" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheDkufKyblhribMA1h84lQWRRrB2UmRFy_IOxm9_OtzqwUQH7OcyykMz4rA6zjCmHofwiV8OlXld9VaWq6XrbWnytgWDXgJpmYxjXeBMqZ03vpaXF1FRZi25NwQ6AQRKJACVsPh5w98Hgf/s400/automata_3.png" width="400" /></a></div>
<br />
<br />
<h3>
Simple Example</h3>
Peter presented a simple example to illustrate the abstract idea of an automaton. He used a javascript <b>class</b> to define an <b>object</b>, the 'thing" which we will consider an automaton.<br />
<br />
The automaton was named a Circle in his code, and it had two bits of state - a colour and a size. That's all that's needed to define a simple automaton - but we can't see it. We can add capabilities to this automaton to make it visible. Peter added a javascript class method to draw this Circle object, and another to evolve its state. Drawing takes into account the automaton's state - colour and size.<br />
<br />
The evolution is simple. Both colour and size are incremented at each step, and reset to a small value if they reach an upper limit, to prevent them from growing ever larger. Repeated application of these simple rules is the idea of <b>iteration</b> we set out above.<br />
<br />
This all sounds like a lot of words for what is essentially doing simple things - but we're framing it in the context of automata.<br />
<br />
Here is this simple automaton evolving - both in size and colour. The code is online at <a href="https://codepen.io/spluko/pen/WaZxyM">https://codepen.io/spluko/pen/WaZxyM</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://codepen.io/spluko/pen/WaZxyM" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="342" data-original-width="600" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWpVbblF_zoGglJSkltuwTt62vydJIm5SvZn_8kuHjFXoA6fVKfuJzG3oio9j_uNKOAjG1-xpeY2ug2NgZv_m09G_DtvE6km_P3wb7wBKvhE2ohDAPPpZ_8OG0ver_72TkKdk84kjIWEqi/s400/a_circles.gif" width="400" /></a></div>
<br />
<br />
<h3>
More Than One Automaton</h3>
Peter then progressed to simulating more than one automaton. This is the idea of <b>multiplicity</b> we listed above.<br />
<br />
Peter created <b>300</b> individual automata. Each of these <b>300</b> <b>Particles</b>, as he called them in code, have state and a way to evolve that state. A Particle was given two bits of state - a <b>position</b> and a <b>velocity</b>.<br />
<br />
The <b>position</b> is used to determine where each Particle is drawn, and the <b>velocity</b> is used to determine how the position changes over time, using simple school-level physics. To make the simulation a little more realistic, gravity was also used to adjust a particle's velocity. You'll remember from school that gravity is a force, which directly affects velocity, which in turn affects position.<br />
<br />
If school physics isn't exciting you, don't worry - the main point is having multiple automata, each evolving their state according to simple rules.<br />
<br />
The following shows how 300 Particles move according to their own velocity and also the efffect of gravity. The code is online at <a href="https://codepen.io/spluko/pen/vVeJeW">https://codepen.io/spluko/pen/vVeJeW</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://codepen.io/spluko/pen/vVeJeW" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="279" data-original-width="600" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglp4VmkltOz0RpzhYIYxR_fIvaBm8OMSSiTAs5dWHaH1Mh1QGqOg7tdG9_WYJ6l0KWdidOK13d1RolENTG9vvrZu4Y8lkLC2yVRh1pBZp5wJJl_zF5uG5BMT9BVfuL-gve34HWJrsHdtUf/s400/a_particles.gif" width="400" /></a></div>
<br />
That is a rather nice fireworks effect!<br />
<br />
Peter developed these simple simulations, for example to enhance the rules so the automata bounce off the edge of the canvas. You can find the code at <a href="http://art.spluko.com/ace/">http://art.spluko.com/ace/</a>.<br />
<br />
<br />
<h3>
Chaos</h3>
Before proceeding to illustrate interaction between automata, Peter demonstrated <a href="https://en.wikipedia.org/wiki/Chaos_theory">numerical chaos</a>.<br />
<br />
Intuitively, we expect simple rules to generate simple behaviour. But in fact, some simple schemes result in apparently random and apparently unpredictable behaviour - chaos. Strictly speaking, numerical chaos is not random. The behaviour of a chaotic thing can be calculated. The key point is that it is not possible to predict future behaviour by following a trend - the behaviour is too erratic. Furthermore, two chaotic systems that have very very similar state, will diverge very quickly. Chaotic systems are very sensitive to initial state - and this is basis for the very common <a href="https://en.wikipedia.org/wiki/Butterfly_effect">butterfly-effect</a> analogy.<br />
<br />
Peter's example of numerical chaos was very simple - simply taking a number and multiplying it by a large number, and then taking a modulus (remainder after division). The resulting number are very hard to predict as they follow no obvious pattern. In fact this scheme is the basis for many random number generators in computers. You can see an illustration of this randomness at <a href="https://codepen.io/spluko/pen/bmYjLg">https://codepen.io/spluko/pen/bmYjLg</a>.<br />
<br />
A more interesting simulation is creating automata which have a simple number as their state. The rule for evolution is simply to use that number to calculate another number to become its state. That calculation is the method for creating apparently random chaotic sequences above. As the automata evolve, these chaotic sequences can be used to define curves - which end up looking like scribbles.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://codepen.io/spluko/pen/dqLOGg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="274" data-original-width="600" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD-gWOcBxr94KRtP0at3HVw-aioalrR9HXihkxNue7ETCuq4iyGPOnVJzcm9BCnQINTGIFDxoQCssPMQfhmM0SQIEf4xIH_O0zQ8-Q3DzscJQKTlMyru8SH6J8svCbDhWkinLNQXXyu5ZP/s400/a_scribble.gif" width="400" /></a></div>
<br />
You can find the code at <a href="https://codepen.io/spluko/pen/dqLOGg">https://codepen.io/spluko/pen/dqLOGg</a>. The effect above is achieved by, in effect, darkening the canvas before drawing the next curve. Repeating this has the nice effect of making previous curves slowly disappear.<br />
<br />
<br />
<h3>
Interaction</h3>
Peter then introduced the final idea of <b>interactions</b> between automata. Up to now they've been evolving independently, each unaware and unaffected by other automata in the simulation. The slight exception to this was the balls bouncing off the edge of the screen - they took the environment into account as they moved.<br />
<br />
Peter again implemented simple school physics to model the position and velocity of each automaton, drawn as balls. The rules for evolving the state are the same simple ones we saw before, position is changed according to velocity. In addition, a check for collision is made between balls and the edge of the canvas. Bouncing off the edge is relatively simple, the velocity is reversed. Balls colliding with each other also transfer their momentum according to school physics. We won't go into the details here as the main idea is interactivity, not a <a href="http://archive.ncsa.illinois.edu/Classes/MATH198/townsend/math.html">class</a> on newtonian physics.<br />
<br />
The following shows the rather satisfying, and also surprisingly realistic, simulation of bouncing balls. They start off as a simple <a href="https://en.wikipedia.org/wiki/Newton%27s_cradle">Newton's Cradle</a>. In theory the cradle would continue with its regular predictable movement forever. This simulation breaks down into chaos because one of the balls has its initial position shifted by a tiny tiny 1e-13 units. This shows how sensitive the system is to initial conditions. The code is at <a href="https://codepen.io/spluko/pen/wYvMzW">https://codepen.io/spluko/pen/wYvMzW</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://codepen.io/spluko/pen/wYvMzW" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="374" data-original-width="600" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhI2tqbhLAjr8wYk0HqT6P6devl0Ge-zW3Gapd5k0BQW3HzM5DdL0Gk1NKvTRWnjPAaUdo_prPV9ij9nzXOaZT23_kE7X7fv4gfOPKCo5Mza5jLZ3BvwMTZadtXPhgOgt_meVzFZJcz37k/s400/a_bounce.gif" width="400" /></a></div>
<br />
This completes the key ideas of automata as abstract "things" having state which evolves according to simple rules, iteration, multiplicity, and interaction, with a nice detour looking at chaos.<br />
<br />
<br />
<h3>
Further Examples</h3>
Peter presented further examples of automata which better demonstrate how sophisticated the visual rendering of automata behaviour can be.<br />
<br />
The following demonstrates the evolution of particles, determined by simple mathematical rules using only sine and cosine functions. The code is at <a href="https://codepen.io/spluko/pen/QZmwyp">https://codepen.io/spluko/pen/QZmwyp</a>. Experiment by changing the parameters <b>A</b>, <b>B</b>, <b>C</b> and <b>D</b> in the code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://codepen.io/spluko/pen/QZmwyp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="422" data-original-width="600" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBQyAUMebu7ppXsoOnxAXn-NACjPph1TyGeU7t1vPhaZ0QiIM_CBOFA9FZUC_z8HwlNHZt9sjFntt1tKry2_PlMK4LSunwT7ZymG-OznaPv6CK3K72SdhQAMFuPhnzzn222oUgD0eeoEcH/s400/a_dejong.gif" width="400" /></a></div>
<br />
You can read more about these <b>De Jong</b> attractors <a href="http://www.complexification.net/gallery/machines/peterdejong/">here</a>, <a href="http://paulbourke.net/fractals/peterdejong/">here</a> and <a href="http://www.algosome.com/articles/strange-attractors-de-jong.html">here</a>.<br />
<br />
It is worth thinking a little more about this example. We have automata which follow very simple rules, yet their paths are chaotic. But out of that chaos appears a definite pattern - the <b>emergence</b> of order out of chaos.<br />
<br />
Peter also extended the previous colliding balls simulation to include <b>repulsion</b> when balls are too close. This has analogies in atomic physics where atoms can attract but then repel when they get too close. You can see the code at <a href="https://codepen.io/spluko/pen/GYOwXo">https://codepen.io/spluko/pen/GYOwXo</a>. In this example, the balls surprisingly arrange themselves into a circle because<br />
<br />
A very compelling example of automata interacting is when the rules are similar to how flies or birds might adjust their flights in response to their neighbours. These flies <a href="http://www.vergenet.net/~conrad/boids/pseudocode.html">behave</a> as follows:<br />
<br />
<ul>
<li>each one tries to fly towards the centre of mass of neighbouring boids</li>
<li>they try to avoid getting too close to other flies</li>
<li>they try to match the velocity of their neighbours</li>
</ul>
These are very simply rules, and they don't seem wrong if applied to birds of flies.<br />
<div>
<br /></div>
<div>
The resulting motion is pleasantly surprising <a href="http://www.cs.toronto.edu/~dt/siggraph97-course/cwr87/">flocking</a>.<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://codepen.io/spluko/pen/ZqRyaE" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="383" data-original-width="600" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRfFoikShuFtqanOpxneIf6Wfg5c9mZtRxm5eKbE-32yU5vrSNtvwbd3TYz-vYifr_IGvErum1INrTxpkXO0zEqZbsuPFh3L8Zoa8c8hHoZkMY_EnISztYT8r9hpqca4AEn6attHZk0oAs/s400/a_flocking.gif" width="400" /></a></div>
<br />
You can find the code at <a href="https://codepen.io/spluko/pen/ZqRyaE">https://codepen.io/spluko/pen/ZqRyaE</a>.<br />
<br />
<br />
<h3>
Conclusion</h3>
Peter succeeded in explaining automata as an intentionally abstract concept of "things" with state, which evolves through the repeated application of simple rules. He also set out and illustrated the key ideas for simulating automata:<br />
<br />
<ul>
<li>iteration</li>
<li>multiplicity</li>
<li>interaction</li>
</ul>
<div>
<br /></div>
<div>
Speaking to a few attendees, the feedback was really positive, indicating a desire for more sessions covering ideas and concepts.</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTW3mGkMO6BTQkMv2h7NuOO8H965dm04xq4rI3Gq1H1T3UGrCM_h4HzYP_OW8L2HVVyX6PqghYmUG-C5LKySumUp1wjcJzH1I7AK_l8EfqCQ6zL4m3JHecLK4vCzeRvkvLvbpzQtK8R48a/s1600/IMG_20181022_190011-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTW3mGkMO6BTQkMv2h7NuOO8H965dm04xq4rI3Gq1H1T3UGrCM_h4HzYP_OW8L2HVVyX6PqghYmUG-C5LKySumUp1wjcJzH1I7AK_l8EfqCQ6zL4m3JHecLK4vCzeRvkvLvbpzQtK8R48a/s400/IMG_20181022_190011-01.jpg" width="400" /></a></div>
<br />
<br /></div>
</div>
Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-7298035299964970242018-08-21T13:53:00.001-07:002018-08-21T13:54:20.653-07:00Creative Uses for Not Quite Random NoiseThis month we looked at <a href="https://www.meetup.com/Algorithmic-Art/events/252971210/">creative uses for not quite random noise</a>, including a brief insight into how Perlin noise works.<br />
<br />
Noise is an important algorithm for digital artists, 3d designers and is used widely in visual effects.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1L_97XfTSmPmLGQ4gRdufsAYIBwRRpndlOX9EHBS00Sw4L0BpksA1jUehei2TOaBX3NP0_CRmXvoRUkKP4nqwhOVU5CTmfPCzT_beP8xqwqkim7KpvVg89SLPYBDUtOwdsAAEW8JjoUgo/s1600/Screen+Shot+2018-08-21+at+15.31.11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1L_97XfTSmPmLGQ4gRdufsAYIBwRRpndlOX9EHBS00Sw4L0BpksA1jUehei2TOaBX3NP0_CRmXvoRUkKP4nqwhOVU5CTmfPCzT_beP8xqwqkim7KpvVg89SLPYBDUtOwdsAAEW8JjoUgo/s400/Screen+Shot+2018-08-21+at+15.31.11.png" width="400" /></a></div>
<br />
This month there was no video recording of the talk, so this blog will be a little more narrative than usual.<br />
<br />
The slides are at <a href="https://goo.gl/eYgqq6">https://goo.gl/eYgqq6</a> and contain links to code and further references.<br />
<br />
<br />
<h3>
Motivation - When Random Isn't Useful</h3>
We started by looking at a very simple landscape.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcOEaSEAs0wvPN8tyvFcWr0h1CTDtPrZg4HzzUMMr3zuvMCvMwgf0oafVQuKgzp0BvnBfZAbx3DWyAHtv6AQPfv8atDFMItsVpcD5MlCqjf2yW-2v0PEFThPyWtnpMczxsKjOilpYnLocS/s1600/not_quite_random_noise-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcOEaSEAs0wvPN8tyvFcWr0h1CTDtPrZg4HzzUMMr3zuvMCvMwgf0oafVQuKgzp0BvnBfZAbx3DWyAHtv6AQPfv8atDFMItsVpcD5MlCqjf2yW-2v0PEFThPyWtnpMczxsKjOilpYnLocS/s400/not_quite_random_noise-3.png" width="400" /></a></div>
<br />
We asked ourselves how we could generate such a landscape using our computers. An initial suggestion is to use random numbers for the height (altitude) of each part of the terrain. That's not an entirely bad suggestion.<br />
<br />
We looked at an example of heights created by purely random numbers. The results didn't look very realistic.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn2VwT1lZQntmlwnbKteMYundz-EjyYU1z7p412js1DmIL-VZaluF3dUlyb63xiet4erIH9crckWqcpNjQYOHVixj5WXkQK-ay3efUhv0sZbyzigSHz6nDTWa4n1G8Dv149w8qqus0E7it/s1600/not_quite_random_noise-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn2VwT1lZQntmlwnbKteMYundz-EjyYU1z7p412js1DmIL-VZaluF3dUlyb63xiet4erIH9crckWqcpNjQYOHVixj5WXkQK-ay3efUhv0sZbyzigSHz6nDTWa4n1G8Dv149w8qqus0E7it/s400/not_quite_random_noise-2.png" width="400" /></a></div>
<br />
We discussed what would need to be improved to make the terrain more like a natural landscape. The main idea was that the jump between successive values was too high, and a more realistic landscape would moderate the changes. In other words, the jump up or down between consecutive values wouldn't be too large.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg92Oh8KqFWpN1VdeoC6oqs0ydsTtbmvkMZAljMSgovoamz7ALcmjfg0VSc-WcjrUZscZ9tfwSY8b_lB0ca5KN1UoSJMJ4t0f6ZMDQiZ_DLE1uLGnNsrbNrQWgHAXq2fFttscQmM3VkZxVK/s1600/not_quite_random_noise.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg92Oh8KqFWpN1VdeoC6oqs0ydsTtbmvkMZAljMSgovoamz7ALcmjfg0VSc-WcjrUZscZ9tfwSY8b_lB0ca5KN1UoSJMJ4t0f6ZMDQiZ_DLE1uLGnNsrbNrQWgHAXq2fFttscQmM3VkZxVK/s400/not_quite_random_noise.png" width="400" /></a></div>
<br />
This is a problem that something called <b>noise</b> solves. It is random, but no so random, because the values vary more smoothly. Noise values are not independent of the values before and after them, unlike purely random numbers which are totally independent of each other.<br />
<br />
The results were much more realistic.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpXLC96Jkmif6Q8t5bViDm7P7BXxnlQFcliMTDVZRbbiILVOWGbuSS_yhC8S4_zEiqM7aEKnBx2vZRPiP3EyJ2kL38wkFX3NEOGVqjqID7cPNhlNMDmBZZl9XtBNXf-RQct0JMGfWkUFlg/s1600/not_quite_random_noise-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpXLC96Jkmif6Q8t5bViDm7P7BXxnlQFcliMTDVZRbbiILVOWGbuSS_yhC8S4_zEiqM7aEKnBx2vZRPiP3EyJ2kL38wkFX3NEOGVqjqID7cPNhlNMDmBZZl9XtBNXf-RQct0JMGfWkUFlg/s400/not_quite_random_noise-5.png" width="400" /></a></div>
<br />
You can see the very simple <b>p5js</b> code here: <a href="https://www.openprocessing.org/sketch/501546">https://www.openprocessing.org/sketch/501546</a><br />
<br />
<br />
<h3>
Why Noise Needs a Parameter</h3>
Th audience was asked to pick a random number. That was easy enough. The audience was then asked to pick a noise value. That wasn't so easy. The reason is important.<br />
<br />
To pick a noise value, we or. the computer, needs to know were we are in relation to neighbouring noise values. Without this context, we have no way of making sure the number we pick is not too different from the neighbouring ones.<br />
<br />
One way to know this context is to use a parameter to describe how far long the sequence of noise values we are.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMQWeUj-929-IP6BWCE88uMtNX7elsjMvQl0EEmvLRh0WlbDTwRWBErrFh2aA0hXS4HLc88KjEcjJVt8Ral_yLKeOeYY3w_6JLG9dko4r84P2prEfC9jKdGZS5Y3zlvvCl92aQkDFXPIB9/s1600/not_quite_random_noise-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMQWeUj-929-IP6BWCE88uMtNX7elsjMvQl0EEmvLRh0WlbDTwRWBErrFh2aA0hXS4HLc88KjEcjJVt8Ral_yLKeOeYY3w_6JLG9dko4r84P2prEfC9jKdGZS5Y3zlvvCl92aQkDFXPIB9/s400/not_quite_random_noise-4.png" width="400" /></a></div>
<br />
And that's why the <b>noise()</b> function provided by your favourite library takes a parameter. Noise values for similar parameters will be similar.<br />
<br />
To encourage us to think about this, we considered what the noise parameter was that created these rings which have had noise added to them.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmsWUMW0rPOQKfPB3aEzeABBPbrmgNeMs4yzss-48RK9kUci1oJ3q64leUy5iZpZ6d3EhD72wEXpwQeQQpD4RKFgs6eLgVP16WJKvslhOEUosYbiUWJELdOcc6B1j8bk8NrOvDeJVGUmXW/s1600/not_quite_random_noise-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmsWUMW0rPOQKfPB3aEzeABBPbrmgNeMs4yzss-48RK9kUci1oJ3q64leUy5iZpZ6d3EhD72wEXpwQeQQpD4RKFgs6eLgVP16WJKvslhOEUosYbiUWJELdOcc6B1j8bk8NrOvDeJVGUmXW/s400/not_quite_random_noise-6.png" width="400" /></a></div>
<br />
An initial thought might be that the radius of these circles has noise added using the radius as a parameter. This isn't correct, because the radius is the same all the way around the circles. What various around the circles? The angle. So the radius that is drawn is the basic circle radius plus <b>noise(angle)</b>.<br />
<br />
<br />
<h3>
Two Dimensional Noise</h3>
Before thinking about two-dimensional noise, we looked at 2-dimensional randomness. The following shows a 2-dimensional array filled with random numbers, represented by colours from a grey scale.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOnAWN0TvVcUFaAbPpswfmt-q3ZuHR2CjZ0dIZb49bl3Pja6Eoyisx10R6Sno_6_ulFr-jPZRbdClroWae6E9dr4YpUlekS2anbfKyPVpd9jTOeU8YIuecJnIoxB7tks9KUgAvpzOTs2Ye/s1600/not_quite_random_noise-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOnAWN0TvVcUFaAbPpswfmt-q3ZuHR2CjZ0dIZb49bl3Pja6Eoyisx10R6Sno_6_ulFr-jPZRbdClroWae6E9dr4YpUlekS2anbfKyPVpd9jTOeU8YIuecJnIoxB7tks9KUgAvpzOTs2Ye/s400/not_quite_random_noise-7.png" width="400" /></a></div>
<br />
As expected, the image is random, with no intentional pattern.<br />
<br />
In contrast, 2-dimensional noise does have a discernible structure. The following is the same grid but with noise values deciding the colour of each pixel. The blue to white scale makes the image look like a photo of clouds.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUx_igCBJdoTum95R2W6IUQFc7iZ3iobUSzNBnDfQkKzkL8KvB-SEHcIy0xXMyP2_vNwq1qywP5CCPkzaEf2jc9oWSGK_6JTZYxgml85c2K-YHYw7w7mZPbDMLVFdheODJSJCk0On2uIJP/s1600/not_quite_random_noise-8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUx_igCBJdoTum95R2W6IUQFc7iZ3iobUSzNBnDfQkKzkL8KvB-SEHcIy0xXMyP2_vNwq1qywP5CCPkzaEf2jc9oWSGK_6JTZYxgml85c2K-YHYw7w7mZPbDMLVFdheODJSJCk0On2uIJP/s400/not_quite_random_noise-8.png" width="400" /></a></div>
<br />
Just as before, the noise values don't vary wildly, but change in a more moderated way as we follow them up or across the grid. It's easy to see that a 2-dimensional noise function takes 2 parameters so that it knows how far along and up the sequence of noise values it is.<br />
<br />
The code for these clouds is at <a href="https://www.openprocessing.org/sketch/502021">https://www.openprocessing.org/sketch/502021</a>.<br />
<br />
<br />
<h3>
3D Landscape</h3>
Thinking back to the green landscape we started with, why don't we try again to recreate it more realistically. We don't actually need to implement a proper 3-dimensional model with perspective and so on. We can just have layers of 2-dimensional "fences" which have their height set using 2-dimensional noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9rWrICp2nbdn6grKANQRMGGKznkofkw9vwYD0d_q7q8GWOEg94-91-hAi_9hoKUo66ZXSeBRAosA1RXue7VeAT_qLNybmlsRPgHUqXe3h5VXbejVbO_uBjk-4_OLrbqkANpGXEYwCfaTb/s1600/not_quite_random_noise-9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9rWrICp2nbdn6grKANQRMGGKznkofkw9vwYD0d_q7q8GWOEg94-91-hAi_9hoKUo66ZXSeBRAosA1RXue7VeAT_qLNybmlsRPgHUqXe3h5VXbejVbO_uBjk-4_OLrbqkANpGXEYwCfaTb/s400/not_quite_random_noise-9.png" width="400" /></a></div>
<br />
We can start with a grid of points, which will be the points which will be raised (or lowered) according to the noise values at that position.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5CcjfBpdtO_yh_vTO3j-s3nhj2-_J1YeMlDYzQoqwwF_O7pWIh-lMX99r5vtrBWl0yJH4Ldsza7DWglkPKfp-uPWEvRQ8VaRM4Sf5c4JlEx-fMu8M8LtaLVYcY8nP6hA8r6nFLvtLzKvC/s1600/not_quite_random_noise-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5CcjfBpdtO_yh_vTO3j-s3nhj2-_J1YeMlDYzQoqwwF_O7pWIh-lMX99r5vtrBWl0yJH4Ldsza7DWglkPKfp-uPWEvRQ8VaRM4Sf5c4JlEx-fMu8M8LtaLVYcY8nP6hA8r6nFLvtLzKvC/s400/not_quite_random_noise-10.png" width="400" /></a></div>
<br />
The results are impressive, given the simplicity of the idea.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd5d050JZCWxCD2rnybl2DX7erlIEpz5HS3NyaxvU8Fm0FEB2djZvDi2EMWz3Qlh43TSAQnKeAleI8TBP86af3lzdVQyeXU56OqT6YY2UIEfSDbQE5Ki54Abj9A-6dgDKNKm13g6n262q2/s1600/not_quite_random_noise-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd5d050JZCWxCD2rnybl2DX7erlIEpz5HS3NyaxvU8Fm0FEB2djZvDi2EMWz3Qlh43TSAQnKeAleI8TBP86af3lzdVQyeXU56OqT6YY2UIEfSDbQE5Ki54Abj9A-6dgDKNKm13g6n262q2/s400/not_quite_random_noise-11.png" width="400" /></a></div>
<br />
That really does look like some kind of alien terrain, perhaps a scan of a planet's surface before landing...<br />
<br />
<br />
<h3>
Multiple Octaves of Noise</h3>
By stretching or squishing the parameters so they change slow for faster, we can control how lumpy or smooth the surface is. We saw this earlier in the talk with a simple 1-dimensional noise too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzGMbMg1o5HsK2BECh_eVeDP_WDouCmC1NOFgGj4cNCQJystFhOSiGN7KQtBTlYDnjWkpidXzbEUCQemHnmSGDTLgOoi5r_ISCvhdU2jokB7TqGFL7PJw1qV2Kzu_Kccb9HgiZzDL_su4J/s1600/not_quite_random_noise-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzGMbMg1o5HsK2BECh_eVeDP_WDouCmC1NOFgGj4cNCQJystFhOSiGN7KQtBTlYDnjWkpidXzbEUCQemHnmSGDTLgOoi5r_ISCvhdU2jokB7TqGFL7PJw1qV2Kzu_Kccb9HgiZzDL_su4J/s400/not_quite_random_noise-12.png" width="400" /></a></div>
<br />
It is common practise to combine different "octaves" of noise to have a result that has both a macro structure as well as finger-grained micro-structural detail.<br />
<br />
You might be familiar with this idea from music or electronic signal processing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUMFIlEulptLZzZicLRRC5PrrDjtyydDDEwQgqsck-zz9Yg3555EkUmpYDPGJH7em-puOxHPBaSEVb4DHQ6bje18sjJrmVITxlF9chUrg2z7R1M3ndJi63ZUeLn6b9OntYE7AIv6p3Y-yv/s1600/not_quite_random_noise-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUMFIlEulptLZzZicLRRC5PrrDjtyydDDEwQgqsck-zz9Yg3555EkUmpYDPGJH7em-puOxHPBaSEVb4DHQ6bje18sjJrmVITxlF9chUrg2z7R1M3ndJi63ZUeLn6b9OntYE7AIv6p3Y-yv/s400/not_quite_random_noise-13.png" width="400" /></a></div>
<br />
Here's a comparison of a smooth landscape with one that has had finer-grained higher-frequency noise added to it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMMnm6uh053C5btmWSPngtMuixrshLsjXMgDNcOTUmli-K0yDYnHYjc36LMD8aS6ubZSYEC28E5CH4vvLX0IXPmuHIW5wXchESmp9xTHZnoY63CDW54I3vRUcxHsu4c6j0iloCoAjcWw4E/s1600/not_quite_random_noise-14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMMnm6uh053C5btmWSPngtMuixrshLsjXMgDNcOTUmli-K0yDYnHYjc36LMD8aS6ubZSYEC28E5CH4vvLX0IXPmuHIW5wXchESmp9xTHZnoY63CDW54I3vRUcxHsu4c6j0iloCoAjcWw4E/s400/not_quite_random_noise-14.png" width="400" /></a></div>
<br />
<br />
<h3>
Refining the Landscape</h3>
That landscape is simple and very effective. But we can do more with it.<br />
<br />
Here is the landscape generated with 800 points. To avoid over saturation, each dot has been drawn with a high translucency. This allows detail to re-emerge even with large numbers of points being drawn - a broadly applicable technique.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_YkF9yEFPM6Y2zAWPFZUHLQN0TGsw9ycoAhdO75D5VMs83yTd1hwpugTctAFGCIuPUcUylyx6RFpIYT-hpZbnhiXlPDrmALQUYYM4fAVY5wqYaElVs-HniLBe0CGGIFgIc-gEynJTguP5/s1600/not_quite_random_noise-15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_YkF9yEFPM6Y2zAWPFZUHLQN0TGsw9ycoAhdO75D5VMs83yTd1hwpugTctAFGCIuPUcUylyx6RFpIYT-hpZbnhiXlPDrmALQUYYM4fAVY5wqYaElVs-HniLBe0CGGIFgIc-gEynJTguP5/s400/not_quite_random_noise-15.png" width="400" /></a></div>
<br />
The code for this sketch is at <a href="https://www.openprocessing.org/sketch/504970">https://www.openprocessing.org/sketch/504970</a>.<br />
<br />
We can use the noise values, not just to determine the landscapes height, but also the colour. Here is an example showing more Earth-like greens and blues.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheSJrSv0BUL7pQq1-Unr18Lw13hqhnZ1ZuFFgiWACwrla9_fc1icHIhG_keb6wkwJmo5499X7G6licqpTpGdb3kOvnI7U0i_7ZsdD1pzv6C_OwpDh1Q4T2DR8yLkPorV3vN2Xsj_TqjOTh/s1600/not_quite_random_noise-16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheSJrSv0BUL7pQq1-Unr18Lw13hqhnZ1ZuFFgiWACwrla9_fc1icHIhG_keb6wkwJmo5499X7G6licqpTpGdb3kOvnI7U0i_7ZsdD1pzv6C_OwpDh1Q4T2DR8yLkPorV3vN2Xsj_TqjOTh/s400/not_quite_random_noise-16.png" width="400" /></a></div>
<br />
We can even cut-off the lower values to create what looks like a lake or a sea.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9eRfPSlHUCUCG0RysfrxRaSvS8awC8vmFJJ5r5yNUibTRQVwLonED7ehUHvyehpJ0B78GhBXbtRnDLLnXds2mkIydBI7R2wrMQCrvUEAWm9DBGwoWgWP3N0UpCEhjwkaLGYMFfvaqkTy2/s1600/not_quite_random_noise-17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9eRfPSlHUCUCG0RysfrxRaSvS8awC8vmFJJ5r5yNUibTRQVwLonED7ehUHvyehpJ0B78GhBXbtRnDLLnXds2mkIydBI7R2wrMQCrvUEAWm9DBGwoWgWP3N0UpCEhjwkaLGYMFfvaqkTy2/s400/not_quite_random_noise-17.png" width="400" /></a></div>
<br />
After seeing these examples, it's not a surprise that noise is used to generate landscapes in games and films.<br />
<br />
<br />
<h3>
Simple Textures</h3>
We looked at how noise can be used to generate textures - in fact, a common use for noise. Here is the simple starting point showing rings created by sin waves using the distance from the centre of the canvas as a parameter.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgElv7TDd3LjrkWRe9BcW868UMAoNaJAug4LOano0rFqobTzoH07yAoifIU_YjTyM9Oxij6Han1mPwsx38CzEMYou67YujiQlNeqjxCrtoAPmBSxejGSkOqSe0c339gIeeZNHE-7ojJlpcM/s1600/not_quite_random_noise-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgElv7TDd3LjrkWRe9BcW868UMAoNaJAug4LOano0rFqobTzoH07yAoifIU_YjTyM9Oxij6Han1mPwsx38CzEMYou67YujiQlNeqjxCrtoAPmBSxejGSkOqSe0c339gIeeZNHE-7ojJlpcM/s400/not_quite_random_noise-18.png" width="400" /></a></div>
<br />
That's fairly regular as we'd expect. We can adjust the colour that's drawn using 2-dimensional noise that takes the (x,y) position as parameters. The result looks remarkably like wood or a sliced rock.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8Kvpijvw3wX3JuatFtG4iNFfz93wRHPuW06EcefAKjiXvZRbstWjC-6YCG7GPOhUtTZ_RqtdNy5xhlmTRUu6SEDASDCjFefyqSGgZVv4azF4ESKCGXMURSiFDHh8BkQdWiT9NKJoGWODH/s1600/not_quite_random_noise-19.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8Kvpijvw3wX3JuatFtG4iNFfz93wRHPuW06EcefAKjiXvZRbstWjC-6YCG7GPOhUtTZ_RqtdNy5xhlmTRUu6SEDASDCjFefyqSGgZVv4azF4ESKCGXMURSiFDHh8BkQdWiT9NKJoGWODH/s400/not_quite_random_noise-19.png" width="400" /></a></div>
<br />
It doesn't take much to refine this further to make it look like polished wood - a slight change of colour palette and a vertical squish.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIy7xrTWaV-nzXC1WzJpT00waz-C4jwJUxjt5IemJ_GAQ1HVGjQCxmzWI3gFOxub1xE_h28y9vQiAdBEU1301ocNsg-YM0q1sf5PC4HSGs24s6_ARtT8JTQKy9DcwBHXVakoTUzEqWNY69/s1600/not_quite_random_noise-20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIy7xrTWaV-nzXC1WzJpT00waz-C4jwJUxjt5IemJ_GAQ1HVGjQCxmzWI3gFOxub1xE_h28y9vQiAdBEU1301ocNsg-YM0q1sf5PC4HSGs24s6_ARtT8JTQKy9DcwBHXVakoTUzEqWNY69/s400/not_quite_random_noise-20.png" width="400" /></a></div>
<br />
The code for this wood effect is at <a href="https://www.openprocessing.org/sketch/577875">https://www.openprocessing.org/sketch/577875</a>.<br />
<br />
We also looked at an <a href="https://www.openprocessing.org/sketch/502123">agate</a> texture which is just the above but with a green-blue colour scale. We evens saw the use of noise to create a lumpy fog effect to be used in <a href="http://algorithmicartmeetup.blogspot.com/2017/08/ray-tracing-for-realistic-scenes.html">ray-tracing</a> a 3-d scene.<br />
<br />
Noise to create texture is a very popular technique, used directly by coders or indirectly by using modelling tools which provide textures based on noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ29GdS9v_gZyoNEp_D0onqo2Y1ALoLSszh4yiqGGRs4x7caJeyOokti7x00wBSbCUP3ayijmXXvxwUxgtaoYYvjuBKSK-rCTvIuzGYUFax4OQtJgIpS4sHvgh_7PQrCmemP6blgdjyLAd/s1600/not_quite_random_noise-21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ29GdS9v_gZyoNEp_D0onqo2Y1ALoLSszh4yiqGGRs4x7caJeyOokti7x00wBSbCUP3ayijmXXvxwUxgtaoYYvjuBKSK-rCTvIuzGYUFax4OQtJgIpS4sHvgh_7PQrCmemP6blgdjyLAd/s400/not_quite_random_noise-21.png" width="400" /></a></div>
<br />
<br />
<h3>
Genuinely 3-Dimensional Noise</h3>
So ar we've only used 1-dimensional and 2-dimensinal noise, even when we're creating 3-dimensional scenes. The height values for the landscape are based on noise(x,y) for example.<br />
<br />
It is possible to have 3-dimensional noise, based on 3 parameters.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWCtz9fl_s9bh5UPNtZtpea1d-WtWkmYYDQDhq38ecup68XaxkWcHXdvfedOfBiKiBaZbbk0pZ2X3nxe24myxMJBE62nXlXGfrnJVEcszqGpjKD9hpYen42mhk7V0LThoyptn25KU0Hfm_/s1600/not_quite_random_noise.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWCtz9fl_s9bh5UPNtZtpea1d-WtWkmYYDQDhq38ecup68XaxkWcHXdvfedOfBiKiBaZbbk0pZ2X3nxe24myxMJBE62nXlXGfrnJVEcszqGpjKD9hpYen42mhk7V0LThoyptn25KU0Hfm_/s400/not_quite_random_noise.png" width="400" /></a></div>
<br />
The results can be used to create 3-dimensional structures. Some games use noise to create worlds which include caves.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4FEtpzkxnxpmR0FzhY3VjxXJlGBAWSTLbOHM1IqYpwoNb2WXycunRJ_T5wa2WqFB_fjFQ-pSDZ5YeOy4YMew8ywmBp4YlEJTY_e3CBd7t-RSDWh1O4e2LHjJ3K8AncejrAOUOCX-ilJHR/s1600/not_quite_random_noise-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4FEtpzkxnxpmR0FzhY3VjxXJlGBAWSTLbOHM1IqYpwoNb2WXycunRJ_T5wa2WqFB_fjFQ-pSDZ5YeOy4YMew8ywmBp4YlEJTY_e3CBd7t-RSDWh1O4e2LHjJ3K8AncejrAOUOCX-ilJHR/s400/not_quite_random_noise-2.png" width="400" /></a></div>
<br />
<br />
<h3>
Animated Noise</h3>
An interesting idea is to take 2-d slices of 3-d noise, and use that 3-rd parameter as time, or frame count. This way we can animate the 2-d slices.<br />
<br />
We expect the resulting patterns to be smoothly changing because noise should vary smoothly along all its dimensions, inlacing any we consider time.<br />
<br />
Here is an example of moving lava created by taking 2-d slices of 3-d noise and using a threshold to decide the colour.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmKMmVG_X5uFd0HZRucTUOai7z4XBkDwszoUzt9-AcV3Tvn8lTlKt4bZ7SK13DKEou-0gsBT8j2IMDVmp7iBslINkBxz5S9L4hv1YOblPrzaKBDAwCCWQy9ZBUyImD1MNjLJD-uA0PVtE1/s1600/lava_perlin.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="456" data-original-width="460" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmKMmVG_X5uFd0HZRucTUOai7z4XBkDwszoUzt9-AcV3Tvn8lTlKt4bZ7SK13DKEou-0gsBT8j2IMDVmp7iBslINkBxz5S9L4hv1YOblPrzaKBDAwCCWQy9ZBUyImD1MNjLJD-uA0PVtE1/s400/lava_perlin.gif" width="400" /></a></div>
<br />
That's rather effective! The simple code for this lava is at <a href="https://www.openprocessing.org/sketch/577863">https://www.openprocessing.org/sketch/577863</a>.<br />
<br />
<br />
<h3>
How Perlin Noise Actually Works</h3>
Many guides sadly don't give any insight into how this really useful not-so-random noise is actually created.<br />
<br />
I wrote a blog explaining it on another blog <a href="http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html">http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html</a><br />
<br />
Briefly, we discussed how even interpolating between random values wasn't good enough. That's because we have sharp bends (discontinuities) which we don't want for our smoother noise.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimAwC-lzLlg_vOz2iW4QpsEmdHjo4QG_XUplBHaHH9H06InreBAXPLyzaDT-eKrtmpGCy4KWZGMWqM08B_lpSV_OhW-5UfWiDad6UCS7fy-smlyzMfnUq-BlSCRSM5Ipe0Na5DdZYhLj25/s1600/not_quite_random_noise-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimAwC-lzLlg_vOz2iW4QpsEmdHjo4QG_XUplBHaHH9H06InreBAXPLyzaDT-eKrtmpGCy4KWZGMWqM08B_lpSV_OhW-5UfWiDad6UCS7fy-smlyzMfnUq-BlSCRSM5Ipe0Na5DdZYhLj25/s400/not_quite_random_noise-3.png" width="400" /></a></div>
<br />
Even applying a smoothing function to this linear interpolation still has a problem.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcPg-yoOSDLy4Z2DNmu1JCddYX143qgtsDcZWkDfkRaL6u_ZpkPSfMcL5PzKXzeeADwtQYNYmxHm4DUbzN_XKp4F2G_JYR3p5oWEgyzSYVaD-TjlaAlWaXrWvReLGF3kF_rDrvryufdaEi/s1600/not_quite_random_noise-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcPg-yoOSDLy4Z2DNmu1JCddYX143qgtsDcZWkDfkRaL6u_ZpkPSfMcL5PzKXzeeADwtQYNYmxHm4DUbzN_XKp4F2G_JYR3p5oWEgyzSYVaD-TjlaAlWaXrWvReLGF3kF_rDrvryufdaEi/s400/not_quite_random_noise-4.png" width="400" /></a></div>
<br />
The problem is that values that come from this process could remain high for too long a sequence, or alternatively, they could flip positive and negative too often. That is, the frequency is too free. Yo may be familiar with the term bandwidth-limited, which says that the frequency with which a signal is allowed to fluctuate is limited to a range. We want our noise to be band-width limited.<br />
<br />
So a different approach is used. We start with a grid of regularly spaced points, but this time we place random unit vectors at each point. Their directions are totally random, and that's ok.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL91rmL3oD0abZicb5cSscDjGvyErM9WSZsmx64Js_CTpk6GTvBMwFAmMcsIrUpEgtR3S5zmjIAXuFAJ0oF7c1Bg_K8_ICFg0PFp3lA7aQ60numiko9ksfhl5EJWyrn3WF5X1Fe-eY6ppE/s1600/not_quite_random_noise-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL91rmL3oD0abZicb5cSscDjGvyErM9WSZsmx64Js_CTpk6GTvBMwFAmMcsIrUpEgtR3S5zmjIAXuFAJ0oF7c1Bg_K8_ICFg0PFp3lA7aQ60numiko9ksfhl5EJWyrn3WF5X1Fe-eY6ppE/s400/not_quite_random_noise-5.png" width="400" /></a></div>
<br />
We then take a candidate point at <b>x</b>, and calculate the dot product of the vector from the previous grid point to <b>x</b> and the random unit vector at that grid point. Dot products, when normalised, only vary between -1 and +1 like a cosine wave. That gives us a nice smoothness (very smooth in fact because the first and second and derivatives of this value are also smooth). The dot product of the next unit vector and the vector from the next grid point to x is also calculated and the two are combined, even a simple addition is fine.<br />
<br />
As <b>x</b> moves along the axis, the values that result from this process are smooth, based on an underlying pure randomness, and importantly are limited in frequency. You can see that between any two grid points, the values can only flip once or never. That gives us a tight bound on frequency.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggXHigE5HKSP7xaveXnlMw1VelUHTvMlXg1Ed-swX5OabVYqdXlX9c8MMvhmTxFP8mJo_jMRnQwnU4Kf5fndpRcZxV1HrruPtzwnBG4q1yTxT6erfjaE2ex4_Br9tuoQEnrQ1mn2B60bkr/s1600/not_quite_random_noise-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggXHigE5HKSP7xaveXnlMw1VelUHTvMlXg1Ed-swX5OabVYqdXlX9c8MMvhmTxFP8mJo_jMRnQwnU4Kf5fndpRcZxV1HrruPtzwnBG4q1yTxT6erfjaE2ex4_Br9tuoQEnrQ1mn2B60bkr/s400/not_quite_random_noise-6.png" width="400" /></a></div>
<br />
You can find a Python notebook demonstrating this idea here:<br />
<br />
<ul>
<li><a href="https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/perlin_gradient_noise/1d_perlin.ipynb">https://github.com/makeyourownalgorithmicart/makeyourownalgorithmicart/blob/master/blog/perlin_gradient_noise/1d_perlin.ipynb</a></li>
</ul>
<br />
<br />
Real libraries providing noise will combine several octaves of signals generated like this. And the extension to more than 2 dimensions still follows this basic idea.<br />
<br />
<br />
<h3>
OpenSimplex Noise</h3>
Ken Perlin, who invented the Perlin noise algorithm, updated it a few years later to address some weaknesses. In higher dimensions, the original algorithm started to display patterns that were too regular and not the desired lumpy noise.<br />
<br />
Have a look at the following comparison. The top row is too "straight" in parts.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNig4YkXwlGWz1PlYBL_ye7w642XE31DuDHVsnFybNdqbdM-wKd0Pb-iOloQbJGrTn-drrFD5LZBNIakRAnduyotF60zNACpb4kCvdgIwFxZYH1VtpbWNvloi6suZ-4PFswlhLqSNAK56n/s1600/not_quite_random_noise-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNig4YkXwlGWz1PlYBL_ye7w642XE31DuDHVsnFybNdqbdM-wKd0Pb-iOloQbJGrTn-drrFD5LZBNIakRAnduyotF60zNACpb4kCvdgIwFxZYH1VtpbWNvloi6suZ-4PFswlhLqSNAK56n/s400/not_quite_random_noise-7.png" width="400" /></a></div>
<br />
His updated algorithm was patented, so sadly is not open source friendly. Luckily, the open source community developed an open algorithm called <b>OpenSimplex</b> which you can find out more here:<br />
<br />
<ul>
<li><a href="http://uniblock.tumblr.com/post/99279694832/2d-and-4d-noise-too">http://uniblock.tumblr.com/post/99279694832/2d-and-4d-noise-too</a></li>
<li><a href="https://pypi.org/project/opensimplex/">https://pypi.org/project/opensimplex/</a></li>
</ul>
<br />
<br />
I had previously used OpenSimplex to create 3-d textures for ray traced objects. This works better than mapping a 2-d pattern into 3-d spheres, which suffers from the well-known map projection distortion issues.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizfmTbLWnOJpFiPaeS215uRqbtMnc9dKk9s_6qUiFH4qh6AGTdKxcKhU2ECvpEt033vVvXWKWWSBNXNWIpjsAdDDBN1k9ntR_LlJ8IJOynmixOr9iBf0HEqp8-lIWzo2yRnGboaoliwvV8/s1600/not_quite_random_noise-8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizfmTbLWnOJpFiPaeS215uRqbtMnc9dKk9s_6qUiFH4qh6AGTdKxcKhU2ECvpEt033vVvXWKWWSBNXNWIpjsAdDDBN1k9ntR_LlJ8IJOynmixOr9iBf0HEqp8-lIWzo2yRnGboaoliwvV8/s400/not_quite_random_noise-8.png" width="400" /></a></div>
<br />
<br />
<h3>
Moving Particles</h3>
Finally we looked at a rather different use of noise.<br />
<br />
Following the path of one, or many, particles which move in a random direction at each step is a well known experiment. The results of can look interesting if we use the translucency technique to avoid over-saturation.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcu4jef5rtERupiCnDmyEcHOyTaoIMHXhgWpFSwS6Aer_Ffq2P5lwDudR-Pezf9QPapRX6-IpGduUv6sh4X40z_Jj37vmCGdD1QJqVILMyGYbhCLM3kR1kYtaUSb2DTLwNlY9f44IBjYUl/s1600/not_quite_random_noise-9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcu4jef5rtERupiCnDmyEcHOyTaoIMHXhgWpFSwS6Aer_Ffq2P5lwDudR-Pezf9QPapRX6-IpGduUv6sh4X40z_Jj37vmCGdD1QJqVILMyGYbhCLM3kR1kYtaUSb2DTLwNlY9f44IBjYUl/s400/not_quite_random_noise-9.png" width="400" /></a></div>
<br />
What if we changed the way these particles moved, so that they took a step in a direction determined by noise and not pure randomness?<br />
<br />
The results are spectacular!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirxkgXK6LmGzQ5Af2Z62Ai1_9X20bNitB9IuK5t2XdAY-h_K0G9M-OFtkKSlalDDPH5Bl6DmN67KC-wIw4oxWVSIAFToj8-O05fVtnIKd0TkneVSAKxXnNyz6YAOtEuhlThh1RhjdB2Rka/s1600/not_quite_random_noise-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirxkgXK6LmGzQ5Af2Z62Ai1_9X20bNitB9IuK5t2XdAY-h_K0G9M-OFtkKSlalDDPH5Bl6DmN67KC-wIw4oxWVSIAFToj8-O05fVtnIKd0TkneVSAKxXnNyz6YAOtEuhlThh1RhjdB2Rka/s400/not_quite_random_noise-10.png" width="400" /></a></div>
<br />
The image really looks like a pen and ink work. Amazing, given the simplicity of the underlying idea.<br />
<br />
You can explore the code yourself at <a href="https://www.openprocessing.org/sketch/578607">https://www.openprocessing.org/sketch/578607</a>.<br />
<br />
As a final extra idea, we can use an image like the following, and move particles based on the underlying colour/luminosity.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjovcQ_iMiJO7gmSiTsGMPnF502IR8dH7bvu48sp43LvJBjH79iWV9_lonkOBJNi8ooPCAdtY64M7m-G9n6rcLDK_ec3UdY35NqVQ9sHxounE-gng1Qb6F3TRtQbRy4GzBNxi4pi05tdvuT/s1600/not_quite_random_noise-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjovcQ_iMiJO7gmSiTsGMPnF502IR8dH7bvu48sp43LvJBjH79iWV9_lonkOBJNi8ooPCAdtY64M7m-G9n6rcLDK_ec3UdY35NqVQ9sHxounE-gng1Qb6F3TRtQbRy4GzBNxi4pi05tdvuT/s400/not_quite_random_noise-12.png" width="400" /></a></div>
<br />
We can use the luminosity to determine the colour and the length of the stroke drawn at a point. the results is rather hairy!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0s-8oWXDjlsYXUs5uX035XxkY-bhsJnprvoGee6zN4h9BRGug7wQyFRMQipsim5oC36bF-xkSpxUYVCmKUTKnpxNN3SfHdkWb6vxo0BIjs8RKhOJKIWNrrjRAbvjgC-Exk3NdfQvsfS2h/s1600/not_quite_random_noise-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0s-8oWXDjlsYXUs5uX035XxkY-bhsJnprvoGee6zN4h9BRGug7wQyFRMQipsim5oC36bF-xkSpxUYVCmKUTKnpxNN3SfHdkWb6vxo0BIjs8RKhOJKIWNrrjRAbvjgC-Exk3NdfQvsfS2h/s400/not_quite_random_noise-11.png" width="400" /></a></div>
<br />
You can explore the code here <a href="https://www.openprocessing.org/sketch/533299">https://www.openprocessing.org/sketch/533299</a>.<br />
<br />
<br />
<h3>
Feedback and Examples</h3>
Peter developed a couple of really nice animated sketches during the class using noise - take a look, they're really effective.<br />
<br />
<ul>
<li>Animated Sea - <a href="https://www.openprocessing.org/sketch/581530" target="_blank">https://www.openprocessing.org/sketch/581530</a></li>
</ul>
<br />
<ul>
<li>Fire Hole - <a href="https://www.openprocessing.org/sketch/458507" target="_blank">https://www.openprocessing.org/sketch/458507</a></li>
</ul>
<br />
I was a little unsure if the audience would be bored by a talk which took a beginner-friendly approach and kept things fairly simple. I was pleased that quite a few people responded positively and - best of all - said they'd go and try using noise themselves!<br />
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-13587975258174407222018-07-22T15:15:00.001-07:002018-07-22T16:41:15.116-07:00Creating 3D Printable Art with OpenJSCADThis month we were lucky to have the multi-talented <a href="http://www.complexview.com/articles/james-porter">James Porter</a> help us explore creating algorithmically designed for 3D printing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1cqFzDKNWsNooJGbsLrjoYQMb5IT2QTOqr91b8KvnyVfzZwo1WOaNGtcArIz7YoXGLNlVKAWdAU6uNqseRk0I4fvesoAq4AQjT7dIH3GDvxfZ2IqGQXEuYPJzOySkcGtJEsvGfkJNYGMV/s1600/IMG_20180718_191346-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1201" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1cqFzDKNWsNooJGbsLrjoYQMb5IT2QTOqr91b8KvnyVfzZwo1WOaNGtcArIz7YoXGLNlVKAWdAU6uNqseRk0I4fvesoAq4AQjT7dIH3GDvxfZ2IqGQXEuYPJzOySkcGtJEsvGfkJNYGMV/s400/IMG_20180718_191346-01.jpg" width="400" /></a></div>
<br />
The slides for James' tutorial are here: [<a href="https://drive.google.com/file/d/1f3tvK9sXdaq593_eE3VNlpY5hT8vf7Pl/view">pdf</a>]. His event page is here: [<a href="https://talknotes.amimetic.co.uk/algorithmic-art-for-3d-printing/">link</a>].<br />
<br />
A video recording is here: [<a href="https://skillsmatter.com/skillscasts/12157-introduction-to-openjscad">skillsmatter</a>].<br />
<br />
<br />
<h3>
Why 3D Printing</h3>
The ever onward march of technology brings with it not just new innovations, but also makes them ever more affordable and practical.<br />
<br />
Printing 3-dimensional physical objects has seen a growth in popularity and accessibility in recent years. Practical applications are plenty, but so are creative ones too.<br />
<br />
Suddenly, imagining 3-dimensional objects and making them reality is no longer the realm of magical fantasy or science fiction.<br />
<br />
Here is an example of James' experiments - an interesting landscape made of hexagonal rock forms.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6TVadJVkOrT8wtK8uu0zcFsNmjK5qXHuqP4RfVrIfvx83s4Csi3nrngZEOBaeTGohTzddizuj5q6R2J99UmFwlRDufxksDAm3mVoiPhVx7_sn6nWM_piyp5i7qPq4lcipkX7e_HmmWIC_/s1600/IMG_20180720_112939.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6TVadJVkOrT8wtK8uu0zcFsNmjK5qXHuqP4RfVrIfvx83s4Csi3nrngZEOBaeTGohTzddizuj5q6R2J99UmFwlRDufxksDAm3mVoiPhVx7_sn6nWM_piyp5i7qPq4lcipkX7e_HmmWIC_/s400/IMG_20180720_112939.jpg" width="400" /></a></div>
<br />
In algorithmic art, we can use computers to create art forms that no human hand could ever create. Extending this to 3-dimensional forms is exciting!<br />
<br />
<br />
<h3>
OpenJSCAD</h3>
We're very fond of tools that work entirely in a browser, with no additional software needing to be installed. Not only does it make the tools independent of your computer brand, it also reduces technical complexity making them ideal for beginners. We love <b>openprocessing</b>, which is a <b>p5js</b> environment entirely on the web.<br />
<br />
James introduced <a href="https://www.openjscad.org/" style="font-weight: bold;">OpenJSCAD</a>, which allows us to use code to create 3-dimensional forms, which can then be exported in a form suitable for 3D printers.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWcW-xOttATJ_4MUga038BGyGKs61yM7WV4mCVPN50gIHYwbgCpOv9wKXmfmCtwF9TELzM4shyHjh44r-2DYm9aoZmWIfVCJ476yA2FJ-qv2bVKBMIFbmuWpKqFSaYMFLCcl8h5LZ6ZqU2/s1600/ezgif.com-crop.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="324" data-original-width="591" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWcW-xOttATJ_4MUga038BGyGKs61yM7WV4mCVPN50gIHYwbgCpOv9wKXmfmCtwF9TELzM4shyHjh44r-2DYm9aoZmWIfVCJ476yA2FJ-qv2bVKBMIFbmuWpKqFSaYMFLCcl8h5LZ6ZqU2/s400/ezgif.com-crop.gif" width="400" /></a></div>
<br />
James then led us through the basic concepts for coding in OpenJSCAD, together with some interesting challenges for us to tackle. You can see them being discussed on the video.<br />
<br />
Here I'll try my own introductory tutorial to create simple 3D forms.<br />
<br />
<br />
<h3>
Basic OpenJSCAD Ideas</h3>
OpenJSCAD will create 3-dimensional forms defined by computer program we write. That program is written in code which looks very much like <b>javascript </b>(<a href="https://www.codecademy.com/learn/introduction-to-javascript">tutorial</a>).<br />
<br />
OpenJSCAD expects to run a <b>main()</b> function, and expects it to return a single object. That single object can be a single sphere or cube, or a collection of shapes which together form an interesting form.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX5qWSRYwoW92V5SKcjWT5judVKS6FaB0gb9n4eFCFFHT5CRrjKWo19ev1ihiC8Bjq5iMQjRIJaL6gTkiH97T-rlcaYSEkpuB5BMDuSQbs92-LGoPiKmE59JnbeVq8i3ELHPaFscDWXjNV/s1600/openjscad_tutorial_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="989" data-original-width="1600" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX5qWSRYwoW92V5SKcjWT5judVKS6FaB0gb9n4eFCFFHT5CRrjKWo19ev1ihiC8Bjq5iMQjRIJaL6gTkiH97T-rlcaYSEkpuB5BMDuSQbs92-LGoPiKmE59JnbeVq8i3ELHPaFscDWXjNV/s400/openjscad_tutorial_0.png" width="400" /></a></div>
<br />
Let's try creating the simplest of objects. Try replacing the <b>main()</b> function with just the following simple code:<br />
<br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">function main () {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> return cube({size: 10, center: true});</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">}</span><br />
<div>
<br /></div>
You can see the thing being returned by <b>main()</b> is a <b>cube</b>. The data inside the <b>cube()</b> function sets the size to <b>10</b>, and locates the centre of the object at the centre of the virtual world. Let's have a look at the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtwGLseVoo9DiaQ1yczJkGFYuQit-S9LhEQ7nvqCLzvTE717tUQm00uqZ3Noyjol9RHeDFnjlo0c1NllHAnkrW_9Ly7xJyLt4J8X-kE76WXPheIIP1cUprXCjf3Q8ALJtafm7sdy_xwa4s/s1600/oj_cube.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="948" data-original-width="1600" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtwGLseVoo9DiaQ1yczJkGFYuQit-S9LhEQ7nvqCLzvTE717tUQm00uqZ3Noyjol9RHeDFnjlo0c1NllHAnkrW_9Ly7xJyLt4J8X-kE76WXPheIIP1cUprXCjf3Q8ALJtafm7sdy_xwa4s/s400/oj_cube.png" width="400" /></a></div>
<br />
You can use your pointer to drag the view around and confirm it is indeed a 3-dimensional object:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTslBG641UFJ8zH4VcOMpldpQToavYDvpVnqwKnDfmvzNJXXhJL4yzXnBeG7p_6h5kTwTcMzGQ5lJHalCbV60A6vR6MdGX_NMwnmTJkKyJSc5r_pO6vWvwB09bVEK3x5hTXguyCDp5CIi-/s1600/ezgif.com-video-to-gif.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="345" data-original-width="600" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTslBG641UFJ8zH4VcOMpldpQToavYDvpVnqwKnDfmvzNJXXhJL4yzXnBeG7p_6h5kTwTcMzGQ5lJHalCbV60A6vR6MdGX_NMwnmTJkKyJSc5r_pO6vWvwB09bVEK3x5hTXguyCDp5CIi-/s400/ezgif.com-video-to-gif.gif" width="400" /></a></div>
<br />
If we want to compose a more interesting form, we need to use several basic shapes. Remember that the <b>main()</b> function can only return one single thing, so that thing needs to be a group of other objects. That's called a <b>union</b> here, which reflects the mathematical term, a <b>union</b> of sets.<br />
<br />
Here's how we use <b>union</b>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7v5An8RUQDZzizHUJextUZXHWk4srSb6w0NMQ5z4NbAkeFnDtIeaKR9g-Ejef_hlFjSfG-72lOxBJ0YlBw0-ZJJFRnZ2lQaOZJRy0SEdu-m4CyV06ZeDqnH12X3iYqfOUTaIpIATxVFmm/s1600/openjscad_tutorial_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="989" data-original-width="1600" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7v5An8RUQDZzizHUJextUZXHWk4srSb6w0NMQ5z4NbAkeFnDtIeaKR9g-Ejef_hlFjSfG-72lOxBJ0YlBw0-ZJJFRnZ2lQaOZJRy0SEdu-m4CyV06ZeDqnH12X3iYqfOUTaIpIATxVFmm/s400/openjscad_tutorial_1.png" width="400" /></a></div>
<br />
Let's try joining a <b>cube</b> and a <b>sphere</b> together:<br />
<br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);">function main () {</span></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);"> return union(</span></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);"><br /></span></span>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);"> cube({size: 20, center: true}),</span></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);"> sphere({r: 12, center: true})</span></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);"><br /></span></span>
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);"> );</span></span><br />
<span style="color: blue; font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fce5cd; caret-color: rgb(0, 0, 255);">}</span></span><br />
<br />
The sphere() function needs its <b>radius</b> set, which we can see is set to <b>12</b> here. Here's the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBlDXfLd1-zoMyD99TTVVJtGXY_S0Pyj0WXcQgjtxdCra1zBgXQgguigxGX_TUgeEeBGkGKQJI_rQWHbEprr32AdO0aKxN9Tun33raIMuwz7Sqo1YBdVWvjmBimw6-WLQQx84MwGPH8VMd/s1600/Screen+Shot+2018-07-22+at+14.34.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1043" data-original-width="1600" height="260" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBlDXfLd1-zoMyD99TTVVJtGXY_S0Pyj0WXcQgjtxdCra1zBgXQgguigxGX_TUgeEeBGkGKQJI_rQWHbEprr32AdO0aKxN9Tun33raIMuwz7Sqo1YBdVWvjmBimw6-WLQQx84MwGPH8VMd/s400/Screen+Shot+2018-07-22+at+14.34.17.png" width="400" /></a></div>
<br />
If we kept adding more shapes, they'd all be overcrowding the same origin of this 3-d world. We need a way to move them around. We can do this by using a <b>translate()</b> function:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLZidN6vTgOdYCa4xMiJdUt9BJXjLhvdWNCfx4GuXn4QSgeSWZVSE7jGM8ubwgaL4ufcqQaJ_EZYN5-k8yqrJGbnjXPjM2PcP-C1sCN7i7oZ3ZmYtQv86kn3E0qnc7RWZFKVNLAk3xAj8q/s1600/openjscad_tutorial_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="989" data-original-width="1600" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLZidN6vTgOdYCa4xMiJdUt9BJXjLhvdWNCfx4GuXn4QSgeSWZVSE7jGM8ubwgaL4ufcqQaJ_EZYN5-k8yqrJGbnjXPjM2PcP-C1sCN7i7oZ3ZmYtQv86kn3E0qnc7RWZFKVNLAk3xAj8q/s400/openjscad_tutorial_2.png" width="400" /></a></div>
<br />
The <b>translate()</b> function takes an object and translates it by <b>[x, y, z]</b> along these axes. A translation of <b>[1, 0, 0] </b>would translate an object only along the x-axis by <b>1</b>.<br />
<br />
Let's try it:<br />
<br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">function main () {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> return union(</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> cube({size: 10, center: true}),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([10, 0, 0], sphere({r: 6, center: true}))</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> );</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
The result is a <b>cube</b> at the centre of the world, and a <b>sphere</b> which has been shifted along the x-axis by <b>10</b> units.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxMTkdAH8UHIbgEl_RsgitbHyQ4SErkyDrc5dpiKk_5B2o-OM0FZOSKPfe6gKo75m_h6l1dUwir8tykqWi-W3meTQZKB_6-2gc3Fh_X-_7j230n6hi764LsCHOO8u8lf8K92dHOSxXdM8r/s1600/Screen+Shot+2018-07-22+at+15.01.41.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="990" data-original-width="1600" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxMTkdAH8UHIbgEl_RsgitbHyQ4SErkyDrc5dpiKk_5B2o-OM0FZOSKPfe6gKo75m_h6l1dUwir8tykqWi-W3meTQZKB_6-2gc3Fh_X-_7j230n6hi764LsCHOO8u8lf8K92dHOSxXdM8r/s400/Screen+Shot+2018-07-22+at+15.01.41.png" width="400" /></a></div>
<br />
Let's chain a few of these shapes together. Here's some code which has a series of spheres and cubes all shifted along so that they form a nice line:<br />
<br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">function main () {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return union(</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([-30, 0, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([-20, 0, 0], cube({size: 10, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([-10, 0, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([0, 0, 0], cube({size: 10, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([10, 0, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([20, 0, 0], cube({size: 10, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([30, 0, 0], sphere({r: 6, center: true}))</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> );</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span><br />
<div>
<br /></div>
Here's the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJrS85D8lm0UMi2ywHG1neisYCj_X1LSpjg2IuTyda-8dPR9uopqPMLo6AoZeyQY_fJoftFk-tUpc6bj5WTa5A-mnUIhFZz-atVnQVqtSRLspV7pyWNKQu79ZCdg_ldKJyqNGheQgokbXa/s1600/Screen+Shot+2018-07-22+at+15.05.40.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="908" data-original-width="1600" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJrS85D8lm0UMi2ywHG1neisYCj_X1LSpjg2IuTyda-8dPR9uopqPMLo6AoZeyQY_fJoftFk-tUpc6bj5WTa5A-mnUIhFZz-atVnQVqtSRLspV7pyWNKQu79ZCdg_ldKJyqNGheQgokbXa/s400/Screen+Shot+2018-07-22+at+15.05.40.png" width="400" /></a></div>
<br />
Cool!<br />
<br />
We can see how we could create quite sophisticated forms just by using a <b>union</b> of simple objects. I you look at the OpenJSCAD reference, you'll see that other simple shapes like a cylinder, torus and a polyhedron, as well as flat shapes like a circle and a rectangle.You can use any of these in a union, and you can translate any of them too.<br />
<br />
Let's look at one more shape modifier - <b>scale</b> - which you can guess scales a shape. We use it in a similar way to translate where we pass it the object we want to scale.<br />
<br />
The following code is the same as that above, but has the spheres scaled by <b>1.7</b>.<br />
<br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">function main () {</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return union(</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([-30, 0, 0], <b>scale(1.7, sphere({r: 6, center: true}))</b>),</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([-20, 0, 0], cube({size: 10, center: true})),</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([-10, 0, 0], <b>scale(1.7, sphere({r: 6, center: true}))</b>),</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([0, 0, 0], cube({size: 10, center: true})),</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([10, 0, 0], <b>scale(1.7, sphere({r: 6, center: true}))</b>),</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([20, 0, 0], cube({size: 10, center: true})),</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> translate([30, 0, 0], <b>scale(1.7, sphere({r: 6, center: true}))</b>)</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> );</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></span><br />
<br />
Here's the result.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXuGytL68eOer6J3XhLyCXZbc_NG7RyFiuEVI8MV0z0ooc5uH-uhW7HHVCEQp84O77lfzZlMGv-7CHVdCLMvzE4XcFvZjNlkVUBe9eh5QbLd04I8Sj2rFfLrOvZp30nXVwK_FbXHpyiZDA/s1600/Screen+Shot+2018-07-22+at+15.13.26.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="861" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXuGytL68eOer6J3XhLyCXZbc_NG7RyFiuEVI8MV0z0ooc5uH-uhW7HHVCEQp84O77lfzZlMGv-7CHVdCLMvzE4XcFvZjNlkVUBe9eh5QbLd04I8Sj2rFfLrOvZp30nXVwK_FbXHpyiZDA/s400/Screen+Shot+2018-07-22+at+15.13.26.png" width="400" /></a></div>
<br />
We can see that only the spheres have been scaled, and that's because we only applied <b>scale()</b> to the spheres.<br />
<br />
We have an interesting shape that we could now bring to life with a 3D printer. We can use the export options to save a file accepted by many printers. The <a href="https://en.wikipedia.org/wiki/STL_(file_format)">STL</a> format is more or less the standard for 3D printing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdGp1EFIy0geYnfgNxik_tLTegjLK6W8aq-Ci2h6uSue8AjrruLHxzk49QK4dM4KFQ0vmvDSGev4GniQWhVpVAPko4wPQ7IQlbVVGzIc8e0jTdphR1xqFywF0oRkQFlW-cSHzWUIZ6Hc96/s1600/Screen+Shot+2018-07-22+at+15.16.59.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="534" data-original-width="1185" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdGp1EFIy0geYnfgNxik_tLTegjLK6W8aq-Ci2h6uSue8AjrruLHxzk49QK4dM4KFQ0vmvDSGev4GniQWhVpVAPko4wPQ7IQlbVVGzIc8e0jTdphR1xqFywF0oRkQFlW-cSHzWUIZ6Hc96/s400/Screen+Shot+2018-07-22+at+15.16.59.png" width="400" /></a></div>
<br />
<br />
<h3>
More Interesting Ideas </h3>
We can do more than just join objects together. One really interesting idea is to subtract one object from another, a bit like carving out one shape from another.<br />
<br />
Let's go back to our example which had a simple union of a cube and a sphere. Let's change the union to a difference:<br />
<br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">function main () {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> return <b>difference</b>(</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> cube({size: 10, center: true}),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([10, 0, 0], sphere({r: 6, center: true}))</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> );</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
Comparing the results, we can see that the difference takes the first object and craves out the second object.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmp-26Ko_2a6PkVik5ZJHAiEKeymVJRgxd_n9XvwATKObe77yuk96OwkkswZ0FcfmaYqBeC3uuYwfECsK30dx8Jb0S1fDExlqKQJGCc0cVPjXYtDHjFTJTVWSH6iVXme6JuuBzp_EFeieW/s1600/openjscad_tutorial_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="738" data-original-width="1600" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmp-26Ko_2a6PkVik5ZJHAiEKeymVJRgxd_n9XvwATKObe77yuk96OwkkswZ0FcfmaYqBeC3uuYwfECsK30dx8Jb0S1fDExlqKQJGCc0cVPjXYtDHjFTJTVWSH6iVXme6JuuBzp_EFeieW/s400/openjscad_tutorial_3.png" width="400" /></a></div>
<br />
We can combine several objects into a union, and use that union to crave out a shape from another object. Have a look at this code:<br />
<br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">function main () {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> return <b>difference</b> (</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> cube({size: 10, center: true}),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> <b>union</b> (</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([10, 0, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([-10, 0, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([0, 10, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([0, -10, 0], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([0, 0, 10], sphere({r: 6, center: true})),</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> translate([0, 0, -10], sphere({r: 6, center: true}))</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> )</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;"> );</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
We can see that we've constructed a union of six spheres, and that union is taken from a cube.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Kgbm5V4PdbHBzx7TOgMD5vqgCJSkN9gG5IN0IaVDd37MxzOu8weJ6thNxXN85pimWx1bzbtLXkUplqwg_T36lZC0NRnwuDAxPhso8jrLyH6zPdVLDWhJVsc-9N01tio4FsChBY92CzeX/s1600/openjscad_tutorial_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="651" data-original-width="1600" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Kgbm5V4PdbHBzx7TOgMD5vqgCJSkN9gG5IN0IaVDd37MxzOu8weJ6thNxXN85pimWx1bzbtLXkUplqwg_T36lZC0NRnwuDAxPhso8jrLyH6zPdVLDWhJVsc-9N01tio4FsChBY92CzeX/s400/openjscad_tutorial_4.png" width="400" /></a></div>
<br />
You can explore more ways of combining and transforming objects on the OpenSCAD <a href="https://openjscad.org/dokuwiki/doku.php">reference pages</a>.<br />
<br />
<br />
<h3>
JavaScript Power</h3>
We also have the full power of javascript at our disposal. That means we can use loops, functions, and lasts to help construct sophisticated shapes more efficiently.<br />
<br />
Let's use a loop to construct a circle of spheres.<br />
<br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">function main () {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // list of sheres</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> <b>var spheres = [];</b></span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // loop</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for (let angle = 0; angle < 360; angle += 40) {</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let x = 10 * cos(angle);</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let y = 10 * sin(angle);</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> <b>spheres.push</b>( translate([x, y, 0], sphere({r: 3, center: true})) );</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return <b>union(spheres)</b>;</span><br />
<span style="background-color: #fce5cd; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span><br />
<br />
You can see we create an empty list called <b>spheres</b>, and then using a loop, we add lots of spheres to it, each translated according to a bit of trigonometry to follow the edge of a larger circle. Finally the <b>main()</b> function returns the <b>union</b> of the list of spheres.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ037x96yvMzktGGIpBjZaINge2QUgn8HUeCOx3JFxHj5NWUKEXVfSYKKghGFjrfmGP2uy-mi6AbpxvVrVlZs3qTQYz8T8HfNY_FKLKHGs4u46fbyiapyst0YbWuzJ94hMjIuLoxGKglrp/s1600/Screen+Shot+2018-07-22+at+21.23.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1149" data-original-width="1600" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ037x96yvMzktGGIpBjZaINge2QUgn8HUeCOx3JFxHj5NWUKEXVfSYKKghGFjrfmGP2uy-mi6AbpxvVrVlZs3qTQYz8T8HfNY_FKLKHGs4u46fbyiapyst0YbWuzJ94hMjIuLoxGKglrp/s400/Screen+Shot+2018-07-22+at+21.23.02.png" width="400" /></a></div>
<br />
We can extend this idea into the z-axis, and vary the size of the spheres too.<br />
<br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">function main () {</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // list of sheres</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> var spheres = [];</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> var z = 0;</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> var distance = 10;</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> var size = 1;</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // loop</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for (let angle = 0; angle < 720; angle += 10) {</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let x = (0.1 + distance) * cos(angle);</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let y = (0.1 + distance) * sin(angle);</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> spheres.push( translate([x, y, z], sphere({r: 0.1+size, center: true})) );</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> z += 0.2;</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> distance *= 0.99;</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> size *= 0.95;</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return union (spheres);</span></span><br />
<span style="background-color: #fce5cd;"><span style="color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span></span><br />
<br />
The result is interesting, although not printable as it isn't a fully connected object.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisuWhOeJEZG4Lptt91jLEuQyd50_yHv9XUi9sMU_kUmqi98x2q4_5_Sn2YRu8oDbrEfI5l9WdIqFoZg3AOL3vmBrEX1dZZITMUn8xWYgxpI8kZiZLyx2GxGIZ1Gokj8iG6YNOhg8c6fDuD/s1600/Screen+Shot+2018-07-22+at+22.27.15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1149" data-original-width="1600" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisuWhOeJEZG4Lptt91jLEuQyd50_yHv9XUi9sMU_kUmqi98x2q4_5_Sn2YRu8oDbrEfI5l9WdIqFoZg3AOL3vmBrEX1dZZITMUn8xWYgxpI8kZiZLyx2GxGIZ1Gokj8iG6YNOhg8c6fDuD/s400/Screen+Shot+2018-07-22+at+22.27.15.png" width="400" /></a></div>
<br />
A more printable composition can be made by carving out spheres from a block:<br />
<br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">function main () {</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // list of sheres</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> var spheres = [];</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // loop</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> for (let angle = 0; angle < 360; angle += 40) {</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let x = 10 * cos(angle);</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let y = 10 * sin(angle);</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> spheres.push( translate([x, y, 0], sphere({r: 3, center: true})) );</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> var block = translate([0, 0, -3], scale( [3, 3, 0.3], cube({size: 10, center: true}) ) );</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;"> return difference(block, union(spheres));</span><br />
<span style="background-color: #fff2cc; color: blue; font-family: "courier new" , "courier" , monospace; font-size: x-small;">}</span><br />
<br />
The results are rather nice. In fact the union would make a nice physical object itself.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMx6_FABuOp7IEe7rOWYXcwb0K8UMUca1VCp6k4SfrsAItSbtbXrTFE7y_glzm8azCdHEAnVcvzFkW_u8adT9Xua04h00xP6huVeSsGrJz5dcZyWKHI1M7XuWfYmktmdkAZvkdvy9Q6ASV/s1600/openjscad_tutorial_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="608" data-original-width="1600" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMx6_FABuOp7IEe7rOWYXcwb0K8UMUca1VCp6k4SfrsAItSbtbXrTFE7y_glzm8azCdHEAnVcvzFkW_u8adT9Xua04h00xP6huVeSsGrJz5dcZyWKHI1M7XuWfYmktmdkAZvkdvy9Q6ASV/s400/openjscad_tutorial_5.png" width="400" /></a></div>
<br />
In the meetup itself, we were encouraged to explore using simple maths to calculate vertical blocks which form a landscape when places regularly on a grid.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl30LV7vCsraLFjnfk307-W_pnS-AkLJnuyoN68Rj2i-6Z1MuIQy4UI5bcVw36vAVPXpEmd2Hn97H-BykTq9F9hFfNUAdcFhYGVsrsPKI1H01W6R9nGuql545zbKUOMGztNk6lERUTI7J8/s1600/IMG_20180718_201031-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl30LV7vCsraLFjnfk307-W_pnS-AkLJnuyoN68Rj2i-6Z1MuIQy4UI5bcVw36vAVPXpEmd2Hn97H-BykTq9F9hFfNUAdcFhYGVsrsPKI1H01W6R9nGuql545zbKUOMGztNk6lERUTI7J8/s400/IMG_20180718_201031-01.jpg" width="400" /></a></div>
<br />
James provides many more examples to explore on his GitHub <a href="https://github.com/jamesporter/learning-openjscad">repository</a>.<br />
<br />
<br />
<h3>
Physical Objects</h3>
James also brought along examples of 3D printed forms for us to experience for real.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1uC2NueYh_min4AdWH1keiFDlAfx3-5x8CS4MT2U6YwG8gA8CHiHvb9qFWuJgqdL01kDr7hlrmvhG14fMqqMTglev4l3EXCVm28A9hpnJMf12NzGW5Sg9MFHlLgFxpJbpDKSvD1l3_OGm/s1600/IMG_20180720_113309.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1uC2NueYh_min4AdWH1keiFDlAfx3-5x8CS4MT2U6YwG8gA8CHiHvb9qFWuJgqdL01kDr7hlrmvhG14fMqqMTglev4l3EXCVm28A9hpnJMf12NzGW5Sg9MFHlLgFxpJbpDKSvD1l3_OGm/s400/IMG_20180720_113309.jpg" width="400" /></a></div>
<br />
He did discuss some of the limitations of 3D printers that are priced to appeal to home enthusiasts.<br />
<br />
<ul>
<li>there is a limit to the fine detail and intricacy that cheaper printers can reproduce</li>
<li>some objects bend and distort during the printing process</li>
<li>some shapes are either impossible, or barely constructible</li>
<li>the time taken to print objects is long, many minutes or hours even at medium quality settings</li>
</ul>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOtT0HL-6ncVWHWdVkgTaTj0bUQlVSxR4h7Eb3J-sJ-KUJkUPEOpFYq-oZ9nA8oRm5h_MDCQpzGOQcOyaN2dlvf2Wal5jhMlgblcIHb95nwf_nxhb2lnRY41djziAqUTqswt0KeRkrA9tL/s1600/Screen+Shot+2018-07-22+at+22.54.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1062" data-original-width="1600" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOtT0HL-6ncVWHWdVkgTaTj0bUQlVSxR4h7Eb3J-sJ-KUJkUPEOpFYq-oZ9nA8oRm5h_MDCQpzGOQcOyaN2dlvf2Wal5jhMlgblcIHb95nwf_nxhb2lnRY41djziAqUTqswt0KeRkrA9tL/s400/Screen+Shot+2018-07-22+at+22.54.04.png" width="400" /></a></div>
<br />
<br />
<h3>
Conclusion</h3>
James succeeded in showing how easily and accessibly we can create objects ready for 3D printing, and not just any object but objects created algorithmically through code.<br />
<br />
I was really pleased that the class was inspired by James, with some wanting to go on to try 3D printing themselves.<br />
<br />
<br />
<h3>
References</h3>
<ul>
<li>3D and 3D printer file formats - <a href="https://all3dp.com/3d-printing-file-formats/">https://all3dp.com/3d-printing-file-formats/</a></li>
<li>James' GitHub repository of OpenJSCAD examples - <a href="https://github.com/jamesporter/learning-openjscad">https://github.com/jamesporter/learning-openjscad</a></li>
</ul>
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-91525917723286646752018-05-31T15:54:00.002-07:002018-06-01T08:36:16.021-07:00Making Data HumanThis <a href="https://www.meetup.com/Algorithmic-Art/events/249669412/">month</a> we had a more thoughtful session contemplating how algorithms and data can oppress people.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1BHgpqzMwMShpNN5e9Uk0KPGGmrz4bWvp27WC42MaM1_V3ZxmWvbcZh8qJV6awijapJV6MFxAkMpRLImujz7Smh4QGcTk3xIMX69c24dzFeensCp6qr-CNt46Ge0YdHzSsOPxUkrhUFO1/s1600/Dd_iZ8QVQAIM1cr.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1200" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1BHgpqzMwMShpNN5e9Uk0KPGGmrz4bWvp27WC42MaM1_V3ZxmWvbcZh8qJV6awijapJV6MFxAkMpRLImujz7Smh4QGcTk3xIMX69c24dzFeensCp6qr-CNt46Ge0YdHzSsOPxUkrhUFO1/s400/Dd_iZ8QVQAIM1cr.jpg" width="400" /></a></div>
<br />
<br />
We were very lucky to have <a href="http://edfish.co.uk/">Ed Fish</a>, an artist who uses technology, algorithms and code, to create powerful contemplative and thought-provoking work.<br />
<br />
The slides for this talk are here [<a href="https://docs.google.com/presentation/d/1TTUzAvwCyfOPHFm7znwcj4cvmRUbqt4NwhQLjVm7KpY/">link</a>].<br />
<br />
A video recording of the talk is here [<a href="https://skillsmatter.com/skillscasts/11865-algorithmic-art-may">link</a>].<br />
<br />
<br />
<h3>
66,081 and Statistical Numbing</h3>
Ed started with a bang. He presented a single number, in a plain white font on a dark background:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQxY9NPu5QL195aAR6lIqlR-lHP_DWPZ1wrQvQMVD9bFDYU32jAgQFzuO1F47a3EIBmwCGKyFTsFr-cGF6k1eMysrlGaF1c5P8pnlUaxAZS0gDMhRjFuUTthuNJtEWI57Y0oOFHpljiuCI/s1600/number.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="843" data-original-width="1500" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQxY9NPu5QL195aAR6lIqlR-lHP_DWPZ1wrQvQMVD9bFDYU32jAgQFzuO1F47a3EIBmwCGKyFTsFr-cGF6k1eMysrlGaF1c5P8pnlUaxAZS0gDMhRjFuUTthuNJtEWI57Y0oOFHpljiuCI/s400/number.png" width="400" /></a></div>
<br />
That number <b>66,081</b> is the number of civilian casualties of the Iraq War recognised by the Allies. Ed's starting point was his initial response to this number of deaths - or rather, <b>lack of response</b>. That bothered and intrigued him.<br />
<br />
This led to the idea that humans have different responses to, say, <b>1</b> death than <b>100</b> deaths. The emotional response is not a hundred times greater for <b>100</b> deaths. He reflected on the saying that one death is a tragedy, and a million is merely a statistic.<br />
<br />
Ed's motivation was then to understand how and why this difference in response happens - and how to then create art that actually does resonate with those experiencing it in a way that more truly reflects a tragedy.<br />
<br />
Ed pointed us to Paul Slovic who is an authority on <b><a href="http://datastori.es/84-statistical-numbing-with-paul-slovic/">statistical numbing</a></b> - this very effect of us having more emotional connection, empathy and response to <b>1</b> death than <b>100</b> deaths.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWyylUf2Pn-y9dfJyCeWGXy7DkOoZIFmGICd9RAl8mgP6g9R37X-mGsBRqlf5JdPUByjN4CqdGjfhQIAuZt6niGZjX2zzVKfNuAzfkWI76BPE8JAvWrbLNXqRi7Y0u_3L6NZaY6B5V2S-a/s1600/slovic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="843" data-original-width="1500" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWyylUf2Pn-y9dfJyCeWGXy7DkOoZIFmGICd9RAl8mgP6g9R37X-mGsBRqlf5JdPUByjN4CqdGjfhQIAuZt6niGZjX2zzVKfNuAzfkWI76BPE8JAvWrbLNXqRi7Y0u_3L6NZaY6B5V2S-a/s400/slovic.png" width="400" /></a></div>
<br />
Ed then showed a powerful graph demonstrating the non-linear response we, humans, have to different physical stimuli as they grow.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAGIudMVNtnzc6r9q71bR41vXVluH4rCdvbzjYdS1bhXNHgWkmJO73nJKqjGz4AbUQUZiClZFj4E9WVI3T-zu1pnc-K6VQyplpl9tn3Mizg4nRpNFMRIIvOfhUMLBfZdgTtchAJqHT3jpz/s1600/responces.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="843" data-original-width="781" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAGIudMVNtnzc6r9q71bR41vXVluH4rCdvbzjYdS1bhXNHgWkmJO73nJKqjGz4AbUQUZiClZFj4E9WVI3T-zu1pnc-K6VQyplpl9tn3Mizg4nRpNFMRIIvOfhUMLBfZdgTtchAJqHT3jpz/s400/responces.png" width="370" /></a></div>
<br />
For example:<br />
<ul>
<li>In a darkened room, a small <b>light</b> makes significant impression. Doubling the intensity of the light increases our response but doesn't double it. As the light continues to get brighter, our perception of it doesn't double. The largest change in response is between complete darkness and some light. </li>
<li><b>Sound</b> is similar to light - small noises against silence are perceived with greater difference than loud sounds compared with even louder sounds.</li>
<li><b>Heaviness</b> works in the opposite way - small tiny weights are imperceptible. Larger weights are definitely felt, and doubling a weight feels as if the weight was more than doubled. <b>Electric shocks</b>, like heaviness, are a direct pain sensation and we don't desensitise to them either.</li>
</ul>
<br />
There is some justification for these effects - evolution required us to be sensitive to small sounds and light - in order to survive in a sometimes hostile natural environment.<br />
<br />
From experiments, a similar graph can be constructed for human response for number of victims. It shows that our desire to help victims is most felt when there few victims. When there are many victims, our response doesn't multiply to the same extent.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWT_rVfTh1hVxBgb_NKT-SGlRGXhsxqrqCpftk8r-Dex_nfbhLVbqJmu_AH13dinYsyHhaQqu5o_KXJf_gENU_-Pc91vs0wLUHTKHKxjFmY0LQtY5dyzVkpDVzhGMsGmjj6JXcZY7jRDFn/s1600/victims.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="533" data-original-width="750" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWT_rVfTh1hVxBgb_NKT-SGlRGXhsxqrqCpftk8r-Dex_nfbhLVbqJmu_AH13dinYsyHhaQqu5o_KXJf_gENU_-Pc91vs0wLUHTKHKxjFmY0LQtY5dyzVkpDVzhGMsGmjj6JXcZY7jRDFn/s400/victims.png" width="400" /></a></div>
<br />
Large numbers of victims are more anonymous - statistics - harder to identify with as individuals.<br />
<br />
<br />
<h3>
Iraq Body Count Project</h3>
Ed contacted the <a href="https://www.iraqbodycount.org/">Iraq Body Count Project</a> which tries to maintain a count of civilian deaths as a result of the 2003 Iraq War.<br />
<br />
In an attempt to make the huge numbers more meaningful, and counter the effects of statistical numbing, Ed created an audio work to encourage a Slovic slow thinking response.<br />
<br />
He extracted key parameters from the body count data, such as victim age, and passed these into the <a href="https://supercollider.github.io/">Super Collider</a> audio programming environment. He used a method, called <b>granular synthesis</b>, taking small sound segments and further decomposing these in order to reconstruct a wider soundscape.<br />
<br />
A key compositional decision was not to create an amplitude based audio work. Instead, granular synthesis based on a sampling of earth being crunched, was used to layer sounds to create a sound texture over time.<br />
<br />
His piece, <b>For Dead Children and Electronics (2015)</b> is <b>8</b> minutes long.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuNZx8ijp6iCj8O0yT2OlMFzAItaVDonePqD-lUQI_tOeuMj45BHkiYRIE3Ea3Z-9mOEO0LwKaHwkbC-Jh37LyYpblUg7xzyD7jKy5he9u3cdIgGQ3_AjwTEfBn5Wwj0JgpoVV8x4_hS26/s1600/electronics.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="843" data-original-width="1500" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuNZx8ijp6iCj8O0yT2OlMFzAItaVDonePqD-lUQI_tOeuMj45BHkiYRIE3Ea3Z-9mOEO0LwKaHwkbC-Jh37LyYpblUg7xzyD7jKy5he9u3cdIgGQ3_AjwTEfBn5Wwj0JgpoVV8x4_hS26/s400/electronics.png" width="400" /></a></div>
<br />
In Ed's own <a href="https://soundcloud.com/ed-fish-2/for-dead-children-and-live-electronics">words</a>:<br />
<br />
<i>"A sonification of <b>10340</b> civilian deaths in Iraq since 2003. Using information provided by Wikileaks and Iraqbodycount.com the age of the fatality dicatates the duration, amplitude and reverberance of the grain. The younger the victim the louder, longer and more reverberant the pop."</i><br />
<br />
<div style="text-align: center;">
<iframe allow="autoplay" frameborder="no" height="200" scrolling="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/150556928&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true" width="80%"></iframe></div>
<br />
Listening to the piece, even for a couple of minutes, was a sombre, thoughtful and reflective experience. Knowing that each sound grain represented a death, and the louder ones were for younger children, forced us to think and understand, in slow time, the reality of the tragedy of the Iraq War.<br />
<br />
Ed's work of art grimly succeeded in forcing us to empathise with the human disaster, his work architected and designed to directly counter statistical numbing.<br />
<br />
Many of us felt a sadness descend on us as we listened.<br />
<br />
<br />
<h3>
Algorithmic Bias</h3>
Ed talked next about the tyranny of algorithms that, through their inflexibility or unsophistication, cause human misery by imposing the bias of their creators on others, especially those who have different ethnic origins or are transgender.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7ZOvHg104cKGvKl-cH_BYaUp4Y_G5QeYRzX5EVv_eo0WJObr_Nr-OcEaZvsyGv16CSdeYYJE2QclEOY-CWqj8xIg7G1z_6PW2mNErS9ZJiahy7leC2A8KkwxsaJdAsvOl2ewibzjU1WWO/s1600/bias.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="638" data-original-width="1277" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7ZOvHg104cKGvKl-cH_BYaUp4Y_G5QeYRzX5EVv_eo0WJObr_Nr-OcEaZvsyGv16CSdeYYJE2QclEOY-CWqj8xIg7G1z_6PW2mNErS9ZJiahy7leC2A8KkwxsaJdAsvOl2ewibzjU1WWO/s400/bias.png" width="400" /></a></div>
<br />
Ed talked about an example of facial recognition software, used by government, trained on a limited diversity of faces. The failure to recognise people who might be of different ethnic origin is not just an issue of inconvenience. The fact that they are then treated as suspects or with suspicion is a major issue. In addition, the wider public seeing these individuals being pulled aside for further questioning reinforces the stereo type that people who are Asian, for example, are more likely to be doing something illegal.<br />
<br />
The algorithm, badly designed or trained, becomes an unchallengeable tyrant.<br />
<br />
As an artists' response to this, <a href="https://www.gold.ac.uk/visual-cultures/staff/blas-zach/">Zach Blas</a> developed this own method for capturing the faces of people with diverse backgrounds and shapes. He crafted the meshes calculated from these captures into masks to be worn. But because these faces were more diverse than the software is typically expecting, the masks were an uncomfortable fit. To underline the issue, the tyranny, the masks were made of metal, and putting them on was not just uncomfortable, but a literal prison of metal bars.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxaOE2EFzswrUy1Rn1ud4Xa-ZkbtRBF0ZWW41nzB_Y90jXRaUAyBIjtHqo7Snt42bxBdBZA6l00hr2-X2-uB9S3KhGg1W9ynQx2vxjpX8foSRjdQ4GSJOy6GpxvBs19RgEaPhzBalatyvr/s1600/ezgif.com-video-to-gif.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="600" height="341" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxaOE2EFzswrUy1Rn1ud4Xa-ZkbtRBF0ZWW41nzB_Y90jXRaUAyBIjtHqo7Snt42bxBdBZA6l00hr2-X2-uB9S3KhGg1W9ynQx2vxjpX8foSRjdQ4GSJOy6GpxvBs19RgEaPhzBalatyvr/s400/ezgif.com-video-to-gif.gif" width="400" /></a></div>
<br />
<br />
<h3>
Are We Complicit?</h3>
Ed then took the discussion further and asked the provocative question: are we responsible?<br />
<br />
If these algorithms are using our data to act in undesirable ways, should we be more active in preventing our own personal data from being used?<br />
<br />
This question led Ed to develop a work of art which focussed on the connection between us, the passive or mildly participating public, and the actions of an algorithm.<br />
<br />
His research took him to the visualisation of slaves packed inhumanely tight into transport ships. Those slave ships themselves were consciously and intentionally designed for that purpose - to maximise the transportation of slaves with just enough room and air to keep enough alive. These macabre dimensions and proportions were used to inform the design if a pyramid sculpture which moved in response to viewers moving around and in proximity to it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlDz476guj_S-2MAzyw2ouKi2jAP-fYNkwLTrNOXayH1Y1AcAein3nax_9Hxl-CUrpeealdId9wH5fnYVcfIBE2dghkMYjDLhhQw4vxqzOJQZm7G37M0MCrPAKL9d593129mq-WgnzBvB-/s1600/DdKYlrfWkAAPyHY.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="646" data-original-width="761" height="338" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlDz476guj_S-2MAzyw2ouKi2jAP-fYNkwLTrNOXayH1Y1AcAein3nax_9Hxl-CUrpeealdId9wH5fnYVcfIBE2dghkMYjDLhhQw4vxqzOJQZm7G37M0MCrPAKL9d593129mq-WgnzBvB-/s400/DdKYlrfWkAAPyHY.jpg" width="400" /></a></div>
<br />
Ed reported that viewers initially couldn't understand how this triangular pyramid moves and changes in response to their own movement. The cause and effect is there - but the culpability isn't clear.<br />
<br />
The work starkly illustrates the core idea that each of us, individually, can't easily understand our own effect on the machine, exacerbated by the machine combining data from many of us. And that, in effect, distances our responsibility for the algorithm's actions.<br />
<br />
Ed also highlighted the converse - where a mob will deliberately subvert an algorithm by flooding it with biased or malicious data. In this sense, the culpability is real, but each individual participant of these attacks is again anonymous, hiding amongst the mob.<br />
<br />
<br />
<h3>
Group Discussion</h3>
Ed's talk stimulated us into a great passionate discussion covering a broad range of themes, included:<br />
<br />
<ul>
<li>Transparency and algorithms - is it as simple as demanding they must be open source? Can most people understand open sourced algorithms?</li>
<li>How journalists and artists can better explain tragedies given an understanding of statistical number.</li>
<li>The algorithm used to create the audio piece, For Dead Children and Electronics (2015).</li>
<li>The artist as a privileged person commenting on the lives of less privileged people - is that right? Or is it a duty on privileged artists to use their talents to create art that raises awareness?</li>
<li>The challenge of teaching children and younger people around personal data hygiene and privacy. The lack of education on personal data issues - and the need to do this before corporations take a lead on getting more personal data.</li>
<li>The toll on mental health of hyper-active social media platforms - and the benefits of digital disconnection. The idea of a "medical" limit on social media analogous to limits on alcohol and sugar. </li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWhfazg9i5wtXgKAnYdTRqU4Q6mGnT2PWeKu7AhszFaWiNr5UdfT8lI0ph4fISLF3IxYLW08iFionHahVFkpSCQGRSF9Rt4iiP5Pi0CnY3uErBmmHthXmTL-fGaaoLAVyDZLLRUy2gv3w9/s1600/ezgif.com-crop.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="302" data-original-width="600" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWhfazg9i5wtXgKAnYdTRqU4Q6mGnT2PWeKu7AhszFaWiNr5UdfT8lI0ph4fISLF3IxYLW08iFionHahVFkpSCQGRSF9Rt4iiP5Pi0CnY3uErBmmHthXmTL-fGaaoLAVyDZLLRUy2gv3w9/s400/ezgif.com-crop.gif" width="400" /></a></div>
<br />
<br />
<h3>
Further Links</h3>
<ul>
<li><b>Ed Fish's</b> website - <a href="http://edfish.co.uk/">http://edfish.co.uk</a></li>
<li><b>Granular Synthesis</b> explained again - <a href="http://granularsynthesis.com/guide.php">http://granularsynthesis.com/guide.php</a></li>
<li>Video interview / documentary on <b>Granular Synthesis</b> - <a href="https://www.youtube.com/watch?v=_Xy0szkt7ao">Part 1</a>, <a href="https://www.youtube.com/watch?v=_ehu8u_JTjw">Part 2</a>, <a href="https://www.youtube.com/watch?v=ul4y_e3TLyk">Part 3</a>.</li>
<li><b>Zach Blas, Face Cages </b>- <a href="http://www.zachblas.info/works/face-cages/">http://www.zachblas.info/works/face-cages/</a></li>
<li><b>Algorithmic Justice League</b> - <a href="https://www.ajlunited.org/">https://www.ajlunited.org</a></li>
</ul>
<br />Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-39362912232728520892018-04-29T06:13:00.002-07:002018-04-29T06:15:21.252-07:00Art From the PyData Art HackathonThis week <b>Algorithmic Art</b> were at the annual <b>PyData London</b> conference, where we ran a <a href="http://algorithmicartmeetup.blogspot.com/2018/04/algorithmic-art-hackathon-at-pydata.html">hackathon</a>.<br />
<br />
Data science skills and artistic creativity is a potent mix!<br />
<br />
<br />
<h3>
Donald Trump In Words</h3>
One of the teams combined text analytics and generative deep learning to great effect.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDj7-1Fb5WuwHQRKzW5mbzSA5NoYxAsigoBspqxAlgmSifQzngFCXUsCX_5dhWbZvinzzcDETK7zMn9Jp0ofEY9ekgzfjHpSZaHaHxXft_Yla_7AYyJ35kqGWwDBhJTL1ZQTv-sb1QZzdr/s1600/UMfzK3c.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1296" data-original-width="1168" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDj7-1Fb5WuwHQRKzW5mbzSA5NoYxAsigoBspqxAlgmSifQzngFCXUsCX_5dhWbZvinzzcDETK7zMn9Jp0ofEY9ekgzfjHpSZaHaHxXft_Yla_7AYyJ35kqGWwDBhJTL1ZQTv-sb1QZzdr/s400/UMfzK3c.jpg" width="360" /></a></div>
<br />
<br />
They developed a word cloud of Donald Trump's utterances, and then fed that to Google's deep dream system to combine the word cloud with a portrait of Trump.<br />
<br />
The result is very effective. A powerful element of the design is that the coloured shapes on the image are recognisable as words, but they are so distorted that they are hard to make sense of. This resonates with many people's view that Trump's speeches and tweets are difficult to understand, and that they bend and twist reality. As a portrait, his form is made up of these ambiguous words - a powerful statement on who his is.<br />
<br />
Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-76315009189662445022018-04-27T16:27:00.000-07:002018-04-27T23:47:15.490-07:00Algorithmic Art Hackathon at PyData London 2018<b>PyData London</b> is one of London's leading <a href="https://www.meetup.com/PyData-London-Meetup/">meetup</a> communities focussing on Python, open source and data science. They also organise a popular and well regarded annual <a href="https://pydata.org/london2018/">conference</a>.<br />
<br />
This year, <b>Algorithmic Art</b> have been kindly selected as a community sponsor. As well as an expo, we will run a hackathon as part of the conference <a href="https://pydata.org/london2018/schedule/">schedule</a>.<br />
<br />
<br />
<h3>
<span style="color: purple;">Theme: In The News</span></h3>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi12L-WC2vMn5Zl0dEHaxYDxGlb6kXGRNN-4d-J4BzUPVthdof_4EoP43OfgYrTMlbfPQUWjLIT01isI7GqysxFm5-5cFhxQMoEe1S9L55D2OyHWqwfLwOXuABjt9lO78awHmabc9GRJAuW/s1600/In_The_News.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="443" data-original-width="1600" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi12L-WC2vMn5Zl0dEHaxYDxGlb6kXGRNN-4d-J4BzUPVthdof_4EoP43OfgYrTMlbfPQUWjLIT01isI7GqysxFm5-5cFhxQMoEe1S9L55D2OyHWqwfLwOXuABjt9lO78awHmabc9GRJAuW/s640/In_The_News.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
<span style="color: purple;">Hackathons</span></h3>
An art <a href="https://en.wikipedia.org/wiki/Hackathon">hackathon</a> means coming together in a shared space, and being collectively inspired to create algorithmic art at the event itself.<br />
<br />
Hackathons are really fun, hands on practical (there's no talk or lecture), and we're often surprised how much can be created in a limited time.<br />
<br />
Beginners are very welcome, as well as more experienced friends who can help others.<br />
<br />
<br />
<h3>
<span style="color: purple;">Artistic and Practical Constraints</span></h3>
All the best art emerges from constraints, often consciously self-imposed. This hack will have some constraints:<br />
<br />
<ul>
<li>Your art must be accessible over the internet using a web browser - without the need for additional plug-ins or extensions.</li>
</ul>
<ul>
<li>The code which creates your art must also be available over the internet.</li>
</ul>
<ul>
<li>You must allow your code and work to be publicly viewable, freely copyable and reusable (<a href="https://creativecommons.org/licenses/by-sa/4.0/">CC-SA</a>). </li>
</ul>
<ul>
<li>We have 90 minutes to create the art from scratch.</li>
</ul>
<ul>
<li>The work must be inspired by the theme "<b>In The News</b>". You are free to interpret this as you wish. You may wish to consider using data or algorithms based on current affairs and issues currently in the news. Unlike more objective data visualisation, you're encouraged to infuse your art with your opinion or emotional response.</li>
</ul>
<ul>
<li>You should use open source tools wherever possible. Others should be able to recreate your work or re-apply your method without undue barriers.</li>
</ul>
<ul>
<li>Your own constraints (colour, shape, mathematical, other) - do tell us when you're showing your work.</li>
</ul>
<br />
<br />
<br />
<h3>
<span style="color: purple;">Timing</span></h3>
To make sure things get done, we'll stick to the following schedule:<br />
<br />
<ul>
<li>13.30 - 13.45 <b>Introduction</b>, organising teams if you wish to work in a team, identifying helpers</li>
</ul>
<ul>
<li>13.45 - 15.15 <b>Art Hackathon!</b></li>
</ul>
<ul>
<li>15.15 - 15.45 <b>Showcase </b>- talk about your work, inspiration, aim, method, algorithm. </li>
</ul>
<ul>
<li>15.45 <b>Prizes</b> awarded!</li>
</ul>
<br />
<br />
<br />
<h3>
<span style="color: purple;">Beginners</span></h3>
Support will be available for beginners to get going. Volunteers for helping out really welcome!<br />
<br />
If you're very new, an good option is using <a href="https://processing.org/">Processing</a> - an easy to learn and use language designed for artists and designers. Code directly on the web using <a href="https://www.openprocessing.org/">openprocessing</a> which makes it even easier to use <a href="https://p5js.org/">p5js</a>, the very popular web version of Processing. You can refer to online tutorials for p5js, including:<br />
<br />
<ul>
<li>Daniel Shiffman's friendly and fun <a href="https://www.youtube.com/user/shiffman/playlists?shelf_id=2&view=50&sort=dd">Introductory Videos</a></li>
<li>Tutorial from a previous meetup - <a href="http://algorithmicartmeetup.blogspot.co.uk/2017/12/a-gentle-intro-to-processing-coding-for.html">A Gentle Intro To Coding For Artists</a></li>
<li><a href="https://p5js.org/reference/">P5js Referece</a> - covers 2d, animation, sound, video, interaction</li>
<li>Inspiration from previous hackathons - <a href="http://algorithmicartmeetup.blogspot.co.uk/2018/03/art-hackathon-i-want-to-believe.html">"I Want To Believe"</a> and <a href="http://algorithmicartmeetup.blogspot.co.uk/2017/09/art-hackathon-future-pangs.html">"Future Pangs"</a></li>
</ul>
<br />
<br />
<br />
<h3>
<span style="color: purple;">Prizes</span></h3>
Three prizes will be awarded in the following categories:<br />
<br />
<ol>
<li>Complete <b>beginner</b> award</li>
<li>Best use of <b>algorithms</b> and/or <b>data</b></li>
<li>Most effective <b>emotional impact</b></li>
<li>Most convincing algorithmic <b>text generation</b></li>
</ol>
<br />
<br />
<h3>
<span style="color: purple;">Submissions</span></h3>
Please complete this online form to make your submission:<br />
<br />
<ul>
<li><a href="https://docs.google.com/forms/d/e/1FAIpQLSe9IUnKmbhBAD3FksYvuAdkbDLq965AAcMjHSQEvPoQcUvf3g/viewform?usp=sf_link" target="_blank"><b><span style="color: blue;">Submission Form</span></b></a></li>
</ul>
<br />
<br />
Your work may be displayed on the <a href="http://algorithmicartmeetup.blogspot.co.uk/">Algorithmic Art blog</a> or shared on <a href="https://twitter.com/algorithmic_art">Twitter @algorithmic_art</a>. Do let us know if you prefer your work not to be shared like this.Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-21082514132619171102018-04-26T17:09:00.002-07:002018-04-26T17:09:42.240-07:00Recursion for BeginnersThis <a href="https://www.meetup.com/Algorithmic-Art/events/248300309/">month</a> we had a gentle introduction to <a href="https://en.wikipedia.org/wiki/Recursion">recursion</a> - a powerful idea that can create wonderful patterns - but one that we sometimes struggle with when we first come across it.<br />
<br />
Here's an example of the kind of pattern that can emerge from recursion.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguNAo9I8JnzWs98qTvErjgNucwf8w4EmR2qlwh2dZP6sF0Iv62-0mLnqz28Dw7xfsXhCQu23SOfT9NI6oZjhVgqc0MhpwrzLc3iEG7iA5oDbdaq1UqrW9gdGxEte7Enkn96lHamx14xXiM/s1600/p6_turtle_out_9c.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1194" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguNAo9I8JnzWs98qTvErjgNucwf8w4EmR2qlwh2dZP6sF0Iv62-0mLnqz28Dw7xfsXhCQu23SOfT9NI6oZjhVgqc0MhpwrzLc3iEG7iA5oDbdaq1UqrW9gdGxEte7Enkn96lHamx14xXiM/s400/p6_turtle_out_9c.png" width="400" /></a></div>
<br />
The <b>slides</b> are always at: <a href="https://goo.gl/w9C8Kg">[link]</a>. The slides also contain links to <b>code</b> you can experiment with.<div>
<br /></div>
<div>
<b>Video</b> of the talk is at: <a href="https://skillsmatter.com/skillscasts/11636-recursion-for-beginners">[skillsmatter]</a>.</div>
<br />
<br />
<h3>
Aim</h3>
The aim of the session was try to:<br />
<br />
<ul>
<li>explain what recursion is, and to be able to recognise it when others use it</li>
<li>use simple examples to get a feel for the mechanics of recursion</li>
<li>to develop a way of thinking which can help make our own recursive algorithms</li>
</ul>
<br />
<div>
And to inspire members to try their own ideas for recursive algorithms.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Start With Observation</h3>
<div>
We warmed up by looking at a few examples of patterns and natural forms. We observed that a common theme amongst the images was self-similarity at different scales - which some knew to call <a href="https://en.wikipedia.org/wiki/Fractal">fractal</a>.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK_ZIIMBZbXI_JZO4b58evvMXLOp8bc9k19ZQXoHwMBGVqLlTYN0b1Yp5TM316Ku2fLA69xVUGkQSTeb2vJ6faNx5KhmnJTgx_lqvzAxwqv7hV5BjcIhty0uGTuTfs6BqLqJL7_6cKJ5fg/s1600/fern_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1453" data-original-width="1600" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK_ZIIMBZbXI_JZO4b58evvMXLOp8bc9k19ZQXoHwMBGVqLlTYN0b1Yp5TM316Ku2fLA69xVUGkQSTeb2vJ6faNx5KhmnJTgx_lqvzAxwqv7hV5BjcIhty0uGTuTfs6BqLqJL7_6cKJ5fg/s400/fern_0.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
A good example was from nature itself - a fern leaf. Looking at the fern above, we can imagine snipping off one of the branches, and examining it to find that it looks remarkably like the whole. In fact the snippet itself has smaller branches. When you're looking for self-similarity, you start to see it everywhere - from the artery structure of a human body to the fluffy clouds in a summer sky, from the lumps and bumps of a mountain, to the repeated motif of purely mathematical fractals like this <a href="http://algorithmicartmeetup.blogspot.co.uk/2017/03/the-haunting-beauty-of-mandelbrot.html">Julia fractal</a>.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGWv9bWbeuaUG5ScYz_XaYb4syTLi1BOp2yCUW5E_k0v57VPg4DnCADDUf1EMZ8wA_hOa_9on_ycpWsI2amQmTYQ4Uq1QSDIvIH3SWmxhtjuIuAdxRCYE-pAmHS6Lc65pdtw0dvvt8r00t/s1600/p4_julia_final.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1600" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGWv9bWbeuaUG5ScYz_XaYb4syTLi1BOp2yCUW5E_k0v57VPg4DnCADDUf1EMZ8wA_hOa_9on_ycpWsI2amQmTYQ4Uq1QSDIvIH3SWmxhtjuIuAdxRCYE-pAmHS6Lc65pdtw0dvvt8r00t/s400/p4_julia_final.png" width="400" /></a></div>
<div>
<br /></div>
<div>
After a few examples, our mind's eye was primed to spot this kind of self-similarity for the rest of the talk.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
An Apparently Unhelpful Definition</h3>
<div>
We started our discussion, not by defining recursion or talking about someone else's definition. The reason many of us were here is because that approach hadn't worked!</div>
<div>
<div>
<br /></div>
<div>
We started instead by pondering this interesting conversations between ladies in a Victorian garden:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW2GSsw5E8Rg4lqeuF1KAjK41tLwDoLxvz7D2aNQsyfrCSnSMtKkpPsVK4S4R3YonvMr6dmwUR9azYYRgTosB_TaAldrcwVjbpTZEd3GxJHPIyXH6raLlzwSI5oB4kg3yxBQIOpx6jNdPH/s1600/recursive_defn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="952" data-original-width="1600" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW2GSsw5E8Rg4lqeuF1KAjK41tLwDoLxvz7D2aNQsyfrCSnSMtKkpPsVK4S4R3YonvMr6dmwUR9azYYRgTosB_TaAldrcwVjbpTZEd3GxJHPIyXH6raLlzwSI5oB4kg3yxBQIOpx6jNdPH/s400/recursive_defn.png" width="400" /></a></div>
<div>
<br /></div>
<div>
We overhear a lady asking another lady (with the rose), <b><i><span style="color: blue;">"what's 3?</span>"</i></b>. The reply is <b><i><span style="color: #cc0000;">"1 more than 2"</span></i></b>. That doesn't seem very helpful, so the lady asks again, <b><i><span style="color: blue;">"what's 2?"</span></i></b>. Again the reply is <b><i><span style="color: #cc0000;">"1 more than 1"</span></i></b>. How annoying! The lady tries again, <b><i><span style="color: blue;">"what's 1?"</span></i></b>. This time the reply is a little bit more helpful, <b><i><span style="color: #cc0000;">"that's how many noses you have."</span></i></b></div>
<div>
<br /></div>
<div>
It does seem like the lady with the rose is being very obtuse and determined to be unhelpful. I'm not sure I'd enjoy a conversation like that. Imagine if I'd started with <b><i><span style="color: blue;">"what's 100?"</span></i></b> - the conversation would have been very long and boring.</div>
<div>
<br /></div>
<div>
Let's look at the conversation from a different perspective. </div>
<div>
<br /></div>
<div>
The lady with the rose has actually been very clever. She has only used <b>2</b> kinds of responses:</div>
<div>
<ol>
<li><b>"1 more than ...."</b></li>
<li><b>"that's how many noses you have".</b></li>
</ol>
<div>
<br /></div>
Using only these two responses, she is able to describe any whole number, be that <b>3</b>, <b>7</b>, <b>99</b> or even <b>22139</b>. Sure, the conversation that starts with <b><i><span style="color: blue;">"what's 22139?"</span></i></b> will be long and boring, but remember that we can offload repetitive and boring tasks to our computers to do quickly and without fuss or boredom error. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsXj61tXUqhLZi-RsWXBEsBmL1J9PTY_P6vyZOrA7zwRMQvWKXjPijPv-4bLg-v2mZ7s4x5LLXaNDaVQOgW_oitLMw6drryBqq2Jww8nS6TTw84EzvxtTz8SxwuoThGYg3paVmA1pJ8TOl/s1600/Recursion+for+Beginners.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsXj61tXUqhLZi-RsWXBEsBmL1J9PTY_P6vyZOrA7zwRMQvWKXjPijPv-4bLg-v2mZ7s4x5LLXaNDaVQOgW_oitLMw6drryBqq2Jww8nS6TTw84EzvxtTz8SxwuoThGYg3paVmA1pJ8TOl/s400/Recursion+for+Beginners.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Let's say that again - the lady with the rose, has been able to describe any one of the infinitely many whole positive numbers using just those 2 rules. That's pretty amazing!</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Visual Patterns with Just Two Rules?</h3>
<div>
Then came a thought leap. What if .. what if it was possible to describe complex patterns using just <b>2</b> rules? </div>
<div>
<br /></div>
<div>
That's a powerful and ambitious statement. But let's start with a not so complicated pattern so we can focus on the idea first. </div>
<div>
<br /></div>
<div>
Here are the ladies describing circles.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXrj7GnqcNcSOJudqK2YNT4w-aeKIUvnytXVLd93LeifAYEKIVGH2KN_uxPjAvRPOcmpdBXPWoTw4uM2tbi2aALZ1crz55SILA4xiHNdH3023XGdd1a_vE__eY6yYnXowDXLrMotXrPvhE/s1600/recursive_defn_circle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="952" data-original-width="1600" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXrj7GnqcNcSOJudqK2YNT4w-aeKIUvnytXVLd93LeifAYEKIVGH2KN_uxPjAvRPOcmpdBXPWoTw4uM2tbi2aALZ1crz55SILA4xiHNdH3023XGdd1a_vE__eY6yYnXowDXLrMotXrPvhE/s400/recursive_defn_circle.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Again, the lady with the rose is able to respond to questions about circles of any size using only <b>2</b> replies:</div>
<div>
<ol>
<li><b>"... one size bigger than ..."</b></li>
<li><b>"O"</b></li>
</ol>
</div>
<div>
<br /></div>
<div>
And again, her approach is clever, because with just those 2 rules, albeit with lots of repetition, she is is able to describe circles of any size. </div>
</div>
<div>
<br /></div>
<div>
We then tried to visualise this mechanism of describing something in term so the next thing, whether that's a number or a circle. Visualising something, or even trying to visualising something, is a good way of developing empathy with the mechanism at play.</div>
<div>
<br /></div>
<div>
We did this visualisation with just "pen and paper" not with code, to keep our focus on what's important - the concept. We started with the idea of a circle of size <b>3</b>, which is one size bigger than a circle of size <b>2</b> .. which is one size bigger than a circle of size <b>1</b> .. and a circle of size one is just <b>O</b>. This resulted in a picture of concentric circles with the largest being of size <b>3</b>.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgt8iVnI-XaMC3xlLUBFQLPku8ugNuNT3rLFyNmkF5HNDZyDXopulNO-xt-1jLZCP90naMmM-g3tJ9qQ3W2BdA2tYxQcXpaC5v_bTmMxpt8UY7rkLmKZubxIcBQXwPQmTI_IaU91F12FO/s1600/Recursion+for+Beginners-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgt8iVnI-XaMC3xlLUBFQLPku8ugNuNT3rLFyNmkF5HNDZyDXopulNO-xt-1jLZCP90naMmM-g3tJ9qQ3W2BdA2tYxQcXpaC5v_bTmMxpt8UY7rkLmKZubxIcBQXwPQmTI_IaU91F12FO/s400/Recursion+for+Beginners-3.png" width="400" /></a></div>
<div>
<br /></div>
<div>
We then asked ourselves the question - what if we had started at size <b>4</b>? We know a circle of size <b>4</b> is one size bigger than a circle of size <b>3</b>. That means the picture we drew starting at size <b>3</b> can be reused. We've already done the work for circles of size <b>3</b>, <b>2</b> and <b>1</b>. The overall picture is a little bit more complex than the one starting at size <b>3</b>.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHm8CjQynvVBCF07GAUZkt1CpHxa5GYnLshmKUTKuCrX0bAhIc7Ypn2YP6QfnrJKSszoYIJa2W3TZi5O63Ih-qlH0k-DyczxAuIlqCXv8D-ok4R3z4EoIxbQgoN7vQNVeK0eanMj7JRx0f/s1600/Recursion+for+Beginners-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHm8CjQynvVBCF07GAUZkt1CpHxa5GYnLshmKUTKuCrX0bAhIc7Ypn2YP6QfnrJKSszoYIJa2W3TZi5O63Ih-qlH0k-DyczxAuIlqCXv8D-ok4R3z4EoIxbQgoN7vQNVeK0eanMj7JRx0f/s400/Recursion+for+Beginners-2.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Although these concentric circles aren't very intricate in design, we can start to see how the very same <b>2 rules</b> can be used to create more and more complex or detailed patterns. </div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Coding</h3>
<div>
We then started thinking about how we might write code to create the previous pattern, which is visualising the relationship between circles of different sizes, as defined by the <b>2 rules</b>.</div>
<div>
<br /></div>
<div>
To keep things clear, we wrote in plain-English pseudocode, avoiding the distractions of real programming languages and their peculiar syntax.</div>
<div>
<br /></div>
<div>
Our first attempt was to simple three instructions to draw a circle: <b>circle(size = 3)</b>, <b>circle(size = 2)</b>, and <b>circle(size = 1)</b>. That would certainly create that pattern of three concentric circles. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitooykzTo4rwVZ_g9NeB4Nexuf1aAgbG4u1JbFMvSIQRHyjT6etbEpDqJhSWedxh1IuWzRVEDxFObRXTHnf8I0y0D4n91HiellMXSrXc5Zw8Vuh3FiLUfp0YQrxCWaLsAsNm_6ly3WS-Kv/s1600/Recursion+for+Beginners-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitooykzTo4rwVZ_g9NeB4Nexuf1aAgbG4u1JbFMvSIQRHyjT6etbEpDqJhSWedxh1IuWzRVEDxFObRXTHnf8I0y0D4n91HiellMXSrXc5Zw8Vuh3FiLUfp0YQrxCWaLsAsNm_6ly3WS-Kv/s400/Recursion+for+Beginners-4.png" width="400" /></a></div>
<div>
<br /></div>
<div>
But - what if we wanted to start with a circle of size <b>100</b>? We'd have to write out <b>100</b> different <b>circle()</b> commands!</div>
<div>
<br /></div>
<div>
We'd forgotten the clever ladies in the Victorian garden. They were clever enough to be able to describe numbers or circles of any size with just <b>2 rules</b>. They didn't need <b>100</b> statements to describe <b>100</b> different circles. </div>
<div>
<br /></div>
<div>
We tried again, this time trying to reflect the ladies' approach:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8hAD6a6IL-EF19bo7hc4m6RqNnUtEusaoSdOU-7ydWZHmdPNIHRsn8ztCPCPXU0VbLR1HBvGDxvD5fIDgb3JVFDuGUmGYgQOEfB6dq10XSkJRwCR42MBSesuZQVzVZnPh5KUbd6to4E_I/s1600/Recursion+for+Beginners-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8hAD6a6IL-EF19bo7hc4m6RqNnUtEusaoSdOU-7ydWZHmdPNIHRsn8ztCPCPXU0VbLR1HBvGDxvD5fIDgb3JVFDuGUmGYgQOEfB6dq10XSkJRwCR42MBSesuZQVzVZnPh5KUbd6to4E_I/s400/Recursion+for+Beginners-5.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Here we're saying "let's draw a pattern of size 3", and we're defining that pattern.</div>
<div>
<br /></div>
<div>
The definition of a pattern of size<b> s</b> is a circle of size <b>s</b>, and a smaller pattern of size <b>s-1</b>. That needed a bit of thinking but is it does reflect the ladies' thinking - defining one thing in terms of the next thing. </div>
<div>
<br /></div>
<div>
It can seem strange that we are allowed to define something in terms of itself, especially in a computer programming language - but many programming languages do allows us to do this - and it is incredibly useful.</div>
<div>
<br /></div>
<div>
And definitions which refer to themselves are <b>recursive</b> definitions - hence the word <b>recursion</b>.</div>
<div>
<br /></div>
<h3>
<br />Logic Error!</h3>
<div>
Let's see what happens if we invoke that newly defined <b>my_pattern()</b> with an size of <b>4</b>, that is, <b>my_pattern(4)</b>. </div>
<div>
<br /></div>
<div>
We expect to see a pattern of <b>4</b> concentric circles, like this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmiUqYAkw-L4EOvUbMQd3pORHojk0B_wnYSr8iMqlLIKJXXI98dHRQwSYvQbO2hPj1v3x5v6MQT2X4MZM0elr43Rq_z_gXTnccPw35oPSWUsK6BIfMCUzNmLZdLSAZO3LAQiw6sd5TjuyX/s1600/Recursion+for+Beginners-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmiUqYAkw-L4EOvUbMQd3pORHojk0B_wnYSr8iMqlLIKJXXI98dHRQwSYvQbO2hPj1v3x5v6MQT2X4MZM0elr43Rq_z_gXTnccPw35oPSWUsK6BIfMCUzNmLZdLSAZO3LAQiw6sd5TjuyX/s400/Recursion+for+Beginners-6.png" width="400" /></a></div>
<div>
<br /></div>
<div>
If we actually ran that code, it's unlikely that we'd see these 4 circles. </div>
<div>
<br /></div>
<div>
Instead we'd probably find our computer giving us an error, or becoming unresponsive. Why?</div>
<div>
<br /></div>
<div>
If we look again at the code, and follow it through step by step, we can see what happens:</div>
<div>
<ul>
<li><b>my_pattern(4)</b> means a circle of size <b>4</b>, and then <b>my_pattern(3)</b></li>
<li><b>my_pattern(3)</b> means a circle of size <b>3</b>, and then <b>my_pattern(2)</b></li>
<li><b>my_pattern(2)</b> means a circle of size <b>2</b>, and then <b>my_pattern(1)</b></li>
<li><b>my_pattern(1)</b> means a circle of size <b>1</b>, and then <b>my_pattern(0)</b></li>
<li><b>my_pattern(0)</b> means a circle of size <b>0</b>, and then <b>my_pattern(-1)</b></li>
<li><b>my_pattern(-1)</b> means a circle of size <b>-1</b>, and then <b>my_pattern(-2)</b></li>
<li><b>my_pattern(-2)</b> means a circle of size <b>-2</b>, and then <b>my_pattern(-3)</b></li>
<li>.... and so on</li>
</ul>
</div>
<div>
<br /></div>
<div>
Our code doesn't stop at circle size <b>1</b> ... it carries on. </div>
<div>
<br /></div>
<div>
We missed one of the <b>two rules</b> that the ladies' discussed, the rule that <b>terminates</b> this chain. With the numbers example, the rules terminated at number <b>1</b>, and the circles example terminates at circle size <b>1</b>. We need to terminate this pattern at pattern size <b>1</b>.</div>
<div>
<br /></div>
<div>
Let's try again, and this time care care to include both rules:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1NHY4j7hl4nLWa9_rLCsA-vUdukAGBOwUc81_y2lwUlzuIWGs-iYvY_J90DCf2q3cAKq5CW-O1m7ZW258pcelB5DZXcW5pB4CqJclUG_dijHw0cmjTAb3-6JvUAWAhcrksMNFaouTYKGf/s1600/Recursion+for+Beginners-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1NHY4j7hl4nLWa9_rLCsA-vUdukAGBOwUc81_y2lwUlzuIWGs-iYvY_J90DCf2q3cAKq5CW-O1m7ZW258pcelB5DZXcW5pB4CqJclUG_dijHw0cmjTAb3-6JvUAWAhcrksMNFaouTYKGf/s400/Recursion+for+Beginners-7.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Here we've written code to explicitly reflect the <b>2 rules</b> - which we've called the <b>continuation rule</b>, and the <b>termination rule</b>. One rule checks to see if the <b>termination</b> condition has been reached - pattern size <b>1</b> - and if it has, then we draw the circle size<b> 1</b> and finish. If we haven't reached the termination condition, we draw the circle of size <b>s</b>, and continue with a smaller pattern of size <b>s-1</b>.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Recursion - Termination and Continuation Rules</h3>
<div>
We talked about the generality of this approach in all recursive definitions:</div>
<div>
<ul>
<li>a <b>continuation rule</b> - which defines how the current level of detail relates to the next level of detail</li>
<li>a <b>termination rule</b> - with defines when the continuation stops</li>
</ul>
</div>
<div>
<br /></div>
<div>
<b>Continuation</b> links one level of detail to the next level of detail. It's the clever bit which recognises a symmetry or pattern that we can use to link, and keep linking, one level of detail or size to the next. </div>
<div>
<br /></div>
<div>
<b>Termination</b> is critical - without it the continuation never stops. That might be fine in pure mathematics (eg 1 + 1/2 + 1/4 + 1/8 + 1/16 ... = 2) but when computing we can't continue to infinity.</div>
<div>
<br /></div>
<div>
We talked about trying to think of imagined patterns, or even forms that we see in nature, in terms of these 2 rules - good practice for becoming a more proficient algorithmic artist.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Hard Work Pays Off</h3>
<div>
Once we've put the effort into defining a pattern recursively, using the two rules, we can start to reap the benefits.</div>
<div>
<br /></div>
<div>
What happens if we invoke <b>my_pattern(10)</b>. We automatically get a pattern of <b>10</b> circles! No additional work needed to be done by us. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyALZVFM5D-DaWC5Zztc2r-i5rPdzOzqEfWxZsgiymwtHGx4U_VAgRmatTebicgCzslNLESDdj1Wb1WxfkzkX-lPCB4Pqut2MXjBTjvGTIo_vnEGtlDeLTCuAOZ-PkUnYj3L_AbOZrnZHn/s1600/pattern_10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1193" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyALZVFM5D-DaWC5Zztc2r-i5rPdzOzqEfWxZsgiymwtHGx4U_VAgRmatTebicgCzslNLESDdj1Wb1WxfkzkX-lPCB4Pqut2MXjBTjvGTIo_vnEGtlDeLTCuAOZ-PkUnYj3L_AbOZrnZHn/s400/pattern_10.png" width="400" /></a></div>
<div>
<br /></div>
<div>
That's an important point. Once we've invested the effort think recursively, and define the pattern recursively, we can then very easily draw patterns of many sizes, or levels of detail.</div>
<div>
<br /></div>
<div>
This goes right back to the original chat the ladies had, where the lady with the rose cleverly defined rules which could describe any positive whole number. </div>
<div>
<br /></div>
<div>
We could easily invoke <b>my_pattern(1000)</b> if we wanted to, and we'd get <b>1000</b> concentric circles.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
More Interesting Patterns</h3>
<div>
Once we've got used to the the key idea of recursion and recursive thinking, we can then have a lot of fun experimenting and extending the ideas.</div>
<div>
<br /></div>
<div>
We discussed an imaginary pattern called <b>The Mysterious Holocrux</b>, which the ladies defined as a circle with two smaller <b>holocrux</b> patterns either side of it.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuvOZ6ezIbAauWplwn63iYb2o3fOocBKePAHlAfsQFnCcmSr6ed9I19pNePSGIy-dpUh7_iDAbe5xNk5bC7XXmS-S7Vqn6UM8zZiLSoYeC34qIZEPkBWuAXAoDG4GE9r4OO9gSMbheMU_r/s1600/recursive_defn_holocrux.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="952" data-original-width="1600" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuvOZ6ezIbAauWplwn63iYb2o3fOocBKePAHlAfsQFnCcmSr6ed9I19pNePSGIy-dpUh7_iDAbe5xNk5bC7XXmS-S7Vqn6UM8zZiLSoYeC34qIZEPkBWuAXAoDG4GE9r4OO9gSMbheMU_r/s400/recursive_defn_holocrux.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Here's a sketch of what a <b>holocrux</b> of size <b>300</b> looks like - a circle of size <b>300</b>, with a <b>holocrux</b> of size <b>200</b> either side of it.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGOMe5AKI7SB4uuiPn3ev7KfJi1rWOtcYE_BPBHMcEdJwdJOVN5XgFmJ7_SRie9bVFVpEJW-G6hSMPAeSOmdBetUdOI1fiwg-NEmwmrGXjrfCauYp8CruS8nHvPpkY9LfGMkW6Ty1oiHWL/s1600/p4_holocrux_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGOMe5AKI7SB4uuiPn3ev7KfJi1rWOtcYE_BPBHMcEdJwdJOVN5XgFmJ7_SRie9bVFVpEJW-G6hSMPAeSOmdBetUdOI1fiwg-NEmwmrGXjrfCauYp8CruS8nHvPpkY9LfGMkW6Ty1oiHWL/s400/p4_holocrux_0.png" width="400" /></a></div>
<div>
<br /></div>
<div>
We can fill in the blanks - because the same rules tell us what a <b>holocrux</b> of size <b>200</b> is.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWR46HQpMcgMSvt7mkcj_4ZCmlgPiFT_68My8uZM69h-Z3zK5FQWaEN0EPmGN4Jxs_tN5tKfryj0pmqbAn4RyBuSEB-O1IIeTGXnZ0GbZ5MA3MJwteLOLnVDLeE98NXIhzGw1HALfYlo5X/s1600/p4_holocrux_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWR46HQpMcgMSvt7mkcj_4ZCmlgPiFT_68My8uZM69h-Z3zK5FQWaEN0EPmGN4Jxs_tN5tKfryj0pmqbAn4RyBuSEB-O1IIeTGXnZ0GbZ5MA3MJwteLOLnVDLeE98NXIhzGw1HALfYlo5X/s400/p4_holocrux_1.png" width="400" /></a></div>
<div>
<br /></div>
<div>
If we carry on to the next level of detail ...</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuKw6sNalIG_aooZXx62_EpBeIWnwEBiSte23IEnZjxcf8FruSZ50mt6B9Vstfd8SLuxQtkGtXFKAc0JtJJrs-_3qZ-jFrcD19WmQx9utt0zgUpUQIjvoczN_fIxcO9REfeAL7BFJPTMV6/s1600/p4_holocrux_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuKw6sNalIG_aooZXx62_EpBeIWnwEBiSte23IEnZjxcf8FruSZ50mt6B9Vstfd8SLuxQtkGtXFKAc0JtJJrs-_3qZ-jFrcD19WmQx9utt0zgUpUQIjvoczN_fIxcO9REfeAL7BFJPTMV6/s400/p4_holocrux_2.png" width="400" /></a></div>
<div>
<br /></div>
<div>
This is just like the concentric circles example but the next level of detail has 2 circles for every 1 circle, and they're shifted along rather than remaining centred on the same point. </div>
<div>
<br /></div>
<div>
When we talked about coding this idea, we introduced a new idea.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcuExVPz7UIvgEfbwIJaBtWqB6fh674DLT_UZKNwynCOAa5occ2m5cqte_dIJEqV-9eKJDRuZYxh7NWVTfqCCt9ipH71z66x3rjxfuO-P1HKHAUsGTxzmig_54ejGV8n_OdjMij_ntE3QR/s1600/Recursion+for+Beginners-8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcuExVPz7UIvgEfbwIJaBtWqB6fh674DLT_UZKNwynCOAa5occ2m5cqte_dIJEqV-9eKJDRuZYxh7NWVTfqCCt9ipH71z66x3rjxfuO-P1HKHAUsGTxzmig_54ejGV8n_OdjMij_ntE3QR/s400/Recursion+for+Beginners-8.png" width="400" /></a></div>
<div>
<br /></div>
<div>
We've combined the termination and continuation rules. The logic is still the same, but the programming language allows us to express both concisely. Here, when we say <b>"continue as long as the size s is more than 0"</b> we're expressing both rules:</div>
<div>
<ul>
<li><b>termination</b> when the size is <b>0</b> or less</li>
<li><b>continuation</b> as long as the size is more than <b>0</b></li>
</ul>
</div>
<div>
<br /></div>
<div>
This is actually a very common way of coding recursive algorithms so worth getting used to spotting.</div>
<div>
<br /></div>
<div>
The results are starting to look more interesting than concentric circles. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJtvYgrIbS_BcPQveg633VUyVvCIF7_1lawBlCvbCPPUKL8tR2e38WBQqJgCkhjhWwUJ7psmtJ_WZ7J8lTLmdYohYHZ9GUGQpw0hNBFuW0yLTWUz-SviM4cXQYANJUpHYcSKlkf6FLpzVo/s1600/Screen+Shot+2018-04-26+at+23.24.29.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1193" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJtvYgrIbS_BcPQveg633VUyVvCIF7_1lawBlCvbCPPUKL8tR2e38WBQqJgCkhjhWwUJ7psmtJ_WZ7J8lTLmdYohYHZ9GUGQpw0hNBFuW0yLTWUz-SviM4cXQYANJUpHYcSKlkf6FLpzVo/s400/Screen+Shot+2018-04-26+at+23.24.29.png" width="400" /></a></div>
<div>
<br /></div>
<div>
That pattern could do with more details, so let's change the logic so that the recursion continues for longer as the circles get smaller. Let's also change the rate at which circles get smaller.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4R25EObmnFpFvOICo-XOC39Us8KrHVdcWDnRv3WFvc-q6Og1MODGlBT1wk4E4Vh08_hP5yQ8PyztnlMeNbqMG7NVBUDsDonoRhEGbtANQSfPep3D8NLcnhx_ZXxLH8CSc_4WH1X4uyxoI/s1600/Recursion+for+Beginners-9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4R25EObmnFpFvOICo-XOC39Us8KrHVdcWDnRv3WFvc-q6Og1MODGlBT1wk4E4Vh08_hP5yQ8PyztnlMeNbqMG7NVBUDsDonoRhEGbtANQSfPep3D8NLcnhx_ZXxLH8CSc_4WH1X4uyxoI/s400/Recursion+for+Beginners-9.png" width="400" /></a></div>
<div>
<br /></div>
<div>
We introduced a new idea again. This time the termination condition was changed to s > 5, and not left as s > 0. We discussed why this might be. </div>
<div>
<br /></div>
<div>
The reason is that we're halving the size of the circles with every continuation. No matter how many times we halve a number, we never get to zero. That would mean our computers groan, become unresponsible and throw us an error. That's why we need to stop when size reaches a number bigger than <b>0</b>, like <b>5</b>.</div>
<div>
<br /></div>
<div>
Here's the result.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpqmWLeP6R2yPYT3eLWkK24Es6_2wnIf43XTC9ksY8TOK4XOpWLcs_UlgAw-ydWGSUIugflAopkZROzFUOsJntd2iPeYwvh7KYz49DWwQBUB-rW3Ut49MKNUOQd6f42u05Ee1GShatGTba/s1600/Screen+Shot+2018-04-26+at+23.32.54.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1193" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpqmWLeP6R2yPYT3eLWkK24Es6_2wnIf43XTC9ksY8TOK4XOpWLcs_UlgAw-ydWGSUIugflAopkZROzFUOsJntd2iPeYwvh7KYz49DWwQBUB-rW3Ut49MKNUOQd6f42u05Ee1GShatGTba/s400/Screen+Shot+2018-04-26+at+23.32.54.png" width="400" /></a></div>
<div>
<br /></div>
<div>
That's much more interesting than anything we've seen yet. And we're starting to see the power of <b>recursion</b> and the intricate patterns that might be possible.</div>
<div>
<br /></div>
<div>
We then saw how easy it was to extend an existing recursive pattern. The <b>holocrux</b> was defined a extending horizontally with every continuation. We can add a vertical extension too.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhohWHuGvC868mA6EoZahyl8nZZmN13r8c-pVpOO-aVpB5orAKFQQ2T4Ru2nghNOQM3BfGAunrWA18dCbtbcSAGEXXVHzBXCzE5SjX-MLfIRTEjCUr02dAp8rpmG9pV9JO_6A7Km01mS9MY/s1600/Recursion+for+Beginners-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhohWHuGvC868mA6EoZahyl8nZZmN13r8c-pVpOO-aVpB5orAKFQQ2T4Ru2nghNOQM3BfGAunrWA18dCbtbcSAGEXXVHzBXCzE5SjX-MLfIRTEjCUr02dAp8rpmG9pV9JO_6A7Km01mS9MY/s400/Recursion+for+Beginners-10.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Now, a <b>holocrux</b> of size s, is a circle of size s, with 4 smaller <b>holocrux</b> patterns above, below, to the left and to the right of it.</div>
<div>
<br /></div>
<div>
The code changes are minimal - a benefit of the investment we made earlier. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO8PMz9zK8yUwtwBoS6PXTya5IJQ33SlxlA6i9qcJTt55KlYDwAzBfu3riKVvIpNnLUFoqzHCMmehmFNj6clj_G1iOMuQ8DP49Bj6iBEUmMzHotZG_K_Oc110hRPDRQMJwawIYuZ2h-hLC/s1600/Recursion+for+Beginners-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO8PMz9zK8yUwtwBoS6PXTya5IJQ33SlxlA6i9qcJTt55KlYDwAzBfu3riKVvIpNnLUFoqzHCMmehmFNj6clj_G1iOMuQ8DP49Bj6iBEUmMzHotZG_K_Oc110hRPDRQMJwawIYuZ2h-hLC/s400/Recursion+for+Beginners-11.png" width="400" /></a></div>
<div>
<br /></div>
<div>
And the result is really rather interesting.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8insg9usSplqx1FnD4kI7cFSSmPw-yZN2psvRCUSTGrsIEBAXySAnbmfyBRHjtMmNlQbMTBhMrW34x8LEClI4b6fO10IRPIVdNzsVV_gEnBzJKmIZK7E5SN2wN-teA8lVHJRKWDMZkOke/s1600/Screen+Shot+2018-04-26+at+23.47.09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1193" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8insg9usSplqx1FnD4kI7cFSSmPw-yZN2psvRCUSTGrsIEBAXySAnbmfyBRHjtMmNlQbMTBhMrW34x8LEClI4b6fO10IRPIVdNzsVV_gEnBzJKmIZK7E5SN2wN-teA8lVHJRKWDMZkOke/s400/Screen+Shot+2018-04-26+at+23.47.09.png" width="400" /></a></div>
<div>
<br /></div>
<div>
The ease of extending a core recursive pattern was stressed again - it's a benefit of putting the effort in early on to cast imagined patterns in terms of a termination and continuation rule.</div>
<div>
<br /></div>
<div>
Its super-easy to take that last pattern, and tweak how far out the smaller <b>holocrux</b> patterns are placed. We can even change the colouring scheme - here we're using a translucent red for the circles.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0jje3gVDR1UigLpFbNEhWgnrLbz1NhA7iVwavSxS15OIiL62zp_dFJ0PrH4dUM8THaI-xAzeVKQFsmNmosIqfSa8TaYoiE7OI0IqecrhVDQMnFoKQHVWM_pazwPoGwLlL9ei9O4e5Fx7P/s1600/Screen+Shot+2018-04-26+at+23.49.08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1193" data-original-width="1594" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0jje3gVDR1UigLpFbNEhWgnrLbz1NhA7iVwavSxS15OIiL62zp_dFJ0PrH4dUM8THaI-xAzeVKQFsmNmosIqfSa8TaYoiE7OI0IqecrhVDQMnFoKQHVWM_pazwPoGwLlL9ei9O4e5Fx7P/s400/Screen+Shot+2018-04-26+at+23.49.08.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Playing and experimenting is definitely encouraged.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Randomness and Recursion</h3>
<div>
<b>Randomness</b> is a powerful algorithmic art method in its own right. Could we usefully combine it with <b>recursion</b>?</div>
<div>
<br /></div>
<div>
We talked about another imagined pattern the <b>Jewel of Drax</b>. It's very similar to the <b>holocrux</b>, but is based on squares not circles. The important difference is that the next level of detail could be one of two options. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiftdNT6nysyaL9gVwO4xTBZyKzT1Ri2sjwr2sGwt-HsFJszuDIvpArC9t9IXhi9GPRyLKr2x7IddbjuRIuu2TwHX_kPbj-O9skavImUzirveb_f_7J8N7fUO0tQo5N1utL6A9xrsbuWgL9/s1600/Recursion+for+Beginners.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiftdNT6nysyaL9gVwO4xTBZyKzT1Ri2sjwr2sGwt-HsFJszuDIvpArC9t9IXhi9GPRyLKr2x7IddbjuRIuu2TwHX_kPbj-O9skavImUzirveb_f_7J8N7fUO0tQo5N1utL6A9xrsbuWgL9/s400/Recursion+for+Beginners.png" width="400" /></a></div>
<div>
<br /></div>
<div>
When we <b>continue </b>the<b> recursion</b> and define the next level of detail, we choose one of two possible options, chosen with equal probability:</div>
<div>
<ul>
<li>50% chance - jewels of drax placed top right and bottom left</li>
<li>50% chance - jewels of drax placed top left and bottom right </li>
</ul>
</div>
<div>
<br /></div>
<div>
We've introduced an element of chance into the recursive pattern - with means the results will be different every time we run our code. Here are the results from four runs.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcG9WSr_GLGwNfFjvrjbC9pT2Xzyf2ZF0ZJLQ48hErRpTjEp4sVm0dGTVkPj5w9TSXsCdFf4HYDKqPev0gfgKd-0JCb0yQ1SpoEqyD1GvEgs1_BBUJTVq_EiPqwBpOM1GXwosZ-Vu5EL2/s1600/Recursion+for+Beginners-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="572" data-original-width="758" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcG9WSr_GLGwNfFjvrjbC9pT2Xzyf2ZF0ZJLQ48hErRpTjEp4sVm0dGTVkPj5w9TSXsCdFf4HYDKqPev0gfgKd-0JCb0yQ1SpoEqyD1GvEgs1_BBUJTVq_EiPqwBpOM1GXwosZ-Vu5EL2/s400/Recursion+for+Beginners-2.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Randomness adds a particularly unique dimension to recursive patterns. </div>
<div>
<br /></div>
<div>
We continued to explore a slightly more involved example, inspired by nature - a tree in Richmond park in fact!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmoegWpbCc7t9hAH1hHSX6APFx3sJvjMh0xLFsZIHkUbho7eIpRdUP6Lg_w6f453zaIn6Z5ewgv3J5OcbF0Spv30uNFqd1Sw3Qz6UhVqcOzNMYfmK_46j3xx0XG4q5jq_dxPVBiPFcYSqq/s1600/tree_0_FotoSketcher2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1107" data-original-width="1600" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmoegWpbCc7t9hAH1hHSX6APFx3sJvjMh0xLFsZIHkUbho7eIpRdUP6Lg_w6f453zaIn6Z5ewgv3J5OcbF0Spv30uNFqd1Sw3Qz6UhVqcOzNMYfmK_46j3xx0XG4q5jq_dxPVBiPFcYSqq/s400/tree_0_FotoSketcher2.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
We can see that the tree is self-similar in it's branching. A chosen branch could be the whole tree, or a snippet form a larger branch.</div>
<div>
<br /></div>
<div>
We can formulate a recursive pattern for a tree:</div>
<div>
<ul>
<li><b>continue</b>: a tree of <b>depth 3</b> is a branch with two trees of <b>depth 2</b> emerging from the end of the branch</li>
<li><b>terminate</b>: a tree of <b>depth 1</b> is just a branch</li>
</ul>
</div>
<div>
<br /></div>
<div>
A picture explains the idea better:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge-V2JHSOK5YtQsY12t9K04wsn0Npz-zHGwWGbxYZUbM1bh3YhWKNzWoTOy3CmKb959v3EaNoBcQ9rb64eG2yZxaYk4x5ZKRyXV0QgDNL_2dT8TNay1koNZqvjuOH5tUhEwBBAgnjRAb15/s1600/p4_tree_1a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge-V2JHSOK5YtQsY12t9K04wsn0Npz-zHGwWGbxYZUbM1bh3YhWKNzWoTOy3CmKb959v3EaNoBcQ9rb64eG2yZxaYk4x5ZKRyXV0QgDNL_2dT8TNay1koNZqvjuOH5tUhEwBBAgnjRAb15/s400/p4_tree_1a.png" width="400" /></a></div>
<div>
<br /></div>
<div>
The initial results weren't very natural.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuiSFst5qGT0K-8i1w8_DkSnq3h_XcEiI3Fint71S3sl4gwzCer0YNP_teT-l5QF_e0Tdr8vPmaa3VXZKehrNgKwZyCOZVgy2_oKHSmPOVKS4z4aIKdTS6IxyP9OyjEc5nUfXHU_Y-VEaB/s1600/p4_tree_out_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1192" data-original-width="1592" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuiSFst5qGT0K-8i1w8_DkSnq3h_XcEiI3Fint71S3sl4gwzCer0YNP_teT-l5QF_e0Tdr8vPmaa3VXZKehrNgKwZyCOZVgy2_oKHSmPOVKS4z4aIKdTS6IxyP9OyjEc5nUfXHU_Y-VEaB/s400/p4_tree_out_1.png" width="400" /></a></div>
<div>
<br /></div>
<div>
The branching is there and works fine but the overall structure is too regular. Let's introduce some randomness to the direction of the emerging branches. Here are the results of four runs.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmuCzXepSHQjtN0s_nRBjbW1YktTHoEKmBIlioKQAsw2Qvabnb3AyzCFym0mbKci-6QWw0oOLazPUIe0F5vg_XsJ0Er93LGyU8GBdP1I0yZwdwX6uQuAsLgJhw0TyrZTwDVzylR-9A6y2t/s1600/Screen+Shot+2018-04-27+at+00.22.38.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1204" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmuCzXepSHQjtN0s_nRBjbW1YktTHoEKmBIlioKQAsw2Qvabnb3AyzCFym0mbKci-6QWw0oOLazPUIe0F5vg_XsJ0Er93LGyU8GBdP1I0yZwdwX6uQuAsLgJhw0TyrZTwDVzylR-9A6y2t/s400/Screen+Shot+2018-04-27+at+00.22.38.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Much more interesting and sometimes rather pleasing too. We can refine the trees further by making the branches thicker for larger depths, which results in thinner outer branches. We can also link the length of the branches to the depth, so that branches get shorter further up the tree. The results are more grasslike and really rather nice!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXAoHsJWQUDKO1SRe5Z7X7gTFZVCzV-3Cgxy6y0V3OJYD0IVrylW_6MLEYX_nP9usW6EoHgG-ydZeMfDZEt0XcpVJQS8q_mIMoLFJOj4RJYzTTpDhf8t4SM25nTcffSxvvTUcu2-Hh_crd/s1600/Screen+Shot+2018-04-27+at+00.26.53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1223" data-original-width="1600" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXAoHsJWQUDKO1SRe5Z7X7gTFZVCzV-3Cgxy6y0V3OJYD0IVrylW_6MLEYX_nP9usW6EoHgG-ydZeMfDZEt0XcpVJQS8q_mIMoLFJOj4RJYzTTpDhf8t4SM25nTcffSxvvTUcu2-Hh_crd/s400/Screen+Shot+2018-04-27+at+00.26.53.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Nice!</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Quick Test</h3>
<div>
As a test of our abilities to spot recursion we looked at these bubble images.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI1O5gmeC7aXH6APc7qQYoKbRpU5-8P94fXE6pSPAVZY3YtaLWQxmqMnTw4MHhDzI0-EFsNHgkCaqOMXEJzZOwtqT1pApF4g6O3R9o3YFOtGy1Dw5BCqn6SyTm-_NNv8gOXxPBFEkXjXlD/s1600/Screen+Shot+2018-04-27+at+00.30.58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1218" data-original-width="1600" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI1O5gmeC7aXH6APc7qQYoKbRpU5-8P94fXE6pSPAVZY3YtaLWQxmqMnTw4MHhDzI0-EFsNHgkCaqOMXEJzZOwtqT1pApF4g6O3R9o3YFOtGy1Dw5BCqn6SyTm-_NNv8gOXxPBFEkXjXlD/s400/Screen+Shot+2018-04-27+at+00.30.58.png" width="400" /></a></div>
<div>
<br /></div>
<div>
After some observation it because clear that the patterns are random but start with a circle with has 3 smaller circles placed at a random location on it's edge .. and those circle too have their own circles.. and so on.</div>
<div>
<br /></div>
<div>
This pattern was inspired by the work of an Algorithmic Art member who created a similar work at a previous hackathon.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Summary</h3>
<div>
The key points to take away were repeated - trying to think about patterns in terms of a continuation rule and a termination rule. These might be patterns we see in nature, or patterns we're imagining.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMxMjST9Wlq8UmVkYuWZ29Abw4WxZeKTNjewgFgJ71rK-zlZtoJqpBXdffpBNeUbLBktYXUxkdXeZF3GQdFDZ5fkdaMpYq4mm1XNqmKijpwfZGztC5HDx50C5sz-o2ncufr-W1E-cyWhG7/s1600/Recursion+for+Beginners-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMxMjST9Wlq8UmVkYuWZ29Abw4WxZeKTNjewgFgJ71rK-zlZtoJqpBXdffpBNeUbLBktYXUxkdXeZF3GQdFDZ5fkdaMpYq4mm1XNqmKijpwfZGztC5HDx50C5sz-o2ncufr-W1E-cyWhG7/s400/Recursion+for+Beginners-3.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Hopefully, the session clarified recursion, and more importantly, showed it working. A few members were inspired to try their own recursive pattern ideas - which is great!</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
A Slightly More Advanced Idea</h3>
<div>
At the end of the session we briefly talked about a slightly more advanced idea.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHqOhgZQE2E1sJrcwvszrI9Zyzgqz4zVSBu7Va4im6IK7G-3g9prauEfXpCbHe8bIQ1WCH4gXkQ39YMIFlrQGbe7WKvrUCJBwFLNyTUpeN3WAEwmikAwzHLvU11bFJtl5hHf9aQe3KbR41/s1600/human_robot_turtle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHqOhgZQE2E1sJrcwvszrI9Zyzgqz4zVSBu7Va4im6IK7G-3g9prauEfXpCbHe8bIQ1WCH4gXkQ39YMIFlrQGbe7WKvrUCJBwFLNyTUpeN3WAEwmikAwzHLvU11bFJtl5hHf9aQe3KbR41/s400/human_robot_turtle.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Instead of us writing code which draws patterns .. why don't we write code which grows code recursively ... and see what patterns that makes?</div>
<div>
<br /></div>
<div>
This is interesting on several levels. The idea of code writing code is interesting in itself. The idea of growing code recursively is really interesting too.</div>
<div>
<br /></div>
<div>
We started by defining a simple "turtle code' language with commands like <b>L</b> for left, <b>F</b> for forward, <b>R</b> for right. We also included commands to save and restore state, <b>[</b> and <b>]</b>. We saw how even this simple language could draw a very wide variety of patterns - the simple turtle code language is very expressive.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8urrwkUK3udAhihVX0TrAyUKN7Eb8_xZBekbxFFFmfWrVSiSGlUW1L9dKnR2hcSlsrJlrJdZXt1YBvS9q0Do0QwUA1028FQgXgrPMJFeVmxdmSkzhHMdzqbwyFphnI9DWq4vc5GWy7wsA/s1600/06_turtle_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="634" data-original-width="1600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8urrwkUK3udAhihVX0TrAyUKN7Eb8_xZBekbxFFFmfWrVSiSGlUW1L9dKnR2hcSlsrJlrJdZXt1YBvS9q0Do0QwUA1028FQgXgrPMJFeVmxdmSkzhHMdzqbwyFphnI9DWq4vc5GWy7wsA/s400/06_turtle_3.png" width="400" /></a></div>
<div>
<br /></div>
<div>
We then <b>grew</b> the code according to simple replacement rules. Each application takes a <b>generation</b> of code to create the next <b>generation</b> of code. </div>
<div>
<br /></div>
<div>
Here we see the extremely simple starting code <b>FRF</b> have the rule <b>F > RFLF</b> rule applies to grow the first generation of code <b>RFLFRRFLF</b> and then again to grow the second generation of code which has <b>21</b> instructions.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI74qdQ_E62-67ursLJgcjVQnqW4Qvf5vLRpAPPu8ccKggoLXBoUluFHsBK6DLhMb5VwxMuYhcvsXfWhCePk3CsXEzHpaHFKmfoe5_M9wjx6DvbCxMFGWdI6-d0wjh-FU05lGHha_geROt/s1600/Recursion+for+Beginners-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI74qdQ_E62-67ursLJgcjVQnqW4Qvf5vLRpAPPu8ccKggoLXBoUluFHsBK6DLhMb5VwxMuYhcvsXfWhCePk3CsXEzHpaHFKmfoe5_M9wjx6DvbCxMFGWdI6-d0wjh-FU05lGHha_geROt/s400/Recursion+for+Beginners-4.png" width="400" /></a></div>
<div>
<br /></div>
<div>
The size of the code grows rapidly. Generation <b>16</b> has <b>393,213</b> instructions - that's over 1/3 of a million!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV75HBK4UWsMPi3-qgB2plc0g4tqohMzcgzGyEQqDOFR5F4CLvBgk_U06ACUIyJqcBaa1v4wwcWH5Ca3GSzuMcSVUPfXbJgU6h18sBT0kF8XZ9ncH0hyd8CHtGzKbk3u5Gq_06OQU6JLJz/s1600/Recursion+for+Beginners-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV75HBK4UWsMPi3-qgB2plc0g4tqohMzcgzGyEQqDOFR5F4CLvBgk_U06ACUIyJqcBaa1v4wwcWH5Ca3GSzuMcSVUPfXbJgU6h18sBT0kF8XZ9ncH0hyd8CHtGzKbk3u5Gq_06OQU6JLJz/s400/Recursion+for+Beginners-5.png" width="400" /></a></div>
<div>
<br /></div>
<div>
The resulting pattern is intricate and self-similar. Although this particular one doesn't look very pleasing, close up it is more interesting.</div>
<div>
<br /></div>
<div>
This method of growing code produces a wide variety of patterns .. including trees!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDgViYet1MfuQ25lE36409a_j1jAbXDK7KMrWpmjnDpPGEDQZT1pWMjt7G0ivWFbFP60xV7HDwsEmK7ybbKCmiS7Ynq0_BqMdfIk95dgEpqOmNUUNyb-P0qDtncQVEN0u2Lkrzj2KczieX/s1600/Recursion+for+Beginners-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDgViYet1MfuQ25lE36409a_j1jAbXDK7KMrWpmjnDpPGEDQZT1pWMjt7G0ivWFbFP60xV7HDwsEmK7ybbKCmiS7Ynq0_BqMdfIk95dgEpqOmNUUNyb-P0qDtncQVEN0u2Lkrzj2KczieX/s400/Recursion+for+Beginners-7.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Other patterns that a little experimentation found include beehives, geometric growths, curly curls and rather ominous spikes.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpmbMhjDYsEfZOJqNUBOvhX9YmHAZAFjj65ga5zN_gmrX54taN0aVqB7eHNCTqc_qHaXAAc2U8MtH9UY36PG4wnlXlGqKejJ78koHD4sFxTLccqzFujt3VtaNQdTXuanwCV_DC4zSMj9Oc/s1600/Recursion+for+Beginners-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpmbMhjDYsEfZOJqNUBOvhX9YmHAZAFjj65ga5zN_gmrX54taN0aVqB7eHNCTqc_qHaXAAc2U8MtH9UY36PG4wnlXlGqKejJ78koHD4sFxTLccqzFujt3VtaNQdTXuanwCV_DC4zSMj9Oc/s400/Recursion+for+Beginners-6.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Feedback</h3>
<div>
It's always useful to get feedback on the group's sessions. I was really pleased that many members do want more sessions aimed at beginners - they do seem popular. </div>
<div>
<br /></div>
<div>
Demand for more practical hands-on sessions is strong, so we'll do more in future.</div>
<div>
<br /></div>
<div>
Overall I was really pleased that some members were inspired to try these ideas themselves.</div>
Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0tag:blogger.com,1999:blog-2044972050276999466.post-45305004081315481032018-03-20T08:48:00.003-07:002018-03-20T08:58:31.536-07:00Art Hackathon - "I Want To Believe"The <a href="http://algorithmicartmeetup.blogspot.com/2017/09/art-hackathon-future-pangs.html" target="_blank">first hackathon </a>we did last year was very popular, and there was demand for another.<br />
<br />
The theme of this one was <b><a href="https://www.meetup.com/Algorithmic-Art/events/247529668/" target="_blank">"I Want To Believe</a></b>" - which some of us interpreted as an <a href="https://en.wikipedia.org/wiki/The_X-Files" target="_blank">X-Files</a> reference, with connotations of aliens, government conspiracies, monsters and unexplained phenomena.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBdsGl74ggNea-4CgVc7h6HNy69uKDTeETGBES02xjIgoC5tM0pBdUCEWXSP-VyuEuTEABKt2n5STHDY5DprsznWs8aOB_Uc42heBNf1Q21s_izQGwrDOs8CmXbf0ADJNfEqZxnzlZHh2d/s1600/x-files-1_FotoSketcher.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBdsGl74ggNea-4CgVc7h6HNy69uKDTeETGBES02xjIgoC5tM0pBdUCEWXSP-VyuEuTEABKt2n5STHDY5DprsznWs8aOB_Uc42heBNf1Q21s_izQGwrDOs8CmXbf0ADJNfEqZxnzlZHh2d/s400/x-files-1_FotoSketcher.jpg" width="400" /></a></div>
<br />
<br />
<h3>
Group Mix</h3>
I was really pleased that again we're attracting complete beginners to coding, and members who are artists and are experimenting with technology and code.<br />
<br />
We will always maintain a beginner friendly feel to our events.<br />
<br />
I was also pleased to welcome female technologists - I know that many meet up groups are working hard to make sure they don't inadvertently signal that only boys are welcome.<br />
<br />
<br />
<h3>
P5js and OpenProcessing</h3>
Over the last year we've explored different environments and languages for creative coding. The one that emerged as the most beginner friendly was <a href="https://processing.org/" target="_blank"><b>Processing</b></a>. The web version <a href="https://p5js.org/" target="_blank"><b>p5js</b></a> is very useful because it allows work to be viewed in a browser - which is the most open and accessible technology platform on the planet.<br />
<br />
Even better, <b><a href="https://www.openprocessing.org/">openprocessing.org</a></b> allows us to code in the web too - removing the hassle of source code files and installing and configuring libraries and environments. Creative coding becomes as simple as typing code into a web browser and clicking "run" to see the results.<br />
<br />
Sharing work is supremely easy - you just save your work and share the web URL. That allows others to see your code and the resulting image/animation it creates. Overall this supports the open source ethos of sharing your work, and how you work.<br />
<br />
For beginners, I've not found anything easier than openprocessing.<br />
<br />
<br />
<h3>
Organisation</h3>
The first hackathon was organised with very little experience of organising similar events. It went well but we were conscious of some feedback and things we could do better.<br />
<br />
This time we tried to identify those who:<br />
<br />
<ul>
<li>were more experienced and were willing to help others.</li>
<li>were very new and wanted some help or guidance.</li>
<li>who wanted to work alone or in groups.</li>
</ul>
<br />
A quick introduction to openrprocessing and sharing links was thought to be helpful. A link to our previous gentle introduction to Processing with p5js were also found to be very helpful - they are always at <a href="https://goo.gl/Gygvom" target="_blank">https://goo.gl/Gygvom</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://goo.gl/Gygvom" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="720" data-original-width="960" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzvGntqyylp4lEzcX5EDsJzaoQI2T6CvYuz4IajKtx5fDMGIKhoqRtr2fymlWB9Rqzv6mQr96thxTVakss1o8UtsCcHwNV6GhaT3-_XxTkv_ay3cB4D1SKrlgQ35vmGxZ5UdgmxSBEKth3/s400/A+Gentle+Introduction+to+Processing+with+p5js.png" width="400" /></a></div>
<br />
We did feel that the session was not long enough, even though we continued to 1h 15 minutes. Next time we should try to start at 6.30pm to see if we can fit a 2 hour session into the evening.<br />
<br />
<br />
<h3>
Themes</h3>
<div>
Some new interesting themes emerged during the course of the hackathon.</div>
<div>
<br /></div>
<div>
Several members used the 3d capabilities (<a href="https://en.wikipedia.org/wiki/WebGL"><b>WebGL</b></a>) of p5js to create and animate 3d objects. Here's a getting started guide to webGL with p5js - [<a href="https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5">link</a>].</div>
<br />
Others used colour to great effect, using the <b>Hue Saturation Brightness</b> <a href="http://www.tomjewett.com/colors/hsb.html">HSB colour model</a> as an alternative to RGB. It can be easier to achieve several tasks in the HSB colour model - such as calculating the complementary hue to a given hue.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUPPWFmRCGy4GTi8dYRDPKdMzNvz5X1EtaPgAErahujwOFUbuLZHXSSIwjFUIUhvQsklgSneLM-pfOK6JEGwF5VjggPKw7F_79wZWAnghaA1kopV8d1Dvj4XzptYpD4aNnPIB2xlV35R2D/s1600/p5_hsb_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="980" data-original-width="1600" height="245" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUPPWFmRCGy4GTi8dYRDPKdMzNvz5X1EtaPgAErahujwOFUbuLZHXSSIwjFUIUhvQsklgSneLM-pfOK6JEGwF5VjggPKw7F_79wZWAnghaA1kopV8d1Dvj4XzptYpD4aNnPIB2xlV35R2D/s400/p5_hsb_3.png" width="400" /></a></div>
<br />
You can see that complementary colours are located opposite to each other on the HSB colour wheel.<br />
<br />
<br />
<h3>
Great Work!</h3>
Here is a sample of some of the great work created in the class. As before, the show-n-tell at the end was really interesting, because we see how others work, and hear them talk about their interpretation and inspiration, and also the obstacles they might have emerged as they worked.<br />
<br />
There was lots of well-deserved applause for everyone!<br />
<br />
<hr />
<br />
<b>Space Going Fast</b> by Mark<br />
<a href="https://www.openprocessing.org/sketch/524439">https://www.openprocessing.org/sketch/524439</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524439" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="833" data-original-width="1600" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlPEnh_-jmtAMd7b9U47OmOZOhdvOm2FJ_E6wkeNBWLJEgxr0Rwx80uKIUiH8GvjZ-BykPuhoVdEewEhanDesJ5h-Dr9Nx53h4qVw-k5iuQlOdhfmOg2ia-xClrlqrrsUANkUMg5SqpiQx/s400/space_fast.png" width="400" /></a></div>
<br />
Great use of colour and animation to create the sense of space travel. I love the coloured rectangles, which have also been rotated using a p5js idiom I need to learn more about (push, rotate, translate, pop).<br />
<br />
<hr />
<br />
<b>I Want (Not) To Believe</b> by James<br />
<a href="https://www.openprocessing.org/sketch/524410">https://www.openprocessing.org/sketch/524410</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524410" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="833" data-original-width="1600" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAYmDgOaEmngOi-aEGfaxpAPF7eANXkQbwdC225To9jo73DpKB_5kWd6V_lKJV9zQfiyb-ZaSWc_mdDB9jyf5MtKVyDwm1gvIR65c2neKsp-PgVjv9RQ_B7J8AwGcp-n_6B8DV7Nh_aC9C/s400/notbelieve.png" width="400" /></a></div>
<br />
Great use of text and animation to create a philosophical piece playing with ideas and beliefs. The lottery dynamics suggest a certain arbitrariness of belief. Unsettling.<br />
<br />
<hr />
<br />
<b>Believe</b> by Vicky<br />
<a href="https://www.openprocessing.org/sketch/524456">https://www.openprocessing.org/sketch/524456</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524456" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="1349" data-original-width="1339" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0bOaXW3HooImDL0UEAbJ6lBS-_7CCSyTD5ys2g6ayeSBBuysEMoMJZdOElcACZ8JRHw2fJPFUHOCHsvP349hckggXIRpJxRLmn1wQFbfgYJ2LNyp923dz5lN4jxA7TbtyxUzJVzFds-M1/s320/ghosts.png" width="316" /></a></div>
<br />
A very playful work making subtle use of hidden alien heads. This one makes use of <a href="https://en.wikipedia.org/wiki/B%C3%A9zier_curve">Bezier curves</a> to create the heads - something I too must look into.<br />
<br />
<hr />
<br />
<b>Planets and Donuts</b> by Tomasz<br />
<a href="https://www.openprocessing.org/sketch/524458">https://www.openprocessing.org/sketch/524458</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524458" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="833" data-original-width="1600" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLfy3dsYGZemIGm8tuzSjlK0XHYoPbFp7uNMvD6IcvptFGjbkudlt7K87Ugm0lCXBQliFgliITwAK9zxwDKKHPbeHJfvyBqLC-hh037Vmxh03RvfNVjhe5yl4BkjpO4hyphenhyphenL88VBr0Y99Rac/s400/webgl.png" width="400" /></a></div>
<br />
<br />
Tamasz made extensive use of 3d OpenGL objects to create a fun interactive piece. Your pointer controls the central planet which repels the donuts. Lovely feel to this one!<br />
<br />
<hr />
<br />
<b>I Want To ...</b> by Simon<br />
<a href="https://www.openprocessing.org/sketch/524466">https://www.openprocessing.org/sketch/524466</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524466" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="1127" data-original-width="1600" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx7X8zVlkPeo6rCxOofqMUA7dxBlqY5t3ykhb62ofxcaqm1wsaDEMbrSWytdpqtF_qmGkgnZ1WoWpfHGcZy_-cI6bqKcqF9rj2O5yOEN6rmFULDIT_ZX8vT4QmrHswk23Ahux9K143vtNi/s400/text.png" width="400" /></a></div>
<br />
<br />
Simon has created a work which for me really resonates with my memories of the X Files. Dark, sinister, and a movement that suggests something bad is about to happen soon. Simon has used the repetitive overlaying of varying styles of text to great effect.<br />
<br />
<hr />
<br />
<b>Shakespeare ...</b> by Borg Droid<br />
<a href="https://www.openprocessing.org/sketch/524297">https://www.openprocessing.org/sketch/524297</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524297" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="1094" data-original-width="1536" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6iYasAbaaEQQqqVWZvsbolODZXStYD5YvDYtFWLt4Lx3vASc3liS4mPfURcHXgTg7waTEQDOUmv31RE3wAJlP_B8QLBfgkSqlWX9qVI7OrnsLM0JaK07TOUd3jiTfynsLFnGf9CqfZmn8/s400/shakespeare.png" width="400" /></a></div>
<br />
Borg Droid has used both animation and text to create a very funny, and at times poignant, dialogue between two characters. Their eyes and mouths are also animated to great effect.<br />
<br />
Borg Droid created many more works, you can find link in the comments of the meet up page.<br />
<br />
<hr />
<br />
<b>Future Cities ...</b> by Simon<br />
<a href="https://www.openprocessing.org/sketch/524444">https://www.openprocessing.org/sketch/524444</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524444" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="833" data-original-width="1600" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJiuchZYL7cSxCoGqx4Vb5mjHwp6HAe4Sb00AcmaxKiq7DK1TV9ZT3m5yV1jibZj24mKkAs7RHUnAV5YrqLJ2jqpq2a3U6QaY5ytubvJ6JNLlsUVFPR9tmTa1ciDS9273vGhrKj2A9OSCj/s400/future_cities.png" width="400" /></a></div>
<br />
Simon has used simple techniques to create powerful compositions. He uses the HSB colour model to pick two opposite colours, with one becoming the sky and the other for buildings. He uses a brightness gradient to add depth and dimension to the work. I find this one very atmospheric - reminding me of the dystopian urban landscapes of <a href="https://www.youtube.com/watch?v=6jHnwWXcar0">Ghost In The Shell</a> or <a href="https://www.youtube.com/watch?v=7OWyGRs_yAc">BladeRunner</a>.<br />
<div>
<br /></div>
<hr />
<br />
<b>My Sketch (Untitled) ...</b> by Julian<br />
<a href="https://www.openprocessing.org/sketch/524469">https://www.openprocessing.org/sketch/524469</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524469" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="833" data-original-width="1600" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhITsSNt38jUmorxz72L55IpSZ4Rs5T4D3FH-XsFqWZfkH8avClaeaJQP55ICuV0boxIQBVmhZcTMGOyOBTAxpDQkuHjX1sKEyUJye8vSqSGvCHPdoczBWJSHf7Lx_prCDogdk5t5mbY2AA/s400/fire.png" width="400" /></a></div>
<br />
<div style="-webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; color: black; font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; margin: 0px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Julian has created a very striking image that builds overtime. He uses an additive <a href="https://p5js.org/reference/#/p5/blendMode">blend mode</a> so that lines, when layered over each other, result in a lighter colour. Julian says this wasn't the effect he set out to achieve, but nonetheless, this is a great accident.<br />
<br />
<hr />
<br />
<b>Sphere ...</b> by Zinab<br />
<a href="https://www.openprocessing.org/sketch/524453">https://www.openprocessing.org/sketch/524453</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.openprocessing.org/sketch/524453" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="1160" data-original-width="1600" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6jHoEt9KIX1EBW-v6CGudf-cRnwpRdXfjlVnrKz5XURNGHrQ1P823CoumkvMxFVMG0oTKHtWUlwcNTwRAR0lcAEcHDAjFrw2DcOdeldRio1uNy_pGGAkAhMik1UqPqF96s_KpdVg_ODlf/s400/webgl2.png" width="400" /></a></div>
<br />
<br />
<div style="margin: 0px;">
Zinab has created a really nice animated work with 3d OpenGL elements. Her code is really instructive to look at - you can see how the shapes are given a surface texture, created, and then one of them is set to rotate. She said she normally works with 3DS Max and this was her first 3d work created with code - great job!<br />
<div>
<br /></div>
<div>
<hr />
<br />
<br /></div>
</div>
</div>
<h3>
Conclusion</h3>
I'm really pleased with the diversity of ideas, techniques and that everyone who was new to coding or coding with p5js did great work!Algorithmic Arthttp://www.blogger.com/profile/06049656342327467538noreply@blogger.com0