Solitary Bird of Paradise

Solitary Bird of Paradise

We had breakfast with family members one Sunday morning at a somewhat rural themed diner. During our post-meal chat in front of the restaurant there was this awesome Bird of Paradise just sitting there begging for a photo...both my wife and I captured a few shots.

Really thought this would make awesome subject matter for some computational art exploration. My first thought was to use a Voronoi approach for augmenting the image, and it is of my favorite techniques since it produces an interesting, non-repeating pattern. However, there is a fair amount of Math involved and I was a bit too impatient to attempt to write something from scratch.

Generating Voronoi Directly in Processing

I used to use a small one-off JavaScript program which imported the d3.js library itself and node.js to create an SVG vector file and then load the file into Inkscape for colorization. However, I really wanted to eliminate the extra steps by creating and coloring everything directly in Python mode for Processing sketch file itself. You can check out the script here if you'd like. It is located inside the nodejs folder and is called voronoi-svg.js. Nothing fancy. Just a tool to get the SVG file out ASAP :P

Turns out somebody had already created a library just for this purpose. Lee Byron created a Java library named Mesh which used another library called QuickHull3D. I wasn't sure how to use it with Python Mode for Processing since it was written for Java, but I discovered a few tweaks to make it work.

Tweaks to Use Mesh with Python Mode Processing

2D Array (List) of X-Y Coordinates

Voronoi requires a number of floating point, x-y coordinates to use for the midpoint of the cells. In Java, and ultimately for Mesh and Processing, you would use this declaration and then populate the array elements with a floating point value.

// Java snippet
float[][] points = new float[x][y];

This will not work in Python unfortunately. I believe it is much simpler to do with the NumPy library but I wasn't yet sure how NumPy would work for the Jython/Python based Processing implementation. Instead I used the following declaration and for loop to create my 2d array (list) of points. It is not super efficient, but I needed to use the coords variable elsewhere, otherwise I would have just populated each array (list) element directly. One item to note here is that I am rendering to a PGraphics object, rather then the default Processing output window, hence the larger image dimensions.

# Python snippet
IMAGE_WIDTH=2000
IMAGE_HEIGHT=2000

points = []
for i in range(2000):
  coords = [
    random.random() * IMAGE_WIDTH,
    random.random() * IMAGE_HEIGHT
  ]
  points.append(coords)

Rendering the (M)Polygon

Mesh creates MPolygon objects from the set of x-y coordinates. Rendering to the default output window in Processing requires calling the draw method using this parameter after obtaining the regions from the Mesh Voronoi object itself. "this" refers to the PApplet instance.

// Java snippet
// Renders polygon to the stage
regions[i].draw(this);

The .draw() method is overloaded in Mesh, but unfortunately, calling regions[n].draw(pgraphics) in Python mode did not work for me. I would have casted it to the correct object type in Java, but AFAIK there was not a means to do this in Python. What I ended up doing was iterating the regions myself and calling the .vertex() method directly.

# Python snippet
# Note variable i was obtained from the number of regions
for j in range(regions[i].count()):
  c = regions[i].getCoords()
  pg.vertex(c[j][0],c[j][1])

It was now possible to render to the PGraphics instance. Yay!


Love this design? Get it on a poster and other products!

Cheers!