UNPKG

dc.graph

Version:

Graph visualizations integrated with crossfilter and dc.js

1,330 lines 765 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cola = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); __export(require("./src/adaptor")); __export(require("./src/d3adaptor")); __export(require("./src/descent")); __export(require("./src/geom")); __export(require("./src/gridrouter")); __export(require("./src/handledisconnected")); __export(require("./src/layout")); __export(require("./src/layout3d")); __export(require("./src/linklengths")); __export(require("./src/powergraph")); __export(require("./src/pqueue")); __export(require("./src/rbtree")); __export(require("./src/rectangle")); __export(require("./src/shortestpaths")); __export(require("./src/vpsc")); __export(require("./src/batch")); },{"./src/adaptor":2,"./src/batch":3,"./src/d3adaptor":4,"./src/descent":7,"./src/geom":8,"./src/gridrouter":9,"./src/handledisconnected":10,"./src/layout":11,"./src/layout3d":12,"./src/linklengths":13,"./src/powergraph":14,"./src/pqueue":15,"./src/rbtree":16,"./src/rectangle":17,"./src/shortestpaths":18,"./src/vpsc":19}],2:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var layout_1 = require("./layout"); var LayoutAdaptor = (function (_super) { __extends(LayoutAdaptor, _super); function LayoutAdaptor(options) { var _this = _super.call(this) || this; var self = _this; var o = options; if (o.trigger) { _this.trigger = o.trigger; } if (o.kick) { _this.kick = o.kick; } if (o.drag) { _this.drag = o.drag; } if (o.on) { _this.on = o.on; } _this.dragstart = _this.dragStart = layout_1.Layout.dragStart; _this.dragend = _this.dragEnd = layout_1.Layout.dragEnd; return _this; } LayoutAdaptor.prototype.trigger = function (e) { }; ; LayoutAdaptor.prototype.kick = function () { }; ; LayoutAdaptor.prototype.drag = function () { }; ; LayoutAdaptor.prototype.on = function (eventType, listener) { return this; }; ; return LayoutAdaptor; }(layout_1.Layout)); exports.LayoutAdaptor = LayoutAdaptor; function adaptor(options) { return new LayoutAdaptor(options); } exports.adaptor = adaptor; },{"./layout":11}],3:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var layout_1 = require("./layout"); var gridrouter_1 = require("./gridrouter"); function gridify(pgLayout, nudgeGap, margin, groupMargin) { pgLayout.cola.start(0, 0, 0, 10, false); var gridrouter = route(pgLayout.cola.nodes(), pgLayout.cola.groups(), margin, groupMargin); return gridrouter.routeEdges(pgLayout.powerGraph.powerEdges, nudgeGap, function (e) { return e.source.routerNode.id; }, function (e) { return e.target.routerNode.id; }); } exports.gridify = gridify; function route(nodes, groups, margin, groupMargin) { nodes.forEach(function (d) { d.routerNode = { name: d.name, bounds: d.bounds.inflate(-margin) }; }); groups.forEach(function (d) { d.routerNode = { bounds: d.bounds.inflate(-groupMargin), children: (typeof d.groups !== 'undefined' ? d.groups.map(function (c) { return nodes.length + c.id; }) : []) .concat(typeof d.leaves !== 'undefined' ? d.leaves.map(function (c) { return c.index; }) : []) }; }); var gridRouterNodes = nodes.concat(groups).map(function (d, i) { d.routerNode.id = i; return d.routerNode; }); return new gridrouter_1.GridRouter(gridRouterNodes, { getChildren: function (v) { return v.children; }, getBounds: function (v) { return v.bounds; } }, margin - groupMargin); } function powerGraphGridLayout(graph, size, grouppadding) { var powerGraph; graph.nodes.forEach(function (v, i) { return v.index = i; }); new layout_1.Layout() .avoidOverlaps(false) .nodes(graph.nodes) .links(graph.links) .powerGraphGroups(function (d) { powerGraph = d; powerGraph.groups.forEach(function (v) { return v.padding = grouppadding; }); }); var n = graph.nodes.length; var edges = []; var vs = graph.nodes.slice(0); vs.forEach(function (v, i) { return v.index = i; }); powerGraph.groups.forEach(function (g) { var sourceInd = g.index = g.id + n; vs.push(g); if (typeof g.leaves !== 'undefined') g.leaves.forEach(function (v) { return edges.push({ source: sourceInd, target: v.index }); }); if (typeof g.groups !== 'undefined') g.groups.forEach(function (gg) { return edges.push({ source: sourceInd, target: gg.id + n }); }); }); powerGraph.powerEdges.forEach(function (e) { edges.push({ source: e.source.index, target: e.target.index }); }); new layout_1.Layout() .size(size) .nodes(vs) .links(edges) .avoidOverlaps(false) .linkDistance(30) .symmetricDiffLinkLengths(5) .convergenceThreshold(1e-4) .start(100, 0, 0, 0, false); return { cola: new layout_1.Layout() .convergenceThreshold(1e-3) .size(size) .avoidOverlaps(true) .nodes(graph.nodes) .links(graph.links) .groupCompactness(1e-4) .linkDistance(30) .symmetricDiffLinkLengths(5) .powerGraphGroups(function (d) { powerGraph = d; powerGraph.groups.forEach(function (v) { v.padding = grouppadding; }); }).start(50, 0, 100, 0, false), powerGraph: powerGraph }; } exports.powerGraphGridLayout = powerGraphGridLayout; },{"./gridrouter":9,"./layout":11}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var d3v3 = require("./d3v3adaptor"); var d3v4 = require("./d3v4adaptor"); ; function d3adaptor(d3Context) { if (!d3Context || isD3V3(d3Context)) { return new d3v3.D3StyleLayoutAdaptor(); } return new d3v4.D3StyleLayoutAdaptor(d3Context); } exports.d3adaptor = d3adaptor; function isD3V3(d3Context) { var v3exp = /^3\./; return d3Context.version && d3Context.version.match(v3exp) !== null; } },{"./d3v3adaptor":5,"./d3v4adaptor":6}],5:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var layout_1 = require("./layout"); var D3StyleLayoutAdaptor = (function (_super) { __extends(D3StyleLayoutAdaptor, _super); function D3StyleLayoutAdaptor() { var _this = _super.call(this) || this; _this.event = d3.dispatch(layout_1.EventType[layout_1.EventType.start], layout_1.EventType[layout_1.EventType.tick], layout_1.EventType[layout_1.EventType.end]); var d3layout = _this; var drag; _this.drag = function () { if (!drag) { var drag = d3.behavior.drag() .origin(layout_1.Layout.dragOrigin) .on("dragstart.d3adaptor", layout_1.Layout.dragStart) .on("drag.d3adaptor", function (d) { layout_1.Layout.drag(d, d3.event); d3layout.resume(); }) .on("dragend.d3adaptor", layout_1.Layout.dragEnd); } if (!arguments.length) return drag; this .call(drag); }; return _this; } D3StyleLayoutAdaptor.prototype.trigger = function (e) { var d3event = { type: layout_1.EventType[e.type], alpha: e.alpha, stress: e.stress }; this.event[d3event.type](d3event); }; D3StyleLayoutAdaptor.prototype.kick = function () { var _this = this; d3.timer(function () { return _super.prototype.tick.call(_this); }); }; D3StyleLayoutAdaptor.prototype.on = function (eventType, listener) { if (typeof eventType === 'string') { this.event.on(eventType, listener); } else { this.event.on(layout_1.EventType[eventType], listener); } return this; }; return D3StyleLayoutAdaptor; }(layout_1.Layout)); exports.D3StyleLayoutAdaptor = D3StyleLayoutAdaptor; function d3adaptor() { return new D3StyleLayoutAdaptor(); } exports.d3adaptor = d3adaptor; },{"./layout":11}],6:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var layout_1 = require("./layout"); var D3StyleLayoutAdaptor = (function (_super) { __extends(D3StyleLayoutAdaptor, _super); function D3StyleLayoutAdaptor(d3Context) { var _this = _super.call(this) || this; _this.d3Context = d3Context; _this.event = d3Context.dispatch(layout_1.EventType[layout_1.EventType.start], layout_1.EventType[layout_1.EventType.tick], layout_1.EventType[layout_1.EventType.end]); var d3layout = _this; var drag; _this.drag = function () { if (!drag) { var drag = d3Context.drag() .subject(layout_1.Layout.dragOrigin) .on("start.d3adaptor", layout_1.Layout.dragStart) .on("drag.d3adaptor", function (d) { layout_1.Layout.drag(d, d3Context.event); d3layout.resume(); }) .on("end.d3adaptor", layout_1.Layout.dragEnd); } if (!arguments.length) return drag; arguments[0].call(drag); }; return _this; } D3StyleLayoutAdaptor.prototype.trigger = function (e) { var d3event = { type: layout_1.EventType[e.type], alpha: e.alpha, stress: e.stress }; this.event.call(d3event.type, d3event); }; D3StyleLayoutAdaptor.prototype.kick = function () { var _this = this; var t = this.d3Context.timer(function () { return _super.prototype.tick.call(_this) && t.stop(); }); }; D3StyleLayoutAdaptor.prototype.on = function (eventType, listener) { if (typeof eventType === 'string') { this.event.on(eventType, listener); } else { this.event.on(layout_1.EventType[eventType], listener); } return this; }; return D3StyleLayoutAdaptor; }(layout_1.Layout)); exports.D3StyleLayoutAdaptor = D3StyleLayoutAdaptor; },{"./layout":11}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Locks = (function () { function Locks() { this.locks = {}; } Locks.prototype.add = function (id, x) { this.locks[id] = x; }; Locks.prototype.clear = function () { this.locks = {}; }; Locks.prototype.isEmpty = function () { for (var l in this.locks) return false; return true; }; Locks.prototype.apply = function (f) { for (var l in this.locks) { f(Number(l), this.locks[l]); } }; return Locks; }()); exports.Locks = Locks; var Descent = (function () { function Descent(x, D, G) { if (G === void 0) { G = null; } this.D = D; this.G = G; this.threshold = 0.0001; this.numGridSnapNodes = 0; this.snapGridSize = 100; this.snapStrength = 1000; this.scaleSnapByMaxH = false; this.random = new PseudoRandom(); this.project = null; this.x = x; this.k = x.length; var n = this.n = x[0].length; this.H = new Array(this.k); this.g = new Array(this.k); this.Hd = new Array(this.k); this.a = new Array(this.k); this.b = new Array(this.k); this.c = new Array(this.k); this.d = new Array(this.k); this.e = new Array(this.k); this.ia = new Array(this.k); this.ib = new Array(this.k); this.xtmp = new Array(this.k); this.locks = new Locks(); this.minD = Number.MAX_VALUE; var i = n, j; while (i--) { j = n; while (--j > i) { var d = D[i][j]; if (d > 0 && d < this.minD) { this.minD = d; } } } if (this.minD === Number.MAX_VALUE) this.minD = 1; i = this.k; while (i--) { this.g[i] = new Array(n); this.H[i] = new Array(n); j = n; while (j--) { this.H[i][j] = new Array(n); } this.Hd[i] = new Array(n); this.a[i] = new Array(n); this.b[i] = new Array(n); this.c[i] = new Array(n); this.d[i] = new Array(n); this.e[i] = new Array(n); this.ia[i] = new Array(n); this.ib[i] = new Array(n); this.xtmp[i] = new Array(n); } } Descent.createSquareMatrix = function (n, f) { var M = new Array(n); for (var i = 0; i < n; ++i) { M[i] = new Array(n); for (var j = 0; j < n; ++j) { M[i][j] = f(i, j); } } return M; }; Descent.prototype.offsetDir = function () { var _this = this; var u = new Array(this.k); var l = 0; for (var i = 0; i < this.k; ++i) { var x = u[i] = this.random.getNextBetween(0.01, 1) - 0.5; l += x * x; } l = Math.sqrt(l); return u.map(function (x) { return x *= _this.minD / l; }); }; Descent.prototype.computeDerivatives = function (x) { var _this = this; var n = this.n; if (n < 1) return; var i; var d = new Array(this.k); var d2 = new Array(this.k); var Huu = new Array(this.k); var maxH = 0; for (var u = 0; u < n; ++u) { for (i = 0; i < this.k; ++i) Huu[i] = this.g[i][u] = 0; for (var v = 0; v < n; ++v) { if (u === v) continue; var maxDisplaces = n; while (maxDisplaces--) { var sd2 = 0; for (i = 0; i < this.k; ++i) { var dx = d[i] = x[i][u] - x[i][v]; sd2 += d2[i] = dx * dx; } if (sd2 > 1e-9) break; var rd = this.offsetDir(); for (i = 0; i < this.k; ++i) x[i][v] += rd[i]; } var l = Math.sqrt(sd2); var D = this.D[u][v]; var weight = this.G != null ? this.G[u][v] : 1; if (weight > 1 && l > D || !isFinite(D)) { for (i = 0; i < this.k; ++i) this.H[i][u][v] = 0; continue; } if (weight > 1) { weight = 1; } var D2 = D * D; var gs = 2 * weight * (l - D) / (D2 * l); var l3 = l * l * l; var hs = 2 * -weight / (D2 * l3); if (!isFinite(gs)) console.log(gs); for (i = 0; i < this.k; ++i) { this.g[i][u] += d[i] * gs; Huu[i] -= this.H[i][u][v] = hs * (l3 + D * (d2[i] - sd2) + l * sd2); } } for (i = 0; i < this.k; ++i) maxH = Math.max(maxH, this.H[i][u][u] = Huu[i]); } var r = this.snapGridSize / 2; var g = this.snapGridSize; var w = this.snapStrength; var k = w / (r * r); var numNodes = this.numGridSnapNodes; for (var u = 0; u < numNodes; ++u) { for (i = 0; i < this.k; ++i) { var xiu = this.x[i][u]; var m = xiu / g; var f = m % 1; var q = m - f; var a = Math.abs(f); var dx = (a <= 0.5) ? xiu - q * g : (xiu > 0) ? xiu - (q + 1) * g : xiu - (q - 1) * g; if (-r < dx && dx <= r) { if (this.scaleSnapByMaxH) { this.g[i][u] += maxH * k * dx; this.H[i][u][u] += maxH * k; } else { this.g[i][u] += k * dx; this.H[i][u][u] += k; } } } } if (!this.locks.isEmpty()) { this.locks.apply(function (u, p) { for (i = 0; i < _this.k; ++i) { _this.H[i][u][u] += maxH; _this.g[i][u] -= maxH * (p[i] - x[i][u]); } }); } }; Descent.dotProd = function (a, b) { var x = 0, i = a.length; while (i--) x += a[i] * b[i]; return x; }; Descent.rightMultiply = function (m, v, r) { var i = m.length; while (i--) r[i] = Descent.dotProd(m[i], v); }; Descent.prototype.computeStepSize = function (d) { var numerator = 0, denominator = 0; for (var i = 0; i < this.k; ++i) { numerator += Descent.dotProd(this.g[i], d[i]); Descent.rightMultiply(this.H[i], d[i], this.Hd[i]); denominator += Descent.dotProd(d[i], this.Hd[i]); } if (denominator === 0 || !isFinite(denominator)) return 0; return 1 * numerator / denominator; }; Descent.prototype.reduceStress = function () { this.computeDerivatives(this.x); var alpha = this.computeStepSize(this.g); for (var i = 0; i < this.k; ++i) { this.takeDescentStep(this.x[i], this.g[i], alpha); } return this.computeStress(); }; Descent.copy = function (a, b) { var m = a.length, n = b[0].length; for (var i = 0; i < m; ++i) { for (var j = 0; j < n; ++j) { b[i][j] = a[i][j]; } } }; Descent.prototype.stepAndProject = function (x0, r, d, stepSize) { Descent.copy(x0, r); this.takeDescentStep(r[0], d[0], stepSize); if (this.project) this.project[0](x0[0], x0[1], r[0]); this.takeDescentStep(r[1], d[1], stepSize); if (this.project) this.project[1](r[0], x0[1], r[1]); for (var i = 2; i < this.k; i++) this.takeDescentStep(r[i], d[i], stepSize); }; Descent.mApply = function (m, n, f) { var i = m; while (i-- > 0) { var j = n; while (j-- > 0) f(i, j); } }; Descent.prototype.matrixApply = function (f) { Descent.mApply(this.k, this.n, f); }; Descent.prototype.computeNextPosition = function (x0, r) { var _this = this; this.computeDerivatives(x0); var alpha = this.computeStepSize(this.g); this.stepAndProject(x0, r, this.g, alpha); if (this.project) { this.matrixApply(function (i, j) { return _this.e[i][j] = x0[i][j] - r[i][j]; }); var beta = this.computeStepSize(this.e); beta = Math.max(0.2, Math.min(beta, 1)); this.stepAndProject(x0, r, this.e, beta); } }; Descent.prototype.run = function (iterations) { var stress = Number.MAX_VALUE, converged = false; while (!converged && iterations-- > 0) { var s = this.rungeKutta(); converged = Math.abs(stress / s - 1) < this.threshold; stress = s; } return stress; }; Descent.prototype.rungeKutta = function () { var _this = this; this.computeNextPosition(this.x, this.a); Descent.mid(this.x, this.a, this.ia); this.computeNextPosition(this.ia, this.b); Descent.mid(this.x, this.b, this.ib); this.computeNextPosition(this.ib, this.c); this.computeNextPosition(this.c, this.d); var disp = 0; this.matrixApply(function (i, j) { var x = (_this.a[i][j] + 2.0 * _this.b[i][j] + 2.0 * _this.c[i][j] + _this.d[i][j]) / 6.0, d = _this.x[i][j] - x; disp += d * d; _this.x[i][j] = x; }); return disp; }; Descent.mid = function (a, b, m) { Descent.mApply(a.length, a[0].length, function (i, j) { return m[i][j] = a[i][j] + (b[i][j] - a[i][j]) / 2.0; }); }; Descent.prototype.takeDescentStep = function (x, d, stepSize) { for (var i = 0; i < this.n; ++i) { x[i] = x[i] - stepSize * d[i]; } }; Descent.prototype.computeStress = function () { var stress = 0; for (var u = 0, nMinus1 = this.n - 1; u < nMinus1; ++u) { for (var v = u + 1, n = this.n; v < n; ++v) { var l = 0; for (var i = 0; i < this.k; ++i) { var dx = this.x[i][u] - this.x[i][v]; l += dx * dx; } l = Math.sqrt(l); var d = this.D[u][v]; if (!isFinite(d)) continue; var rl = d - l; var d2 = d * d; stress += rl * rl / d2; } } return stress; }; Descent.zeroDistance = 1e-10; return Descent; }()); exports.Descent = Descent; var PseudoRandom = (function () { function PseudoRandom(seed) { if (seed === void 0) { seed = 1; } this.seed = seed; this.a = 214013; this.c = 2531011; this.m = 2147483648; this.range = 32767; } PseudoRandom.prototype.getNext = function () { this.seed = (this.seed * this.a + this.c) % this.m; return (this.seed >> 16) / this.range; }; PseudoRandom.prototype.getNextBetween = function (min, max) { return min + this.getNext() * (max - min); }; return PseudoRandom; }()); exports.PseudoRandom = PseudoRandom; },{}],8:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var rectangle_1 = require("./rectangle"); var Point = (function () { function Point() { } return Point; }()); exports.Point = Point; var LineSegment = (function () { function LineSegment(x1, y1, x2, y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } return LineSegment; }()); exports.LineSegment = LineSegment; var PolyPoint = (function (_super) { __extends(PolyPoint, _super); function PolyPoint() { return _super !== null && _super.apply(this, arguments) || this; } return PolyPoint; }(Point)); exports.PolyPoint = PolyPoint; function isLeft(P0, P1, P2) { return (P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y); } exports.isLeft = isLeft; function above(p, vi, vj) { return isLeft(p, vi, vj) > 0; } function below(p, vi, vj) { return isLeft(p, vi, vj) < 0; } function ConvexHull(S) { var P = S.slice(0).sort(function (a, b) { return a.x !== b.x ? b.x - a.x : b.y - a.y; }); var n = S.length, i; var minmin = 0; var xmin = P[0].x; for (i = 1; i < n; ++i) { if (P[i].x !== xmin) break; } var minmax = i - 1; var H = []; H.push(P[minmin]); if (minmax === n - 1) { if (P[minmax].y !== P[minmin].y) H.push(P[minmax]); } else { var maxmin, maxmax = n - 1; var xmax = P[n - 1].x; for (i = n - 2; i >= 0; i--) if (P[i].x !== xmax) break; maxmin = i + 1; i = minmax; while (++i <= maxmin) { if (isLeft(P[minmin], P[maxmin], P[i]) >= 0 && i < maxmin) continue; while (H.length > 1) { if (isLeft(H[H.length - 2], H[H.length - 1], P[i]) > 0) break; else H.length -= 1; } if (i != minmin) H.push(P[i]); } if (maxmax != maxmin) H.push(P[maxmax]); var bot = H.length; i = maxmin; while (--i >= minmax) { if (isLeft(P[maxmax], P[minmax], P[i]) >= 0 && i > minmax) continue; while (H.length > bot) { if (isLeft(H[H.length - 2], H[H.length - 1], P[i]) > 0) break; else H.length -= 1; } if (i != minmin) H.push(P[i]); } } return H; } exports.ConvexHull = ConvexHull; function clockwiseRadialSweep(p, P, f) { P.slice(0).sort(function (a, b) { return Math.atan2(a.y - p.y, a.x - p.x) - Math.atan2(b.y - p.y, b.x - p.x); }).forEach(f); } exports.clockwiseRadialSweep = clockwiseRadialSweep; function nextPolyPoint(p, ps) { if (p.polyIndex === ps.length - 1) return ps[0]; return ps[p.polyIndex + 1]; } function prevPolyPoint(p, ps) { if (p.polyIndex === 0) return ps[ps.length - 1]; return ps[p.polyIndex - 1]; } function tangent_PointPolyC(P, V) { var Vclosed = V.slice(0); Vclosed.push(V[0]); return { rtan: Rtangent_PointPolyC(P, Vclosed), ltan: Ltangent_PointPolyC(P, Vclosed) }; } function Rtangent_PointPolyC(P, V) { var n = V.length - 1; var a, b, c; var upA, dnC; if (below(P, V[1], V[0]) && !above(P, V[n - 1], V[0])) return 0; for (a = 0, b = n;;) { if (b - a === 1) if (above(P, V[a], V[b])) return a; else return b; c = Math.floor((a + b) / 2); dnC = below(P, V[c + 1], V[c]); if (dnC && !above(P, V[c - 1], V[c])) return c; upA = above(P, V[a + 1], V[a]); if (upA) { if (dnC) b = c; else { if (above(P, V[a], V[c])) b = c; else a = c; } } else { if (!dnC) a = c; else { if (below(P, V[a], V[c])) b = c; else a = c; } } } } function Ltangent_PointPolyC(P, V) { var n = V.length - 1; var a, b, c; var dnA, dnC; if (above(P, V[n - 1], V[0]) && !below(P, V[1], V[0])) return 0; for (a = 0, b = n;;) { if (b - a === 1) if (below(P, V[a], V[b])) return a; else return b; c = Math.floor((a + b) / 2); dnC = below(P, V[c + 1], V[c]); if (above(P, V[c - 1], V[c]) && !dnC) return c; dnA = below(P, V[a + 1], V[a]); if (dnA) { if (!dnC) b = c; else { if (below(P, V[a], V[c])) b = c; else a = c; } } else { if (dnC) a = c; else { if (above(P, V[a], V[c])) b = c; else a = c; } } } } function tangent_PolyPolyC(V, W, t1, t2, cmp1, cmp2) { var ix1, ix2; ix1 = t1(W[0], V); ix2 = t2(V[ix1], W); var done = false; while (!done) { done = true; while (true) { if (ix1 === V.length - 1) ix1 = 0; if (cmp1(W[ix2], V[ix1], V[ix1 + 1])) break; ++ix1; } while (true) { if (ix2 === 0) ix2 = W.length - 1; if (cmp2(V[ix1], W[ix2], W[ix2 - 1])) break; --ix2; done = false; } } return { t1: ix1, t2: ix2 }; } exports.tangent_PolyPolyC = tangent_PolyPolyC; function LRtangent_PolyPolyC(V, W) { var rl = RLtangent_PolyPolyC(W, V); return { t1: rl.t2, t2: rl.t1 }; } exports.LRtangent_PolyPolyC = LRtangent_PolyPolyC; function RLtangent_PolyPolyC(V, W) { return tangent_PolyPolyC(V, W, Rtangent_PointPolyC, Ltangent_PointPolyC, above, below); } exports.RLtangent_PolyPolyC = RLtangent_PolyPolyC; function LLtangent_PolyPolyC(V, W) { return tangent_PolyPolyC(V, W, Ltangent_PointPolyC, Ltangent_PointPolyC, below, below); } exports.LLtangent_PolyPolyC = LLtangent_PolyPolyC; function RRtangent_PolyPolyC(V, W) { return tangent_PolyPolyC(V, W, Rtangent_PointPolyC, Rtangent_PointPolyC, above, above); } exports.RRtangent_PolyPolyC = RRtangent_PolyPolyC; var BiTangent = (function () { function BiTangent(t1, t2) { this.t1 = t1; this.t2 = t2; } return BiTangent; }()); exports.BiTangent = BiTangent; var BiTangents = (function () { function BiTangents() { } return BiTangents; }()); exports.BiTangents = BiTangents; var TVGPoint = (function (_super) { __extends(TVGPoint, _super); function TVGPoint() { return _super !== null && _super.apply(this, arguments) || this; } return TVGPoint; }(Point)); exports.TVGPoint = TVGPoint; var VisibilityVertex = (function () { function VisibilityVertex(id, polyid, polyvertid, p) { this.id = id; this.polyid = polyid; this.polyvertid = polyvertid; this.p = p; p.vv = this; } return VisibilityVertex; }()); exports.VisibilityVertex = VisibilityVertex; var VisibilityEdge = (function () { function VisibilityEdge(source, target) { this.source = source; this.target = target; } VisibilityEdge.prototype.length = function () { var dx = this.source.p.x - this.target.p.x; var dy = this.source.p.y - this.target.p.y; return Math.sqrt(dx * dx + dy * dy); }; return VisibilityEdge; }()); exports.VisibilityEdge = VisibilityEdge; var TangentVisibilityGraph = (function () { function TangentVisibilityGraph(P, g0) { this.P = P; this.V = []; this.E = []; if (!g0) { var n = P.length; for (var i = 0; i < n; i++) { var p = P[i]; for (var j = 0; j < p.length; ++j) { var pj = p[j], vv = new VisibilityVertex(this.V.length, i, j, pj); this.V.push(vv); if (j > 0) this.E.push(new VisibilityEdge(p[j - 1].vv, vv)); } if (p.length > 1) this.E.push(new VisibilityEdge(p[0].vv, p[p.length - 1].vv)); } for (var i = 0; i < n - 1; i++) { var Pi = P[i]; for (var j = i + 1; j < n; j++) { var Pj = P[j], t = tangents(Pi, Pj); for (var q in t) { var c = t[q], source = Pi[c.t1], target = Pj[c.t2]; this.addEdgeIfVisible(source, target, i, j); } } } } else { this.V = g0.V.slice(0); this.E = g0.E.slice(0); } } TangentVisibilityGraph.prototype.addEdgeIfVisible = function (u, v, i1, i2) { if (!this.intersectsPolys(new LineSegment(u.x, u.y, v.x, v.y), i1, i2)) { this.E.push(new VisibilityEdge(u.vv, v.vv)); } }; TangentVisibilityGraph.prototype.addPoint = function (p, i1) { var n = this.P.length; this.V.push(new VisibilityVertex(this.V.length, n, 0, p)); for (var i = 0; i < n; ++i) { if (i === i1) continue; var poly = this.P[i], t = tangent_PointPolyC(p, poly); this.addEdgeIfVisible(p, poly[t.ltan], i1, i); this.addEdgeIfVisible(p, poly[t.rtan], i1, i); } return p.vv; }; TangentVisibilityGraph.prototype.intersectsPolys = function (l, i1, i2) { for (var i = 0, n = this.P.length; i < n; ++i) { if (i != i1 && i != i2 && intersects(l, this.P[i]).length > 0) { return true; } } return false; }; return TangentVisibilityGraph; }()); exports.TangentVisibilityGraph = TangentVisibilityGraph; function intersects(l, P) { var ints = []; for (var i = 1, n = P.length; i < n; ++i) { var int = rectangle_1.Rectangle.lineIntersection(l.x1, l.y1, l.x2, l.y2, P[i - 1].x, P[i - 1].y, P[i].x, P[i].y); if (int) ints.push(int); } return ints; } function tangents(V, W) { var m = V.length - 1, n = W.length - 1; var bt = new BiTangents(); for (var i = 0; i < m; ++i) { for (var j = 0; j < n; ++j) { var v1 = V[i == 0 ? m - 1 : i - 1]; var v2 = V[i]; var v3 = V[i + 1]; var w1 = W[j == 0 ? n - 1 : j - 1]; var w2 = W[j]; var w3 = W[j + 1]; var v1v2w2 = isLeft(v1, v2, w2); var v2w1w2 = isLeft(v2, w1, w2); var v2w2w3 = isLeft(v2, w2, w3); var w1w2v2 = isLeft(w1, w2, v2); var w2v1v2 = isLeft(w2, v1, v2); var w2v2v3 = isLeft(w2, v2, v3); if (v1v2w2 >= 0 && v2w1w2 >= 0 && v2w2w3 < 0 && w1w2v2 >= 0 && w2v1v2 >= 0 && w2v2v3 < 0) { bt.ll = new BiTangent(i, j); } else if (v1v2w2 <= 0 && v2w1w2 <= 0 && v2w2w3 > 0 && w1w2v2 <= 0 && w2v1v2 <= 0 && w2v2v3 > 0) { bt.rr = new BiTangent(i, j); } else if (v1v2w2 <= 0 && v2w1w2 > 0 && v2w2w3 <= 0 && w1w2v2 >= 0 && w2v1v2 < 0 && w2v2v3 >= 0) { bt.rl = new BiTangent(i, j); } else if (v1v2w2 >= 0 && v2w1w2 < 0 && v2w2w3 >= 0 && w1w2v2 <= 0 && w2v1v2 > 0 && w2v2v3 <= 0) { bt.lr = new BiTangent(i, j); } } } return bt; } exports.tangents = tangents; function isPointInsidePoly(p, poly) { for (var i = 1, n = poly.length; i < n; ++i) if (below(poly[i - 1], poly[i], p)) return false; return true; } function isAnyPInQ(p, q) { return !p.every(function (v) { return !isPointInsidePoly(v, q); }); } function polysOverlap(p, q) { if (isAnyPInQ(p, q)) return true; if (isAnyPInQ(q, p)) return true; for (var i = 1, n = p.length; i < n; ++i) { var v = p[i], u = p[i - 1]; if (intersects(new LineSegment(u.x, u.y, v.x, v.y), q).length > 0) return true; } return false; } exports.polysOverlap = polysOverlap; },{"./rectangle":17}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var rectangle_1 = require("./rectangle"); var vpsc_1 = require("./vpsc"); var shortestpaths_1 = require("./shortestpaths"); var NodeWrapper = (function () { function NodeWrapper(id, rect, children) { this.id = id; this.rect = rect; this.children = children; this.leaf = typeof children === 'undefined' || children.length === 0; } return NodeWrapper; }()); exports.NodeWrapper = NodeWrapper; var Vert = (function () { function Vert(id, x, y, node, line) { if (node === void 0) { node = null; } if (line === void 0) { line = null; } this.id = id; this.x = x; this.y = y; this.node = node; this.line = line; } return Vert; }()); exports.Vert = Vert; var LongestCommonSubsequence = (function () { function LongestCommonSubsequence(s, t) { this.s = s; this.t = t; var mf = LongestCommonSubsequence.findMatch(s, t); var tr = t.slice(0).reverse(); var mr = LongestCommonSubsequence.findMatch(s, tr); if (mf.length >= mr.length) { this.length = mf.length; this.si = mf.si; this.ti = mf.ti; this.reversed = false; } else { this.length = mr.length; this.si = mr.si; this.ti = t.length - mr.ti - mr.length; this.reversed = true; } } LongestCommonSubsequence.findMatch = function (s, t) { var m = s.length; var n = t.length; var match = { length: 0, si: -1, ti: -1 }; var l = new Array(m); for (var i = 0; i < m; i++) { l[i] = new Array(n); for (var j = 0; j < n; j++) if (s[i] === t[j]) { var v = l[i][j] = (i === 0 || j === 0) ? 1 : l[i - 1][j - 1] + 1; if (v > match.length) { match.length = v; match.si = i - v + 1; match.ti = j - v + 1; } ; } else l[i][j] = 0; } return match; }; LongestCommonSubsequence.prototype.getSequence = function () { return this.length >= 0 ? this.s.slice(this.si, this.si + this.length) : []; }; return LongestCommonSubsequence; }()); exports.LongestCommonSubsequence = LongestCommonSubsequence; var GridRouter = (function () { function GridRouter(originalnodes, accessor, groupPadding) { var _this = this; if (groupPadding === void 0) { groupPadding = 12; } this.originalnodes = originalnodes; this.groupPadding = groupPadding; this.leaves = null; this.nodes = originalnodes.map(function (v, i) { return new NodeWrapper(i, accessor.getBounds(v), accessor.getChildren(v)); }); this.leaves = this.nodes.filter(function (v) { return v.leaf; }); this.groups = this.nodes.filter(function (g) { return !g.leaf; }); this.cols = this.getGridLines('x'); this.rows = this.getGridLines('y'); this.groups.forEach(function (v) { return v.children.forEach(function (c) { return _this.nodes[c].parent = v; }); }); this.root = { children: [] }; this.nodes.forEach(function (v) { if (typeof v.parent === 'undefined') { v.parent = _this.root; _this.root.children.push(v.id); } v.ports = []; }); this.backToFront = this.nodes.slice(0); this.backToFront.sort(function (x, y) { return _this.getDepth(x) - _this.getDepth(y); }); var frontToBackGroups = this.backToFront.slice(0).reverse().filter(function (g) { return !g.leaf; }); frontToBackGroups.forEach(function (v) { var r = rectangle_1.Rectangle.empty(); v.children.forEach(function (c) { return r = r.union(_this.nodes[c].rect); }); v.rect = r.inflate(_this.groupPadding); }); var colMids = this.midPoints(this.cols.map(function (r) { return r.pos; })); var rowMids = this.midPoints(this.rows.map(function (r) { return r.pos; })); var rowx = colMids[0], rowX = colMids[colMids.length - 1]; var coly = rowMids[0], colY = rowMids[rowMids.length - 1]; var hlines = this.rows.map(function (r) { return ({ x1: rowx, x2: rowX, y1: r.pos, y2: r.pos }); }) .concat(rowMids.map(function (m) { return ({ x1: rowx, x2: rowX, y1: m, y2: m }); })); var vlines = this.cols.map(function (c) { return ({ x1: c.pos, x2: c.pos, y1: coly, y2: colY }); }) .concat(colMids.map(function (m) { return ({ x1: m, x2: m, y1: coly, y2: colY }); })); var lines = hlines.concat(vlines); lines.forEach(function (l) { return l.verts = []; }); this.verts = []; this.edges = []; hlines.forEach(function (h) { return vlines.forEach(function (v) { var p = new Vert(_this.verts.length, v.x1, h.y1); h.verts.push(p); v.verts.push(p); _this.verts.push(p); var i = _this.backToFront.length; while (i-- > 0) { var node = _this.backToFront[i], r = node.rect; var dx = Math.abs(p.x - r.cx()), dy = Math.abs(p.y - r.cy()); if (dx < r.width() / 2 && dy < r.height() / 2) { p.node = node; break; } } }); }); lines.forEach(function (l, li) { _this.nodes.forEach(function (v, i) { v.rect.lineIntersections(l.x1, l.y1, l.x2, l.y2).forEach(function (intersect, j) { var p = new Vert(_this.verts.length, intersect.x, intersect.y, v, l); _this.verts.push(p); l.verts.push(p); v.ports.push(p); }); }); var isHoriz = Math.abs(l.y1 - l.y2) < 0.1; var delta = function (a, b) { return isHoriz ? b.x - a.x : b.y - a.y; }; l.verts.sort(delta); for (var i = 1; i < l.verts.length; i++) { var u = l.verts[i - 1], v = l.verts[i]; if (u.node && u.node === v.node && u.node.leaf) continue; _this.edges.push({ source: u.id, target: v.id, length: Math.abs(delta(u, v)) }); } }); } GridRouter.prototype.avg = function (a) { return a.reduce(function (x, y) { return x + y; }) / a.length; }; GridRouter.prototype.getGridLines = function (axis) { var columns = []; var ls = this.leaves.slice(0, this.leaves.length); while (ls.length > 0) { var overlapping = ls.filter(function (v) { return v.rect['overlap' + axis.toUpperCase()](ls[0].rect); }); var col = { nodes: overlapping, pos: this.avg(overlapping.map(function (v) { return v.rect['c' + axis](); })) }; columns.push(col); col.nodes.forEach(function (v) { return ls.splice(ls.indexOf(v), 1); }); } columns.sort(function (a, b) { return a.pos - b.pos; }); return columns; }; GridRouter.prototype.getDepth = function (v) { var depth = 0; while (v.parent !== this.root) { depth++; v = v.parent; } return depth; }; GridRouter.prototype.midPoints = function (a) { var gap = a[1] - a[0]; var mids = [a[0] - gap / 2]; for (var i = 1; i < a.length; i++) { mids.push((a[i] + a[i - 1]) / 2); } mids.push(a[a.length - 1] + gap / 2); return mids; }; GridRouter.prototype.findLineage = function (v) { var lineage = [v]; do { v = v.parent; lineage.push(v); } while (v !== this.root); return lineage.reverse(); }; GridRouter.prototype.findAncestorPathBetween = function (a, b) { var aa = this.findLineage(a), ba = this.findLineage(b), i = 0; while (aa[i] === ba[i]) i++; return { commonAncestor: aa[i - 1], lineages: aa.slice(i).concat(ba.slice(i)) }; }; GridRouter.prototype.siblingObstacles = function (a, b) { var _this = this; var path = this.findAncestorPathBetween(a, b); var lineageLookup = {}; path.lineages.forEach(function (v) { return lineageLookup[v.id] = {}; }); var obstacles = path.commonAncestor.children.filter(function (v) { return !(v in lineageLookup); }); path.lineages .filter(function (v) { return v.parent !== path.commonAncestor; }) .forEach(function (v) { return obstacles = obstacles.concat(v.parent.children.filter(function (c) { return c !== v.id; })); }); return obstacles.map(function (v) { return _this.nodes[v]; }); }; GridRouter.getSegmentSets = function (routes, x, y) { var vsegments = []; for (var ei = 0; ei < routes.length; ei++) { var route = routes[ei]; for (var si = 0; si < route.length; si++) { var s = route[si]; s.edgeid = ei; s.i = si; var sdx = s[1][x] - s[0][x]; if (Math.abs(sdx) < 0.1) { vsegments.push(s); } } } vsegments.sort(function (a, b) { return a[0][x] - b[0][x]; }); var vsegmentsets = []; var segmentset = null; for (var i = 0; i < vsegments.length; i++) { var s = vsegments[i]; if (!segmentset || Math.abs(s[0][x] - segmentset.pos) > 0.1) { segmentset = { pos: s[0][x], segments: [] }; vsegmentsets.push(segmentset); } segmentset.segments.push(s); } return vsegmentsets; }; GridRouter.nudgeSegs = function (x, y, routes, segments, leftOf, gap) { var n = segments.length; if (n <= 1) return; var vs = segments.map(function (s) { return new vpsc_1.Variable(s[0][x]); }); var cs = []; for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { if (