You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
550 lines
23 KiB
550 lines
23 KiB
"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 (i === j)
|
|
continue;
|
|
var s1 = segments[i], s2 = segments[j], e1 = s1.edgeid, e2 = s2.edgeid, lind = -1, rind = -1;
|
|
if (x == 'x') {
|
|
if (leftOf(e1, e2)) {
|
|
if (s1[0][y] < s1[1][y]) {
|
|
lind = j, rind = i;
|
|
}
|
|
else {
|
|
lind = i, rind = j;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (leftOf(e1, e2)) {
|
|
if (s1[0][y] < s1[1][y]) {
|
|
lind = i, rind = j;
|
|
}
|
|
else {
|
|
lind = j, rind = i;
|
|
}
|
|
}
|
|
}
|
|
if (lind >= 0) {
|
|
cs.push(new vpsc_1.Constraint(vs[lind], vs[rind], gap));
|
|
}
|
|
}
|
|
}
|
|
var solver = new vpsc_1.Solver(vs, cs);
|
|
solver.solve();
|
|
vs.forEach(function (v, i) {
|
|
var s = segments[i];
|
|
var pos = v.position();
|
|
s[0][x] = s[1][x] = pos;
|
|
var route = routes[s.edgeid];
|
|
if (s.i > 0)
|
|
route[s.i - 1][1][x] = pos;
|
|
if (s.i < route.length - 1)
|
|
route[s.i + 1][0][x] = pos;
|
|
});
|
|
};
|
|
GridRouter.nudgeSegments = function (routes, x, y, leftOf, gap) {
|
|
var vsegmentsets = GridRouter.getSegmentSets(routes, x, y);
|
|
for (var i = 0; i < vsegmentsets.length; i++) {
|
|
var ss = vsegmentsets[i];
|
|
var events = [];
|
|
for (var j = 0; j < ss.segments.length; j++) {
|
|
var s = ss.segments[j];
|
|
events.push({ type: 0, s: s, pos: Math.min(s[0][y], s[1][y]) });
|
|
events.push({ type: 1, s: s, pos: Math.max(s[0][y], s[1][y]) });
|
|
}
|
|
events.sort(function (a, b) { return a.pos - b.pos + a.type - b.type; });
|
|
var open = [];
|
|
var openCount = 0;
|
|
events.forEach(function (e) {
|
|
if (e.type === 0) {
|
|
open.push(e.s);
|
|
openCount++;
|
|
}
|
|
else {
|
|
openCount--;
|
|
}
|
|
if (openCount == 0) {
|
|
GridRouter.nudgeSegs(x, y, routes, open, leftOf, gap);
|
|
open = [];
|
|
}
|
|
});
|
|
}
|
|
};
|
|
GridRouter.prototype.routeEdges = function (edges, nudgeGap, source, target) {
|
|
var _this = this;
|
|
var routePaths = edges.map(function (e) { return _this.route(source(e), target(e)); });
|
|
var order = GridRouter.orderEdges(routePaths);
|
|
var routes = routePaths.map(function (e) { return GridRouter.makeSegments(e); });
|
|
GridRouter.nudgeSegments(routes, 'x', 'y', order, nudgeGap);
|
|
GridRouter.nudgeSegments(routes, 'y', 'x', order, nudgeGap);
|
|
GridRouter.unreverseEdges(routes, routePaths);
|
|
return routes;
|
|
};
|
|
GridRouter.unreverseEdges = function (routes, routePaths) {
|
|
routes.forEach(function (segments, i) {
|
|
var path = routePaths[i];
|
|
if (path.reversed) {
|
|
segments.reverse();
|
|
segments.forEach(function (segment) {
|
|
segment.reverse();
|
|
});
|
|
}
|
|
});
|
|
};
|
|
GridRouter.angleBetween2Lines = function (line1, line2) {
|
|
var angle1 = Math.atan2(line1[0].y - line1[1].y, line1[0].x - line1[1].x);
|
|
var angle2 = Math.atan2(line2[0].y - line2[1].y, line2[0].x - line2[1].x);
|
|
var diff = angle1 - angle2;
|
|
if (diff > Math.PI || diff < -Math.PI) {
|
|
diff = angle2 - angle1;
|
|
}
|
|
return diff;
|
|
};
|
|
GridRouter.isLeft = function (a, b, c) {
|
|
return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) <= 0;
|
|
};
|
|
GridRouter.getOrder = function (pairs) {
|
|
var outgoing = {};
|
|
for (var i = 0; i < pairs.length; i++) {
|
|
var p = pairs[i];
|
|
if (typeof outgoing[p.l] === 'undefined')
|
|
outgoing[p.l] = {};
|
|
outgoing[p.l][p.r] = true;
|
|
}
|
|
return function (l, r) { return typeof outgoing[l] !== 'undefined' && outgoing[l][r]; };
|
|
};
|
|
GridRouter.orderEdges = function (edges) {
|
|
var edgeOrder = [];
|
|
for (var i = 0; i < edges.length - 1; i++) {
|
|
for (var j = i + 1; j < edges.length; j++) {
|
|
var e = edges[i], f = edges[j], lcs = new LongestCommonSubsequence(e, f);
|
|
var u, vi, vj;
|
|
if (lcs.length === 0)
|
|
continue;
|
|
if (lcs.reversed) {
|
|
f.reverse();
|
|
f.reversed = true;
|
|
lcs = new LongestCommonSubsequence(e, f);
|
|
}
|
|
if ((lcs.si <= 0 || lcs.ti <= 0) &&
|
|
(lcs.si + lcs.length >= e.length || lcs.ti + lcs.length >= f.length)) {
|
|
edgeOrder.push({ l: i, r: j });
|
|
continue;
|
|
}
|
|
if (lcs.si + lcs.length >= e.length || lcs.ti + lcs.length >= f.length) {
|
|
u = e[lcs.si + 1];
|
|
vj = e[lcs.si - 1];
|
|
vi = f[lcs.ti - 1];
|
|
}
|
|
else {
|
|
u = e[lcs.si + lcs.length - 2];
|
|
vi = e[lcs.si + lcs.length];
|
|
vj = f[lcs.ti + lcs.length];
|
|
}
|
|
if (GridRouter.isLeft(u, vi, vj)) {
|
|
edgeOrder.push({ l: j, r: i });
|
|
}
|
|
else {
|
|
edgeOrder.push({ l: i, r: j });
|
|
}
|
|
}
|
|
}
|
|
return GridRouter.getOrder(edgeOrder);
|
|
};
|
|
GridRouter.makeSegments = function (path) {
|
|
function copyPoint(p) {
|
|
return { x: p.x, y: p.y };
|
|
}
|
|
var isStraight = function (a, b, c) { return Math.abs((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) < 0.001; };
|
|
var segments = [];
|
|
var a = copyPoint(path[0]);
|
|
for (var i = 1; i < path.length; i++) {
|
|
var b = copyPoint(path[i]), c = i < path.length - 1 ? path[i + 1] : null;
|
|
if (!c || !isStraight(a, b, c)) {
|
|
segments.push([a, b]);
|
|
a = b;
|
|
}
|
|
}
|
|
return segments;
|
|
};
|
|
GridRouter.prototype.route = function (s, t) {
|
|
var _this = this;
|
|
var source = this.nodes[s], target = this.nodes[t];
|
|
this.obstacles = this.siblingObstacles(source, target);
|
|
var obstacleLookup = {};
|
|
this.obstacles.forEach(function (o) { return obstacleLookup[o.id] = o; });
|
|
this.passableEdges = this.edges.filter(function (e) {
|
|
var u = _this.verts[e.source], v = _this.verts[e.target];
|
|
return !(u.node && u.node.id in obstacleLookup
|
|
|| v.node && v.node.id in obstacleLookup);
|
|
});
|
|
for (var i = 1; i < source.ports.length; i++) {
|
|
var u = source.ports[0].id;
|
|
var v = source.ports[i].id;
|
|
this.passableEdges.push({
|
|
source: u,
|
|
target: v,
|
|
length: 0
|
|
});
|
|
}
|
|
for (var i = 1; i < target.ports.length; i++) {
|
|
var u = target.ports[0].id;
|
|
var v = target.ports[i].id;
|
|
this.passableEdges.push({
|
|
source: u,
|
|
target: v,
|
|
length: 0
|
|
});
|
|
}
|
|
var getSource = function (e) { return e.source; }, getTarget = function (e) { return e.target; }, getLength = function (e) { return e.length; };
|
|
var shortestPathCalculator = new shortestpaths_1.Calculator(this.verts.length, this.passableEdges, getSource, getTarget, getLength);
|
|
var bendPenalty = function (u, v, w) {
|
|
var a = _this.verts[u], b = _this.verts[v], c = _this.verts[w];
|
|
var dx = Math.abs(c.x - a.x), dy = Math.abs(c.y - a.y);
|
|
if (a.node === source && a.node === b.node || b.node === target && b.node === c.node)
|
|
return 0;
|
|
return dx > 1 && dy > 1 ? 1000 : 0;
|
|
};
|
|
var shortestPath = shortestPathCalculator.PathFromNodeToNodeWithPrevCost(source.ports[0].id, target.ports[0].id, bendPenalty);
|
|
var pathPoints = shortestPath.reverse().map(function (vi) { return _this.verts[vi]; });
|
|
pathPoints.push(this.nodes[target.id].ports[0]);
|
|
return pathPoints.filter(function (v, i) {
|
|
return !(i < pathPoints.length - 1 && pathPoints[i + 1].node === source && v.node === source
|
|
|| i > 0 && v.node === target && pathPoints[i - 1].node === target);
|
|
});
|
|
};
|
|
GridRouter.getRoutePath = function (route, cornerradius, arrowwidth, arrowheight) {
|
|
var result = {
|
|
routepath: 'M ' + route[0][0].x + ' ' + route[0][0].y + ' ',
|
|
arrowpath: ''
|
|
};
|
|
if (route.length > 1) {
|
|
for (var i = 0; i < route.length; i++) {
|
|
var li = route[i];
|
|
var x = li[1].x, y = li[1].y;
|
|
var dx = x - li[0].x;
|
|
var dy = y - li[0].y;
|
|
if (i < route.length - 1) {
|
|
if (Math.abs(dx) > 0) {
|
|
x -= dx / Math.abs(dx) * cornerradius;
|
|
}
|
|
else {
|
|
y -= dy / Math.abs(dy) * cornerradius;
|
|
}
|
|
result.routepath += 'L ' + x + ' ' + y + ' ';
|
|
var l = route[i + 1];
|
|
var x0 = l[0].x, y0 = l[0].y;
|
|
var x1 = l[1].x;
|
|
var y1 = l[1].y;
|
|
dx = x1 - x0;
|
|
dy = y1 - y0;
|
|
var angle = GridRouter.angleBetween2Lines(li, l) < 0 ? 1 : 0;
|
|
var x2, y2;
|
|
if (Math.abs(dx) > 0) {
|
|
x2 = x0 + dx / Math.abs(dx) * cornerradius;
|
|
y2 = y0;
|
|
}
|
|
else {
|
|
x2 = x0;
|
|
y2 = y0 + dy / Math.abs(dy) * cornerradius;
|
|
}
|
|
var cx = Math.abs(x2 - x);
|
|
var cy = Math.abs(y2 - y);
|
|
result.routepath += 'A ' + cx + ' ' + cy + ' 0 0 ' + angle + ' ' + x2 + ' ' + y2 + ' ';
|
|
}
|
|
else {
|
|
var arrowtip = [x, y];
|
|
var arrowcorner1, arrowcorner2;
|
|
if (Math.abs(dx) > 0) {
|
|
x -= dx / Math.abs(dx) * arrowheight;
|
|
arrowcorner1 = [x, y + arrowwidth];
|
|
arrowcorner2 = [x, y - arrowwidth];
|
|
}
|
|
else {
|
|
y -= dy / Math.abs(dy) * arrowheight;
|
|
arrowcorner1 = [x + arrowwidth, y];
|
|
arrowcorner2 = [x - arrowwidth, y];
|
|
}
|
|
result.routepath += 'L ' + x + ' ' + y + ' ';
|
|
if (arrowheight > 0) {
|
|
result.arrowpath = 'M ' + arrowtip[0] + ' ' + arrowtip[1] + ' L ' + arrowcorner1[0] + ' ' + arrowcorner1[1]
|
|
+ ' L ' + arrowcorner2[0] + ' ' + arrowcorner2[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
var li = route[0];
|
|
var x = li[1].x, y = li[1].y;
|
|
var dx = x - li[0].x;
|
|
var dy = y - li[0].y;
|
|
var arrowtip = [x, y];
|
|
var arrowcorner1, arrowcorner2;
|
|
if (Math.abs(dx) > 0) {
|
|
x -= dx / Math.abs(dx) * arrowheight;
|
|
arrowcorner1 = [x, y + arrowwidth];
|
|
arrowcorner2 = [x, y - arrowwidth];
|
|
}
|
|
else {
|
|
y -= dy / Math.abs(dy) * arrowheight;
|
|
arrowcorner1 = [x + arrowwidth, y];
|
|
arrowcorner2 = [x - arrowwidth, y];
|
|
}
|
|
result.routepath += 'L ' + x + ' ' + y + ' ';
|
|
if (arrowheight > 0) {
|
|
result.arrowpath = 'M ' + arrowtip[0] + ' ' + arrowtip[1] + ' L ' + arrowcorner1[0] + ' ' + arrowcorner1[1]
|
|
+ ' L ' + arrowcorner2[0] + ' ' + arrowcorner2[1];
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
return GridRouter;
|
|
}());
|
|
exports.GridRouter = GridRouter;
|
|
//# sourceMappingURL=gridrouter.js.map
|