// Generated by CoffeeScript 1.4.0 (function() { var LABEL_WIDTH, PAD_MULTIPLIER, PROP_R, R, d3cola, defs, enter_label_box, enter_links, enter_nodes, enter_terms, graph, height, i, l, levels, links, n, nn, nodes, svg, topological_order, tspans, vis, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _m, _n, _o, _p, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; graph = { nodes: [ { id: 0, type: 'class', terms: [], label: 'Thing' }, { id: 1, type: 'class', terms: [], label: 'Physical_Object' }, { id: 2, type: 'class', terms: ['Stellula'], label: 'Celestial_Body' }, { id: 3, type: 'class', terms: [], label: 'Wandering_Star' }, { id: 4, type: 'class', terms: ['inerrans stella'], label: 'Fixed_Star' }, { id: 5, type: 'class', label: 'Galilean_Moon', terms: [] }, { id: 6, type: 'instance', terms: [], label: 'Moon' }, { id: 7, type: 'instance', terms: [], label: 'Earth' }, { id: 8, type: 'instance', terms: ['Iuppiter'], label: 'Jupiter' }, { id: 9, type: 'instance', terms: [] }, { id: 10, type: 'instance', terms: [] }, { id: 11, type: 'instance', terms: [] } ], links: [ { id: 1, source: 1, target: 0, type: 'is_a' }, { id: 2, source: 2, target: 1, type: 'is_a' }, { id: 3, source: 3, target: 2, type: 'is_a' }, { id: 4, source: 4, target: 2, type: 'is_a' }, { id: 5, source: 5, target: 4, type: 'is_a' }, { id: 6, source: 6, target: 3, type: 'instance_of' }, { id: 7, source: 7, target: 3, type: 'instance_of' }, { id: 8, source: 8, target: 3, type: 'instance_of' }, { id: 9, source: 9, target: 5, type: 'instance_of' }, { id: 10, source: 10, target: 5, type: 'instance_of' }, { id: 11, source: 11, target: 5, type: 'instance_of' }, { id: 13, source: 9, target: 8, type: 'is_near' }, { id: 14, source: 10, target: 8, type: 'is_near' }, { id: 15, source: 11, target: 8, type: 'is_near' } ] }; /* objectify the graph */ /* resolve node IDs (not optimized at all!) */ _ref = graph.links; for (_i = 0, _len = _ref.length; _i < _len; _i++) { l = _ref[_i]; _ref1 = graph.nodes; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { n = _ref1[_j]; if (l.source === n.id) { l.source = n; } if (l.target === n.id) { l.target = n; } } } /* store the node index into the node itself */ _ref2 = graph.nodes; for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = ++_k) { n = _ref2[i]; n.i = i; } /* store neighbor nodes into each node */ _ref3 = graph.nodes; for (i = _l = 0, _len3 = _ref3.length; _l < _len3; i = ++_l) { n = _ref3[i]; n.in_neighbors = []; n.out_neighbors = []; } _ref4 = graph.links; for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) { l = _ref4[_m]; l.source.out_neighbors.push(l.target); l.target.in_neighbors.push(l.source); } /* compute longest distances */ topological_order = tsort(graph.links.filter(function(l) { return l.type === 'is_a' || l.type === 'instance_of'; }).map(function(l) { return [l.source.i, l.target.i]; })); _ref5 = graph.nodes; for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) { n = _ref5[_n]; n.longest_dist = -Infinity; } graph.nodes[0].longest_dist = 0; _ref6 = topological_order.reverse(); for (_o = 0, _len6 = _ref6.length; _o < _len6; _o++) { i = _ref6[_o]; n = graph.nodes[i]; _ref7 = n.in_neighbors; for (_p = 0, _len7 = _ref7.length; _p < _len7; _p++) { nn = _ref7[_p]; if (nn.longest_dist < n.longest_dist + 1) { nn.longest_dist = n.longest_dist + 1; } } } graph.constraints = []; /* create the alignment contraints */ levels = _.uniq(graph.nodes.filter(function(n) { return n.type === 'class' || n.type === 'instance'; }).map(function(n) { return n.longest_dist; })); levels.forEach(function(depth) { return graph.constraints.push({ type: 'alignment', axis: 'y', offsets: graph.nodes.filter(function(n) { return n.longest_dist === depth; }).map(function(n) { return { node: n.i, offset: 0 }; }) }); }); R = 18; PROP_R = 1; PAD_MULTIPLIER = 3.5; LABEL_WIDTH = 100; /* create the position contraints */ levels.forEach(function(depth, i) { var n1, n2; if (i < levels.length - 1) { n1 = _.find(graph.nodes, function(n) { return n.longest_dist === depth; }); n2 = _.find(graph.nodes, function(n) { return n.longest_dist === depth + 1; }); return graph.constraints.push({ axis: 'y', left: n1.i, right: n2.i, gap: 2 * R }); } }); svg = d3.select('svg'); width = svg.node().getBoundingClientRect().width; height = svg.node().getBoundingClientRect().height; defs = svg.append('defs'); vis = svg.append('g').attr({ transform: 'translate(20,80)' }); /* define arrow markers for graph links */ defs.append('marker').attr({ id: 'end_arrow_is_a', viewBox: '-2 -2 10 14', refX: 5 + R, refY: 5, markerWidth: 6.3, markerHeight: 4.5, orient: 'auto' }).append('path').attr({ d: 'M0,0 L0,10 L9,5 z' }); defs.append('marker').attr({ id: 'end_arrow_instance_of', viewBox: '-2 -2 10 14', refX: 5 + R, refY: 5, markerWidth: 6.3, markerHeight: 4.5, orient: 'auto' }).append('path').attr({ d: 'M0,0 L0,10 L9,5 z' }); /* create nodes and links */ links = vis.selectAll('.link').data(graph.links, function(d) { return d.id; }); enter_links = links.enter().append('line').attr('class', function(d) { return "link " + d.type; }); enter_links.append('title').text(function(d) { var s, t; s = d.source.label != null ? d.source.label.toUpperCase() : "Unlabeled " + d.source.type; t = d.target.label != null ? d.target.label.toUpperCase() : "Unlabeled " + d.target.type; return "" + s + " " + d.type + " " + t; }); nodes = vis.selectAll('.node').data(graph.nodes, function(d) { return d.id; }); enter_nodes = nodes.enter().append('g').attr('class', function(d) { return "node " + d.type; }); enter_nodes.append('circle').attr('r', R); enter_nodes.append('title').text(function(d) { if (d.label != null) { return "" + (d.label.toUpperCase()) + " (" + d.type + ")"; } else { return "Unlabeled " + d.type; } }); /* draw the label box */ enter_label_box = enter_nodes.append('g'); enter_label_box.append('text').text(function(d) { return d.label; }).attr({ "class": 'label', x: R + 4, dy: function(d) { if ((d.terms != null) && d.terms.length > 0) { return '-0.25em'; } else { return '0.35em'; } } }); /* draw the terms */ enter_terms = enter_label_box.append('text').attr({ "class": 'terms' }); tspans = enter_terms.selectAll('tspan').data(function(d) { if (d.terms != null) { return d.terms; } else { return []; } }); tspans.enter().append('tspan').text(function(d) { return d; }).attr({ x: R + 6, y: function(d, i) { return "" + i + "em"; }, dy: '0.85em' }); /* cola layout */ graph.nodes.forEach(function(v) { if (v.type === 'property') { v.width = 2 * PROP_R; return v.height = 2 * PROP_R; } else { v.width = PAD_MULTIPLIER * R + ((v.label != null) || (v.terms != null) && v.terms.length > 0 ? LABEL_WIDTH : 0); return v.height = PAD_MULTIPLIER * R; } }); d3cola = cola.d3adaptor().size([width, height]).linkDistance(function(l) { if (l.type === 'instance_of') { return 60; } else if (l.type === '_has_property') { return 20; } else { return 80; } }).constraints(graph.constraints).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; }); }); d3cola.start(100, 30, 30); svg.append('foreignObject').html('