Spaces:
Running
Running
| import "../arrays/range"; | |
| import "../math/trigonometry"; | |
| import "layout"; | |
| d3.layout.chord = function() { | |
| var chord = {}, | |
| chords, | |
| groups, | |
| matrix, | |
| n, | |
| padding = 0, | |
| sortGroups, | |
| sortSubgroups, | |
| sortChords; | |
| function relayout() { | |
| var subgroups = {}, | |
| groupSums = [], | |
| groupIndex = d3.range(n), | |
| subgroupIndex = [], | |
| k, | |
| x, | |
| x0, | |
| i, | |
| j; | |
| chords = []; | |
| groups = []; | |
| // 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(d3.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 = (τ - padding * n) / k; | |
| // 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[di + "-" + dj] = { | |
| index: di, | |
| subindex: dj, | |
| startAngle: a0, | |
| endAngle: a1, | |
| value: v | |
| }; | |
| } | |
| groups[di] = { | |
| index: di, | |
| startAngle: x0, | |
| endAngle: x, | |
| value: groupSums[di] | |
| }; | |
| x += padding; | |
| } | |
| // Generate chords for each (non-empty) subgroup-subgroup link. | |
| i = -1; while (++i < n) { | |
| j = i - 1; while (++j < n) { | |
| var source = subgroups[i + "-" + j], | |
| target = subgroups[j + "-" + i]; | |
| if (source.value || target.value) { | |
| chords.push(source.value < target.value | |
| ? {source: target, target: source} | |
| : {source: source, target: target}); | |
| } | |
| } | |
| } | |
| if (sortChords) resort(); | |
| } | |
| function resort() { | |
| chords.sort(function(a, b) { | |
| return sortChords( | |
| (a.source.value + a.target.value) / 2, | |
| (b.source.value + b.target.value) / 2); | |
| }); | |
| } | |
| chord.matrix = function(x) { | |
| if (!arguments.length) return matrix; | |
| n = (matrix = x) && matrix.length; | |
| chords = groups = null; | |
| return chord; | |
| }; | |
| chord.padding = function(x) { | |
| if (!arguments.length) return padding; | |
| padding = x; | |
| chords = groups = null; | |
| return chord; | |
| }; | |
| chord.sortGroups = function(x) { | |
| if (!arguments.length) return sortGroups; | |
| sortGroups = x; | |
| chords = groups = null; | |
| return chord; | |
| }; | |
| chord.sortSubgroups = function(x) { | |
| if (!arguments.length) return sortSubgroups; | |
| sortSubgroups = x; | |
| chords = null; | |
| return chord; | |
| }; | |
| chord.sortChords = function(x) { | |
| if (!arguments.length) return sortChords; | |
| sortChords = x; | |
| if (chords) resort(); | |
| return chord; | |
| }; | |
| chord.chords = function() { | |
| if (!chords) relayout(); | |
| return chords; | |
| }; | |
| chord.groups = function() { | |
| if (!groups) relayout(); | |
| return groups; | |
| }; | |
| return chord; | |
| }; | |