mirror of
https://github.com/nunocoracao/blowfish.git
synced 2026-01-30 16:31:52 +01:00
config redirect
This commit is contained in:
2
node_modules/dagre-d3-es/src/dagre-js/arrows.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre-js/arrows.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export var arrows: any;
|
||||
export function setArrows(value: any): any;
|
||||
82
node_modules/dagre-d3-es/src/dagre-js/arrows.js
generated
vendored
Normal file
82
node_modules/dagre-d3-es/src/dagre-js/arrows.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import * as util from './util.js';
|
||||
|
||||
export { arrows, setArrows };
|
||||
|
||||
var arrows = {
|
||||
normal,
|
||||
vee,
|
||||
undirected,
|
||||
};
|
||||
|
||||
function setArrows(value) {
|
||||
arrows = value;
|
||||
}
|
||||
|
||||
function normal(parent, id, edge, type) {
|
||||
var marker = parent
|
||||
.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto');
|
||||
|
||||
var path = marker
|
||||
.append('path')
|
||||
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
|
||||
.style('stroke-width', 1)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
util.applyStyle(path, edge[type + 'Style']);
|
||||
if (edge[type + 'Class']) {
|
||||
path.attr('class', edge[type + 'Class']);
|
||||
}
|
||||
}
|
||||
|
||||
function vee(parent, id, edge, type) {
|
||||
var marker = parent
|
||||
.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto');
|
||||
|
||||
var path = marker
|
||||
.append('path')
|
||||
.attr('d', 'M 0 0 L 10 5 L 0 10 L 4 5 z')
|
||||
.style('stroke-width', 1)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
util.applyStyle(path, edge[type + 'Style']);
|
||||
if (edge[type + 'Class']) {
|
||||
path.attr('class', edge[type + 'Class']);
|
||||
}
|
||||
}
|
||||
|
||||
function undirected(parent, id, edge, type) {
|
||||
var marker = parent
|
||||
.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto');
|
||||
|
||||
var path = marker
|
||||
.append('path')
|
||||
.attr('d', 'M 0 5 L 10 5')
|
||||
.style('stroke-width', 1)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
util.applyStyle(path, edge[type + 'Style']);
|
||||
if (edge[type + 'Class']) {
|
||||
path.attr('class', edge[type + 'Class']);
|
||||
}
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre-js/create-clusters.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre-js/create-clusters.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function createClusters(selection: any, g: any): any;
|
||||
export function setCreateClusters(value: any): any;
|
||||
49
node_modules/dagre-d3-es/src/dagre-js/create-clusters.js
generated
vendored
Normal file
49
node_modules/dagre-d3-es/src/dagre-js/create-clusters.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import * as d3 from 'd3';
|
||||
import { addLabel } from './label/add-label.js';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { createClusters, setCreateClusters };
|
||||
|
||||
var createClusters = function (selection, g) {
|
||||
var clusters = g.nodes().filter(function (v) {
|
||||
return util.isSubgraph(g, v);
|
||||
});
|
||||
var svgClusters = selection.selectAll('g.cluster').data(clusters, function (v) {
|
||||
return v;
|
||||
});
|
||||
|
||||
util.applyTransition(svgClusters.exit(), g).style('opacity', 0).remove();
|
||||
|
||||
var enterSelection = svgClusters
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('class', 'cluster')
|
||||
.attr('id', function (v) {
|
||||
var node = g.node(v);
|
||||
return node.id;
|
||||
})
|
||||
.style('opacity', 0)
|
||||
.each(function (v) {
|
||||
var node = g.node(v);
|
||||
var thisGroup = d3.select(this);
|
||||
d3.select(this).append('rect');
|
||||
var labelGroup = thisGroup.append('g').attr('class', 'label');
|
||||
addLabel(labelGroup, node, node.clusterLabelPos);
|
||||
});
|
||||
|
||||
svgClusters = svgClusters.merge(enterSelection);
|
||||
|
||||
svgClusters = util.applyTransition(svgClusters, g).style('opacity', 1);
|
||||
|
||||
svgClusters.selectAll('rect').each(function (c) {
|
||||
var node = g.node(c);
|
||||
var domCluster = d3.select(this);
|
||||
util.applyStyle(domCluster, node.style);
|
||||
});
|
||||
|
||||
return svgClusters;
|
||||
};
|
||||
|
||||
function setCreateClusters(value) {
|
||||
createClusters = value;
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre-js/create-edge-labels.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre-js/create-edge-labels.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function createEdgeLabels(selection: any, g: any): any;
|
||||
export function setCreateEdgeLabels(value: any): any;
|
||||
54
node_modules/dagre-d3-es/src/dagre-js/create-edge-labels.js
generated
vendored
Normal file
54
node_modules/dagre-d3-es/src/dagre-js/create-edge-labels.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as _ from 'lodash-es';
|
||||
import { addLabel } from './label/add-label.js';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { createEdgeLabels, setCreateEdgeLabels };
|
||||
|
||||
let createEdgeLabels = function (selection, g) {
|
||||
var svgEdgeLabels = selection
|
||||
.selectAll('g.edgeLabel')
|
||||
.data(g.edges(), function (e) {
|
||||
return util.edgeToId(e);
|
||||
})
|
||||
.classed('update', true);
|
||||
|
||||
svgEdgeLabels.exit().remove();
|
||||
svgEdgeLabels.enter().append('g').classed('edgeLabel', true).style('opacity', 0);
|
||||
|
||||
svgEdgeLabels = selection.selectAll('g.edgeLabel');
|
||||
|
||||
svgEdgeLabels.each(function (e) {
|
||||
var root = d3.select(this);
|
||||
root.select('.label').remove();
|
||||
var edge = g.edge(e);
|
||||
var label = addLabel(root, g.edge(e), 0, 0).classed('label', true);
|
||||
var bbox = label.node().getBBox();
|
||||
|
||||
if (edge.labelId) {
|
||||
label.attr('id', edge.labelId);
|
||||
}
|
||||
if (!_.has(edge, 'width')) {
|
||||
edge.width = bbox.width;
|
||||
}
|
||||
if (!_.has(edge, 'height')) {
|
||||
edge.height = bbox.height;
|
||||
}
|
||||
});
|
||||
|
||||
var exitSelection;
|
||||
|
||||
if (svgEdgeLabels.exit) {
|
||||
exitSelection = svgEdgeLabels.exit();
|
||||
} else {
|
||||
exitSelection = svgEdgeLabels.selectAll(null); // empty selection
|
||||
}
|
||||
|
||||
util.applyTransition(exitSelection, g).style('opacity', 0).remove();
|
||||
|
||||
return svgEdgeLabels;
|
||||
};
|
||||
|
||||
function setCreateEdgeLabels(value) {
|
||||
createEdgeLabels = value;
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre-js/create-edge-paths.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre-js/create-edge-paths.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function createEdgePaths(selection: any, g: any, arrows: any): any;
|
||||
export function setCreateEdgePaths(value: any): any;
|
||||
131
node_modules/dagre-d3-es/src/dagre-js/create-edge-paths.js
generated
vendored
Normal file
131
node_modules/dagre-d3-es/src/dagre-js/create-edge-paths.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as _ from 'lodash-es';
|
||||
import { intersectNode } from './intersect/intersect-node.js';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { createEdgePaths, setCreateEdgePaths };
|
||||
|
||||
var createEdgePaths = function (selection, g, arrows) {
|
||||
var previousPaths = selection
|
||||
.selectAll('g.edgePath')
|
||||
.data(g.edges(), function (e) {
|
||||
return util.edgeToId(e);
|
||||
})
|
||||
.classed('update', true);
|
||||
|
||||
var newPaths = enter(previousPaths, g);
|
||||
exit(previousPaths, g);
|
||||
|
||||
var svgPaths = previousPaths.merge !== undefined ? previousPaths.merge(newPaths) : previousPaths;
|
||||
util.applyTransition(svgPaths, g).style('opacity', 1);
|
||||
|
||||
// Save DOM element in the path group, and set ID and class
|
||||
svgPaths.each(function (e) {
|
||||
var domEdge = d3.select(this);
|
||||
var edge = g.edge(e);
|
||||
edge.elem = this;
|
||||
|
||||
if (edge.id) {
|
||||
domEdge.attr('id', edge.id);
|
||||
}
|
||||
|
||||
util.applyClass(
|
||||
domEdge,
|
||||
edge['class'],
|
||||
(domEdge.classed('update') ? 'update ' : '') + 'edgePath'
|
||||
);
|
||||
});
|
||||
|
||||
svgPaths.selectAll('path.path').each(function (e) {
|
||||
var edge = g.edge(e);
|
||||
edge.arrowheadId = _.uniqueId('arrowhead');
|
||||
|
||||
var domEdge = d3
|
||||
.select(this)
|
||||
.attr('marker-end', function () {
|
||||
return 'url(' + makeFragmentRef(location.href, edge.arrowheadId) + ')';
|
||||
})
|
||||
.style('fill', 'none');
|
||||
|
||||
util.applyTransition(domEdge, g).attr('d', function (e) {
|
||||
return calcPoints(g, e);
|
||||
});
|
||||
|
||||
util.applyStyle(domEdge, edge.style);
|
||||
});
|
||||
|
||||
svgPaths.selectAll('defs *').remove();
|
||||
svgPaths.selectAll('defs').each(function (e) {
|
||||
var edge = g.edge(e);
|
||||
var arrowhead = arrows[edge.arrowhead];
|
||||
arrowhead(d3.select(this), edge.arrowheadId, edge, 'arrowhead');
|
||||
});
|
||||
|
||||
return svgPaths;
|
||||
};
|
||||
|
||||
function setCreateEdgePaths(value) {
|
||||
createEdgePaths = value;
|
||||
}
|
||||
|
||||
function makeFragmentRef(url, fragmentId) {
|
||||
var baseUrl = url.split('#')[0];
|
||||
return baseUrl + '#' + fragmentId;
|
||||
}
|
||||
|
||||
function calcPoints(g, e) {
|
||||
var edge = g.edge(e);
|
||||
var tail = g.node(e.v);
|
||||
var head = g.node(e.w);
|
||||
var points = edge.points.slice(1, edge.points.length - 1);
|
||||
points.unshift(intersectNode(tail, points[0]));
|
||||
points.push(intersectNode(head, points[points.length - 1]));
|
||||
|
||||
return createLine(edge, points);
|
||||
}
|
||||
|
||||
function createLine(edge, points) {
|
||||
var line = (d3.line || d3.svg.line)()
|
||||
.x(function (d) {
|
||||
return d.x;
|
||||
})
|
||||
.y(function (d) {
|
||||
return d.y;
|
||||
});
|
||||
|
||||
(line.curve || line.interpolate)(edge.curve);
|
||||
|
||||
return line(points);
|
||||
}
|
||||
|
||||
function getCoords(elem) {
|
||||
var bbox = elem.getBBox();
|
||||
var matrix = elem.ownerSVGElement
|
||||
.getScreenCTM()
|
||||
.inverse()
|
||||
.multiply(elem.getScreenCTM())
|
||||
.translate(bbox.width / 2, bbox.height / 2);
|
||||
return { x: matrix.e, y: matrix.f };
|
||||
}
|
||||
|
||||
function enter(svgPaths, g) {
|
||||
var svgPathsEnter = svgPaths.enter().append('g').attr('class', 'edgePath').style('opacity', 0);
|
||||
svgPathsEnter
|
||||
.append('path')
|
||||
.attr('class', 'path')
|
||||
.attr('d', function (e) {
|
||||
var edge = g.edge(e);
|
||||
var sourceElem = g.node(e.v).elem;
|
||||
var points = _.range(edge.points.length).map(function () {
|
||||
return getCoords(sourceElem);
|
||||
});
|
||||
return createLine(edge, points);
|
||||
});
|
||||
svgPathsEnter.append('defs');
|
||||
return svgPathsEnter;
|
||||
}
|
||||
|
||||
function exit(svgPaths, g) {
|
||||
var svgPathExit = svgPaths.exit();
|
||||
util.applyTransition(svgPathExit, g).style('opacity', 0).remove();
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre-js/create-nodes.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre-js/create-nodes.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function createNodes(selection: any, g: any, shapes: any): any;
|
||||
export function setCreateNodes(value: any): any;
|
||||
92
node_modules/dagre-d3-es/src/dagre-js/create-nodes.js
generated
vendored
Normal file
92
node_modules/dagre-d3-es/src/dagre-js/create-nodes.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as _ from 'lodash-es';
|
||||
import { addLabel } from './label/add-label.js';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { createNodes, setCreateNodes };
|
||||
|
||||
var createNodes = function (selection, g, shapes) {
|
||||
var simpleNodes = g.nodes().filter(function (v) {
|
||||
return !util.isSubgraph(g, v);
|
||||
});
|
||||
var svgNodes = selection
|
||||
.selectAll('g.node')
|
||||
.data(simpleNodes, function (v) {
|
||||
return v;
|
||||
})
|
||||
.classed('update', true);
|
||||
|
||||
svgNodes.exit().remove();
|
||||
|
||||
svgNodes.enter().append('g').attr('class', 'node').style('opacity', 0);
|
||||
|
||||
svgNodes = selection.selectAll('g.node');
|
||||
|
||||
svgNodes.each(function (v) {
|
||||
var node = g.node(v);
|
||||
var thisGroup = d3.select(this);
|
||||
util.applyClass(
|
||||
thisGroup,
|
||||
node['class'],
|
||||
(thisGroup.classed('update') ? 'update ' : '') + 'node'
|
||||
);
|
||||
|
||||
thisGroup.select('g.label').remove();
|
||||
var labelGroup = thisGroup.append('g').attr('class', 'label');
|
||||
var labelDom = addLabel(labelGroup, node);
|
||||
var shape = shapes[node.shape];
|
||||
var bbox = _.pick(labelDom.node().getBBox(), 'width', 'height');
|
||||
|
||||
node.elem = this;
|
||||
|
||||
if (node.id) {
|
||||
thisGroup.attr('id', node.id);
|
||||
}
|
||||
if (node.labelId) {
|
||||
labelGroup.attr('id', node.labelId);
|
||||
}
|
||||
|
||||
if (_.has(node, 'width')) {
|
||||
bbox.width = node.width;
|
||||
}
|
||||
if (_.has(node, 'height')) {
|
||||
bbox.height = node.height;
|
||||
}
|
||||
|
||||
bbox.width += node.paddingLeft + node.paddingRight;
|
||||
bbox.height += node.paddingTop + node.paddingBottom;
|
||||
labelGroup.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(node.paddingLeft - node.paddingRight) / 2 +
|
||||
',' +
|
||||
(node.paddingTop - node.paddingBottom) / 2 +
|
||||
')'
|
||||
);
|
||||
|
||||
var root = d3.select(this);
|
||||
root.select('.label-container').remove();
|
||||
var shapeSvg = shape(root, bbox, node).classed('label-container', true);
|
||||
util.applyStyle(shapeSvg, node.style);
|
||||
|
||||
var shapeBBox = shapeSvg.node().getBBox();
|
||||
node.width = shapeBBox.width;
|
||||
node.height = shapeBBox.height;
|
||||
});
|
||||
|
||||
var exitSelection;
|
||||
|
||||
if (svgNodes.exit) {
|
||||
exitSelection = svgNodes.exit();
|
||||
} else {
|
||||
exitSelection = svgNodes.selectAll(null); // empty selection
|
||||
}
|
||||
|
||||
util.applyTransition(exitSelection, g).style('opacity', 0).remove();
|
||||
|
||||
return svgNodes;
|
||||
};
|
||||
|
||||
function setCreateNodes(value) {
|
||||
createNodes = value;
|
||||
}
|
||||
6
node_modules/dagre-d3-es/src/dagre-js/intersect/index.d.ts
generated
vendored
Normal file
6
node_modules/dagre-d3-es/src/dagre-js/intersect/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import * as node from './intersect-node.js';
|
||||
import * as circle from './intersect-circle.js';
|
||||
import * as ellipse from './intersect-ellipse.js';
|
||||
import * as polygon from './intersect-polygon.js';
|
||||
import * as rect from './intersect-rect.js';
|
||||
export { node, circle, ellipse, polygon, rect };
|
||||
7
node_modules/dagre-d3-es/src/dagre-js/intersect/index.js
generated
vendored
Normal file
7
node_modules/dagre-d3-es/src/dagre-js/intersect/index.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import * as node from './intersect-node.js';
|
||||
import * as circle from './intersect-circle.js';
|
||||
import * as ellipse from './intersect-ellipse.js';
|
||||
import * as polygon from './intersect-polygon.js';
|
||||
import * as rect from './intersect-rect.js';
|
||||
|
||||
export { node, circle, ellipse, polygon, rect };
|
||||
8
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-circle.d.ts
generated
vendored
Normal file
8
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-circle.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export function intersectCircle(
|
||||
node: any,
|
||||
rx: any,
|
||||
point: any
|
||||
): {
|
||||
x: any;
|
||||
y: any;
|
||||
};
|
||||
7
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-circle.js
generated
vendored
Normal file
7
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-circle.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { intersectEllipse } from './intersect-ellipse.js';
|
||||
|
||||
export { intersectCircle };
|
||||
|
||||
function intersectCircle(node, rx, point) {
|
||||
return intersectEllipse(node, rx, rx, point);
|
||||
}
|
||||
9
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-ellipse.d.ts
generated
vendored
Normal file
9
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-ellipse.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export function intersectEllipse(
|
||||
node: any,
|
||||
rx: any,
|
||||
ry: any,
|
||||
point: any
|
||||
): {
|
||||
x: any;
|
||||
y: any;
|
||||
};
|
||||
24
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-ellipse.js
generated
vendored
Normal file
24
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-ellipse.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
export { intersectEllipse };
|
||||
|
||||
function intersectEllipse(node, rx, ry, point) {
|
||||
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
|
||||
|
||||
var cx = node.x;
|
||||
var cy = node.y;
|
||||
|
||||
var px = cx - point.x;
|
||||
var py = cy - point.y;
|
||||
|
||||
var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px);
|
||||
|
||||
var dx = Math.abs((rx * ry * px) / det);
|
||||
if (point.x < cx) {
|
||||
dx = -dx;
|
||||
}
|
||||
var dy = Math.abs((rx * ry * py) / det);
|
||||
if (point.y < cy) {
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
return { x: cx + dx, y: cy + dy };
|
||||
}
|
||||
9
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-line.d.ts
generated
vendored
Normal file
9
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-line.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export function intersectLine(
|
||||
p1: any,
|
||||
p2: any,
|
||||
q1: any,
|
||||
q2: any
|
||||
): {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
70
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-line.js
generated
vendored
Normal file
70
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-line.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
export { intersectLine };
|
||||
|
||||
/*
|
||||
* Returns the point at which two lines, p and q, intersect or returns
|
||||
* undefined if they do not intersect.
|
||||
*/
|
||||
function intersectLine(p1, p2, q1, q2) {
|
||||
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
|
||||
// p7 and p473.
|
||||
|
||||
var a1, a2, b1, b2, c1, c2;
|
||||
var r1, r2, r3, r4;
|
||||
var denom, offset, num;
|
||||
var x, y;
|
||||
|
||||
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
|
||||
// b1 y + c1 = 0.
|
||||
a1 = p2.y - p1.y;
|
||||
b1 = p1.x - p2.x;
|
||||
c1 = p2.x * p1.y - p1.x * p2.y;
|
||||
|
||||
// Compute r3 and r4.
|
||||
r3 = a1 * q1.x + b1 * q1.y + c1;
|
||||
r4 = a1 * q2.x + b1 * q2.y + c1;
|
||||
|
||||
// Check signs of r3 and r4. If both point 3 and point 4 lie on
|
||||
// same side of line 1, the line segments do not intersect.
|
||||
if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) {
|
||||
return /*DONT_INTERSECT*/;
|
||||
}
|
||||
|
||||
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
|
||||
a2 = q2.y - q1.y;
|
||||
b2 = q1.x - q2.x;
|
||||
c2 = q2.x * q1.y - q1.x * q2.y;
|
||||
|
||||
// Compute r1 and r2
|
||||
r1 = a2 * p1.x + b2 * p1.y + c2;
|
||||
r2 = a2 * p2.x + b2 * p2.y + c2;
|
||||
|
||||
// Check signs of r1 and r2. If both point 1 and point 2 lie
|
||||
// on same side of second line segment, the line segments do
|
||||
// not intersect.
|
||||
if (r1 !== 0 && r2 !== 0 && sameSign(r1, r2)) {
|
||||
return /*DONT_INTERSECT*/;
|
||||
}
|
||||
|
||||
// Line segments intersect: compute intersection point.
|
||||
denom = a1 * b2 - a2 * b1;
|
||||
if (denom === 0) {
|
||||
return /*COLLINEAR*/;
|
||||
}
|
||||
|
||||
offset = Math.abs(denom / 2);
|
||||
|
||||
// The denom/2 is to get rounding instead of truncating. It
|
||||
// is added or subtracted to the numerator, depending upon the
|
||||
// sign of the numerator.
|
||||
num = b1 * c2 - b2 * c1;
|
||||
x = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||
|
||||
num = a2 * c1 - a1 * c2;
|
||||
y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||
|
||||
return { x: x, y: y };
|
||||
}
|
||||
|
||||
function sameSign(r1, r2) {
|
||||
return r1 * r2 > 0;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-node.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-node.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function intersectNode(node: any, point: any): any;
|
||||
5
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-node.js
generated
vendored
Normal file
5
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-node.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export { intersectNode };
|
||||
|
||||
function intersectNode(node, point) {
|
||||
return node.intersect(point);
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-polygon.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-polygon.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function intersectPolygon(node: any, polyPoints: any, point: any): any;
|
||||
59
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-polygon.js
generated
vendored
Normal file
59
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-polygon.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import { intersectLine } from './intersect-line.js';
|
||||
|
||||
export { intersectPolygon };
|
||||
|
||||
/*
|
||||
* Returns the point ({x, y}) at which the point argument intersects with the
|
||||
* node argument assuming that it has the shape specified by polygon.
|
||||
*/
|
||||
function intersectPolygon(node, polyPoints, point) {
|
||||
var x1 = node.x;
|
||||
var y1 = node.y;
|
||||
|
||||
var intersections = [];
|
||||
|
||||
var minX = Number.POSITIVE_INFINITY;
|
||||
var minY = Number.POSITIVE_INFINITY;
|
||||
polyPoints.forEach(function (entry) {
|
||||
minX = Math.min(minX, entry.x);
|
||||
minY = Math.min(minY, entry.y);
|
||||
});
|
||||
|
||||
var left = x1 - node.width / 2 - minX;
|
||||
var top = y1 - node.height / 2 - minY;
|
||||
|
||||
for (var i = 0; i < polyPoints.length; i++) {
|
||||
var p1 = polyPoints[i];
|
||||
var p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||||
var intersect = intersectLine(
|
||||
node,
|
||||
point,
|
||||
{ x: left + p1.x, y: top + p1.y },
|
||||
{ x: left + p2.x, y: top + p2.y }
|
||||
);
|
||||
if (intersect) {
|
||||
intersections.push(intersect);
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersections.length) {
|
||||
console.log('NO INTERSECTION FOUND, RETURN NODE CENTER', node);
|
||||
return node;
|
||||
}
|
||||
|
||||
if (intersections.length > 1) {
|
||||
// More intersections, find the one nearest to edge end point
|
||||
intersections.sort(function (p, q) {
|
||||
var pdx = p.x - point.x;
|
||||
var pdy = p.y - point.y;
|
||||
var distp = Math.sqrt(pdx * pdx + pdy * pdy);
|
||||
|
||||
var qdx = q.x - point.x;
|
||||
var qdy = q.y - point.y;
|
||||
var distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||||
|
||||
return distp < distq ? -1 : distp === distq ? 0 : 1;
|
||||
});
|
||||
}
|
||||
return intersections[0];
|
||||
}
|
||||
7
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-rect.d.ts
generated
vendored
Normal file
7
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-rect.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export function intersectRect(
|
||||
node: any,
|
||||
point: any
|
||||
): {
|
||||
x: any;
|
||||
y: any;
|
||||
};
|
||||
32
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-rect.js
generated
vendored
Normal file
32
node_modules/dagre-d3-es/src/dagre-js/intersect/intersect-rect.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
export { intersectRect };
|
||||
|
||||
function intersectRect(node, point) {
|
||||
var x = node.x;
|
||||
var y = node.y;
|
||||
|
||||
// Rectangle intersection algorithm from:
|
||||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||||
var dx = point.x - x;
|
||||
var dy = point.y - y;
|
||||
var w = node.width / 2;
|
||||
var h = node.height / 2;
|
||||
|
||||
var sx, sy;
|
||||
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
||||
// Intersection is top or bottom of rect.
|
||||
if (dy < 0) {
|
||||
h = -h;
|
||||
}
|
||||
sx = dy === 0 ? 0 : (h * dx) / dy;
|
||||
sy = h;
|
||||
} else {
|
||||
// Intersection is left or right of rect.
|
||||
if (dx < 0) {
|
||||
w = -w;
|
||||
}
|
||||
sx = w;
|
||||
sy = dx === 0 ? 0 : (w * dy) / dx;
|
||||
}
|
||||
|
||||
return { x: x + sx, y: y + sy };
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/label/add-html-label.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/label/add-html-label.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function addHtmlLabel(root: any, node: any): any;
|
||||
35
node_modules/dagre-d3-es/src/dagre-js/label/add-html-label.js
generated
vendored
Normal file
35
node_modules/dagre-d3-es/src/dagre-js/label/add-html-label.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import * as util from '../util.js';
|
||||
|
||||
export { addHtmlLabel };
|
||||
|
||||
function addHtmlLabel(root, node) {
|
||||
var fo = root.append('foreignObject').attr('width', '100000');
|
||||
|
||||
var div = fo.append('xhtml:div');
|
||||
div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
||||
|
||||
var label = node.label;
|
||||
switch (typeof label) {
|
||||
case 'function':
|
||||
div.insert(label);
|
||||
break;
|
||||
case 'object':
|
||||
// Currently we assume this is a DOM object.
|
||||
div.insert(function () {
|
||||
return label;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
div.html(label);
|
||||
}
|
||||
|
||||
util.applyStyle(div, node.labelStyle);
|
||||
div.style('display', 'inline-block');
|
||||
// Fix for firefox
|
||||
div.style('white-space', 'nowrap');
|
||||
|
||||
var client = div.node().getBoundingClientRect();
|
||||
fo.attr('width', client.width).attr('height', client.height);
|
||||
|
||||
return fo;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/label/add-label.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/label/add-label.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function addLabel(root: any, node: any, location: any): any;
|
||||
36
node_modules/dagre-d3-es/src/dagre-js/label/add-label.js
generated
vendored
Normal file
36
node_modules/dagre-d3-es/src/dagre-js/label/add-label.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { addHtmlLabel } from './add-html-label.js';
|
||||
import { addSVGLabel } from './add-svg-label.js';
|
||||
import { addTextLabel } from './add-text-label.js';
|
||||
|
||||
export { addLabel };
|
||||
|
||||
function addLabel(root, node, location) {
|
||||
var label = node.label;
|
||||
var labelSvg = root.append('g');
|
||||
|
||||
// Allow the label to be a string, a function that returns a DOM element, or
|
||||
// a DOM element itself.
|
||||
if (node.labelType === 'svg') {
|
||||
addSVGLabel(labelSvg, node);
|
||||
} else if (typeof label !== 'string' || node.labelType === 'html') {
|
||||
addHtmlLabel(labelSvg, node);
|
||||
} else {
|
||||
addTextLabel(labelSvg, node);
|
||||
}
|
||||
|
||||
var labelBBox = labelSvg.node().getBBox();
|
||||
var y;
|
||||
switch (location) {
|
||||
case 'top':
|
||||
y = -node.height / 2;
|
||||
break;
|
||||
case 'bottom':
|
||||
y = node.height / 2 - labelBBox.height;
|
||||
break;
|
||||
default:
|
||||
y = -labelBBox.height / 2;
|
||||
}
|
||||
labelSvg.attr('transform', 'translate(' + -labelBBox.width / 2 + ',' + y + ')');
|
||||
|
||||
return labelSvg;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/label/add-svg-label.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/label/add-svg-label.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function addSVGLabel(root: any, node: any): any;
|
||||
13
node_modules/dagre-d3-es/src/dagre-js/label/add-svg-label.js
generated
vendored
Normal file
13
node_modules/dagre-d3-es/src/dagre-js/label/add-svg-label.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as util from '../util.js';
|
||||
|
||||
export { addSVGLabel };
|
||||
|
||||
function addSVGLabel(root, node) {
|
||||
var domNode = root;
|
||||
|
||||
domNode.node().appendChild(node.label);
|
||||
|
||||
util.applyStyle(domNode, node.labelStyle);
|
||||
|
||||
return domNode;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/label/add-text-label.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/label/add-text-label.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function addTextLabel(root: any, node: any): any;
|
||||
48
node_modules/dagre-d3-es/src/dagre-js/label/add-text-label.js
generated
vendored
Normal file
48
node_modules/dagre-d3-es/src/dagre-js/label/add-text-label.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import * as util from '../util.js';
|
||||
|
||||
export { addTextLabel };
|
||||
|
||||
/*
|
||||
* Attaches a text label to the specified root. Handles escape sequences.
|
||||
*/
|
||||
function addTextLabel(root, node) {
|
||||
var domNode = root.append('text');
|
||||
|
||||
var lines = processEscapeSequences(node.label).split('\n');
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
domNode
|
||||
.append('tspan')
|
||||
.attr('xml:space', 'preserve')
|
||||
.attr('dy', '1em')
|
||||
.attr('x', '1')
|
||||
.text(lines[i]);
|
||||
}
|
||||
|
||||
util.applyStyle(domNode, node.labelStyle);
|
||||
|
||||
return domNode;
|
||||
}
|
||||
|
||||
function processEscapeSequences(text) {
|
||||
var newText = '';
|
||||
var escaped = false;
|
||||
var ch;
|
||||
for (var i = 0; i < text.length; ++i) {
|
||||
ch = text[i];
|
||||
if (escaped) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
newText += '\n';
|
||||
break;
|
||||
default:
|
||||
newText += ch;
|
||||
}
|
||||
escaped = false;
|
||||
} else if (ch === '\\') {
|
||||
escaped = true;
|
||||
} else {
|
||||
newText += ch;
|
||||
}
|
||||
}
|
||||
return newText;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/position-clusters.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/position-clusters.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function positionClusters(selection: any, g: any): void;
|
||||
36
node_modules/dagre-d3-es/src/dagre-js/position-clusters.js
generated
vendored
Normal file
36
node_modules/dagre-d3-es/src/dagre-js/position-clusters.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { positionClusters };
|
||||
|
||||
function positionClusters(selection, g) {
|
||||
var created = selection.filter(function () {
|
||||
return !d3.select(this).classed('update');
|
||||
});
|
||||
|
||||
function translate(v) {
|
||||
var node = g.node(v);
|
||||
return 'translate(' + node.x + ',' + node.y + ')';
|
||||
}
|
||||
|
||||
created.attr('transform', translate);
|
||||
|
||||
util.applyTransition(selection, g).style('opacity', 1).attr('transform', translate);
|
||||
|
||||
util
|
||||
.applyTransition(created.selectAll('rect'), g)
|
||||
.attr('width', function (v) {
|
||||
return g.node(v).width;
|
||||
})
|
||||
.attr('height', function (v) {
|
||||
return g.node(v).height;
|
||||
})
|
||||
.attr('x', function (v) {
|
||||
var node = g.node(v);
|
||||
return -node.width / 2;
|
||||
})
|
||||
.attr('y', function (v) {
|
||||
var node = g.node(v);
|
||||
return -node.height / 2;
|
||||
});
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/position-edge-labels.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/position-edge-labels.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function positionEdgeLabels(selection: any, g: any): void;
|
||||
20
node_modules/dagre-d3-es/src/dagre-js/position-edge-labels.js
generated
vendored
Normal file
20
node_modules/dagre-d3-es/src/dagre-js/position-edge-labels.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as _ from 'lodash-es';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { positionEdgeLabels };
|
||||
|
||||
function positionEdgeLabels(selection, g) {
|
||||
var created = selection.filter(function () {
|
||||
return !d3.select(this).classed('update');
|
||||
});
|
||||
|
||||
function translate(e) {
|
||||
var edge = g.edge(e);
|
||||
return _.has(edge, 'x') ? 'translate(' + edge.x + ',' + edge.y + ')' : '';
|
||||
}
|
||||
|
||||
created.attr('transform', translate);
|
||||
|
||||
util.applyTransition(selection, g).style('opacity', 1).attr('transform', translate);
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre-js/position-nodes.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre-js/position-nodes.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function positionNodes(selection: any, g: any): void;
|
||||
19
node_modules/dagre-d3-es/src/dagre-js/position-nodes.js
generated
vendored
Normal file
19
node_modules/dagre-d3-es/src/dagre-js/position-nodes.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { positionNodes };
|
||||
|
||||
function positionNodes(selection, g) {
|
||||
var created = selection.filter(function () {
|
||||
return !d3.select(this).classed('update');
|
||||
});
|
||||
|
||||
function translate(v) {
|
||||
var node = g.node(v);
|
||||
return 'translate(' + node.x + ',' + node.y + ')';
|
||||
}
|
||||
|
||||
created.attr('transform', translate);
|
||||
|
||||
util.applyTransition(selection, g).style('opacity', 1).attr('transform', translate);
|
||||
}
|
||||
15
node_modules/dagre-d3-es/src/dagre-js/render.d.ts
generated
vendored
Normal file
15
node_modules/dagre-d3-es/src/dagre-js/render.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export function render(): {
|
||||
(svg: any, g: any): void;
|
||||
createNodes(...args: any[]): typeof createNodes;
|
||||
createClusters(value: any, ...args: any[]): typeof createClusters;
|
||||
createEdgeLabels(value: any, ...args: any[]): typeof createEdgeLabels;
|
||||
createEdgePaths(value: any, ...args: any[]): typeof createEdgePaths;
|
||||
shapes(value: any, ...args: any[]): typeof shapes | any;
|
||||
arrows(value: any, ...args: any[]): typeof arrows | any;
|
||||
};
|
||||
import { createNodes } from './create-nodes.js';
|
||||
import { createClusters } from './create-clusters.js';
|
||||
import { createEdgeLabels } from './create-edge-labels.js';
|
||||
import { createEdgePaths } from './create-edge-paths.js';
|
||||
import * as shapes from './shapes.js';
|
||||
import * as arrows from './arrows.js';
|
||||
175
node_modules/dagre-d3-es/src/dagre-js/render.js
generated
vendored
Normal file
175
node_modules/dagre-d3-es/src/dagre-js/render.js
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as _ from 'lodash-es';
|
||||
import { layout } from '../dagre/index.js';
|
||||
import { arrows, setArrows } from './arrows.js';
|
||||
import { createClusters, setCreateClusters } from './create-clusters.js';
|
||||
import { createEdgeLabels, setCreateEdgeLabels } from './create-edge-labels.js';
|
||||
import { createEdgePaths, setCreateEdgePaths } from './create-edge-paths.js';
|
||||
import { createNodes, setCreateNodes } from './create-nodes.js';
|
||||
import { positionClusters } from './position-clusters.js';
|
||||
import { positionEdgeLabels } from './position-edge-labels.js';
|
||||
import { positionNodes } from './position-nodes.js';
|
||||
import { shapes, setShapes } from './shapes.js';
|
||||
|
||||
export { render };
|
||||
|
||||
// This design is based on http://bost.ocks.org/mike/chart/.
|
||||
function render() {
|
||||
var fn = function (svg, g) {
|
||||
preProcessGraph(g);
|
||||
|
||||
var outputGroup = createOrSelectGroup(svg, 'output');
|
||||
var clustersGroup = createOrSelectGroup(outputGroup, 'clusters');
|
||||
var edgePathsGroup = createOrSelectGroup(outputGroup, 'edgePaths');
|
||||
var edgeLabels = createEdgeLabels(createOrSelectGroup(outputGroup, 'edgeLabels'), g);
|
||||
var nodes = createNodes(createOrSelectGroup(outputGroup, 'nodes'), g, shapes);
|
||||
|
||||
layout(g);
|
||||
|
||||
positionNodes(nodes, g);
|
||||
positionEdgeLabels(edgeLabels, g);
|
||||
createEdgePaths(edgePathsGroup, g, arrows);
|
||||
|
||||
var clusters = createClusters(clustersGroup, g);
|
||||
positionClusters(clusters, g);
|
||||
|
||||
postProcessGraph(g);
|
||||
};
|
||||
|
||||
fn.createNodes = function (value) {
|
||||
if (!arguments.length) return createNodes;
|
||||
setCreateNodes(value);
|
||||
return fn;
|
||||
};
|
||||
|
||||
fn.createClusters = function (value) {
|
||||
if (!arguments.length) return createClusters;
|
||||
setCreateClusters(value);
|
||||
return fn;
|
||||
};
|
||||
|
||||
fn.createEdgeLabels = function (value) {
|
||||
if (!arguments.length) return createEdgeLabels;
|
||||
setCreateEdgeLabels(value);
|
||||
return fn;
|
||||
};
|
||||
|
||||
fn.createEdgePaths = function (value) {
|
||||
if (!arguments.length) return createEdgePaths;
|
||||
setCreateEdgePaths(value);
|
||||
return fn;
|
||||
};
|
||||
|
||||
fn.shapes = function (value) {
|
||||
if (!arguments.length) return shapes;
|
||||
setShapes(value);
|
||||
return fn;
|
||||
};
|
||||
|
||||
fn.arrows = function (value) {
|
||||
if (!arguments.length) return arrows;
|
||||
setArrows(value);
|
||||
return fn;
|
||||
};
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
var NODE_DEFAULT_ATTRS = {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
shape: 'rect',
|
||||
};
|
||||
|
||||
var EDGE_DEFAULT_ATTRS = {
|
||||
arrowhead: 'normal',
|
||||
curve: d3.curveLinear,
|
||||
};
|
||||
|
||||
function preProcessGraph(g) {
|
||||
g.nodes().forEach(function (v) {
|
||||
var node = g.node(v);
|
||||
if (!_.has(node, 'label') && !g.children(v).length) {
|
||||
node.label = v;
|
||||
}
|
||||
|
||||
if (_.has(node, 'paddingX')) {
|
||||
_.defaults(node, {
|
||||
paddingLeft: node.paddingX,
|
||||
paddingRight: node.paddingX,
|
||||
});
|
||||
}
|
||||
|
||||
if (_.has(node, 'paddingY')) {
|
||||
_.defaults(node, {
|
||||
paddingTop: node.paddingY,
|
||||
paddingBottom: node.paddingY,
|
||||
});
|
||||
}
|
||||
|
||||
if (_.has(node, 'padding')) {
|
||||
_.defaults(node, {
|
||||
paddingLeft: node.padding,
|
||||
paddingRight: node.padding,
|
||||
paddingTop: node.padding,
|
||||
paddingBottom: node.padding,
|
||||
});
|
||||
}
|
||||
|
||||
_.defaults(node, NODE_DEFAULT_ATTRS);
|
||||
|
||||
_.each(['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'], function (k) {
|
||||
node[k] = Number(node[k]);
|
||||
});
|
||||
|
||||
// Save dimensions for restore during post-processing
|
||||
if (_.has(node, 'width')) {
|
||||
node._prevWidth = node.width;
|
||||
}
|
||||
if (_.has(node, 'height')) {
|
||||
node._prevHeight = node.height;
|
||||
}
|
||||
});
|
||||
|
||||
g.edges().forEach(function (e) {
|
||||
var edge = g.edge(e);
|
||||
if (!_.has(edge, 'label')) {
|
||||
edge.label = '';
|
||||
}
|
||||
_.defaults(edge, EDGE_DEFAULT_ATTRS);
|
||||
});
|
||||
}
|
||||
|
||||
function postProcessGraph(g) {
|
||||
_.each(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
|
||||
// Restore original dimensions
|
||||
if (_.has(node, '_prevWidth')) {
|
||||
node.width = node._prevWidth;
|
||||
} else {
|
||||
delete node.width;
|
||||
}
|
||||
|
||||
if (_.has(node, '_prevHeight')) {
|
||||
node.height = node._prevHeight;
|
||||
} else {
|
||||
delete node.height;
|
||||
}
|
||||
|
||||
delete node._prevWidth;
|
||||
delete node._prevHeight;
|
||||
});
|
||||
}
|
||||
|
||||
function createOrSelectGroup(root, name) {
|
||||
var selection = root.select('g.' + name);
|
||||
if (selection.empty()) {
|
||||
selection = root.append('g').attr('class', name);
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre-js/shapes.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre-js/shapes.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export var shapes: any;
|
||||
export function setShapes(value: any): any;
|
||||
94
node_modules/dagre-d3-es/src/dagre-js/shapes.js
generated
vendored
Normal file
94
node_modules/dagre-d3-es/src/dagre-js/shapes.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
import { intersectCircle } from './intersect/intersect-circle.js';
|
||||
import { intersectEllipse } from './intersect/intersect-ellipse.js';
|
||||
import { intersectPolygon } from './intersect/intersect-polygon.js';
|
||||
import { intersectRect } from './intersect/intersect-rect.js';
|
||||
|
||||
export { shapes, setShapes };
|
||||
|
||||
var shapes = {
|
||||
rect,
|
||||
ellipse,
|
||||
circle,
|
||||
diamond,
|
||||
};
|
||||
|
||||
function setShapes(value) {
|
||||
shapes = value;
|
||||
}
|
||||
|
||||
function rect(parent, bbox, node) {
|
||||
var shapeSvg = parent
|
||||
.insert('rect', ':first-child')
|
||||
.attr('rx', node.rx)
|
||||
.attr('ry', node.ry)
|
||||
.attr('x', -bbox.width / 2)
|
||||
.attr('y', -bbox.height / 2)
|
||||
.attr('width', bbox.width)
|
||||
.attr('height', bbox.height);
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersectRect(node, point);
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
function ellipse(parent, bbox, node) {
|
||||
var rx = bbox.width / 2;
|
||||
var ry = bbox.height / 2;
|
||||
var shapeSvg = parent
|
||||
.insert('ellipse', ':first-child')
|
||||
.attr('x', -bbox.width / 2)
|
||||
.attr('y', -bbox.height / 2)
|
||||
.attr('rx', rx)
|
||||
.attr('ry', ry);
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersectEllipse(node, rx, ry, point);
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
function circle(parent, bbox, node) {
|
||||
var r = Math.max(bbox.width, bbox.height) / 2;
|
||||
var shapeSvg = parent
|
||||
.insert('circle', ':first-child')
|
||||
.attr('x', -bbox.width / 2)
|
||||
.attr('y', -bbox.height / 2)
|
||||
.attr('r', r);
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersectCircle(node, r, point);
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
// Circumscribe an ellipse for the bounding box with a diamond shape. I derived
|
||||
// the function to calculate the diamond shape from:
|
||||
// http://mathforum.org/kb/message.jspa?messageID=3750236
|
||||
function diamond(parent, bbox, node) {
|
||||
var w = (bbox.width * Math.SQRT2) / 2;
|
||||
var h = (bbox.height * Math.SQRT2) / 2;
|
||||
var points = [
|
||||
{ x: 0, y: -h },
|
||||
{ x: -w, y: 0 },
|
||||
{ x: 0, y: h },
|
||||
{ x: w, y: 0 },
|
||||
];
|
||||
var shapeSvg = parent.insert('polygon', ':first-child').attr(
|
||||
'points',
|
||||
points
|
||||
.map(function (p) {
|
||||
return p.x + ',' + p.y;
|
||||
})
|
||||
.join(' ')
|
||||
);
|
||||
|
||||
node.intersect = function (p) {
|
||||
return intersectPolygon(node, points, p);
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
}
|
||||
5
node_modules/dagre-d3-es/src/dagre-js/util.d.ts
generated
vendored
Normal file
5
node_modules/dagre-d3-es/src/dagre-js/util.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export function isSubgraph(g: any, v: any): boolean;
|
||||
export function edgeToId(e: any): string;
|
||||
export function applyStyle(dom: any, styleFn: any): void;
|
||||
export function applyClass(dom: any, classFn: any, otherClasses: any): void;
|
||||
export function applyTransition(selection: any, g: any): any;
|
||||
46
node_modules/dagre-d3-es/src/dagre-js/util.js
generated
vendored
Normal file
46
node_modules/dagre-d3-es/src/dagre-js/util.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
// Public utility functions
|
||||
export { isSubgraph, edgeToId, applyStyle, applyClass, applyTransition };
|
||||
|
||||
/*
|
||||
* Returns true if the specified node in the graph is a subgraph node. A
|
||||
* subgraph node is one that contains other nodes.
|
||||
*/
|
||||
function isSubgraph(g, v) {
|
||||
return !!g.children(v).length;
|
||||
}
|
||||
|
||||
function edgeToId(e) {
|
||||
return escapeId(e.v) + ':' + escapeId(e.w) + ':' + escapeId(e.name);
|
||||
}
|
||||
|
||||
var ID_DELIM = /:/g;
|
||||
function escapeId(str) {
|
||||
return str ? String(str).replace(ID_DELIM, '\\:') : '';
|
||||
}
|
||||
|
||||
function applyStyle(dom, styleFn) {
|
||||
if (styleFn) {
|
||||
dom.attr('style', styleFn);
|
||||
}
|
||||
}
|
||||
|
||||
function applyClass(dom, classFn, otherClasses) {
|
||||
if (classFn) {
|
||||
dom.attr('class', classFn).attr('class', otherClasses + ' ' + dom.attr('class'));
|
||||
}
|
||||
}
|
||||
|
||||
function applyTransition(selection, g) {
|
||||
var graph = g.graph();
|
||||
|
||||
if (_.isPlainObject(graph)) {
|
||||
var transition = graph.transition;
|
||||
if (_.isFunction(transition)) {
|
||||
return transition(selection);
|
||||
}
|
||||
}
|
||||
|
||||
return selection;
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/acyclic.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/acyclic.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function run(g: any): void;
|
||||
export function undo(g: any): void;
|
||||
60
node_modules/dagre-d3-es/src/dagre/acyclic.js
generated
vendored
Normal file
60
node_modules/dagre-d3-es/src/dagre/acyclic.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { greedyFAS } from './greedy-fas.js';
|
||||
|
||||
export { run, undo };
|
||||
|
||||
function run(g) {
|
||||
var fas = g.graph().acyclicer === 'greedy' ? greedyFAS(g, weightFn(g)) : dfsFAS(g);
|
||||
_.forEach(fas, function (e) {
|
||||
var label = g.edge(e);
|
||||
g.removeEdge(e);
|
||||
label.forwardName = e.name;
|
||||
label.reversed = true;
|
||||
g.setEdge(e.w, e.v, label, _.uniqueId('rev'));
|
||||
});
|
||||
|
||||
function weightFn(g) {
|
||||
return function (e) {
|
||||
return g.edge(e).weight;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function dfsFAS(g) {
|
||||
var fas = [];
|
||||
var stack = {};
|
||||
var visited = {};
|
||||
|
||||
function dfs(v) {
|
||||
if (_.has(visited, v)) {
|
||||
return;
|
||||
}
|
||||
visited[v] = true;
|
||||
stack[v] = true;
|
||||
_.forEach(g.outEdges(v), function (e) {
|
||||
if (_.has(stack, e.w)) {
|
||||
fas.push(e);
|
||||
} else {
|
||||
dfs(e.w);
|
||||
}
|
||||
});
|
||||
delete stack[v];
|
||||
}
|
||||
|
||||
_.forEach(g.nodes(), dfs);
|
||||
return fas;
|
||||
}
|
||||
|
||||
function undo(g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var label = g.edge(e);
|
||||
if (label.reversed) {
|
||||
g.removeEdge(e);
|
||||
|
||||
var forwardName = label.forwardName;
|
||||
delete label.reversed;
|
||||
delete label.forwardName;
|
||||
g.setEdge(e.w, e.v, label, forwardName);
|
||||
}
|
||||
});
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/add-border-segments.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/add-border-segments.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function addBorderSegments(g: any): void;
|
||||
36
node_modules/dagre-d3-es/src/dagre/add-border-segments.js
generated
vendored
Normal file
36
node_modules/dagre-d3-es/src/dagre/add-border-segments.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { addBorderSegments };
|
||||
|
||||
function addBorderSegments(g) {
|
||||
function dfs(v) {
|
||||
var children = g.children(v);
|
||||
var node = g.node(v);
|
||||
if (children.length) {
|
||||
_.forEach(children, dfs);
|
||||
}
|
||||
|
||||
if (_.has(node, 'minRank')) {
|
||||
node.borderLeft = [];
|
||||
node.borderRight = [];
|
||||
for (var rank = node.minRank, maxRank = node.maxRank + 1; rank < maxRank; ++rank) {
|
||||
addBorderNode(g, 'borderLeft', '_bl', v, node, rank);
|
||||
addBorderNode(g, 'borderRight', '_br', v, node, rank);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_.forEach(g.children(), dfs);
|
||||
}
|
||||
|
||||
function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
|
||||
var label = { width: 0, height: 0, rank: rank, borderType: prop };
|
||||
var prev = sgNode[prop][rank - 1];
|
||||
var curr = util.addDummyNode(g, 'border', label, prefix);
|
||||
sgNode[prop][rank] = curr;
|
||||
g.setParent(curr, sg);
|
||||
if (prev) {
|
||||
g.setEdge(prev, curr, { weight: 1 });
|
||||
}
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/coordinate-system.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/coordinate-system.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function adjust(g: any): void;
|
||||
export function undo(g: any): void;
|
||||
75
node_modules/dagre-d3-es/src/dagre/coordinate-system.js
generated
vendored
Normal file
75
node_modules/dagre-d3-es/src/dagre/coordinate-system.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { adjust, undo };
|
||||
|
||||
function adjust(g) {
|
||||
var rankDir = g.graph().rankdir.toLowerCase();
|
||||
if (rankDir === 'lr' || rankDir === 'rl') {
|
||||
swapWidthHeight(g);
|
||||
}
|
||||
}
|
||||
|
||||
function undo(g) {
|
||||
var rankDir = g.graph().rankdir.toLowerCase();
|
||||
if (rankDir === 'bt' || rankDir === 'rl') {
|
||||
reverseY(g);
|
||||
}
|
||||
|
||||
if (rankDir === 'lr' || rankDir === 'rl') {
|
||||
swapXY(g);
|
||||
swapWidthHeight(g);
|
||||
}
|
||||
}
|
||||
|
||||
function swapWidthHeight(g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
swapWidthHeightOne(g.node(v));
|
||||
});
|
||||
_.forEach(g.edges(), function (e) {
|
||||
swapWidthHeightOne(g.edge(e));
|
||||
});
|
||||
}
|
||||
|
||||
function swapWidthHeightOne(attrs) {
|
||||
var w = attrs.width;
|
||||
attrs.width = attrs.height;
|
||||
attrs.height = w;
|
||||
}
|
||||
|
||||
function reverseY(g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
reverseYOne(g.node(v));
|
||||
});
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
_.forEach(edge.points, reverseYOne);
|
||||
if (_.has(edge, 'y')) {
|
||||
reverseYOne(edge);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function reverseYOne(attrs) {
|
||||
attrs.y = -attrs.y;
|
||||
}
|
||||
|
||||
function swapXY(g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
swapXYOne(g.node(v));
|
||||
});
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
_.forEach(edge.points, swapXYOne);
|
||||
if (_.has(edge, 'x')) {
|
||||
swapXYOne(edge);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function swapXYOne(attrs) {
|
||||
var x = attrs.x;
|
||||
attrs.x = attrs.y;
|
||||
attrs.y = x;
|
||||
}
|
||||
12
node_modules/dagre-d3-es/src/dagre/data/list.d.ts
generated
vendored
Normal file
12
node_modules/dagre-d3-es/src/dagre/data/list.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
export class List {
|
||||
_sentinel: {
|
||||
_next: any;
|
||||
_prev: any;
|
||||
};
|
||||
dequeue(): {
|
||||
_next: any;
|
||||
_prev: any;
|
||||
};
|
||||
enqueue(entry: any): void;
|
||||
toString(): string;
|
||||
}
|
||||
55
node_modules/dagre-d3-es/src/dagre/data/list.js
generated
vendored
Normal file
55
node_modules/dagre-d3-es/src/dagre/data/list.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Simple doubly linked list implementation derived from Cormen, et al.,
|
||||
* "Introduction to Algorithms".
|
||||
*/
|
||||
|
||||
export { List };
|
||||
|
||||
class List {
|
||||
constructor() {
|
||||
var sentinel = {};
|
||||
sentinel._next = sentinel._prev = sentinel;
|
||||
this._sentinel = sentinel;
|
||||
}
|
||||
dequeue() {
|
||||
var sentinel = this._sentinel;
|
||||
var entry = sentinel._prev;
|
||||
if (entry !== sentinel) {
|
||||
unlink(entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
enqueue(entry) {
|
||||
var sentinel = this._sentinel;
|
||||
if (entry._prev && entry._next) {
|
||||
unlink(entry);
|
||||
}
|
||||
entry._next = sentinel._next;
|
||||
sentinel._next._prev = entry;
|
||||
sentinel._next = entry;
|
||||
entry._prev = sentinel;
|
||||
}
|
||||
toString() {
|
||||
var strs = [];
|
||||
var sentinel = this._sentinel;
|
||||
var curr = sentinel._prev;
|
||||
while (curr !== sentinel) {
|
||||
strs.push(JSON.stringify(curr, filterOutLinks));
|
||||
curr = curr._prev;
|
||||
}
|
||||
return '[' + strs.join(', ') + ']';
|
||||
}
|
||||
}
|
||||
|
||||
function unlink(entry) {
|
||||
entry._prev._next = entry._next;
|
||||
entry._next._prev = entry._prev;
|
||||
delete entry._next;
|
||||
delete entry._prev;
|
||||
}
|
||||
|
||||
function filterOutLinks(k, v) {
|
||||
if (k !== '_next' && k !== '_prev') {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
32
node_modules/dagre-d3-es/src/dagre/debug.js
generated
vendored
Normal file
32
node_modules/dagre-d3-es/src/dagre/debug.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../graphlib/index.js';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { debugOrdering };
|
||||
|
||||
/* istanbul ignore next */
|
||||
function debugOrdering(g) {
|
||||
var layerMatrix = util.buildLayerMatrix(g);
|
||||
|
||||
var h = new Graph({ compound: true, multigraph: true }).setGraph({});
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
h.setNode(v, { label: v });
|
||||
h.setParent(v, 'layer' + g.node(v).rank);
|
||||
});
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
h.setEdge(e.v, e.w, {}, e.name);
|
||||
});
|
||||
|
||||
_.forEach(layerMatrix, function (layer, i) {
|
||||
var layerV = 'layer' + i;
|
||||
h.setNode(layerV, { rank: 'same' });
|
||||
_.reduce(layer, function (u, v) {
|
||||
h.setEdge(u, v, { style: 'invis' });
|
||||
return v;
|
||||
});
|
||||
});
|
||||
|
||||
return h;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/greedy-fas.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/greedy-fas.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function greedyFAS(g: any, weightFn: any): any;
|
||||
127
node_modules/dagre-d3-es/src/dagre/greedy-fas.js
generated
vendored
Normal file
127
node_modules/dagre-d3-es/src/dagre/greedy-fas.js
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../graphlib/index.js';
|
||||
import { List } from './data/list.js';
|
||||
|
||||
/*
|
||||
* A greedy heuristic for finding a feedback arc set for a graph. A feedback
|
||||
* arc set is a set of edges that can be removed to make a graph acyclic.
|
||||
* The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
|
||||
* effective heuristic for the feedback arc set problem." This implementation
|
||||
* adjusts that from the paper to allow for weighted edges.
|
||||
*/
|
||||
export { greedyFAS };
|
||||
|
||||
var DEFAULT_WEIGHT_FN = _.constant(1);
|
||||
|
||||
function greedyFAS(g, weightFn) {
|
||||
if (g.nodeCount() <= 1) {
|
||||
return [];
|
||||
}
|
||||
var state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
|
||||
var results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
|
||||
|
||||
// Expand multi-edges
|
||||
return _.flatten(
|
||||
_.map(results, function (e) {
|
||||
return g.outEdges(e.v, e.w);
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function doGreedyFAS(g, buckets, zeroIdx) {
|
||||
var results = [];
|
||||
var sources = buckets[buckets.length - 1];
|
||||
var sinks = buckets[0];
|
||||
|
||||
var entry;
|
||||
while (g.nodeCount()) {
|
||||
while ((entry = sinks.dequeue())) {
|
||||
removeNode(g, buckets, zeroIdx, entry);
|
||||
}
|
||||
while ((entry = sources.dequeue())) {
|
||||
removeNode(g, buckets, zeroIdx, entry);
|
||||
}
|
||||
if (g.nodeCount()) {
|
||||
for (var i = buckets.length - 2; i > 0; --i) {
|
||||
entry = buckets[i].dequeue();
|
||||
if (entry) {
|
||||
results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
|
||||
var results = collectPredecessors ? [] : undefined;
|
||||
|
||||
_.forEach(g.inEdges(entry.v), function (edge) {
|
||||
var weight = g.edge(edge);
|
||||
var uEntry = g.node(edge.v);
|
||||
|
||||
if (collectPredecessors) {
|
||||
results.push({ v: edge.v, w: edge.w });
|
||||
}
|
||||
|
||||
uEntry.out -= weight;
|
||||
assignBucket(buckets, zeroIdx, uEntry);
|
||||
});
|
||||
|
||||
_.forEach(g.outEdges(entry.v), function (edge) {
|
||||
var weight = g.edge(edge);
|
||||
var w = edge.w;
|
||||
var wEntry = g.node(w);
|
||||
wEntry['in'] -= weight;
|
||||
assignBucket(buckets, zeroIdx, wEntry);
|
||||
});
|
||||
|
||||
g.removeNode(entry.v);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function buildState(g, weightFn) {
|
||||
var fasGraph = new Graph();
|
||||
var maxIn = 0;
|
||||
var maxOut = 0;
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
fasGraph.setNode(v, { v: v, in: 0, out: 0 });
|
||||
});
|
||||
|
||||
// Aggregate weights on nodes, but also sum the weights across multi-edges
|
||||
// into a single edge for the fasGraph.
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var prevWeight = fasGraph.edge(e.v, e.w) || 0;
|
||||
var weight = weightFn(e);
|
||||
var edgeWeight = prevWeight + weight;
|
||||
fasGraph.setEdge(e.v, e.w, edgeWeight);
|
||||
maxOut = Math.max(maxOut, (fasGraph.node(e.v).out += weight));
|
||||
maxIn = Math.max(maxIn, (fasGraph.node(e.w)['in'] += weight));
|
||||
});
|
||||
|
||||
var buckets = _.range(maxOut + maxIn + 3).map(function () {
|
||||
return new List();
|
||||
});
|
||||
var zeroIdx = maxIn + 1;
|
||||
|
||||
_.forEach(fasGraph.nodes(), function (v) {
|
||||
assignBucket(buckets, zeroIdx, fasGraph.node(v));
|
||||
});
|
||||
|
||||
return { graph: fasGraph, buckets: buckets, zeroIdx: zeroIdx };
|
||||
}
|
||||
|
||||
function assignBucket(buckets, zeroIdx, entry) {
|
||||
if (!entry.out) {
|
||||
buckets[0].enqueue(entry);
|
||||
} else if (!entry['in']) {
|
||||
buckets[buckets.length - 1].enqueue(entry);
|
||||
} else {
|
||||
buckets[entry.out - entry['in'] + zeroIdx].enqueue(entry);
|
||||
}
|
||||
}
|
||||
5
node_modules/dagre-d3-es/src/dagre/index.d.ts
generated
vendored
Normal file
5
node_modules/dagre-d3-es/src/dagre/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import * as acyclic from './acyclic.js';
|
||||
import * as normalize from './normalize.js';
|
||||
import { rank } from './rank.js';
|
||||
import { layout } from './layout.js';
|
||||
export { acyclic, normalize, rank, layout };
|
||||
6
node_modules/dagre-d3-es/src/dagre/index.js
generated
vendored
Normal file
6
node_modules/dagre-d3-es/src/dagre/index.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import * as acyclic from './acyclic.js';
|
||||
import { layout } from './layout.js';
|
||||
import * as normalize from './normalize.js';
|
||||
import { rank } from './rank/index.js';
|
||||
|
||||
export { acyclic, normalize, rank, layout };
|
||||
1
node_modules/dagre-d3-es/src/dagre/layout.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/layout.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function layout(g: any, opts: any): void;
|
||||
463
node_modules/dagre-d3-es/src/dagre/layout.js
generated
vendored
Normal file
463
node_modules/dagre-d3-es/src/dagre/layout.js
generated
vendored
Normal file
@@ -0,0 +1,463 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../graphlib/index.js';
|
||||
import { addBorderSegments } from './add-border-segments.js';
|
||||
import * as coordinateSystem from './coordinate-system.js';
|
||||
import { acyclic, normalize, rank } from './index.js';
|
||||
import * as nestingGraph from './nesting-graph.js';
|
||||
import { order } from './order/index.js';
|
||||
import { parentDummyChains } from './parent-dummy-chains.js';
|
||||
import { position } from './position/index.js';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { layout };
|
||||
|
||||
function layout(g, opts) {
|
||||
var time = opts && opts.debugTiming ? util.time : util.notime;
|
||||
time('layout', function () {
|
||||
var layoutGraph = time(' buildLayoutGraph', function () {
|
||||
return buildLayoutGraph(g);
|
||||
});
|
||||
time(' runLayout', function () {
|
||||
runLayout(layoutGraph, time);
|
||||
});
|
||||
time(' updateInputGraph', function () {
|
||||
updateInputGraph(g, layoutGraph);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function runLayout(g, time) {
|
||||
time(' makeSpaceForEdgeLabels', function () {
|
||||
makeSpaceForEdgeLabels(g);
|
||||
});
|
||||
time(' removeSelfEdges', function () {
|
||||
removeSelfEdges(g);
|
||||
});
|
||||
time(' acyclic', function () {
|
||||
acyclic.run(g);
|
||||
});
|
||||
time(' nestingGraph.run', function () {
|
||||
nestingGraph.run(g);
|
||||
});
|
||||
time(' rank', function () {
|
||||
rank(util.asNonCompoundGraph(g));
|
||||
});
|
||||
time(' injectEdgeLabelProxies', function () {
|
||||
injectEdgeLabelProxies(g);
|
||||
});
|
||||
time(' removeEmptyRanks', function () {
|
||||
util.removeEmptyRanks(g);
|
||||
});
|
||||
time(' nestingGraph.cleanup', function () {
|
||||
nestingGraph.cleanup(g);
|
||||
});
|
||||
time(' normalizeRanks', function () {
|
||||
util.normalizeRanks(g);
|
||||
});
|
||||
time(' assignRankMinMax', function () {
|
||||
assignRankMinMax(g);
|
||||
});
|
||||
time(' removeEdgeLabelProxies', function () {
|
||||
removeEdgeLabelProxies(g);
|
||||
});
|
||||
time(' normalize.run', function () {
|
||||
normalize.run(g);
|
||||
});
|
||||
time(' parentDummyChains', function () {
|
||||
parentDummyChains(g);
|
||||
});
|
||||
time(' addBorderSegments', function () {
|
||||
addBorderSegments(g);
|
||||
});
|
||||
time(' order', function () {
|
||||
order(g);
|
||||
});
|
||||
time(' insertSelfEdges', function () {
|
||||
insertSelfEdges(g);
|
||||
});
|
||||
time(' adjustCoordinateSystem', function () {
|
||||
coordinateSystem.adjust(g);
|
||||
});
|
||||
time(' position', function () {
|
||||
position(g);
|
||||
});
|
||||
time(' positionSelfEdges', function () {
|
||||
positionSelfEdges(g);
|
||||
});
|
||||
time(' removeBorderNodes', function () {
|
||||
removeBorderNodes(g);
|
||||
});
|
||||
time(' normalize.undo', function () {
|
||||
normalize.undo(g);
|
||||
});
|
||||
time(' fixupEdgeLabelCoords', function () {
|
||||
fixupEdgeLabelCoords(g);
|
||||
});
|
||||
time(' undoCoordinateSystem', function () {
|
||||
coordinateSystem.undo(g);
|
||||
});
|
||||
time(' translateGraph', function () {
|
||||
translateGraph(g);
|
||||
});
|
||||
time(' assignNodeIntersects', function () {
|
||||
assignNodeIntersects(g);
|
||||
});
|
||||
time(' reversePoints', function () {
|
||||
reversePointsForReversedEdges(g);
|
||||
});
|
||||
time(' acyclic.undo', function () {
|
||||
acyclic.undo(g);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies final layout information from the layout graph back to the input
|
||||
* graph. This process only copies whitelisted attributes from the layout graph
|
||||
* to the input graph, so it serves as a good place to determine what
|
||||
* attributes can influence layout.
|
||||
*/
|
||||
function updateInputGraph(inputGraph, layoutGraph) {
|
||||
_.forEach(inputGraph.nodes(), function (v) {
|
||||
var inputLabel = inputGraph.node(v);
|
||||
var layoutLabel = layoutGraph.node(v);
|
||||
|
||||
if (inputLabel) {
|
||||
inputLabel.x = layoutLabel.x;
|
||||
inputLabel.y = layoutLabel.y;
|
||||
|
||||
if (layoutGraph.children(v).length) {
|
||||
inputLabel.width = layoutLabel.width;
|
||||
inputLabel.height = layoutLabel.height;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(inputGraph.edges(), function (e) {
|
||||
var inputLabel = inputGraph.edge(e);
|
||||
var layoutLabel = layoutGraph.edge(e);
|
||||
|
||||
inputLabel.points = layoutLabel.points;
|
||||
if (_.has(layoutLabel, 'x')) {
|
||||
inputLabel.x = layoutLabel.x;
|
||||
inputLabel.y = layoutLabel.y;
|
||||
}
|
||||
});
|
||||
|
||||
inputGraph.graph().width = layoutGraph.graph().width;
|
||||
inputGraph.graph().height = layoutGraph.graph().height;
|
||||
}
|
||||
|
||||
var graphNumAttrs = ['nodesep', 'edgesep', 'ranksep', 'marginx', 'marginy'];
|
||||
var graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: 'tb' };
|
||||
var graphAttrs = ['acyclicer', 'ranker', 'rankdir', 'align'];
|
||||
var nodeNumAttrs = ['width', 'height'];
|
||||
var nodeDefaults = { width: 0, height: 0 };
|
||||
var edgeNumAttrs = ['minlen', 'weight', 'width', 'height', 'labeloffset'];
|
||||
var edgeDefaults = {
|
||||
minlen: 1,
|
||||
weight: 1,
|
||||
width: 0,
|
||||
height: 0,
|
||||
labeloffset: 10,
|
||||
labelpos: 'r',
|
||||
};
|
||||
var edgeAttrs = ['labelpos'];
|
||||
|
||||
/*
|
||||
* Constructs a new graph from the input graph, which can be used for layout.
|
||||
* This process copies only whitelisted attributes from the input graph to the
|
||||
* layout graph. Thus this function serves as a good place to determine what
|
||||
* attributes can influence layout.
|
||||
*/
|
||||
function buildLayoutGraph(inputGraph) {
|
||||
var g = new Graph({ multigraph: true, compound: true });
|
||||
var graph = canonicalize(inputGraph.graph());
|
||||
|
||||
g.setGraph(
|
||||
_.merge({}, graphDefaults, selectNumberAttrs(graph, graphNumAttrs), _.pick(graph, graphAttrs))
|
||||
);
|
||||
|
||||
_.forEach(inputGraph.nodes(), function (v) {
|
||||
var node = canonicalize(inputGraph.node(v));
|
||||
g.setNode(v, _.defaults(selectNumberAttrs(node, nodeNumAttrs), nodeDefaults));
|
||||
g.setParent(v, inputGraph.parent(v));
|
||||
});
|
||||
|
||||
_.forEach(inputGraph.edges(), function (e) {
|
||||
var edge = canonicalize(inputGraph.edge(e));
|
||||
g.setEdge(
|
||||
e,
|
||||
_.merge({}, edgeDefaults, selectNumberAttrs(edge, edgeNumAttrs), _.pick(edge, edgeAttrs))
|
||||
);
|
||||
});
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/*
|
||||
* This idea comes from the Gansner paper: to account for edge labels in our
|
||||
* layout we split each rank in half by doubling minlen and halving ranksep.
|
||||
* Then we can place labels at these mid-points between nodes.
|
||||
*
|
||||
* We also add some minimal padding to the width to push the label for the edge
|
||||
* away from the edge itself a bit.
|
||||
*/
|
||||
function makeSpaceForEdgeLabels(g) {
|
||||
var graph = g.graph();
|
||||
graph.ranksep /= 2;
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
edge.minlen *= 2;
|
||||
if (edge.labelpos.toLowerCase() !== 'c') {
|
||||
if (graph.rankdir === 'TB' || graph.rankdir === 'BT') {
|
||||
edge.width += edge.labeloffset;
|
||||
} else {
|
||||
edge.height += edge.labeloffset;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates temporary dummy nodes that capture the rank in which each edge's
|
||||
* label is going to, if it has one of non-zero width and height. We do this
|
||||
* so that we can safely remove empty ranks while preserving balance for the
|
||||
* label's position.
|
||||
*/
|
||||
function injectEdgeLabelProxies(g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
if (edge.width && edge.height) {
|
||||
var v = g.node(e.v);
|
||||
var w = g.node(e.w);
|
||||
var label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e };
|
||||
util.addDummyNode(g, 'edge-proxy', label, '_ep');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function assignRankMinMax(g) {
|
||||
var maxRank = 0;
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
if (node.borderTop) {
|
||||
node.minRank = g.node(node.borderTop).rank;
|
||||
node.maxRank = g.node(node.borderBottom).rank;
|
||||
maxRank = _.max(maxRank, node.maxRank);
|
||||
}
|
||||
});
|
||||
g.graph().maxRank = maxRank;
|
||||
}
|
||||
|
||||
function removeEdgeLabelProxies(g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
if (node.dummy === 'edge-proxy') {
|
||||
g.edge(node.e).labelRank = node.rank;
|
||||
g.removeNode(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function translateGraph(g) {
|
||||
var minX = Number.POSITIVE_INFINITY;
|
||||
var maxX = 0;
|
||||
var minY = Number.POSITIVE_INFINITY;
|
||||
var maxY = 0;
|
||||
var graphLabel = g.graph();
|
||||
var marginX = graphLabel.marginx || 0;
|
||||
var marginY = graphLabel.marginy || 0;
|
||||
|
||||
function getExtremes(attrs) {
|
||||
var x = attrs.x;
|
||||
var y = attrs.y;
|
||||
var w = attrs.width;
|
||||
var h = attrs.height;
|
||||
minX = Math.min(minX, x - w / 2);
|
||||
maxX = Math.max(maxX, x + w / 2);
|
||||
minY = Math.min(minY, y - h / 2);
|
||||
maxY = Math.max(maxY, y + h / 2);
|
||||
}
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
getExtremes(g.node(v));
|
||||
});
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
if (_.has(edge, 'x')) {
|
||||
getExtremes(edge);
|
||||
}
|
||||
});
|
||||
|
||||
minX -= marginX;
|
||||
minY -= marginY;
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
node.x -= minX;
|
||||
node.y -= minY;
|
||||
});
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
_.forEach(edge.points, function (p) {
|
||||
p.x -= minX;
|
||||
p.y -= minY;
|
||||
});
|
||||
if (_.has(edge, 'x')) {
|
||||
edge.x -= minX;
|
||||
}
|
||||
if (_.has(edge, 'y')) {
|
||||
edge.y -= minY;
|
||||
}
|
||||
});
|
||||
|
||||
graphLabel.width = maxX - minX + marginX;
|
||||
graphLabel.height = maxY - minY + marginY;
|
||||
}
|
||||
|
||||
function assignNodeIntersects(g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
var nodeV = g.node(e.v);
|
||||
var nodeW = g.node(e.w);
|
||||
var p1, p2;
|
||||
if (!edge.points) {
|
||||
edge.points = [];
|
||||
p1 = nodeW;
|
||||
p2 = nodeV;
|
||||
} else {
|
||||
p1 = edge.points[0];
|
||||
p2 = edge.points[edge.points.length - 1];
|
||||
}
|
||||
edge.points.unshift(util.intersectRect(nodeV, p1));
|
||||
edge.points.push(util.intersectRect(nodeW, p2));
|
||||
});
|
||||
}
|
||||
|
||||
function fixupEdgeLabelCoords(g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
if (_.has(edge, 'x')) {
|
||||
if (edge.labelpos === 'l' || edge.labelpos === 'r') {
|
||||
edge.width -= edge.labeloffset;
|
||||
}
|
||||
switch (edge.labelpos) {
|
||||
case 'l':
|
||||
edge.x -= edge.width / 2 + edge.labeloffset;
|
||||
break;
|
||||
case 'r':
|
||||
edge.x += edge.width / 2 + edge.labeloffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function reversePointsForReversedEdges(g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
if (edge.reversed) {
|
||||
edge.points.reverse();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeBorderNodes(g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
if (g.children(v).length) {
|
||||
var node = g.node(v);
|
||||
var t = g.node(node.borderTop);
|
||||
var b = g.node(node.borderBottom);
|
||||
var l = g.node(_.last(node.borderLeft));
|
||||
var r = g.node(_.last(node.borderRight));
|
||||
|
||||
node.width = Math.abs(r.x - l.x);
|
||||
node.height = Math.abs(b.y - t.y);
|
||||
node.x = l.x + node.width / 2;
|
||||
node.y = t.y + node.height / 2;
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
if (g.node(v).dummy === 'border') {
|
||||
g.removeNode(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeSelfEdges(g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
if (e.v === e.w) {
|
||||
var node = g.node(e.v);
|
||||
if (!node.selfEdges) {
|
||||
node.selfEdges = [];
|
||||
}
|
||||
node.selfEdges.push({ e: e, label: g.edge(e) });
|
||||
g.removeEdge(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertSelfEdges(g) {
|
||||
var layers = util.buildLayerMatrix(g);
|
||||
_.forEach(layers, function (layer) {
|
||||
var orderShift = 0;
|
||||
_.forEach(layer, function (v, i) {
|
||||
var node = g.node(v);
|
||||
node.order = i + orderShift;
|
||||
_.forEach(node.selfEdges, function (selfEdge) {
|
||||
util.addDummyNode(
|
||||
g,
|
||||
'selfedge',
|
||||
{
|
||||
width: selfEdge.label.width,
|
||||
height: selfEdge.label.height,
|
||||
rank: node.rank,
|
||||
order: i + ++orderShift,
|
||||
e: selfEdge.e,
|
||||
label: selfEdge.label,
|
||||
},
|
||||
'_se'
|
||||
);
|
||||
});
|
||||
delete node.selfEdges;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function positionSelfEdges(g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
if (node.dummy === 'selfedge') {
|
||||
var selfNode = g.node(node.e.v);
|
||||
var x = selfNode.x + selfNode.width / 2;
|
||||
var y = selfNode.y;
|
||||
var dx = node.x - x;
|
||||
var dy = selfNode.height / 2;
|
||||
g.setEdge(node.e, node.label);
|
||||
g.removeNode(v);
|
||||
node.label.points = [
|
||||
{ x: x + (2 * dx) / 3, y: y - dy },
|
||||
{ x: x + (5 * dx) / 6, y: y - dy },
|
||||
{ x: x + dx, y: y },
|
||||
{ x: x + (5 * dx) / 6, y: y + dy },
|
||||
{ x: x + (2 * dx) / 3, y: y + dy },
|
||||
];
|
||||
node.label.x = node.x;
|
||||
node.label.y = node.y;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function selectNumberAttrs(obj, attrs) {
|
||||
return _.mapValues(_.pick(obj, attrs), Number);
|
||||
}
|
||||
|
||||
function canonicalize(attrs) {
|
||||
var newAttrs = {};
|
||||
_.forEach(attrs, function (v, k) {
|
||||
newAttrs[k.toLowerCase()] = v;
|
||||
});
|
||||
return newAttrs;
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/nesting-graph.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/nesting-graph.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function run(g: any): void;
|
||||
export function cleanup(g: any): void;
|
||||
137
node_modules/dagre-d3-es/src/dagre/nesting-graph.js
generated
vendored
Normal file
137
node_modules/dagre-d3-es/src/dagre/nesting-graph.js
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { run, cleanup };
|
||||
|
||||
/*
|
||||
* A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,
|
||||
* adds appropriate edges to ensure that all cluster nodes are placed between
|
||||
* these boundries, and ensures that the graph is connected.
|
||||
*
|
||||
* In addition we ensure, through the use of the minlen property, that nodes
|
||||
* and subgraph border nodes to not end up on the same rank.
|
||||
*
|
||||
* Preconditions:
|
||||
*
|
||||
* 1. Input graph is a DAG
|
||||
* 2. Nodes in the input graph has a minlen attribute
|
||||
*
|
||||
* Postconditions:
|
||||
*
|
||||
* 1. Input graph is connected.
|
||||
* 2. Dummy nodes are added for the tops and bottoms of subgraphs.
|
||||
* 3. The minlen attribute for nodes is adjusted to ensure nodes do not
|
||||
* get placed on the same rank as subgraph border nodes.
|
||||
*
|
||||
* The nesting graph idea comes from Sander, "Layout of Compound Directed
|
||||
* Graphs."
|
||||
*/
|
||||
function run(g) {
|
||||
var root = util.addDummyNode(g, 'root', {}, '_root');
|
||||
var depths = treeDepths(g);
|
||||
var height = _.max(_.values(depths)) - 1; // Note: depths is an Object not an array
|
||||
var nodeSep = 2 * height + 1;
|
||||
|
||||
g.graph().nestingRoot = root;
|
||||
|
||||
// Multiply minlen by nodeSep to align nodes on non-border ranks.
|
||||
_.forEach(g.edges(), function (e) {
|
||||
g.edge(e).minlen *= nodeSep;
|
||||
});
|
||||
|
||||
// Calculate a weight that is sufficient to keep subgraphs vertically compact
|
||||
var weight = sumWeights(g) + 1;
|
||||
|
||||
// Create border nodes and link them up
|
||||
_.forEach(g.children(), function (child) {
|
||||
dfs(g, root, nodeSep, weight, height, depths, child);
|
||||
});
|
||||
|
||||
// Save the multiplier for node layers for later removal of empty border
|
||||
// layers.
|
||||
g.graph().nodeRankFactor = nodeSep;
|
||||
}
|
||||
|
||||
function dfs(g, root, nodeSep, weight, height, depths, v) {
|
||||
var children = g.children(v);
|
||||
if (!children.length) {
|
||||
if (v !== root) {
|
||||
g.setEdge(root, v, { weight: 0, minlen: nodeSep });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var top = util.addBorderNode(g, '_bt');
|
||||
var bottom = util.addBorderNode(g, '_bb');
|
||||
var label = g.node(v);
|
||||
|
||||
g.setParent(top, v);
|
||||
label.borderTop = top;
|
||||
g.setParent(bottom, v);
|
||||
label.borderBottom = bottom;
|
||||
|
||||
_.forEach(children, function (child) {
|
||||
dfs(g, root, nodeSep, weight, height, depths, child);
|
||||
|
||||
var childNode = g.node(child);
|
||||
var childTop = childNode.borderTop ? childNode.borderTop : child;
|
||||
var childBottom = childNode.borderBottom ? childNode.borderBottom : child;
|
||||
var thisWeight = childNode.borderTop ? weight : 2 * weight;
|
||||
var minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
|
||||
|
||||
g.setEdge(top, childTop, {
|
||||
weight: thisWeight,
|
||||
minlen: minlen,
|
||||
nestingEdge: true,
|
||||
});
|
||||
|
||||
g.setEdge(childBottom, bottom, {
|
||||
weight: thisWeight,
|
||||
minlen: minlen,
|
||||
nestingEdge: true,
|
||||
});
|
||||
});
|
||||
|
||||
if (!g.parent(v)) {
|
||||
g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
|
||||
}
|
||||
}
|
||||
|
||||
function treeDepths(g) {
|
||||
var depths = {};
|
||||
function dfs(v, depth) {
|
||||
var children = g.children(v);
|
||||
if (children && children.length) {
|
||||
_.forEach(children, function (child) {
|
||||
dfs(child, depth + 1);
|
||||
});
|
||||
}
|
||||
depths[v] = depth;
|
||||
}
|
||||
_.forEach(g.children(), function (v) {
|
||||
dfs(v, 1);
|
||||
});
|
||||
return depths;
|
||||
}
|
||||
|
||||
function sumWeights(g) {
|
||||
return _.reduce(
|
||||
g.edges(),
|
||||
function (acc, e) {
|
||||
return acc + g.edge(e).weight;
|
||||
},
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
function cleanup(g) {
|
||||
var graphLabel = g.graph();
|
||||
g.removeNode(graphLabel.nestingRoot);
|
||||
delete graphLabel.nestingRoot;
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var edge = g.edge(e);
|
||||
if (edge.nestingEdge) {
|
||||
g.removeEdge(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/normalize.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/normalize.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function run(g: any): void;
|
||||
export function undo(g: any): void;
|
||||
89
node_modules/dagre-d3-es/src/dagre/normalize.js
generated
vendored
Normal file
89
node_modules/dagre-d3-es/src/dagre/normalize.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import * as util from './util.js';
|
||||
|
||||
export { run, undo };
|
||||
|
||||
/*
|
||||
* Breaks any long edges in the graph into short segments that span 1 layer
|
||||
* each. This operation is undoable with the denormalize function.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. The input graph is a DAG.
|
||||
* 2. Each node in the graph has a "rank" property.
|
||||
*
|
||||
* Post-condition:
|
||||
*
|
||||
* 1. All edges in the graph have a length of 1.
|
||||
* 2. Dummy nodes are added where edges have been split into segments.
|
||||
* 3. The graph is augmented with a "dummyChains" attribute which contains
|
||||
* the first dummy in each chain of dummy nodes produced.
|
||||
*/
|
||||
function run(g) {
|
||||
g.graph().dummyChains = [];
|
||||
_.forEach(g.edges(), function (edge) {
|
||||
normalizeEdge(g, edge);
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeEdge(g, e) {
|
||||
var v = e.v;
|
||||
var vRank = g.node(v).rank;
|
||||
var w = e.w;
|
||||
var wRank = g.node(w).rank;
|
||||
var name = e.name;
|
||||
var edgeLabel = g.edge(e);
|
||||
var labelRank = edgeLabel.labelRank;
|
||||
|
||||
if (wRank === vRank + 1) return;
|
||||
|
||||
g.removeEdge(e);
|
||||
|
||||
var dummy, attrs, i;
|
||||
for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
|
||||
edgeLabel.points = [];
|
||||
attrs = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
edgeLabel: edgeLabel,
|
||||
edgeObj: e,
|
||||
rank: vRank,
|
||||
};
|
||||
dummy = util.addDummyNode(g, 'edge', attrs, '_d');
|
||||
if (vRank === labelRank) {
|
||||
attrs.width = edgeLabel.width;
|
||||
attrs.height = edgeLabel.height;
|
||||
attrs.dummy = 'edge-label';
|
||||
attrs.labelpos = edgeLabel.labelpos;
|
||||
}
|
||||
g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
|
||||
if (i === 0) {
|
||||
g.graph().dummyChains.push(dummy);
|
||||
}
|
||||
v = dummy;
|
||||
}
|
||||
|
||||
g.setEdge(v, w, { weight: edgeLabel.weight }, name);
|
||||
}
|
||||
|
||||
function undo(g) {
|
||||
_.forEach(g.graph().dummyChains, function (v) {
|
||||
var node = g.node(v);
|
||||
var origLabel = node.edgeLabel;
|
||||
var w;
|
||||
g.setEdge(node.edgeObj, origLabel);
|
||||
while (node.dummy) {
|
||||
w = g.successors(v)[0];
|
||||
g.removeNode(v);
|
||||
origLabel.points.push({ x: node.x, y: node.y });
|
||||
if (node.dummy === 'edge-label') {
|
||||
origLabel.x = node.x;
|
||||
origLabel.y = node.y;
|
||||
origLabel.width = node.width;
|
||||
origLabel.height = node.height;
|
||||
}
|
||||
v = w;
|
||||
node = g.node(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/order/add-subgraph-constraints.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/order/add-subgraph-constraints.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function addSubgraphConstraints(g: any, cg: any, vs: any): void;
|
||||
53
node_modules/dagre-d3-es/src/dagre/order/add-subgraph-constraints.js
generated
vendored
Normal file
53
node_modules/dagre-d3-es/src/dagre/order/add-subgraph-constraints.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { addSubgraphConstraints };
|
||||
|
||||
function addSubgraphConstraints(g, cg, vs) {
|
||||
var prev = {},
|
||||
rootPrev;
|
||||
|
||||
_.forEach(vs, function (v) {
|
||||
var child = g.parent(v),
|
||||
parent,
|
||||
prevChild;
|
||||
while (child) {
|
||||
parent = g.parent(child);
|
||||
if (parent) {
|
||||
prevChild = prev[parent];
|
||||
prev[parent] = child;
|
||||
} else {
|
||||
prevChild = rootPrev;
|
||||
rootPrev = child;
|
||||
}
|
||||
if (prevChild && prevChild !== child) {
|
||||
cg.setEdge(prevChild, child);
|
||||
return;
|
||||
}
|
||||
child = parent;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
function dfs(v) {
|
||||
var children = v ? g.children(v) : g.children();
|
||||
if (children.length) {
|
||||
var min = Number.POSITIVE_INFINITY,
|
||||
subgraphs = [];
|
||||
_.each(children, function(child) {
|
||||
var childMin = dfs(child);
|
||||
if (g.children(child).length) {
|
||||
subgraphs.push({ v: child, order: childMin });
|
||||
}
|
||||
min = Math.min(min, childMin);
|
||||
});
|
||||
_.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
|
||||
cg.setEdge(prev.v, curr.v);
|
||||
return curr;
|
||||
});
|
||||
return min;
|
||||
}
|
||||
return g.node(v).order;
|
||||
}
|
||||
dfs(undefined);
|
||||
*/
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/order/barycenter.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/order/barycenter.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function barycenter(g: any, movable: any): any;
|
||||
31
node_modules/dagre-d3-es/src/dagre/order/barycenter.js
generated
vendored
Normal file
31
node_modules/dagre-d3-es/src/dagre/order/barycenter.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { barycenter };
|
||||
|
||||
function barycenter(g, movable) {
|
||||
return _.map(movable, function (v) {
|
||||
var inV = g.inEdges(v);
|
||||
if (!inV.length) {
|
||||
return { v: v };
|
||||
} else {
|
||||
var result = _.reduce(
|
||||
inV,
|
||||
function (acc, e) {
|
||||
var edge = g.edge(e),
|
||||
nodeU = g.node(e.v);
|
||||
return {
|
||||
sum: acc.sum + edge.weight * nodeU.order,
|
||||
weight: acc.weight + edge.weight,
|
||||
};
|
||||
},
|
||||
{ sum: 0, weight: 0 }
|
||||
);
|
||||
|
||||
return {
|
||||
v: v,
|
||||
barycenter: result.sum / result.weight,
|
||||
weight: result.weight,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/order/build-layer-graph.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/order/build-layer-graph.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function buildLayerGraph(g: any, rank: any, relationship: any): Graph;
|
||||
import { Graph } from '../../graphlib/index.js';
|
||||
76
node_modules/dagre-d3-es/src/dagre/order/build-layer-graph.js
generated
vendored
Normal file
76
node_modules/dagre-d3-es/src/dagre/order/build-layer-graph.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../../graphlib/index.js';
|
||||
|
||||
export { buildLayerGraph };
|
||||
|
||||
/*
|
||||
* Constructs a graph that can be used to sort a layer of nodes. The graph will
|
||||
* contain all base and subgraph nodes from the request layer in their original
|
||||
* hierarchy and any edges that are incident on these nodes and are of the type
|
||||
* requested by the "relationship" parameter.
|
||||
*
|
||||
* Nodes from the requested rank that do not have parents are assigned a root
|
||||
* node in the output graph, which is set in the root graph attribute. This
|
||||
* makes it easy to walk the hierarchy of movable nodes during ordering.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph is a DAG
|
||||
* 2. Base nodes in the input graph have a rank attribute
|
||||
* 3. Subgraph nodes in the input graph has minRank and maxRank attributes
|
||||
* 4. Edges have an assigned weight
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Output graph has all nodes in the movable rank with preserved
|
||||
* hierarchy.
|
||||
* 2. Root nodes in the movable layer are made children of the node
|
||||
* indicated by the root attribute of the graph.
|
||||
* 3. Non-movable nodes incident on movable nodes, selected by the
|
||||
* relationship parameter, are included in the graph (without hierarchy).
|
||||
* 4. Edges incident on movable nodes, selected by the relationship
|
||||
* parameter, are added to the output graph.
|
||||
* 5. The weights for copied edges are aggregated as need, since the output
|
||||
* graph is not a multi-graph.
|
||||
*/
|
||||
function buildLayerGraph(g, rank, relationship) {
|
||||
var root = createRootNode(g),
|
||||
result = new Graph({ compound: true })
|
||||
.setGraph({ root: root })
|
||||
.setDefaultNodeLabel(function (v) {
|
||||
return g.node(v);
|
||||
});
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v),
|
||||
parent = g.parent(v);
|
||||
|
||||
if (node.rank === rank || (node.minRank <= rank && rank <= node.maxRank)) {
|
||||
result.setNode(v);
|
||||
result.setParent(v, parent || root);
|
||||
|
||||
// This assumes we have only short edges!
|
||||
_.forEach(g[relationship](v), function (e) {
|
||||
var u = e.v === v ? e.w : e.v,
|
||||
edge = result.edge(u, v),
|
||||
weight = !_.isUndefined(edge) ? edge.weight : 0;
|
||||
result.setEdge(u, v, { weight: g.edge(e).weight + weight });
|
||||
});
|
||||
|
||||
if (_.has(node, 'minRank')) {
|
||||
result.setNode(v, {
|
||||
borderLeft: node.borderLeft[rank],
|
||||
borderRight: node.borderRight[rank],
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function createRootNode(g) {
|
||||
var v;
|
||||
while (g.hasNode((v = _.uniqueId('_root'))));
|
||||
return v;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/order/cross-count.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/order/cross-count.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function crossCount(g: any, layering: any): number;
|
||||
79
node_modules/dagre-d3-es/src/dagre/order/cross-count.js
generated
vendored
Normal file
79
node_modules/dagre-d3-es/src/dagre/order/cross-count.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { crossCount };
|
||||
|
||||
/*
|
||||
* A function that takes a layering (an array of layers, each with an array of
|
||||
* ordererd nodes) and a graph and returns a weighted crossing count.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph must be simple (not a multigraph), directed, and include
|
||||
* only simple edges.
|
||||
* 2. Edges in the input graph must have assigned weights.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. The graph and layering matrix are left unchanged.
|
||||
*
|
||||
* This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
|
||||
*/
|
||||
function crossCount(g, layering) {
|
||||
var cc = 0;
|
||||
for (var i = 1; i < layering.length; ++i) {
|
||||
cc += twoLayerCrossCount(g, layering[i - 1], layering[i]);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
||||
function twoLayerCrossCount(g, northLayer, southLayer) {
|
||||
// Sort all of the edges between the north and south layers by their position
|
||||
// in the north layer and then the south. Map these edges to the position of
|
||||
// their head in the south layer.
|
||||
var southPos = _.zipObject(
|
||||
southLayer,
|
||||
_.map(southLayer, function (v, i) {
|
||||
return i;
|
||||
})
|
||||
);
|
||||
var southEntries = _.flatten(
|
||||
_.map(northLayer, function (v) {
|
||||
return _.sortBy(
|
||||
_.map(g.outEdges(v), function (e) {
|
||||
return { pos: southPos[e.w], weight: g.edge(e).weight };
|
||||
}),
|
||||
'pos'
|
||||
);
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
// Build the accumulator tree
|
||||
var firstIndex = 1;
|
||||
while (firstIndex < southLayer.length) firstIndex <<= 1;
|
||||
var treeSize = 2 * firstIndex - 1;
|
||||
firstIndex -= 1;
|
||||
var tree = _.map(new Array(treeSize), function () {
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Calculate the weighted crossings
|
||||
var cc = 0;
|
||||
_.forEach(
|
||||
southEntries.forEach(function (entry) {
|
||||
var index = entry.pos + firstIndex;
|
||||
tree[index] += entry.weight;
|
||||
var weightSum = 0;
|
||||
while (index > 0) {
|
||||
if (index % 2) {
|
||||
weightSum += tree[index + 1];
|
||||
}
|
||||
index = (index - 1) >> 1;
|
||||
tree[index] += entry.weight;
|
||||
}
|
||||
cc += entry.weight * weightSum;
|
||||
})
|
||||
);
|
||||
|
||||
return cc;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/order/index.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/order/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function order(g: any): void;
|
||||
77
node_modules/dagre-d3-es/src/dagre/order/index.js
generated
vendored
Normal file
77
node_modules/dagre-d3-es/src/dagre/order/index.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../../graphlib/index.js';
|
||||
import * as util from '../util.js';
|
||||
import { addSubgraphConstraints } from './add-subgraph-constraints.js';
|
||||
import { buildLayerGraph } from './build-layer-graph.js';
|
||||
import { crossCount } from './cross-count.js';
|
||||
import { initOrder } from './init-order.js';
|
||||
import { sortSubgraph } from './sort-subgraph.js';
|
||||
|
||||
export { order };
|
||||
|
||||
/*
|
||||
* Applies heuristics to minimize edge crossings in the graph and sets the best
|
||||
* order solution as an order attribute on each node.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be DAG
|
||||
* 2. Graph nodes must be objects with a "rank" attribute
|
||||
* 3. Graph edges must have the "weight" attribute
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Graph nodes will have an "order" attribute based on the results of the
|
||||
* algorithm.
|
||||
*/
|
||||
function order(g) {
|
||||
var maxRank = util.maxRank(g),
|
||||
downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), 'inEdges'),
|
||||
upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), 'outEdges');
|
||||
|
||||
var layering = initOrder(g);
|
||||
assignOrder(g, layering);
|
||||
|
||||
var bestCC = Number.POSITIVE_INFINITY,
|
||||
best;
|
||||
|
||||
for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
|
||||
sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
|
||||
|
||||
layering = util.buildLayerMatrix(g);
|
||||
var cc = crossCount(g, layering);
|
||||
if (cc < bestCC) {
|
||||
lastBest = 0;
|
||||
best = _.cloneDeep(layering);
|
||||
bestCC = cc;
|
||||
}
|
||||
}
|
||||
|
||||
assignOrder(g, best);
|
||||
}
|
||||
|
||||
function buildLayerGraphs(g, ranks, relationship) {
|
||||
return _.map(ranks, function (rank) {
|
||||
return buildLayerGraph(g, rank, relationship);
|
||||
});
|
||||
}
|
||||
|
||||
function sweepLayerGraphs(layerGraphs, biasRight) {
|
||||
var cg = new Graph();
|
||||
_.forEach(layerGraphs, function (lg) {
|
||||
var root = lg.graph().root;
|
||||
var sorted = sortSubgraph(lg, root, cg, biasRight);
|
||||
_.forEach(sorted.vs, function (v, i) {
|
||||
lg.node(v).order = i;
|
||||
});
|
||||
addSubgraphConstraints(lg, cg, sorted.vs);
|
||||
});
|
||||
}
|
||||
|
||||
function assignOrder(g, layering) {
|
||||
_.forEach(layering, function (layer) {
|
||||
_.forEach(layer, function (v, i) {
|
||||
g.node(v).order = i;
|
||||
});
|
||||
});
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/order/init-order.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/order/init-order.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function initOrder(g: any): any;
|
||||
44
node_modules/dagre-d3-es/src/dagre/order/init-order.js
generated
vendored
Normal file
44
node_modules/dagre-d3-es/src/dagre/order/init-order.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { initOrder };
|
||||
|
||||
/*
|
||||
* Assigns an initial order value for each node by performing a DFS search
|
||||
* starting from nodes in the first rank. Nodes are assigned an order in their
|
||||
* rank as they are first visited.
|
||||
*
|
||||
* This approach comes from Gansner, et al., "A Technique for Drawing Directed
|
||||
* Graphs."
|
||||
*
|
||||
* Returns a layering matrix with an array per layer and each layer sorted by
|
||||
* the order of its nodes.
|
||||
*/
|
||||
function initOrder(g) {
|
||||
var visited = {};
|
||||
var simpleNodes = _.filter(g.nodes(), function (v) {
|
||||
return !g.children(v).length;
|
||||
});
|
||||
var maxRank = _.max(
|
||||
_.map(simpleNodes, function (v) {
|
||||
return g.node(v).rank;
|
||||
})
|
||||
);
|
||||
var layers = _.map(_.range(maxRank + 1), function () {
|
||||
return [];
|
||||
});
|
||||
|
||||
function dfs(v) {
|
||||
if (_.has(visited, v)) return;
|
||||
visited[v] = true;
|
||||
var node = g.node(v);
|
||||
layers[node.rank].push(v);
|
||||
_.forEach(g.successors(v), dfs);
|
||||
}
|
||||
|
||||
var orderedVs = _.sortBy(simpleNodes, function (v) {
|
||||
return g.node(v).rank;
|
||||
});
|
||||
_.forEach(orderedVs, dfs);
|
||||
|
||||
return layers;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/order/resolve-conflicts.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/order/resolve-conflicts.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function resolveConflicts(entries: any, cg: any): any;
|
||||
125
node_modules/dagre-d3-es/src/dagre/order/resolve-conflicts.js
generated
vendored
Normal file
125
node_modules/dagre-d3-es/src/dagre/order/resolve-conflicts.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { resolveConflicts };
|
||||
|
||||
/*
|
||||
* Given a list of entries of the form {v, barycenter, weight} and a
|
||||
* constraint graph this function will resolve any conflicts between the
|
||||
* constraint graph and the barycenters for the entries. If the barycenters for
|
||||
* an entry would violate a constraint in the constraint graph then we coalesce
|
||||
* the nodes in the conflict into a new node that respects the contraint and
|
||||
* aggregates barycenter and weight information.
|
||||
*
|
||||
* This implementation is based on the description in Forster, "A Fast and
|
||||
* Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
|
||||
* differs in some specific details.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Each entry has the form {v, barycenter, weight}, or if the node has
|
||||
* no barycenter, then {v}.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* A new list of entries of the form {vs, i, barycenter, weight}. The list
|
||||
* `vs` may either be a singleton or it may be an aggregation of nodes
|
||||
* ordered such that they do not violate constraints from the constraint
|
||||
* graph. The property `i` is the lowest original index of any of the
|
||||
* elements in `vs`.
|
||||
*/
|
||||
function resolveConflicts(entries, cg) {
|
||||
var mappedEntries = {};
|
||||
_.forEach(entries, function (entry, i) {
|
||||
var tmp = (mappedEntries[entry.v] = {
|
||||
indegree: 0,
|
||||
in: [],
|
||||
out: [],
|
||||
vs: [entry.v],
|
||||
i: i,
|
||||
});
|
||||
if (!_.isUndefined(entry.barycenter)) {
|
||||
tmp.barycenter = entry.barycenter;
|
||||
tmp.weight = entry.weight;
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(cg.edges(), function (e) {
|
||||
var entryV = mappedEntries[e.v];
|
||||
var entryW = mappedEntries[e.w];
|
||||
if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
|
||||
entryW.indegree++;
|
||||
entryV.out.push(mappedEntries[e.w]);
|
||||
}
|
||||
});
|
||||
|
||||
var sourceSet = _.filter(mappedEntries, function (entry) {
|
||||
return !entry.indegree;
|
||||
});
|
||||
|
||||
return doResolveConflicts(sourceSet);
|
||||
}
|
||||
|
||||
function doResolveConflicts(sourceSet) {
|
||||
var entries = [];
|
||||
|
||||
function handleIn(vEntry) {
|
||||
return function (uEntry) {
|
||||
if (uEntry.merged) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
_.isUndefined(uEntry.barycenter) ||
|
||||
_.isUndefined(vEntry.barycenter) ||
|
||||
uEntry.barycenter >= vEntry.barycenter
|
||||
) {
|
||||
mergeEntries(vEntry, uEntry);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleOut(vEntry) {
|
||||
return function (wEntry) {
|
||||
wEntry['in'].push(vEntry);
|
||||
if (--wEntry.indegree === 0) {
|
||||
sourceSet.push(wEntry);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
while (sourceSet.length) {
|
||||
var entry = sourceSet.pop();
|
||||
entries.push(entry);
|
||||
_.forEach(entry['in'].reverse(), handleIn(entry));
|
||||
_.forEach(entry.out, handleOut(entry));
|
||||
}
|
||||
|
||||
return _.map(
|
||||
_.filter(entries, function (entry) {
|
||||
return !entry.merged;
|
||||
}),
|
||||
function (entry) {
|
||||
return _.pick(entry, ['vs', 'i', 'barycenter', 'weight']);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function mergeEntries(target, source) {
|
||||
var sum = 0;
|
||||
var weight = 0;
|
||||
|
||||
if (target.weight) {
|
||||
sum += target.barycenter * target.weight;
|
||||
weight += target.weight;
|
||||
}
|
||||
|
||||
if (source.weight) {
|
||||
sum += source.barycenter * source.weight;
|
||||
weight += source.weight;
|
||||
}
|
||||
|
||||
target.vs = source.vs.concat(target.vs);
|
||||
target.barycenter = sum / weight;
|
||||
target.weight = weight;
|
||||
target.i = Math.min(source.i, target.i);
|
||||
source.merged = true;
|
||||
}
|
||||
8
node_modules/dagre-d3-es/src/dagre/order/sort-subgraph.d.ts
generated
vendored
Normal file
8
node_modules/dagre-d3-es/src/dagre/order/sort-subgraph.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export function sortSubgraph(
|
||||
g: any,
|
||||
v: any,
|
||||
cg: any,
|
||||
biasRight: any
|
||||
): {
|
||||
vs: any;
|
||||
};
|
||||
79
node_modules/dagre-d3-es/src/dagre/order/sort-subgraph.js
generated
vendored
Normal file
79
node_modules/dagre-d3-es/src/dagre/order/sort-subgraph.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { barycenter } from './barycenter.js';
|
||||
import { resolveConflicts } from './resolve-conflicts.js';
|
||||
import { sort } from './sort.js';
|
||||
|
||||
export { sortSubgraph };
|
||||
|
||||
function sortSubgraph(g, v, cg, biasRight) {
|
||||
var movable = g.children(v);
|
||||
var node = g.node(v);
|
||||
var bl = node ? node.borderLeft : undefined;
|
||||
var br = node ? node.borderRight : undefined;
|
||||
var subgraphs = {};
|
||||
|
||||
if (bl) {
|
||||
movable = _.filter(movable, function (w) {
|
||||
return w !== bl && w !== br;
|
||||
});
|
||||
}
|
||||
|
||||
var barycenters = barycenter(g, movable);
|
||||
_.forEach(barycenters, function (entry) {
|
||||
if (g.children(entry.v).length) {
|
||||
var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
|
||||
subgraphs[entry.v] = subgraphResult;
|
||||
if (_.has(subgraphResult, 'barycenter')) {
|
||||
mergeBarycenters(entry, subgraphResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var entries = resolveConflicts(barycenters, cg);
|
||||
expandSubgraphs(entries, subgraphs);
|
||||
|
||||
var result = sort(entries, biasRight);
|
||||
|
||||
if (bl) {
|
||||
result.vs = _.flatten([bl, result.vs, br], true);
|
||||
if (g.predecessors(bl).length) {
|
||||
var blPred = g.node(g.predecessors(bl)[0]),
|
||||
brPred = g.node(g.predecessors(br)[0]);
|
||||
if (!_.has(result, 'barycenter')) {
|
||||
result.barycenter = 0;
|
||||
result.weight = 0;
|
||||
}
|
||||
result.barycenter =
|
||||
(result.barycenter * result.weight + blPred.order + brPred.order) / (result.weight + 2);
|
||||
result.weight += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function expandSubgraphs(entries, subgraphs) {
|
||||
_.forEach(entries, function (entry) {
|
||||
entry.vs = _.flatten(
|
||||
entry.vs.map(function (v) {
|
||||
if (subgraphs[v]) {
|
||||
return subgraphs[v].vs;
|
||||
}
|
||||
return v;
|
||||
}),
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function mergeBarycenters(target, other) {
|
||||
if (!_.isUndefined(target.barycenter)) {
|
||||
target.barycenter =
|
||||
(target.barycenter * target.weight + other.barycenter * other.weight) /
|
||||
(target.weight + other.weight);
|
||||
target.weight += other.weight;
|
||||
} else {
|
||||
target.barycenter = other.barycenter;
|
||||
target.weight = other.weight;
|
||||
}
|
||||
}
|
||||
6
node_modules/dagre-d3-es/src/dagre/order/sort.d.ts
generated
vendored
Normal file
6
node_modules/dagre-d3-es/src/dagre/order/sort.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export function sort(
|
||||
entries: any,
|
||||
biasRight: any
|
||||
): {
|
||||
vs: any;
|
||||
};
|
||||
59
node_modules/dagre-d3-es/src/dagre/order/sort.js
generated
vendored
Normal file
59
node_modules/dagre-d3-es/src/dagre/order/sort.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import * as util from '../util.js';
|
||||
|
||||
export { sort };
|
||||
|
||||
function sort(entries, biasRight) {
|
||||
var parts = util.partition(entries, function (entry) {
|
||||
return _.has(entry, 'barycenter');
|
||||
});
|
||||
var sortable = parts.lhs,
|
||||
unsortable = _.sortBy(parts.rhs, function (entry) {
|
||||
return -entry.i;
|
||||
}),
|
||||
vs = [],
|
||||
sum = 0,
|
||||
weight = 0,
|
||||
vsIndex = 0;
|
||||
|
||||
sortable.sort(compareWithBias(!!biasRight));
|
||||
|
||||
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
||||
|
||||
_.forEach(sortable, function (entry) {
|
||||
vsIndex += entry.vs.length;
|
||||
vs.push(entry.vs);
|
||||
sum += entry.barycenter * entry.weight;
|
||||
weight += entry.weight;
|
||||
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
||||
});
|
||||
|
||||
var result = { vs: _.flatten(vs, true) };
|
||||
if (weight) {
|
||||
result.barycenter = sum / weight;
|
||||
result.weight = weight;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function consumeUnsortable(vs, unsortable, index) {
|
||||
var last;
|
||||
while (unsortable.length && (last = _.last(unsortable)).i <= index) {
|
||||
unsortable.pop();
|
||||
vs.push(last.vs);
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
function compareWithBias(bias) {
|
||||
return function (entryV, entryW) {
|
||||
if (entryV.barycenter < entryW.barycenter) {
|
||||
return -1;
|
||||
} else if (entryV.barycenter > entryW.barycenter) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
|
||||
};
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/parent-dummy-chains.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/parent-dummy-chains.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function parentDummyChains(g: any): void;
|
||||
86
node_modules/dagre-d3-es/src/dagre/parent-dummy-chains.js
generated
vendored
Normal file
86
node_modules/dagre-d3-es/src/dagre/parent-dummy-chains.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { parentDummyChains };
|
||||
|
||||
function parentDummyChains(g) {
|
||||
var postorderNums = postorder(g);
|
||||
|
||||
_.forEach(g.graph().dummyChains, function (v) {
|
||||
var node = g.node(v);
|
||||
var edgeObj = node.edgeObj;
|
||||
var pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w);
|
||||
var path = pathData.path;
|
||||
var lca = pathData.lca;
|
||||
var pathIdx = 0;
|
||||
var pathV = path[pathIdx];
|
||||
var ascending = true;
|
||||
|
||||
while (v !== edgeObj.w) {
|
||||
node = g.node(v);
|
||||
|
||||
if (ascending) {
|
||||
while ((pathV = path[pathIdx]) !== lca && g.node(pathV).maxRank < node.rank) {
|
||||
pathIdx++;
|
||||
}
|
||||
|
||||
if (pathV === lca) {
|
||||
ascending = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ascending) {
|
||||
while (
|
||||
pathIdx < path.length - 1 &&
|
||||
g.node((pathV = path[pathIdx + 1])).minRank <= node.rank
|
||||
) {
|
||||
pathIdx++;
|
||||
}
|
||||
pathV = path[pathIdx];
|
||||
}
|
||||
|
||||
g.setParent(v, pathV);
|
||||
v = g.successors(v)[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Find a path from v to w through the lowest common ancestor (LCA). Return the
|
||||
// full path and the LCA.
|
||||
function findPath(g, postorderNums, v, w) {
|
||||
var vPath = [];
|
||||
var wPath = [];
|
||||
var low = Math.min(postorderNums[v].low, postorderNums[w].low);
|
||||
var lim = Math.max(postorderNums[v].lim, postorderNums[w].lim);
|
||||
var parent;
|
||||
var lca;
|
||||
|
||||
// Traverse up from v to find the LCA
|
||||
parent = v;
|
||||
do {
|
||||
parent = g.parent(parent);
|
||||
vPath.push(parent);
|
||||
} while (parent && (postorderNums[parent].low > low || lim > postorderNums[parent].lim));
|
||||
lca = parent;
|
||||
|
||||
// Traverse from w to LCA
|
||||
parent = w;
|
||||
while ((parent = g.parent(parent)) !== lca) {
|
||||
wPath.push(parent);
|
||||
}
|
||||
|
||||
return { path: vPath.concat(wPath.reverse()), lca: lca };
|
||||
}
|
||||
|
||||
function postorder(g) {
|
||||
var result = {};
|
||||
var lim = 0;
|
||||
|
||||
function dfs(v) {
|
||||
var low = lim;
|
||||
_.forEach(g.children(v), dfs);
|
||||
result[v] = { low: low, lim: lim++ };
|
||||
}
|
||||
_.forEach(g.children(), dfs);
|
||||
|
||||
return result;
|
||||
}
|
||||
24
node_modules/dagre-d3-es/src/dagre/position/bk.d.ts
generated
vendored
Normal file
24
node_modules/dagre-d3-es/src/dagre/position/bk.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
export function positionX(g: any): any;
|
||||
export function findType1Conflicts(g: any, layering: any): {};
|
||||
export function findType2Conflicts(g: any, layering: any): {};
|
||||
export function addConflict(conflicts: any, v: any, w: any): void;
|
||||
export function hasConflict(conflicts: any, v: any, w: any): any;
|
||||
export function verticalAlignment(
|
||||
g: any,
|
||||
layering: any,
|
||||
conflicts: any,
|
||||
neighborFn: any
|
||||
): {
|
||||
root: {};
|
||||
align: {};
|
||||
};
|
||||
export function horizontalCompaction(
|
||||
g: any,
|
||||
layering: any,
|
||||
root: any,
|
||||
align: any,
|
||||
reverseSep: any
|
||||
): {};
|
||||
export function alignCoordinates(xss: any, alignTo: any): void;
|
||||
export function findSmallestWidthAlignment(g: any, xss: any): any;
|
||||
export function balance(xss: any, align: any): any;
|
||||
421
node_modules/dagre-d3-es/src/dagre/position/bk.js
generated
vendored
Normal file
421
node_modules/dagre-d3-es/src/dagre/position/bk.js
generated
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../../graphlib/index.js';
|
||||
import * as util from '../util.js';
|
||||
|
||||
/*
|
||||
* This module provides coordinate assignment based on Brandes and Köpf, "Fast
|
||||
* and Simple Horizontal Coordinate Assignment."
|
||||
*/
|
||||
|
||||
export {
|
||||
positionX,
|
||||
findType1Conflicts,
|
||||
findType2Conflicts,
|
||||
addConflict,
|
||||
hasConflict,
|
||||
verticalAlignment,
|
||||
horizontalCompaction,
|
||||
alignCoordinates,
|
||||
findSmallestWidthAlignment,
|
||||
balance,
|
||||
};
|
||||
|
||||
/*
|
||||
* Marks all edges in the graph with a type-1 conflict with the "type1Conflict"
|
||||
* property. A type-1 conflict is one where a non-inner segment crosses an
|
||||
* inner segment. An inner segment is an edge with both incident nodes marked
|
||||
* with the "dummy" property.
|
||||
*
|
||||
* This algorithm scans layer by layer, starting with the second, for type-1
|
||||
* conflicts between the current layer and the previous layer. For each layer
|
||||
* it scans the nodes from left to right until it reaches one that is incident
|
||||
* on an inner segment. It then scans predecessors to determine if they have
|
||||
* edges that cross that inner segment. At the end a final scan is done for all
|
||||
* nodes on the current rank to see if they cross the last visited inner
|
||||
* segment.
|
||||
*
|
||||
* This algorithm (safely) assumes that a dummy node will only be incident on a
|
||||
* single node in the layers being scanned.
|
||||
*/
|
||||
function findType1Conflicts(g, layering) {
|
||||
var conflicts = {};
|
||||
|
||||
function visitLayer(prevLayer, layer) {
|
||||
var // last visited node in the previous layer that is incident on an inner
|
||||
// segment.
|
||||
k0 = 0,
|
||||
// Tracks the last node in this layer scanned for crossings with a type-1
|
||||
// segment.
|
||||
scanPos = 0,
|
||||
prevLayerLength = prevLayer.length,
|
||||
lastNode = _.last(layer);
|
||||
|
||||
_.forEach(layer, function (v, i) {
|
||||
var w = findOtherInnerSegmentNode(g, v),
|
||||
k1 = w ? g.node(w).order : prevLayerLength;
|
||||
|
||||
if (w || v === lastNode) {
|
||||
_.forEach(layer.slice(scanPos, i + 1), function (scanNode) {
|
||||
_.forEach(g.predecessors(scanNode), function (u) {
|
||||
var uLabel = g.node(u),
|
||||
uPos = uLabel.order;
|
||||
if ((uPos < k0 || k1 < uPos) && !(uLabel.dummy && g.node(scanNode).dummy)) {
|
||||
addConflict(conflicts, u, scanNode);
|
||||
}
|
||||
});
|
||||
});
|
||||
scanPos = i + 1;
|
||||
k0 = k1;
|
||||
}
|
||||
});
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
_.reduce(layering, visitLayer);
|
||||
return conflicts;
|
||||
}
|
||||
|
||||
function findType2Conflicts(g, layering) {
|
||||
var conflicts = {};
|
||||
|
||||
function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
|
||||
var v;
|
||||
_.forEach(_.range(southPos, southEnd), function (i) {
|
||||
v = south[i];
|
||||
if (g.node(v).dummy) {
|
||||
_.forEach(g.predecessors(v), function (u) {
|
||||
var uNode = g.node(u);
|
||||
if (uNode.dummy && (uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
|
||||
addConflict(conflicts, u, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function visitLayer(north, south) {
|
||||
var prevNorthPos = -1,
|
||||
nextNorthPos,
|
||||
southPos = 0;
|
||||
|
||||
_.forEach(south, function (v, southLookahead) {
|
||||
if (g.node(v).dummy === 'border') {
|
||||
var predecessors = g.predecessors(v);
|
||||
if (predecessors.length) {
|
||||
nextNorthPos = g.node(predecessors[0]).order;
|
||||
scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);
|
||||
southPos = southLookahead;
|
||||
prevNorthPos = nextNorthPos;
|
||||
}
|
||||
}
|
||||
scan(south, southPos, south.length, nextNorthPos, north.length);
|
||||
});
|
||||
|
||||
return south;
|
||||
}
|
||||
|
||||
_.reduce(layering, visitLayer);
|
||||
return conflicts;
|
||||
}
|
||||
|
||||
function findOtherInnerSegmentNode(g, v) {
|
||||
if (g.node(v).dummy) {
|
||||
return _.find(g.predecessors(v), function (u) {
|
||||
return g.node(u).dummy;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addConflict(conflicts, v, w) {
|
||||
if (v > w) {
|
||||
var tmp = v;
|
||||
v = w;
|
||||
w = tmp;
|
||||
}
|
||||
|
||||
var conflictsV = conflicts[v];
|
||||
if (!conflictsV) {
|
||||
conflicts[v] = conflictsV = {};
|
||||
}
|
||||
conflictsV[w] = true;
|
||||
}
|
||||
|
||||
function hasConflict(conflicts, v, w) {
|
||||
if (v > w) {
|
||||
var tmp = v;
|
||||
v = w;
|
||||
w = tmp;
|
||||
}
|
||||
return _.has(conflicts[v], w);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to align nodes into vertical "blocks" where possible. This algorithm
|
||||
* attempts to align a node with one of its median neighbors. If the edge
|
||||
* connecting a neighbor is a type-1 conflict then we ignore that possibility.
|
||||
* If a previous node has already formed a block with a node after the node
|
||||
* we're trying to form a block with, we also ignore that possibility - our
|
||||
* blocks would be split in that scenario.
|
||||
*/
|
||||
function verticalAlignment(g, layering, conflicts, neighborFn) {
|
||||
var root = {},
|
||||
align = {},
|
||||
pos = {};
|
||||
|
||||
// We cache the position here based on the layering because the graph and
|
||||
// layering may be out of sync. The layering matrix is manipulated to
|
||||
// generate different extreme alignments.
|
||||
_.forEach(layering, function (layer) {
|
||||
_.forEach(layer, function (v, order) {
|
||||
root[v] = v;
|
||||
align[v] = v;
|
||||
pos[v] = order;
|
||||
});
|
||||
});
|
||||
|
||||
_.forEach(layering, function (layer) {
|
||||
var prevIdx = -1;
|
||||
_.forEach(layer, function (v) {
|
||||
var ws = neighborFn(v);
|
||||
if (ws.length) {
|
||||
ws = _.sortBy(ws, function (w) {
|
||||
return pos[w];
|
||||
});
|
||||
var mp = (ws.length - 1) / 2;
|
||||
for (var i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
|
||||
var w = ws[i];
|
||||
if (align[v] === v && prevIdx < pos[w] && !hasConflict(conflicts, v, w)) {
|
||||
align[w] = v;
|
||||
align[v] = root[v] = root[w];
|
||||
prevIdx = pos[w];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return { root: root, align: align };
|
||||
}
|
||||
|
||||
function horizontalCompaction(g, layering, root, align, reverseSep) {
|
||||
// This portion of the algorithm differs from BK due to a number of problems.
|
||||
// Instead of their algorithm we construct a new block graph and do two
|
||||
// sweeps. The first sweep places blocks with the smallest possible
|
||||
// coordinates. The second sweep removes unused space by moving blocks to the
|
||||
// greatest coordinates without violating separation.
|
||||
var xs = {},
|
||||
blockG = buildBlockGraph(g, layering, root, reverseSep),
|
||||
borderType = reverseSep ? 'borderLeft' : 'borderRight';
|
||||
|
||||
function iterate(setXsFunc, nextNodesFunc) {
|
||||
var stack = blockG.nodes();
|
||||
var elem = stack.pop();
|
||||
var visited = {};
|
||||
while (elem) {
|
||||
if (visited[elem]) {
|
||||
setXsFunc(elem);
|
||||
} else {
|
||||
visited[elem] = true;
|
||||
stack.push(elem);
|
||||
stack = stack.concat(nextNodesFunc(elem));
|
||||
}
|
||||
|
||||
elem = stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// First pass, assign smallest coordinates
|
||||
function pass1(elem) {
|
||||
xs[elem] = blockG.inEdges(elem).reduce(function (acc, e) {
|
||||
return Math.max(acc, xs[e.v] + blockG.edge(e));
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// Second pass, assign greatest coordinates
|
||||
function pass2(elem) {
|
||||
var min = blockG.outEdges(elem).reduce(function (acc, e) {
|
||||
return Math.min(acc, xs[e.w] - blockG.edge(e));
|
||||
}, Number.POSITIVE_INFINITY);
|
||||
|
||||
var node = g.node(elem);
|
||||
if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
|
||||
xs[elem] = Math.max(xs[elem], min);
|
||||
}
|
||||
}
|
||||
|
||||
iterate(pass1, blockG.predecessors.bind(blockG));
|
||||
iterate(pass2, blockG.successors.bind(blockG));
|
||||
|
||||
// Assign x coordinates to all nodes
|
||||
_.forEach(align, function (v) {
|
||||
xs[v] = xs[root[v]];
|
||||
});
|
||||
|
||||
return xs;
|
||||
}
|
||||
|
||||
function buildBlockGraph(g, layering, root, reverseSep) {
|
||||
var blockGraph = new Graph(),
|
||||
graphLabel = g.graph(),
|
||||
sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
|
||||
|
||||
_.forEach(layering, function (layer) {
|
||||
var u;
|
||||
_.forEach(layer, function (v) {
|
||||
var vRoot = root[v];
|
||||
blockGraph.setNode(vRoot);
|
||||
if (u) {
|
||||
var uRoot = root[u],
|
||||
prevMax = blockGraph.edge(uRoot, vRoot);
|
||||
blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0));
|
||||
}
|
||||
u = v;
|
||||
});
|
||||
});
|
||||
|
||||
return blockGraph;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the alignment that has the smallest width of the given alignments.
|
||||
*/
|
||||
function findSmallestWidthAlignment(g, xss) {
|
||||
return _.minBy(_.values(xss), function (xs) {
|
||||
var max = Number.NEGATIVE_INFINITY;
|
||||
var min = Number.POSITIVE_INFINITY;
|
||||
|
||||
_.forIn(xs, function (x, v) {
|
||||
var halfWidth = width(g, v) / 2;
|
||||
|
||||
max = Math.max(x + halfWidth, max);
|
||||
min = Math.min(x - halfWidth, min);
|
||||
});
|
||||
|
||||
return max - min;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Align the coordinates of each of the layout alignments such that
|
||||
* left-biased alignments have their minimum coordinate at the same point as
|
||||
* the minimum coordinate of the smallest width alignment and right-biased
|
||||
* alignments have their maximum coordinate at the same point as the maximum
|
||||
* coordinate of the smallest width alignment.
|
||||
*/
|
||||
function alignCoordinates(xss, alignTo) {
|
||||
var alignToVals = _.values(alignTo),
|
||||
alignToMin = _.min(alignToVals),
|
||||
alignToMax = _.max(alignToVals);
|
||||
|
||||
_.forEach(['u', 'd'], function (vert) {
|
||||
_.forEach(['l', 'r'], function (horiz) {
|
||||
var alignment = vert + horiz,
|
||||
xs = xss[alignment],
|
||||
delta;
|
||||
if (xs === alignTo) return;
|
||||
|
||||
var xsVals = _.values(xs);
|
||||
delta = horiz === 'l' ? alignToMin - _.min(xsVals) : alignToMax - _.max(xsVals);
|
||||
|
||||
if (delta) {
|
||||
xss[alignment] = _.mapValues(xs, function (x) {
|
||||
return x + delta;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function balance(xss, align) {
|
||||
return _.mapValues(xss.ul, function (ignore, v) {
|
||||
if (align) {
|
||||
return xss[align.toLowerCase()][v];
|
||||
} else {
|
||||
var xs = _.sortBy(_.map(xss, v));
|
||||
return (xs[1] + xs[2]) / 2;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function positionX(g) {
|
||||
var layering = util.buildLayerMatrix(g);
|
||||
var conflicts = _.merge(findType1Conflicts(g, layering), findType2Conflicts(g, layering));
|
||||
|
||||
var xss = {};
|
||||
var adjustedLayering;
|
||||
_.forEach(['u', 'd'], function (vert) {
|
||||
adjustedLayering = vert === 'u' ? layering : _.values(layering).reverse();
|
||||
_.forEach(['l', 'r'], function (horiz) {
|
||||
if (horiz === 'r') {
|
||||
adjustedLayering = _.map(adjustedLayering, function (inner) {
|
||||
return _.values(inner).reverse();
|
||||
});
|
||||
}
|
||||
|
||||
var neighborFn = (vert === 'u' ? g.predecessors : g.successors).bind(g);
|
||||
var align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
|
||||
var xs = horizontalCompaction(g, adjustedLayering, align.root, align.align, horiz === 'r');
|
||||
if (horiz === 'r') {
|
||||
xs = _.mapValues(xs, function (x) {
|
||||
return -x;
|
||||
});
|
||||
}
|
||||
xss[vert + horiz] = xs;
|
||||
});
|
||||
});
|
||||
|
||||
var smallestWidth = findSmallestWidthAlignment(g, xss);
|
||||
alignCoordinates(xss, smallestWidth);
|
||||
return balance(xss, g.graph().align);
|
||||
}
|
||||
|
||||
function sep(nodeSep, edgeSep, reverseSep) {
|
||||
return function (g, v, w) {
|
||||
var vLabel = g.node(v);
|
||||
var wLabel = g.node(w);
|
||||
var sum = 0;
|
||||
var delta;
|
||||
|
||||
sum += vLabel.width / 2;
|
||||
if (_.has(vLabel, 'labelpos')) {
|
||||
switch (vLabel.labelpos.toLowerCase()) {
|
||||
case 'l':
|
||||
delta = -vLabel.width / 2;
|
||||
break;
|
||||
case 'r':
|
||||
delta = vLabel.width / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (delta) {
|
||||
sum += reverseSep ? delta : -delta;
|
||||
}
|
||||
delta = 0;
|
||||
|
||||
sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
|
||||
sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
|
||||
|
||||
sum += wLabel.width / 2;
|
||||
if (_.has(wLabel, 'labelpos')) {
|
||||
switch (wLabel.labelpos.toLowerCase()) {
|
||||
case 'l':
|
||||
delta = wLabel.width / 2;
|
||||
break;
|
||||
case 'r':
|
||||
delta = -wLabel.width / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (delta) {
|
||||
sum += reverseSep ? delta : -delta;
|
||||
}
|
||||
delta = 0;
|
||||
|
||||
return sum;
|
||||
};
|
||||
}
|
||||
|
||||
function width(g, v) {
|
||||
return g.node(v).width;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/position/index.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/position/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function position(g: any): void;
|
||||
31
node_modules/dagre-d3-es/src/dagre/position/index.js
generated
vendored
Normal file
31
node_modules/dagre-d3-es/src/dagre/position/index.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import * as util from '../util.js';
|
||||
import { positionX } from './bk.js';
|
||||
|
||||
export { position };
|
||||
|
||||
function position(g) {
|
||||
g = util.asNonCompoundGraph(g);
|
||||
|
||||
positionY(g);
|
||||
_.forEach(positionX(g), function (x, v) {
|
||||
g.node(v).x = x;
|
||||
});
|
||||
}
|
||||
|
||||
function positionY(g) {
|
||||
var layering = util.buildLayerMatrix(g);
|
||||
var rankSep = g.graph().ranksep;
|
||||
var prevY = 0;
|
||||
_.forEach(layering, function (layer) {
|
||||
var maxHeight = _.max(
|
||||
_.map(layer, function (v) {
|
||||
return g.node(v).height;
|
||||
})
|
||||
);
|
||||
_.forEach(layer, function (v) {
|
||||
g.node(v).y = prevY + maxHeight / 2;
|
||||
});
|
||||
prevY += maxHeight + rankSep;
|
||||
});
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/rank/feasible-tree.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/rank/feasible-tree.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function feasibleTree(g: any): Graph;
|
||||
import { Graph } from '../../graphlib/index.js';
|
||||
87
node_modules/dagre-d3-es/src/dagre/rank/feasible-tree.js
generated
vendored
Normal file
87
node_modules/dagre-d3-es/src/dagre/rank/feasible-tree.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../../graphlib/index.js';
|
||||
import { slack } from './util.js';
|
||||
|
||||
export { feasibleTree };
|
||||
|
||||
/*
|
||||
* Constructs a spanning tree with tight edges and adjusted the input node's
|
||||
* ranks to achieve this. A tight edge is one that is has a length that matches
|
||||
* its "minlen" attribute.
|
||||
*
|
||||
* The basic structure for this function is derived from Gansner, et al., "A
|
||||
* Technique for Drawing Directed Graphs."
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be a DAG.
|
||||
* 2. Graph must be connected.
|
||||
* 3. Graph must have at least one node.
|
||||
* 5. Graph nodes must have been previously assigned a "rank" property that
|
||||
* respects the "minlen" property of incident edges.
|
||||
* 6. Graph edges must have a "minlen" property.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* - Graph nodes will have their rank adjusted to ensure that all edges are
|
||||
* tight.
|
||||
*
|
||||
* Returns a tree (undirected graph) that is constructed using only "tight"
|
||||
* edges.
|
||||
*/
|
||||
function feasibleTree(g) {
|
||||
var t = new Graph({ directed: false });
|
||||
|
||||
// Choose arbitrary node from which to start our tree
|
||||
var start = g.nodes()[0];
|
||||
var size = g.nodeCount();
|
||||
t.setNode(start, {});
|
||||
|
||||
var edge, delta;
|
||||
while (tightTree(t, g) < size) {
|
||||
edge = findMinSlackEdge(t, g);
|
||||
delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
|
||||
shiftRanks(t, g, delta);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds a maximal tree of tight edges and returns the number of nodes in the
|
||||
* tree.
|
||||
*/
|
||||
function tightTree(t, g) {
|
||||
function dfs(v) {
|
||||
_.forEach(g.nodeEdges(v), function (e) {
|
||||
var edgeV = e.v,
|
||||
w = v === edgeV ? e.w : edgeV;
|
||||
if (!t.hasNode(w) && !slack(g, e)) {
|
||||
t.setNode(w, {});
|
||||
t.setEdge(v, w, {});
|
||||
dfs(w);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_.forEach(t.nodes(), dfs);
|
||||
return t.nodeCount();
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the edge with the smallest slack that is incident on tree and returns
|
||||
* it.
|
||||
*/
|
||||
function findMinSlackEdge(t, g) {
|
||||
return _.minBy(g.edges(), function (e) {
|
||||
if (t.hasNode(e.v) !== t.hasNode(e.w)) {
|
||||
return slack(g, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function shiftRanks(t, g, delta) {
|
||||
_.forEach(t.nodes(), function (v) {
|
||||
g.node(v).rank += delta;
|
||||
});
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/dagre/rank/index.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/dagre/rank/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function rank(g: any): void;
|
||||
52
node_modules/dagre-d3-es/src/dagre/rank/index.js
generated
vendored
Normal file
52
node_modules/dagre-d3-es/src/dagre/rank/index.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import { feasibleTree } from './feasible-tree.js';
|
||||
import { networkSimplex } from './network-simplex.js';
|
||||
import { longestPath } from './util.js';
|
||||
|
||||
export { rank };
|
||||
|
||||
/*
|
||||
* Assigns a rank to each node in the input graph that respects the "minlen"
|
||||
* constraint specified on edges between nodes.
|
||||
*
|
||||
* This basic structure is derived from Gansner, et al., "A Technique for
|
||||
* Drawing Directed Graphs."
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be a connected DAG
|
||||
* 2. Graph nodes must be objects
|
||||
* 3. Graph edges must have "weight" and "minlen" attributes
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Graph nodes will have a "rank" attribute based on the results of the
|
||||
* algorithm. Ranks can start at any index (including negative), we'll
|
||||
* fix them up later.
|
||||
*/
|
||||
function rank(g) {
|
||||
switch (g.graph().ranker) {
|
||||
case 'network-simplex':
|
||||
networkSimplexRanker(g);
|
||||
break;
|
||||
case 'tight-tree':
|
||||
tightTreeRanker(g);
|
||||
break;
|
||||
case 'longest-path':
|
||||
longestPathRanker(g);
|
||||
break;
|
||||
default:
|
||||
networkSimplexRanker(g);
|
||||
}
|
||||
}
|
||||
|
||||
// A fast and simple ranker, but results are far from optimal.
|
||||
var longestPathRanker = longestPath;
|
||||
|
||||
function tightTreeRanker(g) {
|
||||
longestPath(g);
|
||||
feasibleTree(g);
|
||||
}
|
||||
|
||||
function networkSimplexRanker(g) {
|
||||
networkSimplex(g);
|
||||
}
|
||||
16
node_modules/dagre-d3-es/src/dagre/rank/network-simplex.d.ts
generated
vendored
Normal file
16
node_modules/dagre-d3-es/src/dagre/rank/network-simplex.d.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export function networkSimplex(g: any): void;
|
||||
export namespace networkSimplex {
|
||||
export { initLowLimValues };
|
||||
export { initCutValues };
|
||||
export { calcCutValue };
|
||||
export { leaveEdge };
|
||||
export { enterEdge };
|
||||
export { exchangeEdges };
|
||||
}
|
||||
declare function initLowLimValues(tree: any, root: any, ...args: any[]): void;
|
||||
declare function initCutValues(t: any, g: any): void;
|
||||
declare function calcCutValue(t: any, g: any, child: any): number;
|
||||
declare function leaveEdge(tree: any): any;
|
||||
declare function enterEdge(t: any, g: any, edge: any): any;
|
||||
declare function exchangeEdges(t: any, g: any, e: any, f: any): void;
|
||||
export {};
|
||||
236
node_modules/dagre-d3-es/src/dagre/rank/network-simplex.js
generated
vendored
Normal file
236
node_modules/dagre-d3-es/src/dagre/rank/network-simplex.js
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import * as alg from '../../graphlib/alg/index.js';
|
||||
import { simplify } from '../util.js';
|
||||
import { feasibleTree } from './feasible-tree.js';
|
||||
import { longestPath, slack } from './util.js';
|
||||
|
||||
export { networkSimplex };
|
||||
|
||||
// Expose some internals for testing purposes
|
||||
networkSimplex.initLowLimValues = initLowLimValues;
|
||||
networkSimplex.initCutValues = initCutValues;
|
||||
networkSimplex.calcCutValue = calcCutValue;
|
||||
networkSimplex.leaveEdge = leaveEdge;
|
||||
networkSimplex.enterEdge = enterEdge;
|
||||
networkSimplex.exchangeEdges = exchangeEdges;
|
||||
|
||||
/*
|
||||
* The network simplex algorithm assigns ranks to each node in the input graph
|
||||
* and iteratively improves the ranking to reduce the length of edges.
|
||||
*
|
||||
* Preconditions:
|
||||
*
|
||||
* 1. The input graph must be a DAG.
|
||||
* 2. All nodes in the graph must have an object value.
|
||||
* 3. All edges in the graph must have "minlen" and "weight" attributes.
|
||||
*
|
||||
* Postconditions:
|
||||
*
|
||||
* 1. All nodes in the graph will have an assigned "rank" attribute that has
|
||||
* been optimized by the network simplex algorithm. Ranks start at 0.
|
||||
*
|
||||
*
|
||||
* A rough sketch of the algorithm is as follows:
|
||||
*
|
||||
* 1. Assign initial ranks to each node. We use the longest path algorithm,
|
||||
* which assigns ranks to the lowest position possible. In general this
|
||||
* leads to very wide bottom ranks and unnecessarily long edges.
|
||||
* 2. Construct a feasible tight tree. A tight tree is one such that all
|
||||
* edges in the tree have no slack (difference between length of edge
|
||||
* and minlen for the edge). This by itself greatly improves the assigned
|
||||
* rankings by shorting edges.
|
||||
* 3. Iteratively find edges that have negative cut values. Generally a
|
||||
* negative cut value indicates that the edge could be removed and a new
|
||||
* tree edge could be added to produce a more compact graph.
|
||||
*
|
||||
* Much of the algorithms here are derived from Gansner, et al., "A Technique
|
||||
* for Drawing Directed Graphs." The structure of the file roughly follows the
|
||||
* structure of the overall algorithm.
|
||||
*/
|
||||
function networkSimplex(g) {
|
||||
g = simplify(g);
|
||||
longestPath(g);
|
||||
var t = feasibleTree(g);
|
||||
initLowLimValues(t);
|
||||
initCutValues(t, g);
|
||||
|
||||
var e, f;
|
||||
while ((e = leaveEdge(t))) {
|
||||
f = enterEdge(t, g, e);
|
||||
exchangeEdges(t, g, e, f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes cut values for all edges in the tree.
|
||||
*/
|
||||
function initCutValues(t, g) {
|
||||
var vs = alg.postorder(t, t.nodes());
|
||||
vs = vs.slice(0, vs.length - 1);
|
||||
_.forEach(vs, function (v) {
|
||||
assignCutValue(t, g, v);
|
||||
});
|
||||
}
|
||||
|
||||
function assignCutValue(t, g, child) {
|
||||
var childLab = t.node(child);
|
||||
var parent = childLab.parent;
|
||||
t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the tight tree, its graph, and a child in the graph calculate and
|
||||
* return the cut value for the edge between the child and its parent.
|
||||
*/
|
||||
function calcCutValue(t, g, child) {
|
||||
var childLab = t.node(child);
|
||||
var parent = childLab.parent;
|
||||
// True if the child is on the tail end of the edge in the directed graph
|
||||
var childIsTail = true;
|
||||
// The graph's view of the tree edge we're inspecting
|
||||
var graphEdge = g.edge(child, parent);
|
||||
// The accumulated cut value for the edge between this node and its parent
|
||||
var cutValue = 0;
|
||||
|
||||
if (!graphEdge) {
|
||||
childIsTail = false;
|
||||
graphEdge = g.edge(parent, child);
|
||||
}
|
||||
|
||||
cutValue = graphEdge.weight;
|
||||
|
||||
_.forEach(g.nodeEdges(child), function (e) {
|
||||
var isOutEdge = e.v === child,
|
||||
other = isOutEdge ? e.w : e.v;
|
||||
|
||||
if (other !== parent) {
|
||||
var pointsToHead = isOutEdge === childIsTail,
|
||||
otherWeight = g.edge(e).weight;
|
||||
|
||||
cutValue += pointsToHead ? otherWeight : -otherWeight;
|
||||
if (isTreeEdge(t, child, other)) {
|
||||
var otherCutValue = t.edge(child, other).cutvalue;
|
||||
cutValue += pointsToHead ? -otherCutValue : otherCutValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return cutValue;
|
||||
}
|
||||
|
||||
function initLowLimValues(tree, root) {
|
||||
if (arguments.length < 2) {
|
||||
root = tree.nodes()[0];
|
||||
}
|
||||
dfsAssignLowLim(tree, {}, 1, root);
|
||||
}
|
||||
|
||||
function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
|
||||
var low = nextLim;
|
||||
var label = tree.node(v);
|
||||
|
||||
visited[v] = true;
|
||||
_.forEach(tree.neighbors(v), function (w) {
|
||||
if (!_.has(visited, w)) {
|
||||
nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
|
||||
}
|
||||
});
|
||||
|
||||
label.low = low;
|
||||
label.lim = nextLim++;
|
||||
if (parent) {
|
||||
label.parent = parent;
|
||||
} else {
|
||||
// TODO should be able to remove this when we incrementally update low lim
|
||||
delete label.parent;
|
||||
}
|
||||
|
||||
return nextLim;
|
||||
}
|
||||
|
||||
function leaveEdge(tree) {
|
||||
return _.find(tree.edges(), function (e) {
|
||||
return tree.edge(e).cutvalue < 0;
|
||||
});
|
||||
}
|
||||
|
||||
function enterEdge(t, g, edge) {
|
||||
var v = edge.v;
|
||||
var w = edge.w;
|
||||
|
||||
// For the rest of this function we assume that v is the tail and w is the
|
||||
// head, so if we don't have this edge in the graph we should flip it to
|
||||
// match the correct orientation.
|
||||
if (!g.hasEdge(v, w)) {
|
||||
v = edge.w;
|
||||
w = edge.v;
|
||||
}
|
||||
|
||||
var vLabel = t.node(v);
|
||||
var wLabel = t.node(w);
|
||||
var tailLabel = vLabel;
|
||||
var flip = false;
|
||||
|
||||
// If the root is in the tail of the edge then we need to flip the logic that
|
||||
// checks for the head and tail nodes in the candidates function below.
|
||||
if (vLabel.lim > wLabel.lim) {
|
||||
tailLabel = wLabel;
|
||||
flip = true;
|
||||
}
|
||||
|
||||
var candidates = _.filter(g.edges(), function (edge) {
|
||||
return (
|
||||
flip === isDescendant(t, t.node(edge.v), tailLabel) &&
|
||||
flip !== isDescendant(t, t.node(edge.w), tailLabel)
|
||||
);
|
||||
});
|
||||
|
||||
return _.minBy(candidates, function (edge) {
|
||||
return slack(g, edge);
|
||||
});
|
||||
}
|
||||
|
||||
function exchangeEdges(t, g, e, f) {
|
||||
var v = e.v;
|
||||
var w = e.w;
|
||||
t.removeEdge(v, w);
|
||||
t.setEdge(f.v, f.w, {});
|
||||
initLowLimValues(t);
|
||||
initCutValues(t, g);
|
||||
updateRanks(t, g);
|
||||
}
|
||||
|
||||
function updateRanks(t, g) {
|
||||
var root = _.find(t.nodes(), function (v) {
|
||||
return !g.node(v).parent;
|
||||
});
|
||||
var vs = alg.preorder(t, root);
|
||||
vs = vs.slice(1);
|
||||
_.forEach(vs, function (v) {
|
||||
var parent = t.node(v).parent,
|
||||
edge = g.edge(v, parent),
|
||||
flipped = false;
|
||||
|
||||
if (!edge) {
|
||||
edge = g.edge(parent, v);
|
||||
flipped = true;
|
||||
}
|
||||
|
||||
g.node(v).rank = g.node(parent).rank + (flipped ? edge.minlen : -edge.minlen);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the edge is in the tree.
|
||||
*/
|
||||
function isTreeEdge(tree, u, v) {
|
||||
return tree.hasEdge(u, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the specified node is descendant of the root node per the
|
||||
* assigned low and lim attributes in the tree.
|
||||
*/
|
||||
function isDescendant(tree, vLabel, rootLabel) {
|
||||
return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
|
||||
}
|
||||
2
node_modules/dagre-d3-es/src/dagre/rank/util.d.ts
generated
vendored
Normal file
2
node_modules/dagre-d3-es/src/dagre/rank/util.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export function longestPath(g: any): void;
|
||||
export function slack(g: any, e: any): number;
|
||||
63
node_modules/dagre-d3-es/src/dagre/rank/util.js
generated
vendored
Normal file
63
node_modules/dagre-d3-es/src/dagre/rank/util.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { longestPath, slack };
|
||||
|
||||
/*
|
||||
* Initializes ranks for the input graph using the longest path algorithm. This
|
||||
* algorithm scales well and is fast in practice, it yields rather poor
|
||||
* solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
|
||||
* ranks wide and leaving edges longer than necessary. However, due to its
|
||||
* speed, this algorithm is good for getting an initial ranking that can be fed
|
||||
* into other algorithms.
|
||||
*
|
||||
* This algorithm does not normalize layers because it will be used by other
|
||||
* algorithms in most cases. If using this algorithm directly, be sure to
|
||||
* run normalize at the end.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph is a DAG.
|
||||
* 2. Input graph node labels can be assigned properties.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Each node will be assign an (unnormalized) "rank" property.
|
||||
*/
|
||||
function longestPath(g) {
|
||||
var visited = {};
|
||||
|
||||
function dfs(v) {
|
||||
var label = g.node(v);
|
||||
if (_.has(visited, v)) {
|
||||
return label.rank;
|
||||
}
|
||||
visited[v] = true;
|
||||
|
||||
var rank = _.min(
|
||||
_.map(g.outEdges(v), function (e) {
|
||||
return dfs(e.w) - g.edge(e).minlen;
|
||||
})
|
||||
);
|
||||
|
||||
if (
|
||||
rank === Number.POSITIVE_INFINITY || // return value of _.map([]) for Lodash 3
|
||||
rank === undefined || // return value of _.map([]) for Lodash 4
|
||||
rank === null
|
||||
) {
|
||||
// return value of _.map([null])
|
||||
rank = 0;
|
||||
}
|
||||
|
||||
return (label.rank = rank);
|
||||
}
|
||||
|
||||
_.forEach(g.sources(), dfs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the amount of slack for the given edge. The slack is defined as the
|
||||
* difference between the length of the edge and its minimum length.
|
||||
*/
|
||||
function slack(g, e) {
|
||||
return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen;
|
||||
}
|
||||
27
node_modules/dagre-d3-es/src/dagre/util.d.ts
generated
vendored
Normal file
27
node_modules/dagre-d3-es/src/dagre/util.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export function addDummyNode(g: any, type: any, attrs: any, name: any): any;
|
||||
export function simplify(g: any): Graph;
|
||||
export function asNonCompoundGraph(g: any): Graph;
|
||||
export function successorWeights(g: any): any;
|
||||
export function predecessorWeights(g: any): any;
|
||||
export function intersectRect(
|
||||
rect: any,
|
||||
point: any
|
||||
): {
|
||||
x: any;
|
||||
y: any;
|
||||
};
|
||||
export function buildLayerMatrix(g: any): any;
|
||||
export function normalizeRanks(g: any): void;
|
||||
export function removeEmptyRanks(g: any): void;
|
||||
export function addBorderNode(g: any, prefix: any, rank: any, order: any, ...args: any[]): any;
|
||||
export function maxRank(g: any): any;
|
||||
export function partition(
|
||||
collection: any,
|
||||
fn: any
|
||||
): {
|
||||
lhs: any[];
|
||||
rhs: any[];
|
||||
};
|
||||
export function time(name: any, fn: any): any;
|
||||
export function notime(name: any, fn: any): any;
|
||||
import { Graph } from '../graphlib/index.js';
|
||||
250
node_modules/dagre-d3-es/src/dagre/util.js
generated
vendored
Normal file
250
node_modules/dagre-d3-es/src/dagre/util.js
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
import * as _ from 'lodash-es';
|
||||
import { Graph } from '../graphlib/index.js';
|
||||
|
||||
export {
|
||||
addDummyNode,
|
||||
simplify,
|
||||
asNonCompoundGraph,
|
||||
successorWeights,
|
||||
predecessorWeights,
|
||||
intersectRect,
|
||||
buildLayerMatrix,
|
||||
normalizeRanks,
|
||||
removeEmptyRanks,
|
||||
addBorderNode,
|
||||
maxRank,
|
||||
partition,
|
||||
time,
|
||||
notime,
|
||||
};
|
||||
|
||||
/*
|
||||
* Adds a dummy node to the graph and return v.
|
||||
*/
|
||||
function addDummyNode(g, type, attrs, name) {
|
||||
var v;
|
||||
do {
|
||||
v = _.uniqueId(name);
|
||||
} while (g.hasNode(v));
|
||||
|
||||
attrs.dummy = type;
|
||||
g.setNode(v, attrs);
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new graph with only simple edges. Handles aggregation of data
|
||||
* associated with multi-edges.
|
||||
*/
|
||||
function simplify(g) {
|
||||
var simplified = new Graph().setGraph(g.graph());
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
simplified.setNode(v, g.node(v));
|
||||
});
|
||||
_.forEach(g.edges(), function (e) {
|
||||
var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 };
|
||||
var label = g.edge(e);
|
||||
simplified.setEdge(e.v, e.w, {
|
||||
weight: simpleLabel.weight + label.weight,
|
||||
minlen: Math.max(simpleLabel.minlen, label.minlen),
|
||||
});
|
||||
});
|
||||
return simplified;
|
||||
}
|
||||
|
||||
function asNonCompoundGraph(g) {
|
||||
var simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
if (!g.children(v).length) {
|
||||
simplified.setNode(v, g.node(v));
|
||||
}
|
||||
});
|
||||
_.forEach(g.edges(), function (e) {
|
||||
simplified.setEdge(e, g.edge(e));
|
||||
});
|
||||
return simplified;
|
||||
}
|
||||
|
||||
function successorWeights(g) {
|
||||
var weightMap = _.map(g.nodes(), function (v) {
|
||||
var sucs = {};
|
||||
_.forEach(g.outEdges(v), function (e) {
|
||||
sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
|
||||
});
|
||||
return sucs;
|
||||
});
|
||||
return _.zipObject(g.nodes(), weightMap);
|
||||
}
|
||||
|
||||
function predecessorWeights(g) {
|
||||
var weightMap = _.map(g.nodes(), function (v) {
|
||||
var preds = {};
|
||||
_.forEach(g.inEdges(v), function (e) {
|
||||
preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
|
||||
});
|
||||
return preds;
|
||||
});
|
||||
return _.zipObject(g.nodes(), weightMap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds where a line starting at point ({x, y}) would intersect a rectangle
|
||||
* ({x, y, width, height}) if it were pointing at the rectangle's center.
|
||||
*/
|
||||
function intersectRect(rect, point) {
|
||||
var x = rect.x;
|
||||
var y = rect.y;
|
||||
|
||||
// Rectangle intersection algorithm from:
|
||||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||||
var dx = point.x - x;
|
||||
var dy = point.y - y;
|
||||
var w = rect.width / 2;
|
||||
var h = rect.height / 2;
|
||||
|
||||
if (!dx && !dy) {
|
||||
throw new Error('Not possible to find intersection inside of the rectangle');
|
||||
}
|
||||
|
||||
var sx, sy;
|
||||
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
||||
// Intersection is top or bottom of rect.
|
||||
if (dy < 0) {
|
||||
h = -h;
|
||||
}
|
||||
sx = (h * dx) / dy;
|
||||
sy = h;
|
||||
} else {
|
||||
// Intersection is left or right of rect.
|
||||
if (dx < 0) {
|
||||
w = -w;
|
||||
}
|
||||
sx = w;
|
||||
sy = (w * dy) / dx;
|
||||
}
|
||||
|
||||
return { x: x + sx, y: y + sy };
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a DAG with each node assigned "rank" and "order" properties, this
|
||||
* function will produce a matrix with the ids of each node.
|
||||
*/
|
||||
function buildLayerMatrix(g) {
|
||||
var layering = _.map(_.range(maxRank(g) + 1), function () {
|
||||
return [];
|
||||
});
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
var rank = node.rank;
|
||||
if (!_.isUndefined(rank)) {
|
||||
layering[rank][node.order] = v;
|
||||
}
|
||||
});
|
||||
return layering;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjusts the ranks for all nodes in the graph such that all nodes v have
|
||||
* rank(v) >= 0 and at least one node w has rank(w) = 0.
|
||||
*/
|
||||
function normalizeRanks(g) {
|
||||
var min = _.min(
|
||||
_.map(g.nodes(), function (v) {
|
||||
return g.node(v).rank;
|
||||
})
|
||||
);
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var node = g.node(v);
|
||||
if (_.has(node, 'rank')) {
|
||||
node.rank -= min;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeEmptyRanks(g) {
|
||||
// Ranks may not start at 0, so we need to offset them
|
||||
var offset = _.min(
|
||||
_.map(g.nodes(), function (v) {
|
||||
return g.node(v).rank;
|
||||
})
|
||||
);
|
||||
|
||||
var layers = [];
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
var rank = g.node(v).rank - offset;
|
||||
if (!layers[rank]) {
|
||||
layers[rank] = [];
|
||||
}
|
||||
layers[rank].push(v);
|
||||
});
|
||||
|
||||
var delta = 0;
|
||||
var nodeRankFactor = g.graph().nodeRankFactor;
|
||||
_.forEach(layers, function (vs, i) {
|
||||
if (_.isUndefined(vs) && i % nodeRankFactor !== 0) {
|
||||
--delta;
|
||||
} else if (delta) {
|
||||
_.forEach(vs, function (v) {
|
||||
g.node(v).rank += delta;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addBorderNode(g, prefix, rank, order) {
|
||||
var node = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
if (arguments.length >= 4) {
|
||||
node.rank = rank;
|
||||
node.order = order;
|
||||
}
|
||||
return addDummyNode(g, 'border', node, prefix);
|
||||
}
|
||||
|
||||
function maxRank(g) {
|
||||
return _.max(
|
||||
_.map(g.nodes(), function (v) {
|
||||
var rank = g.node(v).rank;
|
||||
if (!_.isUndefined(rank)) {
|
||||
return rank;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Partition a collection into two groups: `lhs` and `rhs`. If the supplied
|
||||
* function returns true for an entry it goes into `lhs`. Otherwise it goes
|
||||
* into `rhs.
|
||||
*/
|
||||
function partition(collection, fn) {
|
||||
var result = { lhs: [], rhs: [] };
|
||||
_.forEach(collection, function (value) {
|
||||
if (fn(value)) {
|
||||
result.lhs.push(value);
|
||||
} else {
|
||||
result.rhs.push(value);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new function that wraps `fn` with a timer. The wrapper logs the
|
||||
* time it takes to execute the function.
|
||||
*/
|
||||
function time(name, fn) {
|
||||
var start = _.now();
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
console.log(name + ' time: ' + (_.now() - start) + 'ms');
|
||||
}
|
||||
}
|
||||
|
||||
function notime(name, fn) {
|
||||
return fn();
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/graphlib/alg/components.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/graphlib/alg/components.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function components(g: any): any[];
|
||||
27
node_modules/dagre-d3-es/src/graphlib/alg/components.js
generated
vendored
Normal file
27
node_modules/dagre-d3-es/src/graphlib/alg/components.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as _ from 'lodash-es';
|
||||
|
||||
export { components };
|
||||
|
||||
function components(g) {
|
||||
var visited = {};
|
||||
var cmpts = [];
|
||||
var cmpt;
|
||||
|
||||
function dfs(v) {
|
||||
if (_.has(visited, v)) return;
|
||||
visited[v] = true;
|
||||
cmpt.push(v);
|
||||
_.each(g.successors(v), dfs);
|
||||
_.each(g.predecessors(v), dfs);
|
||||
}
|
||||
|
||||
_.each(g.nodes(), function (v) {
|
||||
cmpt = [];
|
||||
dfs(v);
|
||||
if (cmpt.length) {
|
||||
cmpts.push(cmpt);
|
||||
}
|
||||
});
|
||||
|
||||
return cmpts;
|
||||
}
|
||||
1
node_modules/dagre-d3-es/src/graphlib/alg/dfs.d.ts
generated
vendored
Normal file
1
node_modules/dagre-d3-es/src/graphlib/alg/dfs.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export function dfs(g: any, vs: any, order: any): any[];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user