/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://p5js.sketchpad.cc/sp/pad/view/ro.tO37L9PB$pH/rev.198
*
* authors:
* David Griswold
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
var myGraph=new Graph();
var moving;
var connecting;
var xdistance;
var ydistance;
var movingCircle;
var startNode;
var promptedNoKey;
function buildGraph() {
//you build a graph by adding edges (nodes are built automatically as needed, one per name
//For now, all edges are undirected, but the ability to add directions is available, though they can't be visualized.
myGraph.addEdge("A","B",10); //adds an edge between nodes A to B of weight 10
myGraph.addEdge("B","C",11); //adds an edge from B to C of weight 11.
myGraph.addEdge("E", "D", 3); //adds an edge from E to D of weight 3.
myGraph.addEdge("A","E",6);
myGraph.addEdge("A","D",1);
myGraph.addEdge("C","D",4);
//other commands you can use:
//g.getEdges() returns a list of Edges
//g.getNodes() returns a list of Nodes
//g.getNodeString() returns a string you can print to visualize the graph
//n.getEdgesOut() returns a list of edges going OUT of a Node.
//n.getEdgesIn() returns a list of edges coming IN to a Node This list is the same as above for undirected.
//n.getName()
//e.getToNode() returns the node the edge is pointing toward ()
//e.getFromNode() returns the node the edge is coming from
//e.getWeight() returns the weight of an edge
}
function setup() {
createCanvas(500,500);
textSize(16);
textAlign(CENTER,CENTER);
//buildGraph();
}
function draw() {
clear();
fill(0);
noStroke();
text("Ctrl-click for new node. Shift-drag for new edge. Drag to move.",250,10);
if (!mouseIsPressed) {
moving=false;
}
var nodes = myGraph.getNodes();
var edges = myGraph.getEdges();
for (i=0;i<edges.length;i++) {
x1=edges[i].getFromNode().getX();
y1=edges[i].getFromNode().getY();
x2=edges[i].getToNode().getX();
y2=edges[i].getToNode().getY();
stroke(0)
line(x1,y1,x2,y2);
fill(0);
var xpos=(x1+x2)/2;
var ypos=(y1+y2)/2;
var v1=createVector(x2-x1,y2-y1);
v1.normalize();
v1.rotate(PI/2);
v1.mult(10);
noStroke();
text(edges[i].getWeight(),xpos+v1.x,ypos+v1.y);
}
for (i=0;i<nodes.length;i++) {
if(moving && movingCircle==i) {
nodes[i].move(mouseX-xdistance,mouseY-ydistance);
}
if(distance(mouseX,mouseY,nodes[i].getX(),nodes[i].getY())<=25) {
fill(128,0,0);
if(mouseIsPressed && !moving && !connecting && (!keyIsDown(SHIFT) || promptedNoKey)) {
moving=true;
xdistance=mouseX-nodes[i].getX();
ydistance=mouseY-nodes[i].getY();
movingCircle=i;
}
if(mouseIsPressed && !moving && !connecting && keyIsDown(SHIFT) &&!promptedNoKey) {
connecting=true;
startNode=i;
}
if (!mouseIsPressed && connecting && startNode!=i) {
connecting=false;
var w=prompt("Weight for this edge?");
if(w!=null) {myGraph.addEdge(nodes[startNode],nodes[i], w);}
promptedNoKey=true;
}
}else{
fill(0,0,128);
}
ellipse(nodes[i].getX(), nodes[i].getY(),50,50);
fill(255,255,255);
noStroke();
text(nodes[i].getName(),nodes[i].getX(),nodes[i].getY());
}
if(!mouseIsPressed) connecting=false;
if(connecting) {
stroke(255,0,0);
line(nodes[startNode].getX(),nodes[startNode].getY(),mouseX,mouseY);
stroke(0);
}
}
function mouseClicked() {
if (!moving && !connecting && keyIsDown(CONTROL) &&!promptedNoKey) {
var n=prompt("What should I name this new node?")
promptedNoKey=true;
if (n != null) {
var newNode=myGraph.addNode(n);
newNode.move(mouseX,mouseY);
}
}
return false;
}
function keyPressed(){
promptedNoKey=false;
// Do something
return false; // prevent any default behaviour
}
function distance(x1,y1,x2,y2) {
return sqrt(sq(x2-x1)+sq(y2-y1));
}
//----------------------------------//
function Edge(from, to, w, g,twoway) {
this.fromNode = from;
this.toNode = to;
this.weight = w;
this.graph = g;
this.twoway=twoway;
this.getGraph = function() {return this.getGraph;}
this.getFromNode = function() {return this.fromNode;}
this.getToNode = function() {return this.toNode;}
this.getWeight = function() {return this.weight;}
this.getOtherNode = function(n) {
if (n instanceof Node) {
if (n===this.toNode) {
return this.fromNode;
}else{
return this.toNode;
}
}else{
if(n===this.toNode.getName()) {
return this.fromNode;
}else{
return this.toNode;
}
}
}
}
function Node(n, g) {
this.xpos = random(25,475);
this.ypos = random(25,475);
this.name = n;
this.edgesOut = [];
this.edgesIn = [];
this.graph = g;
this.getEdgesOut = function() {return this.edgesOut;}
this.getEdgesIn = function() {return this.edgesIn;}
this.getName = function() {return this.name;}
this.getGraph = function() {return this.graph;}
this.move = function(x,y) {
this.xpos = x;
this.ypos = y;
}
this.getX = function() {return this.xpos};
this.getY = function() {return this.ypos};
this.addEdgeOut = function(e) {
this.edgesOut.push(e);
}
this.addEdgeIn = function(e) {
this.edgesIn.push(e);
}
}
function Graph() {
this.nodes = [];
this.edges = [];
this.addNode = function(name) {
n = new Node(name, this);
this.nodes.push(n);
return n;
}
this.addEdge= function(fromNodeName, toNodeName, weight) {
var n1;
var n2;
if (fromNodeName instanceof Node) n1=fromNodeName;
if (toNodeName instanceof Node) n2=toNodeName;
if(n1===undefined || n2===undefined) {
for (i=0;i<this.nodes.length;i++) {
if (n1===undefined) if(this.nodes[i].getName()===fromNodeName) n1=this.nodes[i];
if (n2===undefined) if(this.nodes[i].getName()===toNodeName) n2=this.nodes[i];
}
}
if (n1 === undefined) {
n1 = this.addNode(fromNodeName);
}
if (n2=== undefined) {
n2 = this.addNode(toNodeName);
}
var e = new Edge(n1, n2, weight, this,true);
n2.addEdgeIn(e);
n1.addEdgeIn(e);
n1.addEdgeOut(e);
n2.addEdgeOut(e);
this.edges.push(e);
return e;
}
this.getNodes = function() {return this.nodes;}
this.getEdges = function() {return this.edges;}
this.getNodeString = function() {
var nodestring="";
console.log(this.nodes.length);
for (i=0;i<this.nodes.length;i++) {
nodestring += this.nodes[i].getName()+" --> {";
var e = this.nodes[i].getEdgesOut();
for (j=0;j<e.length;j++) {
var n=e[j].getOtherNode(this.nodes[i]);
nodestring = nodestring + n.getName() + "," +e[j].getWeight()+" ";
}
nodestring=nodestring.trim();
nodestring = nodestring + '} ';
}
nodestring = nodestring.trim();
return nodestring;
}
}