Skip to content

Instantly share code, notes, and snippets.

@suzukimilanpaak
Last active January 2, 2016 06:39
Show Gist options
  • Save suzukimilanpaak/8264451 to your computer and use it in GitHub Desktop.
Save suzukimilanpaak/8264451 to your computer and use it in GitHub Desktop.
Social graph with Processing Language
Tatsuya Suzuki Emi Ito Bruno Barroso Mattew Day Maxim Dokhlov Mehmet Bagbekleyen Alex Yixnitsky Stuart Gardner Derrick May
Tatsuya Suzuki 0 50 19 10 9 11 15 2 0
Emi Ito 0 0 2 3 3 2 1 2 1
Bruno Barroso 0 0 0 4 3 17 1 2 1
Mattew Day 0 0 0 0 4 5 1 2 1
Maxim Dokhlov 0 0 0 0 0 4 1 2 1
Mehmet Bagbekleyen 0 0 0 0 0 0 1 2 1
Alex Yixnitsky 0 0 0 0 0 0 0 1 1
Stuart Gardner 0 0 0 0 0 0 0 0 1
Derrick May 0 0 0 0 0 0 0 0 0
import java.util.*;
// Size of display
int DISPLAY_WIDTH = 600;
int DISPLAY_HEIGHT = 600;
// Colours
int BLACK = 0;
int WHITE = 255;
int CENTER_X = 0;
int CENTER_Y = 0;
SocialGraphCsv csv;
void setup() {
csv = new SocialGraphCsv("mutual_friends_2014_01_05.csv");
size(DISPLAY_WIDTH, DISPLAY_HEIGHT);
background(WHITE);
noLoop();
}
void draw() {
// Displace the drawn polygon by half width and half height of `display`, which means center.
// With `translate`, we can calculate coodinate of each vertex as distance from the center of a
// diagram, where it's coordinate is as (0, 0), and then, displace the polygon to actual coordinate
// of `display`.
translate(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 2);
int radius = 200;
SocialGraph socialGraph = new SocialGraph(csv, radius);
socialGraph.drawNodes();
socialGraph.drawNodeNames();
socialGraph.drawFamiliarities();
saveFrame("social_graph.jpg");
}
class SocialGraph {
EquilateralPolygon polygon;
Coordinate[] vertexes;
ArrayList<ArrayList<String>> familiarities;
SocialGraphCsv csv;
SocialGraph(SocialGraphCsv csv, int radius) {
this.csv = csv;
this.familiarities = csv.familiarities;
this.polygon = new EquilateralPolygon(this.familiarities.get(0).size(), radius);
}
public void drawNodes() {
polygon.drawVertexes();
}
public void drawNodeNames() {
nodeNames names = new nodeNames(this.polygon, this.csv);
names.draw();
}
public void drawFamiliarities() {
for(int i = 0; i < familiarities.size(); i++) {
color colour = color(random(255), random(255), random(255), 128);
for(int j = 0; j < familiarities.get(i).size(); j++) {
FamiliarityAsLine line = new FamiliarityAsLine(
familiarities.get(i).get(j),
polygon.vertexes[i],
polygon.vertexes[j]
);
line.drawLine(colour);
}
}
}
}
// This class saves coordinate
class Coordinate {
int x;
int y;
// The Constructor is defined with arguments.
Coordinate(float _x, float _y) {
x = int(_x);
y = int(_y);
}
public String toString() {
return x + ", " + y;
}
}
// This class represents equilateral polygon, which draws circles on each vertex
class EquilateralPolygon {
int numVertexes;
int radius;
public float[] angles;
Coordinate[] vertexes;
EquilateralPolygon(int _numVertexes, int _radius) {
this.numVertexes = _numVertexes;
this.angles = new float[numVertexes];
this.radius = _radius;
this.vertexes = vertexes();
}
private float xVertex(int i) {
return cos(angles[i]) * radius;
}
private float yVertex(int i) {
return sin(angles[i]) * radius;
}
public Coordinate[] vertexes() {
vertexes = new Coordinate[numVertexes];
float angleForSingleArc = 2 * PI / numVertexes;
for(int i = 0; i < numVertexes; i++) {
// Sum up angles
angles[i] = HALF_PI - angleForSingleArc * i;
float x = xVertex(i);
float y = - yVertex(i);
vertexes[i] = new Coordinate(x, y);
}
return vertexes;
}
// Put tiny circles onto each vertex
public void drawVertexes() {
smooth();
int r = 20;
for (int i = 0; i < numVertexes; i++) {
// Draw black circle for the first vertex and draw gray ones for the rest
int colorValue = i == 0 ? 0 : 200;
stroke(colorValue);
strokeWeight(1);
ellipse(vertexes[i].x, vertexes[i].y, r, r);
}
}
}
class nodeNames {
EquilateralPolygon polygon;
SocialGraphCsv csv;
nodeNames(EquilateralPolygon polygon, SocialGraphCsv csv) {
this.polygon = polygon;
this.csv = csv;
}
public void draw() {
fill(BLACK);
textAlign(CENTER);
for (int i = 0; i < polygon.angles.length; i++) {
float edtendedRadius = polygon.radius + 30;
float x = cos(polygon.angles[i]) * edtendedRadius;
float y = - sin(polygon.angles[i]) * edtendedRadius;
text(csv.nodeNames.get(i), x, y);
}
noFill();
}
}
class SocialGraphCsv {
ArrayList<ArrayList<String>> stringList;
ArrayList<String> nodeNames;
ArrayList<ArrayList<String>> familiarities;
SocialGraphCsv(String filePath){
String[] rows = loadStrings(filePath);
this.stringList = convertToStrings(rows);
this.nodeNames = nodeNames(this.stringList);
this.familiarities = familiarities(this.stringList);
}
public ArrayList<String> nodeNames(ArrayList<ArrayList<String>> stringValues) {
ArrayList<String> nameOfNodes = (ArrayList<String>) stringValues.get(0).clone();
nameOfNodes.remove(0);
return nameOfNodes;
}
public ArrayList<ArrayList<String>> convertToStrings(String[] rows){
ArrayList<ArrayList<String>> csvRows = new ArrayList<ArrayList<String>>(rows.length -1);
for(String row: rows) {
String[] cols = cols(row);
ArrayList<String> csvCols = new ArrayList<String>();
for(String col: cols) csvCols.add(col);
csvRows.add(csvCols);
}
return csvRows;
}
private String[] cols(String row) {
return split(row, ',');
}
public ArrayList<ArrayList<String>> familiarities(ArrayList<ArrayList<String>> stringValues) {
ArrayList<ArrayList<String>> vals = (ArrayList<ArrayList<String>>) stringValues.clone();
for(ArrayList<String> row: vals) row.remove(0);
vals.remove(0);
return vals;
}
}
class FamiliarityAsLine {
Coordinate vertexMe;
Coordinate vertexPeer;
int weight = 0;
FamiliarityAsLine(String familiarity, Coordinate vertexMe, Coordinate vertexPeer) {
determineWeight(Integer.parseInt(familiarity));
this.vertexMe = vertexMe;
this.vertexPeer = vertexPeer;
}
public void drawLine(color colour){
noFill();
println(vertexMe);
println(vertexPeer);
int x1 = this.vertexMe.x;
int y1 = this.vertexMe.y;
int x2 = this.vertexPeer.x;
int y2 = this.vertexPeer.y;
int ctlX1 = int(x1 - x1 * 0.3);
int ctlY1 = int(y1 - y1 * 0.3);
int ctlX2 = int(x2 - x2 * 0.4);
int ctlY2 = int(y2 - y2 * 0.4);
if(this.weight > 0) stroke(colour);
bezier(x1, y1, ctlX1, ctlY1, ctlX2, ctlY2, x2, y2);
}
public void determineWeight(int familiarity) {
if(familiarity == 0 || familiarity == 1) {
noStroke();
this.weight = 0;
} else {
this.weight = familiarity;
}
strokeWeight(weight);
}
}
@suzukimilanpaak
Copy link
Author

@suzukimilanpaak
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment