|
// Generated by CoffeeScript 1.4.0 |
|
(function() { |
|
var R, attempt, height, input, links_layer, load, nodes_layer, prufer2graph, redraw, select, svg, width; |
|
|
|
prufer2graph = function(prufer) { |
|
var degree, graph, i, n, t, u, v, _i, _len, _ref; |
|
prufer = prufer.map(function(i) { |
|
return i - 1; |
|
}); |
|
t = prufer.length; |
|
graph = { |
|
nodes: d3.range(t + 2).map(function(i) { |
|
return { |
|
id: i + 1 |
|
}; |
|
}), |
|
links: [] |
|
}; |
|
degree = d3.range(t + 2).map(function() { |
|
return 1; |
|
}); |
|
prufer.forEach(function(i) { |
|
if (i > t) { |
|
throw 'Invalid Prufer sequence!'; |
|
} |
|
return degree[i] += 1; |
|
}); |
|
prufer.forEach(function(i) { |
|
var j, n, _i, _len, _ref, _results; |
|
_ref = graph.nodes; |
|
_results = []; |
|
for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) { |
|
n = _ref[j]; |
|
if (degree[j] === 1) { |
|
graph.links.push({ |
|
source: graph.nodes[i], |
|
target: n, |
|
id: "(" + (Math.min(i, j)) + ")--(" + (Math.max(i, j)) + ")" |
|
}); |
|
degree[i] -= 1; |
|
degree[j] -= 1; |
|
break; |
|
} else { |
|
_results.push(void 0); |
|
} |
|
} |
|
return _results; |
|
}); |
|
u = null; |
|
v = null; |
|
_ref = graph.nodes; |
|
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { |
|
n = _ref[i]; |
|
if (degree[i] === 1) { |
|
if (u === null) { |
|
u = n; |
|
} else { |
|
v = n; |
|
break; |
|
} |
|
} |
|
} |
|
graph.links.push({ |
|
source: u, |
|
target: v, |
|
id: "(" + (Math.min(u.id, v.id)) + ")--(" + (Math.max(u.id, v.id)) + ")" |
|
}); |
|
return graph; |
|
}; |
|
|
|
R = 16; |
|
|
|
svg = d3.select('svg'); |
|
|
|
width = svg.node().getBoundingClientRect().width; |
|
|
|
height = svg.node().getBoundingClientRect().height; |
|
|
|
links_layer = svg.append('g'); |
|
|
|
nodes_layer = svg.append('g'); |
|
|
|
redraw = function(data) { |
|
var d3cola, enter_nodes, graph, links, nodes; |
|
graph = prufer2graph(data); |
|
/* create nodes and links |
|
*/ |
|
|
|
nodes = nodes_layer.selectAll('.node').data(graph.nodes, function(d) { |
|
return d.id; |
|
}); |
|
enter_nodes = nodes.enter().append('g').attr('class', 'node'); |
|
enter_nodes.append('circle').attr('r', R); |
|
/* draw the label |
|
*/ |
|
|
|
enter_nodes.append('text').text(function(d) { |
|
return d.id; |
|
}).attr('dy', '0.35em'); |
|
nodes.exit().remove(); |
|
links = links_layer.selectAll('.link').data(graph.links, function(d) { |
|
return d.id; |
|
}); |
|
links.enter().append('line').attr('class', 'link'); |
|
links.exit().remove(); |
|
/* cola layout |
|
*/ |
|
|
|
graph.nodes.forEach(function(v) { |
|
v.width = 2.5 * R; |
|
return v.height = 2.5 * R; |
|
}); |
|
d3cola = cola.d3adaptor().size([width, height]).linkDistance(40).avoidOverlaps(true).nodes(graph.nodes).links(graph.links).on('tick', function() { |
|
/* update nodes and links |
|
*/ |
|
nodes.attr('transform', function(d) { |
|
return "translate(" + d.x + "," + d.y + ")"; |
|
}); |
|
return links.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; |
|
}); |
|
}); |
|
enter_nodes.call(d3cola.drag); |
|
return d3cola.start(30, 30, 30); |
|
}; |
|
|
|
input = d3.select('input'); |
|
|
|
input.on('input', function() { |
|
return attempt(this.value); |
|
}); |
|
|
|
select = d3.select('select'); |
|
|
|
select.on('input', function() { |
|
return load(this.value); |
|
}); |
|
|
|
load = function(value) { |
|
input.node().value = value; |
|
return attempt(value); |
|
}; |
|
|
|
attempt = function(value) { |
|
var data; |
|
try { |
|
data = JSON.parse(value); |
|
redraw(data); |
|
return input.classed('error', false); |
|
} catch (e) { |
|
return input.classed('error', true); |
|
} |
|
}; |
|
|
|
load(select.node().value); |
|
|
|
}).call(this); |