Skip to content

Instantly share code, notes, and snippets.

@darrenjaworski
Last active July 6, 2016 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrenjaworski/d08c1cd33902dbc081d8bd8ff529103e to your computer and use it in GitHub Desktop.
Save darrenjaworski/d08c1cd33902dbc081d8bd8ff529103e to your computer and use it in GitHub Desktop.
Graph Algorithm Viz
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Graphs Viz</title>
<style>
body {
max-width: 55em;
margin: 0 auto;
}
.links line {
stroke: #aaa;
stroke-width: 2;
}
.nodes circle {
pointer-events: all;
stroke: none;
fill: #aaa;
}
</style>
</head>
<body id="width">
<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="script.js"></script>
</body>
</html>
( function(){
var nodeTotal = 50;
var edgeTotal = nodeTotal * 1.25;
var graph = {
nodes: [],
edges: [],
adjacent: []
};
graph.nodes = d3.range(nodeTotal).map(function(i) {
var node = { id : i };
return node;
});
graph.edges = d3.range(edgeTotal).map(function(i) {
var source = i < nodeTotal ? i : Math.floor(Math.random() * nodeTotal);
var target = Math.floor(Math.random() * nodeTotal);
var edge = {
source: source,
target: target
};
if (graph.adjacent[source] === undefined) {
graph.adjacent[source] = [];
}
if (graph.adjacent[target] === undefined) {
graph.adjacent[target] = [];
}
graph.adjacent[source].push(target);
graph.adjacent[target].push(source);
return edge;
});
var svg = d3.select("svg"),
width = document.getElementById('width').clientWidth,
height = width;
svg.attr('width', width)
.attr('height', height);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.edges)
.enter().append("line");
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes, function(d) { return d.id; })
.enter().append("circle")
.attr("r", 5);
node.append("title")
.text(function(d) { return d.id; });
simulation.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.edges);
function ticked() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
var DepthFirstSearch = {
marked: [],
edgeTo: [],
source: 0,
count: 0,
dfs: function(graphObject, nodeIndex) {
var self = DepthFirstSearch;
dfs(graphObject, nodeIndex);
function dfs(graphObject, nodeIndex) {
self.marked[nodeIndex] = true;
self.count++;
graphObject.adjacent[nodeIndex].forEach(function(d){
if (!self.marked[d]) {
self.edgeTo[d] = nodeIndex;
dfs(graphObject, d);
}
});
return;
}
return;
},
hasPathTo: function(endIndex) {
var self = DepthFirstSearch;
return self.marked[endIndex];
},
pathTo: function(graphObject, startIndex, endIndex) {
var self = DepthFirstSearch;
self.dfs(graphObject, startIndex);
if (!self.hasPathTo(endIndex)) {
return null;
}
var path = [];
for (var i = endIndex; i != startIndex; i = self.edgeTo[i]) {
path.push(i);
}
path.push(startIndex);
return path.reverse();
}
};
var BreadthFirstSearch = {
marked: [],
edgeTo: [],
count: 0,
bfs: function(graphObject, nodeIndex) {
var self = BreadthFirstSearch;
var queue = [];
self.marked[nodeIndex] = true;
queue.push(nodeIndex);
while (queue.length > 0) {
var v = queue.shift();
graphObject.adjacent[v].forEach(markedAdjacent);
}
function markedAdjacent(d) {
if (!self.marked[d]) {
self.edgeTo[d] = v;
self.marked[d] = true;
queue.push(d);
}
}
},
hasPathTo: function(endIndex){
var self = BreadthFirstSearch;
return self.marked[endIndex];
},
pathTo: function(graphObject, startIndex, endIndex) {
var self = BreadthFirstSearch;
self.bfs(graphObject, startIndex);
if (!self.hasPathTo(endIndex)) {
return null;
}
var path = [];
for (var i = endIndex; i != startIndex; i = self.edgeTo[i]) {
path.push(i);
}
path.push(startIndex);
return path.reverse();
}
};
var start = Math.floor(Math.random() * nodeTotal);
var end = Math.floor(Math.random() * nodeTotal);
var dfpath = DepthFirstSearch.pathTo(graph, start, end);
var path = BreadthFirstSearch.pathTo(graph, start, end);
if (path !== null) {
var pathNodes = node.filter(function(d){ return path.indexOf(d.id) > -1; })
.style('fill', '#000000');
var pathEdges = link.filter(function(d){
if (path.indexOf(d.source.id) < 0 || path.indexOf(d.target.id) < 0) {
return false;
} else {
var sourceIndex = path.indexOf(d.source.id);
var targetIndex = path.indexOf(d.target.id);
var check = path[sourceIndex - 1] == d.target.id || path[sourceIndex + 1] == d.target.id;
return check;
}
}).style('stroke', '#000000');
}
} )();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment