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.
231 lines
6.0 KiB
231 lines
6.0 KiB
// https://d3js.org/d3-chord/ Version 1.0.4. Copyright 2017 Mike Bostock.
|
|
(function (global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-path')) :
|
|
typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-path'], factory) :
|
|
(factory((global.d3 = global.d3 || {}),global.d3,global.d3));
|
|
}(this, (function (exports,d3Array,d3Path) { 'use strict';
|
|
|
|
var cos = Math.cos;
|
|
var sin = Math.sin;
|
|
var pi = Math.PI;
|
|
var halfPi = pi / 2;
|
|
var tau = pi * 2;
|
|
var max = Math.max;
|
|
|
|
function compareValue(compare) {
|
|
return function(a, b) {
|
|
return compare(
|
|
a.source.value + a.target.value,
|
|
b.source.value + b.target.value
|
|
);
|
|
};
|
|
}
|
|
|
|
var chord = function() {
|
|
var padAngle = 0,
|
|
sortGroups = null,
|
|
sortSubgroups = null,
|
|
sortChords = null;
|
|
|
|
function chord(matrix) {
|
|
var n = matrix.length,
|
|
groupSums = [],
|
|
groupIndex = d3Array.range(n),
|
|
subgroupIndex = [],
|
|
chords = [],
|
|
groups = chords.groups = new Array(n),
|
|
subgroups = new Array(n * n),
|
|
k,
|
|
x,
|
|
x0,
|
|
dx,
|
|
i,
|
|
j;
|
|
|
|
// Compute the sum.
|
|
k = 0, i = -1; while (++i < n) {
|
|
x = 0, j = -1; while (++j < n) {
|
|
x += matrix[i][j];
|
|
}
|
|
groupSums.push(x);
|
|
subgroupIndex.push(d3Array.range(n));
|
|
k += x;
|
|
}
|
|
|
|
// Sort groups…
|
|
if (sortGroups) groupIndex.sort(function(a, b) {
|
|
return sortGroups(groupSums[a], groupSums[b]);
|
|
});
|
|
|
|
// Sort subgroups…
|
|
if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
|
|
d.sort(function(a, b) {
|
|
return sortSubgroups(matrix[i][a], matrix[i][b]);
|
|
});
|
|
});
|
|
|
|
// Convert the sum to scaling factor for [0, 2pi].
|
|
// TODO Allow start and end angle to be specified?
|
|
// TODO Allow padding to be specified as percentage?
|
|
k = max(0, tau - padAngle * n) / k;
|
|
dx = k ? padAngle : tau / n;
|
|
|
|
// Compute the start and end angle for each group and subgroup.
|
|
// Note: Opera has a bug reordering object literal properties!
|
|
x = 0, i = -1; while (++i < n) {
|
|
x0 = x, j = -1; while (++j < n) {
|
|
var di = groupIndex[i],
|
|
dj = subgroupIndex[di][j],
|
|
v = matrix[di][dj],
|
|
a0 = x,
|
|
a1 = x += v * k;
|
|
subgroups[dj * n + di] = {
|
|
index: di,
|
|
subindex: dj,
|
|
startAngle: a0,
|
|
endAngle: a1,
|
|
value: v
|
|
};
|
|
}
|
|
groups[di] = {
|
|
index: di,
|
|
startAngle: x0,
|
|
endAngle: x,
|
|
value: groupSums[di]
|
|
};
|
|
x += dx;
|
|
}
|
|
|
|
// Generate chords for each (non-empty) subgroup-subgroup link.
|
|
i = -1; while (++i < n) {
|
|
j = i - 1; while (++j < n) {
|
|
var source = subgroups[j * n + i],
|
|
target = subgroups[i * n + j];
|
|
if (source.value || target.value) {
|
|
chords.push(source.value < target.value
|
|
? {source: target, target: source}
|
|
: {source: source, target: target});
|
|
}
|
|
}
|
|
}
|
|
|
|
return sortChords ? chords.sort(sortChords) : chords;
|
|
}
|
|
|
|
chord.padAngle = function(_) {
|
|
return arguments.length ? (padAngle = max(0, _), chord) : padAngle;
|
|
};
|
|
|
|
chord.sortGroups = function(_) {
|
|
return arguments.length ? (sortGroups = _, chord) : sortGroups;
|
|
};
|
|
|
|
chord.sortSubgroups = function(_) {
|
|
return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
|
|
};
|
|
|
|
chord.sortChords = function(_) {
|
|
return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
|
|
};
|
|
|
|
return chord;
|
|
};
|
|
|
|
var slice = Array.prototype.slice;
|
|
|
|
var constant = function(x) {
|
|
return function() {
|
|
return x;
|
|
};
|
|
};
|
|
|
|
function defaultSource(d) {
|
|
return d.source;
|
|
}
|
|
|
|
function defaultTarget(d) {
|
|
return d.target;
|
|
}
|
|
|
|
function defaultRadius(d) {
|
|
return d.radius;
|
|
}
|
|
|
|
function defaultStartAngle(d) {
|
|
return d.startAngle;
|
|
}
|
|
|
|
function defaultEndAngle(d) {
|
|
return d.endAngle;
|
|
}
|
|
|
|
var ribbon = function() {
|
|
var source = defaultSource,
|
|
target = defaultTarget,
|
|
radius = defaultRadius,
|
|
startAngle = defaultStartAngle,
|
|
endAngle = defaultEndAngle,
|
|
context = null;
|
|
|
|
function ribbon() {
|
|
var buffer,
|
|
argv = slice.call(arguments),
|
|
s = source.apply(this, argv),
|
|
t = target.apply(this, argv),
|
|
sr = +radius.apply(this, (argv[0] = s, argv)),
|
|
sa0 = startAngle.apply(this, argv) - halfPi,
|
|
sa1 = endAngle.apply(this, argv) - halfPi,
|
|
sx0 = sr * cos(sa0),
|
|
sy0 = sr * sin(sa0),
|
|
tr = +radius.apply(this, (argv[0] = t, argv)),
|
|
ta0 = startAngle.apply(this, argv) - halfPi,
|
|
ta1 = endAngle.apply(this, argv) - halfPi;
|
|
|
|
if (!context) context = buffer = d3Path.path();
|
|
|
|
context.moveTo(sx0, sy0);
|
|
context.arc(0, 0, sr, sa0, sa1);
|
|
if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
|
|
context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
|
|
context.arc(0, 0, tr, ta0, ta1);
|
|
}
|
|
context.quadraticCurveTo(0, 0, sx0, sy0);
|
|
context.closePath();
|
|
|
|
if (buffer) return context = null, buffer + "" || null;
|
|
}
|
|
|
|
ribbon.radius = function(_) {
|
|
return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), ribbon) : radius;
|
|
};
|
|
|
|
ribbon.startAngle = function(_) {
|
|
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), ribbon) : startAngle;
|
|
};
|
|
|
|
ribbon.endAngle = function(_) {
|
|
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), ribbon) : endAngle;
|
|
};
|
|
|
|
ribbon.source = function(_) {
|
|
return arguments.length ? (source = _, ribbon) : source;
|
|
};
|
|
|
|
ribbon.target = function(_) {
|
|
return arguments.length ? (target = _, ribbon) : target;
|
|
};
|
|
|
|
ribbon.context = function(_) {
|
|
return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
|
|
};
|
|
|
|
return ribbon;
|
|
};
|
|
|
|
exports.chord = chord;
|
|
exports.ribbon = ribbon;
|
|
|
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
|
})));
|