Skip to content

Instantly share code, notes, and snippets.

@mathieu-clement
Created March 1, 2018 07:19
Show Gist options
  • Save mathieu-clement/46e6b3530f207af68908f6cacf3e51a4 to your computer and use it in GitHub Desktop.
Save mathieu-clement/46e6b3530f207af68908f6cacf3e51a4 to your computer and use it in GitHub Desktop.
cs560-assign3-force
881 858
828 697
884 864
856 869
889 856
872 873
719 713
861 863
840 803
864 856
719 840
745 805
865 857
874 873
708 823
872 885
870 871
888 889
825 889
869 774
729 888
769 869
823 840
861 729
774 769
805 800
713 819
774 856
885 859
729 876
872 887
895 881
697 890
823 810
870 895
871 879
823 753
819 719
708 869
719 810
745 830
747 830
774 810
856 747
879 881
776 874
774 805
747 819
772 828
888 804
890 753
889 886
856 864
864 893
747 719
861 889
819 708
769 811
867 874
887 874
868 857
828 810
878 889
889 753
719 772
819 823
867 877
819 828
876 889
708 819
828 856
856 708
800 810
708 830
729 882
887 776
867 776
719 774
861 804
856 878
772 713
894 879
810 747
772 805
774 719
753 708
697 830
772 856
885 877
886 889
745 810
729 804
840 823
887 872
893 856
697 753
810 823
804 863
805 713
713 823
830 800
881 871
890 708
830 745
866 881
863 804
800 805
840 708
859 885
828 880
868 865
889 825
745 747
884 825
888 861
872 867
889 729
830 713
747 713
856 804
856 825
871 857
800 719
886 863
703 828
866 879
800 774
819 880
805 830
753 769
772 800
697 800
708 713
823 719
819 753
856 840
886 729
876 886
804 876
708 747
873 776
769 828
885 872
713 774
885 873
869 856
811 856
800 697
823 805
885 776
747 810
697 823
703 819
811 800
753 729
774 811
879 894
825 884
747 774
870 894
713 805
884 893
729 856
747 804
747 769
745 800
774 708
810 856
856 772
869 811
703 747
877 867
811 890
856 888
867 872
703 805
719 697
800 713
713 810
729 863
888 876
856 863
889 888
876 856
823 830
747 803
886 878
774 869
776 867
811 769
873 872
857 868
869 890
719 819
889 878
840 830
828 830
697 828
774 747
747 697
830 708
819 747
871 895
776 873
856 810
864 825
828 703
774 800
708 769
769 800
800 747
823 703
890 811
803 747
890 769
856 769
887 867
697 819
840 697
753 856
697 772
886 804
865 868
729 753
811 708
697 719
819 703
830 840
823 708
697 745
708 753
894 870
708 719
805 880
881 879
697 856
823 856
747 823
828 819
708 697
774 745
878 888
872 776
747 805
800 823
810 800
803 840
804 882
747 856
878 886
753 890
830 697
769 890
866 895
828 823
828 745
882 729
890 869
769 774
708 811
856 823
880 823
804 888
830 719
861 888
719 805
697 747
880 819
776 872
830 856
882 863
863 856
747 880
880 805
745 697
774 823
810 719
810 713
856 800
880 828
769 856
828 800
840 828
869 769
828 708
819 774
772 719
769 798
870 858
713 840
719 745
776 887
823 800
810 745
885 874
819 805
878 856
825 864
876 882
819 840
870 881
873 874
856 828
878 804
867 885
885 887
830 747
713 719
810 828
805 819
856 697
805 747
804 878
823 713
878 729
861 753
745 823
878 861
800 745
828 772
823 745
895 858
873 885
713 697
804 856
878 863
882 889
880 803
881 870
863 878
708 840
872 874
774 828
828 747
713 747
856 889
823 697
708 774
719 708
856 830
882 876
863 876
879 866
747 828
753 823
863 886
703 880
745 713
856 703
823 747
823 828
800 811
769 697
874 872
753 697
895 866
840 747
879 870
873 867
828 769
828 713
868 862
819 830
880 747
874 885
719 828
863 861
713 828
830 823
830 805
840 713
745 774
753 747
869 708
886 876
895 870
887 885
800 769
888 878
747 745
811 869
828 774
697 708
876 804
863 882
862 865
708 800
772 697
803 880
810 774
753 889
713 830
856 811
857 865
840 774
774 840
697 805
729 886
800 828
719 823
747 703
703 856
804 861
858 871
874 776
881 866
862 868
800 708
708 856
769 753
865 862
805 823
805 810
856 861
840 856
729 861
862 857
719 703
828 805
745 828
857 871
713 772
719 830
856 774
800 772
881 895
893 884
697 840
882 856
885 867
713 800
804 729
863 729
747 840
895 871
856 893
876 861
856 876
864 884
863 888
867 887
774 713
828 840
888 856
830 828
708 890
861 856
870 879
876 878
894 866
876 888
889 876
857 862
879 871
863 889
890 697
729 878
747 753
805 719
858 870
745 719
713 745
819 856
805 774
798 769
708 828
729 889
800 830
830 774
769 708
776 885
886 882
867 873
747 708
819 697
861 878
893 864
697 713
805 703
774 819
753 861
858 895
703 823
856 882
874 867
877 885
805 697
719 747
805 828
747 800
823 880
804 747
804 886
805 840
713 708
811 774
889 882
878 876
825 856
888 863
823 819
880 703
882 886
877 776
805 745
776 877
871 881
819 713
856 753
719 800
876 729
840 819
861 876
804 889
889 804
828 719
871 858
889 861
840 805
769 747
805 772
888 729
874 887
840 719
703 719
753 819
871 870
810 805
866 894
889 863
876 863
697 769
882 804
856 729
856 819
774 830
800 856
858 881
823 774
830 819
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
<style> body {padding: 0; margin: 0;} </style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"></script>
<script src="sketch.js"></script>
</head>
<body>
</body>
</html>
var egoNode; // 0, 107, 348, 414, 686, 698, 1684, 1912, 3437, 3980...
var table; // data loaded from csv
var vertices = { };
var edges = [ ];
var adj = { }; // adjacency list. adj[3] = [5, 7] means there is an edge
// from 3 to 5, and from 3 to 7
// Guarantee: adj[x].contains(y) == adj[y].contains(x)
var iteration = 0;
var iterations = 50;
var plotHeight;
var plotWidth;
var t;
function preload() {
// Change ego node by suffixing URL with egoNode=123
var pEgoNode = getURLParams().egoNode;
if (pEgoNode) {
egoNode = int(pEgoNode);
} else {
egoNode = 698; // default
}
table = loadTable(egoNode + '.edges.csv', 'csv');
}
function unique_array(arr) {
var uniqueArr = [];
for (var i = 0 ; i < arr.length ; i++) {
if (uniqueArr.indexOf(arr[i]) < 0) { // not contains
uniqueArr.push(arr[i]);
}
}
return uniqueArr;
}
function int_array(arr) {
var intArr = [];
for (var i = 0 ; i < arr.length ; i++) {
intArr[i] = int(arr[i]);
}
return intArr;
}
class Vertex {
constructor(id) {
this.id = id;
this.disp_x = 0;
this.disp_y = 0;
this.pos_x = int(random(plotWidth));
this.pos_y = int(random(plotHeight));
}
}
function create_vertex(id) {
return new Vertex(id);
}
class Edge {
constructor(u, v) {
this.u = u;
this.v = v;
// color
this.r = random(256);
this.g = random(256);
this.b = random(256);
}
}
function create_edge(u, v) {
return new Edge(u, v);
}
function vector_norm(x, y) {
return sqrt(x*x + y*y);
}
function fr91(W, L, V, E) {
var area = W * L;
var V_length = 0;
for (var v in V) V_length++;
var k = sqrt(area/V_length);
var k2 = k*k;
var fa = function(x) { return x*x/k; }
var fr = function(x) { return x==0 ? 0 : k2/x; }
var cool = function(x) { return t - t/(iteration+2); }
// Calculate repulsive forces
for (var j in V) {
var v = V[j];
v.disp_x = 0;
v.disp_y = 0;
for (var l in V) {
if (j != l) {
var u = V[l];
var delta_x = v.pos_x - u.pos_x;
var delta_y = v.pos_y - u.pos_y;
var dist = vector_norm(delta_x, delta_y);
if (dist > 0) {
v.disp_x = v.disp_x + delta_x/dist * fr(dist);
v.disp_y = v.disp_y + delta_y/dist * fr(dist);
}
}
}
}
// Calculate attractive forces
for (var j in E) {
var e = E[j];
var lambda_x = e.v.pos_x - e.u.pos_x;
var lambda_y = e.v.pos_y - e.u.pos_y;
var dist = vector_norm(lambda_x, lambda_y);
if (dist > 0) {
var ax = lambda_x/dist * fa(dist);
var ay = lambda_y/dist * fa(dist);
e.v.disp_x -= ax;
e.v.disp_y -= ay;
e.u.disp_x += ax;
e.u.disp_y += ay;
}
}
// Limit max displacement to temperature t and
// prevent from displacement outside frame
for (var j in V) {
var v = V[j];
var v_disp_norm = vector_norm(v.disp_x, v.disp_y);
if (v_disp_norm > 0) {
var ddx = v.disp_x/v_disp_norm;
var ddy = v.disp_y/v_disp_norm;
v.pos_x += ddx * min(v_disp_norm, t);
v.pos_y += ddy * min(v_disp_norm, t);
v.pos_x = min(W-30, max(30, v.pos_x));
v.pos_y = min(L-30, max(30, v.pos_y));
}
}
// Reduce the temperature as the layout approaches a
// better configuration
t = cool(t);
}
function setup() {
plotHeight = windowHeight;
plotWidth = windowWidth;
t = plotWidth / 10;
createCanvas(plotWidth, plotHeight);
//randomSeed(500);
frameRate(24);
noSmooth();
// Prepare data
var rows = table.getRows();
// Create Vertex and Edge objects
// and add them to vertices and edges data structures
for (var i = 0 ; i < rows.length ; i++) {
var u_id = int(rows[i].getNum(0));
var v_id = int(rows[i].getNum(1));
if (!vertices.hasOwnProperty(u_id)) {
vertices[u_id] = create_vertex(u_id);
}
if (!vertices.hasOwnProperty(v_id)) {
vertices[v_id] = create_vertex(v_id);
}
var u = vertices[u_id];
var v = vertices[v_id];
edges.push(create_edge(u, v));
// Update adjacency matrix
if (!adj.hasOwnProperty(u_id))
adj[u_id] = [];
adj[u_id].push(v_id);
if (!adj.hasOwnProperty(v_id))
adj[v_id] = [];
adj[v_id].push(u_id);
}
// Create a vertex for the ego node
var egoVertex = create_vertex(egoNode);
vertices[egoNode] = egoVertex;
// Create an edge from each of the other vertices to the ego node
adj[egoNode] = [];
for (var i in vertices) {
if (i == egoNode) continue;
var u = vertices[i];
edges.push(create_edge(u, egoVertex));
if (!adj.hasOwnProperty(u.id))
adj[u.id] = [];
adj[u.id].push(egoNode);
adj[egoNode].push(u.id);
}
}
function draw() {
background(255);
// Execute algorithm
var W = plotWidth;
var L = plotHeight;
var V = vertices;
var E = edges;
if (t > 0 && iteration < iterations) {
fr91(W, L, V, E);
iteration++;
} else {
noLoop();
}
// Draw
for (var i in E) {
var e = E[i];
if (e.u.id == egoNode || e.v.id == egoNode) {
// Ego node: Light gray edges
stroke(224);
} else {
stroke(e.r, e.g, e.b);
}
line(e.u.pos_x, e.u.pos_y, e.v.pos_x, e.v.pos_y);
}
stroke(0);
textAlign(CENTER);
textSize(10);
for (var i in V) {
var v = V[i];
var x = v.pos_x;
var y = v.pos_y;
if (v.id == egoNode) {
continue; // let's do it later so it appears on top
} else {
strokeWeight(4);
point(x, y);
strokeWeight(1);
text(v.id, x, y-5);
}
}
// Ego node: Make it BIG!
var egoVertex = vertices[egoNode];
push();
fill(255, 0, 0); // red
push();
stroke(255, 0, 0);
strokeWeight(8);
point(egoVertex.pos_x, egoVertex.pos_y);
pop();
push();
textSize(20);
text(egoNode, egoVertex.pos_x, egoVertex.pos_y-10);
pop();
pop();
}
function mouseMoved() {
redraw();
var margin = 5;
for (var i in vertices) {
var v = vertices[i];
if (mouseX > v.pos_x - margin &&
mouseX < v.pos_x + margin &&
mouseY > v.pos_y - margin &&
mouseY < v.pos_y + margin) {
push();
for (var j in adj[v.id]) {
var u_id = adj[v.id][j];
var u = vertices[u_id];
strokeWeight(4);
line(v.pos_x, v.pos_y, u.pos_x, u.pos_y);
}
pop();
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment