Processing Code
import traer.physics.*;
//variables for the contact particles
ParticleSystem physics;
Particle[] contacts;
//variables for the contact information, stored by unique id
String[] contactNames; //email address of each contact
int[] numEmails; //number of emails exchanged with contact
int[] ringNumber; //which ring the contact is in
String[] neighbors; //a neighbor list in string format for each contact
float maxEmailNumber = 0; //the largest amount of emails exchanged with one email address
//these define properties of how the visualization looks
int ring1radius = 100;
int ring2radius = 175;
int ring3radius = 250;
int ring4radius = 325;
int minCircleSize = 5;
int maxCircleSize = 50;
PFont emailFont, numberFont;
int selectedID = 0;
boolean mouseDown = false;
boolean contactSelected = false;
//parse the information from the text files and set up the physics
void setup() {
size( 1000, 800 );
smooth();
ellipseMode( CENTER );
physics = new ParticleSystem( 0, 0.1 );
//parse the information from contacts.txt
String[] lines = loadStrings("contacts.txt");
String[] pieces;
contacts = new Particle[lines.length+1];
numEmails = new int[lines.length+1];
ringNumber = new int[lines.length+1];
contactNames = new String[lines.length+1];
for (int counter = 0; counter 2){
int currentID = int(pieces[0]);
contacts[currentID] = physics.makeParticle( 1.0, random( 0, width ), random( 0, height ), 0 );
numEmails[currentID] = int(pieces[2]);
if(numEmails[currentID]>maxEmailNumber)
maxEmailNumber = numEmails[currentID];
contactNames[currentID] = pieces[1];
ringNumber[currentID] = int(pieces[3]);
}
}
//make every contact repel each other to minimize overlapping & create smooth animation
float minDist;
for (int counter = 1; counter1){
id1= int(pieces[0]);
neighbors[id1] = pieces[1];
}
}
//load the fonts to use
emailFont = loadFont("AngsanaNew-BoldItalic-24.vlw");
numberFont = loadFont("BrowalliaNew-18.vlw");
}
//draw the visualization
void draw()
{
physics.tick();
background(255);
//draw the circles
fill(255);
stroke(0);
strokeWeight(2);
ellipse(width/2, height/2, ring4radius*2, ring4radius*2);
ellipse(width/2, height/2, ring3radius*2, ring3radius*2);
ellipse(width/2, height/2, ring2radius*2, ring2radius*2);
ellipse(width/2, height/2, ring1radius*2, ring1radius*2);
strokeWeight(1);
stroke(0);
fill(0);
ellipse(width/2, height/2, 5, 5);
//draw the selected contact first so that it will be on the bottom
if (contactSelected){
//draw the lines for the connections
String[] pieces = split(neighbors[selectedID], ';');
for (int counter2 = 0; counter2 1)
text(numEmails[selectedID] + " emails exchanged", contacts[selectedID].position().x() + ((numEmails[selectedID]/maxEmailNumber)*maxCircleSize)/2 + minCircleSize + 5, contacts[selectedID].position().y()+15, 200, 25);
else
text("1 email exchanged", contacts[selectedID].position().x() + ((numEmails[selectedID]/maxEmailNumber)*maxCircleSize)/2 + minCircleSize + 5, contacts[selectedID].position().y()+15, 200, 25);
}
}
//this puts the location of all the particles on a circle of radius radiusConstraint
void placeOnCircle( Particle p , int radiusConstraint)
{
float xp, yp;
xp= p.position().x()-width/2;
yp= p.position().y()-height/2;
float h = sqrt(sq(xp) + sq(yp));
p.moveTo((xp/h)*radiusConstraint+width/2,(yp/h)*radiusConstraint+height/2,0);
}
//select a contact
void mousePressed()
{
contactSelected = false;
for(int counter = 1; counter