Friday, July 18, 2008

Visualizing GBIF density data in 3D using Processing

Ok, I recognize it, this is pretty nerdy, but I could not resist. Last week Radiohead released its last video House of Cards and I think it is great. Specially because it is made without cameras and lighting, only "scanners". Basically they just take 3D point positions and then visualize them using software. The making of is pretty cool. And even more cool is that they released the data and the code they used to generate the video (well kind of). They used an open source software called Processing. Basically it is a software to program images, animation and interactions. It is very simple to use and I just loved it from the very beginning. 

So after playing a bit with it and radiohead data I could not resist to create my own experiment. And now that I am playing so much with GBIF density data I thought this could be cool data to represent. I am not sure if it has any potential "real" use but never the less it is lot of fun and maybe a little artistic. The idea is to represent the GBIF density data for Fungi using the count of each cell as the z parameter in the 3D space. This is how the output looks like:




You can download the output also as a native application for:
Or use it as a Java applet at this place. It does not work in my computer but you know Java applets, they never work as intended ;)

The source code used to generate this program looks like:

import processing.xml.*;
import processing.opengl.*;

XMLElement xml;

ArrayList points = new ArrayList();

int maxCount = 0;

int currentX;
int currentY;

int frameCounter =1;

void setup() {
size(1024,768, OPENGL);

frameRate(24);

//Draw lines at a width of 1, for now.
strokeWeight(1);

xml = new XMLElement(this, "http://es.mirror.gbif.org/ws/rest/density/list?taxonconceptkey=13140807");
XMLElement[] densityRecords = xml.getChildren()[1].getChildren();
int numSites = densityRecords.length;
for (int i = 0; i < densityrecord =" densityRecords[i].getChildren();" coord =" new"> maxCount) {
maxCount = int(densityRecord[4].getContent());
}
points.add(coord);
}
}
void draw() {

// Lets adjust our center slightly
translate(-500,-400);
// Lets draw things bigger
scale(2);

// We'll use a black background
background(0);
// The data has 0,0,0 at the center and we want to draw that point at the center of our screen
translate(width/2, height/2);

rotateX((mouseY+512)/150.0);
rotateY((mouseX+384)/150.0);

for(int i=0; i1000) {
z= z/10;
}

z = (z*10000)/maxCount;

stroke(z*3.9,z*3.9,200,255);
line(x,y,z,x+1,y+1,z+1);
// println(x+"-"+y+"-"+z);

frameCounter++;
//This is used to save frames to create a video for Youtube
//saveFrame("renderedFrames/"+frameCounter+".tga");
}
}
Lot of things could be improved to make it more interesting, but that was nerdy enough. I have not been available to work much lately due to weddings, climbing mountains, birthdays, etc. Hopefully you will see some more things coming from my side soon.


No comments: