## Worlds

Yesterday I have been to the beautiful exhibition by Pe Lang at the Museum of Digital Art here in Zurich. The exhibition consists of several kinetic systems producing complex behaviours. I was in particular fascinated by a piece called “polarization”, where different disks with polarized filters provide very interesting visual patterns. Those who read this blog know that I am really into systems, and their emergent features, so I was inspired to make the following piece, called “Worlds”. It is also an excuse to show how object oriented programming allows very quickly to replicate a little “cosmos” over and over.

The idea is the following. We have discussed more than once systems of particles which bounce on the canvas, but we never gave the canvas its own ontological properties, a fancy way to say that we never considered the canvas to be an object itself. That’s precisely what is going on in the code below. Namely, there is a class World whose scope is to be the box in which the particles are bound to reside. It comes with a position vector for its center, with a (half) length for the box itself, and with a particle system. The bounce check is done internally to the class World, in the update() function, so to make it behave like its own little universe. Once you have such a gadget, it’s immediate to replicate it over and over again! I disposed the box in a simple array, and I really like the visual effect that comes from it. I also did something else: inspired by statistical mechanics, each box has a “temperature”, which is influenced by how often the particles bounce on the walls of the box. The “hotter” the box, the more red it becomes. There is also a cooling factor: each box tends to cool down. So, after some time, the system goes to equilibrium, and each box stabilizes on a shade of red. This shows also something very nice, and at first counter-intuitive: there are boxes with a lot of particles, which are though very slow, making the box very “cold”.

Here is the code

// Kimri 2018

ArrayList<World> boxes;

int n = 10;

void setup(){

size(1000, 1000);

init();

frameRate(30);

}

void draw(){

background(255);

for (int i = 0; i < boxes.size(); i++){

World w = boxes.get(i);

w.display();

w.update();

}

}

void init(){

background(255);

boxes = new ArrayList<World>();

float step = width/n;

//Generate the array of boxes;

for (float x = step; x < width; x+= step){

for (float y = step; y < height; y+= step){

boxes.add(new World(x, y, step * 0.4));

}

}

}

void keyPressed(){

init();

}

// World class

class World {

PVector pos;

int num;

float len;

float temp = 255;

float coeff = 1.7;

ArrayList<Particle> particles;

World(float _x, float _y, float _len) {

pos = new PVector(_x, _y);

len = _len;

num = int (random(10, 60));

//Add particles to the box

particles = new ArrayList<Particle>();

for (int i = 0; i < num; i++) {

float part_x = pos.x + random(-len, len);

float part_y = pos.y + random(-len, len);

particles.add(new Particle(new PVector(part_x, part_y)));

}

}

World(float _x, float _y, float _len, int _num) {

pos = new PVector(_x, _y);

len = _len;

num = _num;

//Add particles to the box

particles = new ArrayList<Particle>();

for (int i = 0; i < num; i++) {

float part_x = pos.x + random(-len, len);

float part_y = pos.y + random(-len, len);

particles.add(new Particle(new PVector(part_x, part_y)));

}

}

void display() {

fill(255, temp, temp, 90);

stroke(0, 100);

strokeWeight(1.2);

rectMode(CENTER);

rect(pos.x, pos.y, 2 * len, 2 * len);

}

void update() {

for (int i = 0; i < num; i++) {

Particle p = particles.get(i);

p.move();

if ( (p.pos.x - pos.x) >= len - p.rad) {

p.pos.x = pos.x + len - p.rad;

p.vel.x = -p.vel.x;

temp -= 1;

}

if ( (p.pos.x - pos.x) <= -(len - p.rad)) {

p.pos.x = pos.x - (len - p.rad);

p.vel.x = -p.vel.x;

temp -= 1;

}

if ( (p.pos.y - pos.y) >= len - p.rad) {

p.pos.y = pos.y + len - p.rad;

p.vel.y = -p.vel.y;

temp -= 1;

}

if ( (p.pos.y - pos.y) <= -(len - p.rad)) {

p.pos.y = pos.y - (len - p.rad);

p.vel.y = -p.vel.y;

temp -= 1;

}

p.display();

}

if (temp < 0) temp = 0;

temp += coeff;

}

}

//Particle class

class Particle {

PVector pos;

PVector vel;

float rad = 2;

Particle(PVector _pos) {

pos = new PVector(_pos.x, _pos.y);

vel = new PVector(random(-3, 3), random(-3, 3));

}

void move() {

pos.add(vel);

}

void display() {

noStroke();

fill(0, 100);

ellipse(pos.x, pos.y, 2 * rad, 2 *rad);

}

}

And here is how it looks like