You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
4.5 KiB
HTML
112 lines
4.5 KiB
HTML
5 years ago
|
<!doctype html>
|
||
|
<html>
|
||
|
<head>
|
||
|
<script type="text/javascript" src="../../pattern/canvas.js"></script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<script type="text/canvas">
|
||
|
function setup(canvas) {
|
||
|
canvas.size(800, 500);
|
||
|
// Import the graph.js module asynchronously.
|
||
|
// Import the commonsense.js data asynchronously.
|
||
|
include("http://www.clips.ua.ac.be/media/canvas/graph.js");
|
||
|
include("http://www.clips.ua.ac.be/media/canvas/data/commonsense.js");
|
||
|
// Using include() in the setup() function ensures that
|
||
|
// everything will be done loading at the first draw().
|
||
|
// We can think of many interesting ways to import extra JavaScript modules.
|
||
|
try {
|
||
|
g.clear(); halo.clear(); // Clear previous run (if any).
|
||
|
} catch(e) {}
|
||
|
}
|
||
|
function draw(canvas) {
|
||
|
if (canvas.frame == 1) {
|
||
|
// The first frame is a good time to initialize the graph.
|
||
|
// At this point we are certain that the module has finished loading.
|
||
|
// Create a new Graph object:
|
||
|
g = new Graph();
|
||
|
// Traverse the relations in the common sense dataset.
|
||
|
// Loading commonsense.js defines a list of relations named "commonsense".
|
||
|
// Each relation has the form: [concept1, relation, concept2, context].
|
||
|
// For example, ["red", "is-property-of", "rose", "nature"].
|
||
|
// Add each relation as an edge (connection) to the graph.
|
||
|
Array.enumerate(commonsense, function(i, r) {
|
||
|
g.addEdge(r[0], r[2], {type:r[1], context:r[3]});
|
||
|
});
|
||
|
// Graph.node() retrieves a Node object by id.
|
||
|
// Node.flatten() returns a list with the Node (depth=0),
|
||
|
// each node connected to it (depth=1), and so on.
|
||
|
// We call this the concept "halo":
|
||
|
// the latent concepts that reinforce the concept itself.
|
||
|
// Create a subgraph of the node's halo:
|
||
|
halo = g.copy(canvas.element, g.node('rocket').flatten(2));
|
||
|
// Note how we pass Canvas.element, the drawing context.
|
||
|
// Calculcate Graph.eigenvectorCentrality().
|
||
|
// This is a measure of each node's importance,
|
||
|
// based on the (indirect) incoming connections.
|
||
|
// Once calculated we can then use Node.weight.
|
||
|
halo.eigenvectorCentrality();
|
||
|
// Similarly, Graph.betweennessCentrality() is a
|
||
|
// measure of node importance based on passing traffic.
|
||
|
// Once calculted we can use Node.centrality.
|
||
|
halo.betweennessCentrality();
|
||
|
// Traverse all the nodes in the halo.
|
||
|
// Each node will have an associated text label displaying its id.
|
||
|
// The text label is stored in a <div class="node-label"> element,
|
||
|
// for which we can define CSS styles.
|
||
|
Array.enumerate(halo.nodes, function(i, n) {
|
||
|
n.radius = 4 + 6 * n.weight;
|
||
|
n.text.style.marginLeft = n.radius + 2 + "px";
|
||
|
n.text.style.marginTop = -n.radius - 2 + "px";
|
||
|
n.text.style.fontFamily = "Arial";
|
||
|
n.text.style.fontSize = "9px";
|
||
|
n.text.style.textTransform = "uppercase";
|
||
|
});
|
||
|
// Some nodes have a lot of "leaf" nodes, that is,
|
||
|
// nodes that only connect to this node.
|
||
|
// We want to prune some of them to avoid cluttering the visualization.
|
||
|
Array.enumerate(halo.nodes, function(i, n1) {
|
||
|
Array.enumerate(n1.links, function(j, n2) {
|
||
|
if (n1.links.length > 10 && n2.links.length == 1) {
|
||
|
halo.remove(n2);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
// Graph.shortestPath() takes two nodes and returns
|
||
|
// the shortest path between them as a list of nodes.
|
||
|
// To get the edges connecting these nodes, we can use the edges() function.
|
||
|
var p = halo.shortestPath("expensive", "rocket");
|
||
|
Array.enumerate(edges(p), function(i, e) {
|
||
|
e.stroke = color(0, 0.2, 1);
|
||
|
e.strokewidth = 1.25;
|
||
|
});
|
||
|
// We could also highlight the nodes along the path:
|
||
|
Array.enumerate(p, function(i, n) {
|
||
|
n.fill = color(0, 0.2, 1, 0.5);
|
||
|
n.text.style.background = "#000";
|
||
|
n.text.style.color = "#fff";
|
||
|
});
|
||
|
}
|
||
|
// The Graph.layout.iterations increments each time Graph.update() is called.
|
||
|
// Graph.update() calculates the attractive and repulsive forces between nodes.
|
||
|
// We set a limit to the number of updates + redraws,
|
||
|
// so the CPU doesn't start overheating.
|
||
|
if (halo.layout.iterations < 1000) {
|
||
|
canvas.clear();
|
||
|
//shadow(); // Looks nice but slow.
|
||
|
background(1);
|
||
|
fill(0, 0.2, 1, 0.2);
|
||
|
stroke(0, 0.5);
|
||
|
strokewidth(1);
|
||
|
halo.update();
|
||
|
halo.draw(false, true); // weighted=false, directed=true (arrowheads)
|
||
|
}
|
||
|
// When the user drags the mouse on a node,
|
||
|
// Graph.layout.iterations is reset to 0, so the graph is redrawn.
|
||
|
halo.drag(canvas.mouse);
|
||
|
}
|
||
|
function stop(canvas) {
|
||
|
halo.clear();
|
||
|
}
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|