140 lines
3.8 KiB
JavaScript
140 lines
3.8 KiB
JavaScript
|
var NODE_RADIUS = 7;
|
||
|
var GATE_RADIUS = 2;
|
||
|
var REPEL_FORCE = 0;
|
||
|
var LINK_DISTANCE = 100;
|
||
|
|
||
|
var WIDTH = 1000;
|
||
|
var HEIGHT = 500;
|
||
|
|
||
|
function drawGraph (graph, panel) {
|
||
|
var d3cola = cola.d3adaptor()
|
||
|
.avoidOverlaps(true)
|
||
|
.size([WIDTH, HEIGHT]);
|
||
|
|
||
|
var svg = d3.select(panel);
|
||
|
|
||
|
d3.selectAll(panel + '> *').remove();
|
||
|
|
||
|
// define arrow markers for graph links
|
||
|
svg.append('svg:defs').append('svg:marker')
|
||
|
.attr('id', 'end-arrow')
|
||
|
.attr('viewBox', '0 -5 10 10')
|
||
|
.attr('refX', 6)
|
||
|
.attr('markerWidth', 4)
|
||
|
.attr('markerHeight', 4)
|
||
|
.attr('orient', 'auto')
|
||
|
.append('svg:path')
|
||
|
.attr('d', 'M0,-5L10,0L0,5');
|
||
|
|
||
|
graph.nodes.forEach(function (v) {
|
||
|
v.height = v.width = 2 * (v.name === 'GATE' ? GATE_RADIUS : NODE_RADIUS);
|
||
|
});
|
||
|
|
||
|
d3cola
|
||
|
.nodes(graph.nodes)
|
||
|
.links(graph.links)
|
||
|
.constraints(graph.constraints)
|
||
|
.symmetricDiffLinkLengths(REPEL_FORCE)
|
||
|
.linkDistance(LINK_DISTANCE)
|
||
|
.start(10, 15, 20);
|
||
|
|
||
|
var path = svg.selectAll('.link')
|
||
|
.data(graph.links)
|
||
|
.enter().append('svg:path')
|
||
|
.attr('class', 'link');
|
||
|
|
||
|
path.append('title')
|
||
|
.text(function (d) {
|
||
|
var text = '';
|
||
|
text += 'Weight: ' + Math.round(d.weight * 1000) / 1000 + '\n';
|
||
|
text += 'Source: ' + d.source.id + '\n';
|
||
|
text += 'Target: ' + d.target.id;
|
||
|
return text;
|
||
|
});
|
||
|
|
||
|
var node = svg.selectAll('.node')
|
||
|
.data(graph.nodes)
|
||
|
.enter().append('circle')
|
||
|
.attr('class', function (d) {
|
||
|
return 'node ' + d.name;
|
||
|
})
|
||
|
.attr('r', function (d) {
|
||
|
return d.name === 'GATE' ? GATE_RADIUS : NODE_RADIUS;
|
||
|
})
|
||
|
|
||
|
.call(d3cola.drag);
|
||
|
|
||
|
node.append('title')
|
||
|
.text(function (d) {
|
||
|
var text = '';
|
||
|
text += 'Activation: ' + Math.round(d.activation * 1000) / 1000 + '\n';
|
||
|
text += 'Bias: ' + Math.round(d.bias * 1000) / 1000 + '\n';
|
||
|
text += 'Position: ' + d.id;
|
||
|
return text;
|
||
|
});
|
||
|
|
||
|
var label = svg.selectAll('.label')
|
||
|
.data(graph.nodes)
|
||
|
.enter().append('text')
|
||
|
.attr('class', 'label')
|
||
|
.text(function (d) {
|
||
|
return '(' + d.index + ') ' + d.name;
|
||
|
})
|
||
|
.call(d3cola.drag);
|
||
|
|
||
|
d3cola.on('tick', function () {
|
||
|
// draw directed edges with proper padding from node centers
|
||
|
path.attr('d', function (d) {
|
||
|
var deltaX = d.target.x - d.source.x;
|
||
|
var deltaY = d.target.y - d.source.y;
|
||
|
var dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||
|
var normX = deltaX / dist;
|
||
|
var normY = deltaY / dist;
|
||
|
|
||
|
if (isNaN(normX)) normX = 0;
|
||
|
if (isNaN(normY)) normY = 0;
|
||
|
|
||
|
var sourcePadding = d.source.width / 2;
|
||
|
var targetPadding = d.target.width / 2 + 2;
|
||
|
var sourceX = d.source.x + (sourcePadding * normX);
|
||
|
var sourceY = d.source.y + (sourcePadding * normY);
|
||
|
var targetX = d.target.x - (targetPadding * normX);
|
||
|
var targetY = d.target.y - (targetPadding * normY);
|
||
|
|
||
|
// Defaults for normal edge.
|
||
|
var drx = 0;
|
||
|
var dry = 0;
|
||
|
var xRotation = 0; // degrees
|
||
|
var largeArc = 0; // 1 or 0
|
||
|
var sweep = 1; // 1 or 0
|
||
|
|
||
|
// Self edge.
|
||
|
if (d.source.x === d.target.x && d.source.y === d.target.y) {
|
||
|
xRotation = -45;
|
||
|
largeArc = 1;
|
||
|
drx = 20;
|
||
|
dry = 20;
|
||
|
targetX = targetX + 1;
|
||
|
targetY = targetY + 1;
|
||
|
}
|
||
|
return 'M' + sourceX + ',' + sourceY + 'A' + drx + ',' + dry + ' ' + xRotation + ',' + largeArc + ',' + sweep + ' ' + targetX + ',' + targetY;
|
||
|
});
|
||
|
|
||
|
node
|
||
|
.attr('cx', function (d) {
|
||
|
return d.x;
|
||
|
})
|
||
|
.attr('cy', function (d) {
|
||
|
return d.y;
|
||
|
});
|
||
|
|
||
|
label
|
||
|
.attr('x', function (d) {
|
||
|
return d.x + 10;
|
||
|
})
|
||
|
.attr('y', function (d) {
|
||
|
return d.y - 10;
|
||
|
});
|
||
|
});
|
||
|
}
|