dc.graph
Version:
Graph visualizations integrated with crossfilter and dc.js
1,330 lines • 765 kB
JavaScript
(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 (