Comparing version 2.0.0-rc.6 to 2.0.0-rc.7
@@ -1,2 +0,2 @@ | ||
// https://d3js.org/d3-chord/ v2.0.0-rc.6 Copyright 2019 Mike Bostock | ||
// https://d3js.org/d3-chord/ v2.0.0-rc.7 Copyright 2019 Mike Bostock | ||
(function (global, factory) { | ||
@@ -17,4 +17,4 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-path')) : | ||
function range(n) { | ||
return Array.from({length: n}, (_, i) => i); | ||
function range(i, j) { | ||
return Array.from({length: j - i}, (_, k) => i + k); | ||
} | ||
@@ -47,108 +47,58 @@ | ||
var n = matrix.length, | ||
groupSums = [], | ||
groupIndex = range(n), | ||
subgroupIndex = [], | ||
chords = [], | ||
groups = chords.groups = new Array(n), | ||
subgroups = new Array(n * n), | ||
k, | ||
x, | ||
x0, | ||
dx, | ||
i, | ||
j; | ||
groupSums = new Array(n), | ||
groupIndex = range(0, n), | ||
chords = new Array(n * n), | ||
groups = new Array(n), | ||
k = 0, dx; | ||
// Compute the sum. | ||
k = 0, i = -1; while (++i < n) { | ||
x = 0, j = -1; while (++j < n) { | ||
x += matrix[i][j] + directed * matrix[j][i]; | ||
} | ||
groupSums.push(x); | ||
subgroupIndex.push(range(n)); | ||
k += x; | ||
// Compute the scaling factor from value to angle in [0, 2pi]. | ||
for (let i = 0; i < n; ++i) { | ||
let x = 0; | ||
for (let j = 0; j < n; ++j) x += matrix[i][j] + directed * matrix[j][i]; | ||
k += groupSums[i] = x; | ||
} | ||
// Sort. | ||
if (sortGroups) groupIndex.sort((a, b) => sortGroups(groupSums[a], groupSums[b])); | ||
if (sortSubgroups) subgroupIndex.forEach((d, i) => d.sort((a, b) => sortSubgroups(matrix[i][a] - directed * matrix[a][i], matrix[i][b] - directed * matrix[b][i]))); | ||
// 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] + directed * matrix[dj][di], | ||
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], | ||
sourceValue = matrix[i][j], | ||
targetValue = matrix[j][i]; | ||
// Compute the angles for each group and constituent chord. | ||
{ | ||
let x = 0; | ||
if (sortGroups) groupIndex.sort((a, b) => sortGroups(groupSums[a], groupSums[b])); | ||
for (const i of groupIndex) { | ||
const x0 = x; | ||
if (directed) { | ||
var t = sourceValue / (sourceValue + targetValue); | ||
if (sourceValue) { | ||
chords.push({ | ||
source: { | ||
index: i, | ||
startAngle: source.startAngle * t + source.endAngle * (1 - t), | ||
endAngle: source.startAngle * (1 - t) + source.endAngle * t | ||
}, | ||
target: { | ||
index: j, | ||
startAngle: target.startAngle * t + target.endAngle * (1 - t), | ||
endAngle: target.startAngle * (1 - t) + target.endAngle * t | ||
}, | ||
value: sourceValue | ||
}); | ||
const subgroupIndex = range(~n + 1, n).filter(j => j < 0 ? matrix[~j][i] : matrix[i][j]); | ||
if (sortSubgroups) subgroupIndex.sort((a, b) => sortSubgroups(a < 0 ? -matrix[~a][i] : matrix[i][a], b < 0 ? -matrix[~b][i] : matrix[i][b])); | ||
for (const j of subgroupIndex) { | ||
if (j < 0) { | ||
const chord = chords[~j * n + i] || (chords[~j * n + i] = {source: null, target: null}); | ||
chord.target = {index: i, startAngle: x, endAngle: x += matrix[~j][i] * k, value: matrix[~j][i]}; | ||
} else { | ||
const chord = chords[i * n + j] || (chords[i * n + j] = {source: null, target: null}); | ||
chord.source = {index: i, startAngle: x, endAngle: x += matrix[i][j] * k, value: matrix[i][j]}; | ||
} | ||
} | ||
if (targetValue) { | ||
chords.push({ | ||
source: { | ||
index: j, | ||
startAngle: target.startAngle * (1 - t) + target.endAngle * t, | ||
endAngle: target.startAngle * t + target.endAngle * (1 - t) | ||
}, | ||
target: { | ||
index: i, | ||
startAngle: source.startAngle * (1 - t) + source.endAngle * t, | ||
endAngle: source.startAngle * t + source.endAngle * (1 - t) | ||
}, | ||
value: targetValue | ||
}); | ||
groups[i] = {index: i, startAngle: x0, endAngle: x, value: groupSums[i]}; | ||
} else { | ||
const subgroupIndex = range(0, n).filter(j => matrix[i][j] || matrix[j][i]); | ||
if (sortSubgroups) subgroupIndex.sort((a, b) => sortSubgroups(matrix[i][a], matrix[i][b])); | ||
for (const j of subgroupIndex) { | ||
if (i < j) { | ||
const chord = chords[i * n + j] || (chords[i * n + j] = {source: null, target: null}); | ||
chord.source = {index: i, startAngle: x, endAngle: x += matrix[i][j] * k, value: matrix[i][j]}; | ||
} else { | ||
const chord = chords[j * n + i] || (chords[j * n + i] = {source: null, target: null}); | ||
chord.target = {index: i, startAngle: x, endAngle: x += matrix[i][j] * k, value: matrix[i][j]}; | ||
if (i === j) chord.source = chord.target; | ||
} | ||
} | ||
} else if (sourceValue || targetValue) { | ||
chords.push(sourceValue < targetValue | ||
? {source: target, target: source} | ||
: {source: source, target: target}); | ||
groups[i] = {index: i, startAngle: x0, endAngle: x, value: groupSums[i]}; | ||
} | ||
x += dx; | ||
} | ||
} | ||
// Remove empty chords. | ||
chords = Object.values(chords); | ||
chords.groups = groups; | ||
return sortChords ? chords.sort(sortChords) : chords; | ||
@@ -155,0 +105,0 @@ } |
@@ -1,2 +0,2 @@ | ||
// https://d3js.org/d3-chord/ v2.0.0-rc.6 Copyright 2019 Mike Bostock | ||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-path")):"function"==typeof define&&define.amd?define(["exports","d3-path"],t):t((n=n||self).d3=n.d3||{},n.d3)}(this,function(n,t){"use strict";var e=Math.abs,r=Math.cos,u=Math.sin,o=Math.PI,l=o/2,a=2*o,i=Math.max,f=1e-12;function s(n){return Array.from({length:n},(n,t)=>t)}function c(n){return function(t,e){return n(t.source.value+t.target.value,e.source.value+e.target.value)}}function g(n){var t=0,e=null,r=null,u=null;function o(o){var l,f,c,g,d,p,h=o.length,A=[],y=s(h),v=[],x=[],b=x.groups=new Array(h),M=new Array(h*h);for(l=0,d=-1;++d<h;){for(f=0,p=-1;++p<h;)f+=o[d][p]+n*o[p][d];A.push(f),v.push(s(h)),l+=f}for(e&&y.sort((n,t)=>e(A[n],A[t])),r&&v.forEach((t,e)=>t.sort((t,u)=>r(o[e][t]-n*o[t][e],o[e][u]-n*o[u][e]))),g=(l=i(0,a-t*h)/l)?t:a/h,f=0,d=-1;++d<h;){for(c=f,p=-1;++p<h;){var T=y[d],m=v[T][p],q=o[T][m]+n*o[m][T],C=f,_=f+=q*l;M[m*h+T]={index:T,subindex:m,startAngle:C,endAngle:_,value:q}}b[T]={index:T,startAngle:c,endAngle:f,value:A[T]},f+=g}for(d=-1;++d<h;)for(p=d-1;++p<h;){var w=M[p*h+d],P=M[d*h+p],R=o[d][p],j=o[p][d];if(n){var D=R/(R+j);R&&x.push({source:{index:d,startAngle:w.startAngle*D+w.endAngle*(1-D),endAngle:w.startAngle*(1-D)+w.endAngle*D},target:{index:p,startAngle:P.startAngle*D+P.endAngle*(1-D),endAngle:P.startAngle*(1-D)+P.endAngle*D},value:R}),j&&x.push({source:{index:p,startAngle:P.startAngle*(1-D)+P.endAngle*D,endAngle:P.startAngle*D+P.endAngle*(1-D)},target:{index:d,startAngle:w.startAngle*(1-D)+w.endAngle*D,endAngle:w.startAngle*D+w.endAngle*(1-D)},value:j})}else(R||j)&&x.push(R<j?{source:P,target:w}:{source:w,target:P})}return u?x.sort(u):x}return o.padAngle=function(n){return arguments.length?(t=i(0,n),o):t},o.sortGroups=function(n){return arguments.length?(e=n,o):e},o.sortSubgroups=function(n){return arguments.length?(r=n,o):r},o.sortChords=function(n){return arguments.length?(null==n?u=null:(u=c(n))._=n,o):u&&u._},o}var d=Array.prototype.slice;function p(n){return function(){return n}}function h(n){return n.source}function A(n){return n.target}function y(n){return n.radius}function v(n){return n.startAngle}function x(n){return n.endAngle}function b(){return 0}function M(){return 10}function T(n){var o=h,a=A,i=y,s=y,c=v,g=x,M=b,T=null;function m(){var p,h=o.apply(this,arguments),A=a.apply(this,arguments),y=M.apply(this,arguments)/2,v=d.call(arguments),x=+i.apply(this,(v[0]=h,v)),b=c.apply(this,v)-l,m=g.apply(this,v)-l,q=+s.apply(this,(v[0]=A,v)),C=c.apply(this,v)-l,_=g.apply(this,v)-l;if(T||(T=p=t.path()),y>f&&(e(m-b)>2*y+f?m>b?(b+=y,m-=y):(b-=y,m+=y):b=m=(b+m)/2,e(_-C)>2*y+f?_>C?(C+=y,_-=y):(C-=y,_+=y):C=_=(C+_)/2),T.moveTo(x*r(b),x*u(b)),T.arc(0,0,x,b,m),b!==C||m!==_)if(n){var w=q-+n.apply(this,arguments),P=(C+_)/2;T.quadraticCurveTo(0,0,w*r(C),w*u(C)),T.lineTo(q*r(P),q*u(P)),T.lineTo(w*r(_),w*u(_))}else T.quadraticCurveTo(0,0,q*r(C),q*u(C)),T.arc(0,0,q,C,_);if(T.quadraticCurveTo(0,0,x*r(b),x*u(b)),T.closePath(),p)return T=null,p+""||null}return n&&(m.headRadius=function(t){return arguments.length?(n="function"==typeof t?t:p(+t),m):n}),m.radius=function(n){return arguments.length?(i=s="function"==typeof n?n:p(+n),m):i},m.sourceRadius=function(n){return arguments.length?(i="function"==typeof n?n:p(+n),m):i},m.targetRadius=function(n){return arguments.length?(s="function"==typeof n?n:p(+n),m):s},m.startAngle=function(n){return arguments.length?(c="function"==typeof n?n:p(+n),m):c},m.endAngle=function(n){return arguments.length?(g="function"==typeof n?n:p(+n),m):g},m.padAngle=function(n){return arguments.length?(M="function"==typeof n?n:p(+n),m):M},m.source=function(n){return arguments.length?(o=n,m):o},m.target=function(n){return arguments.length?(a=n,m):a},m.context=function(n){return arguments.length?(T=null==n?null:n,m):T},m}n.chord=function(){return g(!1)},n.chordDirected=function(){return g(!0)},n.ribbon=function(){return T()},n.ribbonArrow=function(){return T(M)},Object.defineProperty(n,"__esModule",{value:!0})}); | ||
// https://d3js.org/d3-chord/ v2.0.0-rc.7 Copyright 2019 Mike Bostock | ||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-path")):"function"==typeof define&&define.amd?define(["exports","d3-path"],t):t((n=n||self).d3=n.d3||{},n.d3)}(this,function(n,t){"use strict";var e=Math.abs,r=Math.cos,u=Math.sin,o=Math.PI,l=o/2,i=2*o,a=Math.max,c=1e-12;function f(n,t){return Array.from({length:t-n},(t,e)=>n+e)}function s(n){return function(t,e){return n(t.source.value+t.target.value,e.source.value+e.target.value)}}function g(n){var t=0,e=null,r=null,u=null;function o(o){var l,c=o.length,s=new Array(c),g=f(0,c),p=new Array(c*c),d=new Array(c),h=0;for(let t=0;t<c;++t){let e=0;for(let r=0;r<c;++r)e+=o[t][r]+n*o[r][t];h+=s[t]=e}l=(h=a(0,i-t*c)/h)?t:i/c;{let t=0;e&&g.sort((n,t)=>e(s[n],s[t]));for(const e of g){const u=t;if(n){const n=f(1+~c,c).filter(n=>n<0?o[~n][e]:o[e][n]);r&&n.sort((n,t)=>r(n<0?-o[~n][e]:o[e][n],t<0?-o[~t][e]:o[e][t]));for(const r of n)if(r<0){(p[~r*c+e]||(p[~r*c+e]={source:null,target:null})).target={index:e,startAngle:t,endAngle:t+=o[~r][e]*h,value:o[~r][e]}}else{(p[e*c+r]||(p[e*c+r]={source:null,target:null})).source={index:e,startAngle:t,endAngle:t+=o[e][r]*h,value:o[e][r]}}d[e]={index:e,startAngle:u,endAngle:t,value:s[e]}}else{const n=f(0,c).filter(n=>o[e][n]||o[n][e]);r&&n.sort((n,t)=>r(o[e][n],o[e][t]));for(const r of n)if(e<r){(p[e*c+r]||(p[e*c+r]={source:null,target:null})).source={index:e,startAngle:t,endAngle:t+=o[e][r]*h,value:o[e][r]}}else{const n=p[r*c+e]||(p[r*c+e]={source:null,target:null});n.target={index:e,startAngle:t,endAngle:t+=o[e][r]*h,value:o[e][r]},e===r&&(n.source=n.target)}d[e]={index:e,startAngle:u,endAngle:t,value:s[e]}}t+=l}}return(p=Object.values(p)).groups=d,u?p.sort(u):p}return o.padAngle=function(n){return arguments.length?(t=a(0,n),o):t},o.sortGroups=function(n){return arguments.length?(e=n,o):e},o.sortSubgroups=function(n){return arguments.length?(r=n,o):r},o.sortChords=function(n){return arguments.length?(null==n?u=null:(u=s(n))._=n,o):u&&u._},o}var p=Array.prototype.slice;function d(n){return function(){return n}}function h(n){return n.source}function y(n){return n.target}function A(n){return n.radius}function v(n){return n.startAngle}function x(n){return n.endAngle}function b(){return 0}function M(){return 10}function T(n){var o=h,i=y,a=A,f=A,s=v,g=x,M=b,T=null;function m(){var d,h=o.apply(this,arguments),y=i.apply(this,arguments),A=M.apply(this,arguments)/2,v=p.call(arguments),x=+a.apply(this,(v[0]=h,v)),b=s.apply(this,v)-l,m=g.apply(this,v)-l,q=+f.apply(this,(v[0]=y,v)),w=s.apply(this,v)-l,C=g.apply(this,v)-l;if(T||(T=d=t.path()),A>c&&(e(m-b)>2*A+c?m>b?(b+=A,m-=A):(b-=A,m+=A):b=m=(b+m)/2,e(C-w)>2*A+c?C>w?(w+=A,C-=A):(w-=A,C+=A):w=C=(w+C)/2),T.moveTo(x*r(b),x*u(b)),T.arc(0,0,x,b,m),b!==w||m!==C)if(n){var _=q-+n.apply(this,arguments),j=(w+C)/2;T.quadraticCurveTo(0,0,_*r(w),_*u(w)),T.lineTo(q*r(j),q*u(j)),T.lineTo(_*r(C),_*u(C))}else T.quadraticCurveTo(0,0,q*r(w),q*u(w)),T.arc(0,0,q,w,C);if(T.quadraticCurveTo(0,0,x*r(b),x*u(b)),T.closePath(),d)return T=null,d+""||null}return n&&(m.headRadius=function(t){return arguments.length?(n="function"==typeof t?t:d(+t),m):n}),m.radius=function(n){return arguments.length?(a=f="function"==typeof n?n:d(+n),m):a},m.sourceRadius=function(n){return arguments.length?(a="function"==typeof n?n:d(+n),m):a},m.targetRadius=function(n){return arguments.length?(f="function"==typeof n?n:d(+n),m):f},m.startAngle=function(n){return arguments.length?(s="function"==typeof n?n:d(+n),m):s},m.endAngle=function(n){return arguments.length?(g="function"==typeof n?n:d(+n),m):g},m.padAngle=function(n){return arguments.length?(M="function"==typeof n?n:d(+n),m):M},m.source=function(n){return arguments.length?(o=n,m):o},m.target=function(n){return arguments.length?(i=n,m):i},m.context=function(n){return arguments.length?(T=null==n?null:n,m):T},m}n.chord=function(){return g(!1)},n.chordDirected=function(){return g(!0)},n.ribbon=function(){return T()},n.ribbonArrow=function(){return T(M)},Object.defineProperty(n,"__esModule",{value:!0})}); |
{ | ||
"name": "d3-chord", | ||
"version": "2.0.0-rc.6", | ||
"version": "2.0.0-rc.7", | ||
"publishConfig": { | ||
@@ -42,2 +42,3 @@ "tag": "next" | ||
}, | ||
"sideEffects": false, | ||
"devDependencies": { | ||
@@ -44,0 +45,0 @@ "eslint": "6", |
@@ -51,5 +51,4 @@ # d3-chord | ||
* `index` - the node index *i* | ||
* `subindex` - the node index *j* | ||
The chords are typically passed to [d3.ribbon](#ribbon) to display the network relationships. The returned array includes only chord objects for which the value *matrix*[*i*][*j*] or *matrix*[*j*][*i*] is non-zero. Furthermore, the returned array only contains unique chords: a given chord *ij* represents the bidirectional flow from *i* to *j* *and* from *j* to *i*, and does not contain a duplicate chord *ji*; *i* and *j* are chosen such that the chord’s source always represents the larger of *matrix*[*i*][*j*] and *matrix*[*j*][*i*]. In other words, *chord*.source.index equals *chord*.target.subindex, *chord*.source.subindex equals *chord*.target.index, *chord*.source.value is greater than or equal to *chord*.target.value, and *chord*.source.value is always greater than zero. | ||
The chords are typically passed to [d3.ribbon](#ribbon) to display the network relationships. The returned array includes only chord objects for which the value *matrix*[*i*][*j*] or *matrix*[*j*][*i*] is non-zero. Furthermore, the returned array only contains unique chords: a given chord *ij* represents the bidirectional flow from *i* to *j* *and* from *j* to *i*, and does not contain a duplicate chord *ji*. | ||
@@ -56,0 +55,0 @@ The *chords* array also defines a secondary array of length *n*, *chords*.groups, where each group represents the combined outflow for node *i*, corresponding to the elements *matrix*[*i*][0 … *n* - 1], and is an object with the following properties: |
142
src/chord.js
import {max, tau} from "./math.js"; | ||
function range(n) { | ||
return Array.from({length: n}, (_, i) => i); | ||
function range(i, j) { | ||
return Array.from({length: j - i}, (_, k) => i + k); | ||
} | ||
@@ -32,108 +32,58 @@ | ||
var n = matrix.length, | ||
groupSums = [], | ||
groupIndex = range(n), | ||
subgroupIndex = [], | ||
chords = [], | ||
groups = chords.groups = new Array(n), | ||
subgroups = new Array(n * n), | ||
k, | ||
x, | ||
x0, | ||
dx, | ||
i, | ||
j; | ||
groupSums = new Array(n), | ||
groupIndex = range(0, n), | ||
chords = new Array(n * n), | ||
groups = new Array(n), | ||
k = 0, dx; | ||
// Compute the sum. | ||
k = 0, i = -1; while (++i < n) { | ||
x = 0, j = -1; while (++j < n) { | ||
x += matrix[i][j] + directed * matrix[j][i]; | ||
} | ||
groupSums.push(x); | ||
subgroupIndex.push(range(n)); | ||
k += x; | ||
// Compute the scaling factor from value to angle in [0, 2pi]. | ||
for (let i = 0; i < n; ++i) { | ||
let x = 0; | ||
for (let j = 0; j < n; ++j) x += matrix[i][j] + directed * matrix[j][i]; | ||
k += groupSums[i] = x; | ||
} | ||
// Sort. | ||
if (sortGroups) groupIndex.sort((a, b) => sortGroups(groupSums[a], groupSums[b])); | ||
if (sortSubgroups) subgroupIndex.forEach((d, i) => d.sort((a, b) => sortSubgroups(matrix[i][a] - directed * matrix[a][i], matrix[i][b] - directed * matrix[b][i]))); | ||
// 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] + directed * matrix[dj][di], | ||
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], | ||
sourceValue = matrix[i][j], | ||
targetValue = matrix[j][i]; | ||
// Compute the angles for each group and constituent chord. | ||
{ | ||
let x = 0; | ||
if (sortGroups) groupIndex.sort((a, b) => sortGroups(groupSums[a], groupSums[b])); | ||
for (const i of groupIndex) { | ||
const x0 = x; | ||
if (directed) { | ||
var t = sourceValue / (sourceValue + targetValue); | ||
if (sourceValue) { | ||
chords.push({ | ||
source: { | ||
index: i, | ||
startAngle: source.startAngle * t + source.endAngle * (1 - t), | ||
endAngle: source.startAngle * (1 - t) + source.endAngle * t | ||
}, | ||
target: { | ||
index: j, | ||
startAngle: target.startAngle * t + target.endAngle * (1 - t), | ||
endAngle: target.startAngle * (1 - t) + target.endAngle * t | ||
}, | ||
value: sourceValue | ||
}); | ||
const subgroupIndex = range(~n + 1, n).filter(j => j < 0 ? matrix[~j][i] : matrix[i][j]); | ||
if (sortSubgroups) subgroupIndex.sort((a, b) => sortSubgroups(a < 0 ? -matrix[~a][i] : matrix[i][a], b < 0 ? -matrix[~b][i] : matrix[i][b])); | ||
for (const j of subgroupIndex) { | ||
if (j < 0) { | ||
const chord = chords[~j * n + i] || (chords[~j * n + i] = {source: null, target: null}); | ||
chord.target = {index: i, startAngle: x, endAngle: x += matrix[~j][i] * k, value: matrix[~j][i]}; | ||
} else { | ||
const chord = chords[i * n + j] || (chords[i * n + j] = {source: null, target: null}); | ||
chord.source = {index: i, startAngle: x, endAngle: x += matrix[i][j] * k, value: matrix[i][j]}; | ||
} | ||
} | ||
if (targetValue) { | ||
chords.push({ | ||
source: { | ||
index: j, | ||
startAngle: target.startAngle * (1 - t) + target.endAngle * t, | ||
endAngle: target.startAngle * t + target.endAngle * (1 - t) | ||
}, | ||
target: { | ||
index: i, | ||
startAngle: source.startAngle * (1 - t) + source.endAngle * t, | ||
endAngle: source.startAngle * t + source.endAngle * (1 - t) | ||
}, | ||
value: targetValue | ||
}); | ||
groups[i] = {index: i, startAngle: x0, endAngle: x, value: groupSums[i]}; | ||
} else { | ||
const subgroupIndex = range(0, n).filter(j => matrix[i][j] || matrix[j][i]); | ||
if (sortSubgroups) subgroupIndex.sort((a, b) => sortSubgroups(matrix[i][a], matrix[i][b])); | ||
for (const j of subgroupIndex) { | ||
if (i < j) { | ||
const chord = chords[i * n + j] || (chords[i * n + j] = {source: null, target: null}); | ||
chord.source = {index: i, startAngle: x, endAngle: x += matrix[i][j] * k, value: matrix[i][j]}; | ||
} else { | ||
const chord = chords[j * n + i] || (chords[j * n + i] = {source: null, target: null}); | ||
chord.target = {index: i, startAngle: x, endAngle: x += matrix[i][j] * k, value: matrix[i][j]}; | ||
if (i === j) chord.source = chord.target; | ||
} | ||
} | ||
} else if (sourceValue || targetValue) { | ||
chords.push(sourceValue < targetValue | ||
? {source: target, target: source} | ||
: {source: source, target: target}); | ||
groups[i] = {index: i, startAngle: x0, endAngle: x, value: groupSums[i]}; | ||
} | ||
x += dx; | ||
} | ||
} | ||
// Remove empty chords. | ||
chords = Object.values(chords); | ||
chords.groups = groups; | ||
return sortChords ? chords.sort(sortChords) : chords; | ||
@@ -140,0 +90,0 @@ } |
36386
458
215